OpenAI PaperBench代码架构深度解析:整体结构,核心组件与工作流程

https://github.com/openai/preparedness/tree/main/project/paperbench

项目概述

PaperBench是一个用于评估AI代理复现学术论文能力的综合框架。它提供了完整的工具链,从论文数据管理、代理执行、结果监控到评分系统,旨在自动化和标准化AI代理复现学术研究的过程。通过PaperBench,研究人员可以系统地测试不同AI代理在理解、实现和验证学术论文中的方法和结果方面的能力。

整体架构设计

PaperBench采用模块化设计,主要由以下核心层次组成:

  1. 数据层:负责论文数据的结构化管理和访问
  2. 代理层:实现各种AI代理及其执行环境
  3. 评估层:协调代理执行和结果收集
  4. 评判层:对代理复现结果进行评分和分析
  5. 展示层:提供用户界面和可视化功能
  6. 工具层:提供通用工具和基础设施支持

架构图

┌─────────────────────────────────────────────────────────────┐
│                        展示层 (GUI)                         │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────┼─────────────────────────────────┐
│                        评判层 (Judge)                       │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────┼─────────────────────────────────┐
│                        评估层 (Nano)                        │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────┼─────────────────────────────────┐
│                        代理层 (Agents)                      │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────┼─────────────────────────────────┐
│                        数据层 (Registry)                    │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────┼─────────────────────────────────┐
│                        工具层 (Utils)                       │
└─────────────────────────────────────────────────────────────┘

核心组件详解

1. 数据层

数据层主要由paper_registry.pyagents/registry.py文件实现,负责管理论文数据和代理配置。

PaperRegistry类
@dataclass
class PaperRegistry:
    papers: dict[str, Paper] = field(default_factory=dict)
    paper_dir: Path = field(default_factory=get_paperbench_data_dir)

    def __post_init__(self) -> None:
        self._load_papers()

    def _load_papers(self) -> None:
        for paper_dir in self.paper_dir.iterdir():
            if not paper_dir.is_dir():
                continue
            try:
                paper = Paper.from_dir(paper_dir)
                self.papers[paper.id] = paper
            except Exception as e:
                logger.warning(f"Failed to load paper from {paper_dir}: {e}")

    def get_paper(self, paper_id: str) -> Paper:
        if paper_id not in self.papers:
            raise ValueError(f"Paper with id {paper_id} not found")
        return self.papers[paper_id]

    def get_paper_ids(self) -> list[str]:
        return list(self.papers.keys())

这个类负责加载和管理所有可用的论文数据,提供统一的接口来访问论文信息。类似地,AgentRegistry类负责管理代理配置。

Paper数据类
@dataclass(frozen=True)
class Paper:
    id: str
    title: str
    pdf_path: Path
    md_path: Path
    config_path: Path
    blacklist: Path
    repro_dir: Path
    judge_dir: Path
    rubric_path: Path

    @classmethod
    def from_dir(cls, paper_dir: Path) -> "Paper":
        # 实现从目录加载论文数据的逻辑
        ...

2. 代理层

代理层实现了AI代理的核心逻辑,位于agents目录下。以aisi-basic-agent为例,它提供了基本的AI代理功能。

代理启动脚本
@task
def pb_task():
    if ITERATIVE_AGENT:
        solver = basic_agent_iterative(
            tools=[bash(), read_file_chunk()],
            max_attempts=1,
            disallow_submit=DISALLOW_SUBMIT,
            real_time_limit=int(float(MAX_TIME_IN_HOURS) * 60 * 60),
        )
    else:
        solver = basic_agent_plus(
            tools=[bash(), python(), read_file_chunk(), search_file()] + web_browser(),
            max_attempts=1,
            disallow_submit=DISALLOW_SUBMIT,
            real_time_limit=int(float(MAX_TIME_IN_HOURS) * 60 * 60),
        )
    return Task(
        dataset=[Sample(input=instructions)],
        solver=solver,
        sandbox="local",
    )

这段代码定义了代理任务,配置了代理可以使用的工具(bash、python、文件操作、网页浏览器等),并设置了时间限制和其他参数。

代理配置

代理配置存储在agents/aisi-basic-agent/config.yaml文件中,包含了模型设置、环境变量和启动脚本等信息。

3. 评估层

评估层由nano目录下的文件实现,负责协调代理执行和结果收集。核心类是PaperBenchExternalPythonCodingSolver

PaperBench类
@chz.chz
class PaperBench(PythonCodingEval):
    reproduction: ReproductionConfig = chz.field(default_factory=ReproductionConfig)
    judge: JudgeConfig = chz.field(default_factory=JudgeConfig)

    # task args
    paper_split: Literal["debug", "dev", "human", "testing", "all"] = chz.field(
        default="all",
        doc="Paper split to use. One of 'testing' (lca-on-the-line only), 'debug' (rice only), 'dev' (two papers), 'human' (papers used in human baseline), 'all' (full set)",
    )
    # 其他配置参数...

    @override
    async def get_instances(self) -> list[PBTask]:
        # 创建评估任务实例的逻辑
        ...

这个类定义了评估的整体配置和流程,包括论文选择、复现设置和评判配置等。

ExternalPythonCodingSolver类
@chz.chz
class ExternalPythonCodingSolver(PythonCodingSolver):
    name: str = "PaperBenchSolver"
    agent_id: str
    is_nvidia_gpu_env: bool = chz.field(
        default=False, doc="Whether to make the local NVIDIA GPU available to the agent"
    )
    # 其他配置参数...

    @asynccontextmanager
    async def _start_computer(self, task: PBTask) -> AsyncGenerator[ComputerInterface, None]:
        # 启动计算环境的逻辑
        ...

    @override
    async def run(self, task: ComputerTask) -> AsyncGenerator[Step | FinalResult, None]:
        # 运行代理并收集结果的逻辑
        ...

这个类负责启动计算环境、运行代理并收集结果,是评估流程的核心实现。

4. 评判层

评判层位于judge目录下,负责对代理的复现结果进行评分。核心类是Judge抽象基类和各种具体的评判实现。

Judge抽象基类
class Judge(ABC):
    def __init__(self, paper: Paper, submission_dir: Path, max_depth: int = 999):
        self.paper = paper
        self.submission_dir = submission_dir
        self.max_depth = max_depth
        self.rubric = self._load_rubric()
        self.graded_task_tree: GradedTaskNode | None = None

    @abstractmethod
    async def grade(self) -> GradedTaskNode:
        raise NotImplementedError

    def _load_rubric(self) -> TaskNode:
        # 加载评分标准的逻辑
        ...

这个抽象类定义了评判系统的基本接口,具体的评判实现(如SimpleJudge)需要继承并实现grade方法。

评分任务树

评分系统使用TaskNode数据结构来表示评分标准,定义在rubric/tasks.py文件中:

@dataclass(frozen=True, kw_only=True)
class TaskNode:
    id: str
    requirements: str
    weight: int
    sub_tasks: Sequence[Self] = field(default_factory=list)
    task_category: str | None = None
    finegrained_task_category: str | None = None

    # 各种方法...

5. 展示层

展示层由gui目录下的文件实现,提供了Web界面来可视化和编辑评分任务树。

Flask应用
@app.route("/")
def index() -> str | Response:
    with lock:  # Use lock to support concurrent requests
        try:
            with open(app.config["PATH_TO_PAPER"] / app.config["RUBRIC_FILE_NAME"], "r") as f:
                data = json.load(f)

            task_node = app.config["NODE_TYPE"].from_dict(data)
            if app.config.get("GRADED", False):
                task_node = update_all_grades(task_node)
                with open(app.config["PATH_TO_PAPER"] / app.config["RUBRIC_FILE_NAME"], "w") as f:
                    json.dump(task_node.to_dict(), f, indent=4)

            template = "rubric.html"

            return render_template(
                template,
                task_node=task_node,
                valid_task_categories=VALID_TASK_CATEGORIES,
                use_api=app.config["USE_API"],
            )
        except Exception as e:
            return jsonify(
                {
                    "status": "error",
                    "message": f"Error fetching the task tree: {e}",
                }
            )

这个Flask应用提供了RESTful API来操作评分任务树,并使用HTML模板渲染界面。

6. 监控系统

监控系统位于monitor目录下,负责监控代理的执行过程,检查是否存在违规行为。

BasicMonitor类
class BasicMonitor(Monitor):
    """Simple implementation that checks for occurrences of blacklisted terms with git clone, curl, or wget commands in agent logs."""

    def check_log(self, log_file: str) -> MonitorResult:
        # 检查日志文件的逻辑
        ...

    def _contains_command(self, context: list[str]) -> bool:
        """Check if the context contains git clone, curl, or wget commands."""
        commands = ["git clone", "curl", "wget"]

        for line in context:
            for cmd in commands:
                if cmd in line:
                    return True
        return False

这个类实现了基本的监控功能,检查代理日志中是否存在使用黑名单URL和命令的情况。

7. 脚本工具

项目提供了多个脚本工具来简化常见操作,如run_reproduce.pyrun_judge.py

复现脚本
async def reproduce(
    computer: ComputerInterface,
    submission_path: Path,
    logger: BoundLogger,
    timeout: float | None = None,
    use_py3_11: bool = False,
    make_venv: bool = False,
) -> ReproductionMetadata:
    # 复现论文的逻辑
    ...

这个脚本负责在指定的计算环境中运行复现脚本,并收集复现结果。

评判脚本
async def main(
    submission_path: Path,
    paper_id: str,
    judge_type: str,
    max_depth: int,
    out_dir: Path,
    code_only: bool,
    completer_config: TurnCompleter.Config | None = None,
    resources_provided: bool = False,
) -> None:
    # 运行评判的逻辑
    ...

这个脚本负责对代理的复现结果进行评分,并保存评分结果。

数据结构设计

PaperBench定义了多种数据结构来表示系统中的关键实体:

  1. Paper:表示一篇论文及其相关信息
  2. Agent:表示一个AI代理及其配置
  3. TaskNode:表示评分任务树中的一个节点
  4. GradedTaskNode:表示已评分的任务节点
  5. ReproductionMetadata:存储复现过程的元数据
  6. PaperBenchResult:存储评估结果
  7. PaperBenchGrade:存储评分结果

这些数据结构使用Python的dataclasses模块定义,提供了类型安全和清晰的接口。

工作流程

PaperBench的典型工作流程如下:

  1. 准备阶段:加载论文数据和代理配置
  2. 评估阶段:启动代理,执行复现任务
  3. 监控阶段:监控代理执行过程,检查违规行为
  4. 评判阶段:对复现结果进行评分
  5. 展示阶段:展示和分析评分结果

详细工作流程图

┌─────────────────────────────┐
│        准备阶段             │
│  (加载论文和代理配置)       │
└───────────┬─────────────────┘
            ↓
┌─────────────────────────────┐
│        评估阶段             │
│  (启动代理,执行复现任务)   │
└───────────┬─────────────────┘
            ↓
┌─────────────────────────────┐
│        监控阶段             │
│  (监控代理执行过程)         │
└───────────┬─────────────────┘
            ↓
┌─────────────────────────────┐
│        评判阶段             │
│  (对复现结果进行评分)       │
└───────────┬─────────────────┘
            ↓
┌─────────────────────────────┐
│        展示阶段             │
│  (展示和分析评分结果)       │
└─────────────────────────────┘

技术栈分析

PaperBench使用了以下关键技术:

  1. Python:主要编程语言
  2. Asyncio:异步编程支持
  3. Flask:Web界面开发
  4. Docker:容器化执行环境
  5. Structlog:日志管理
  6. OpenAI API:LLM集成
  7. Chz:配置管理
  8. Blobfile:文件系统抽象

扩展性和定制化

PaperBench的设计考虑了扩展性和定制化需求:

  1. 插件式代理系统:支持多种AI代理的集成
  2. 可扩展的评判系统:支持多种评判方法的实现
  3. 配置驱动:通过配置文件定制系统行为
  4. 模块化设计:各组件之间松耦合,易于替换和扩展

使用示例

运行评估

python -m paperbench.nano.entrypoint --solver.agent_id aisi-basic-agent --paper_split debug

运行复现

python -m paperbench.scripts.run_reproduce --submission-path /path/to/submission --paper-id paper1

运行评判

python -m paperbench.scripts.run_judge --submission-path /path/to/submission --paper-id paper1 --judge simple --model gpt-4

启动Web界面

python -m paperbench.gui.app --path-to-paper /path/to/paper --rubric-file-name rubric.json

总结

PaperBench提供了一个全面的框架来评估AI代理复现学术论文的能力。通过模块化设计和灵活的配置系统,它支持多种代理类型和评判方法,能够适应不同的评估需求。无论是研究人员希望测试AI代理的能力,还是开发人员希望改进AI代理的复现性能,PaperBench都是一个强大的工具。

随着AI技术的不断发展,PaperBench也在不断演进,未来可能会添加更多功能,如支持更多代理类型、改进评判算法、增强可视化功能等。通过开源社区的贡献,PaperBench有望成为AI复现学术研究领域的标准工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这是Jamon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值