Skip to content

实时编码智能体观察

实时观察编码智能体工作,支持暂停、回滚和分支。可选三种后端:本地模型用 Ollama、Anthropic API,以及 Claude Agent SDK。

v2.4.0 新增

静态 trace 标注告诉你智能体做过什么,实时观察则告诉你智能体在人类引导下会怎么做。Potato 的实时编码智能体模式让标注者实时看着编码智能体干活——读文件、改代码、跑测试——并随时介入。你可以暂停智能体、发送新指令、回滚到之前的检查点,或者把轨迹分叉出去尝试别的思路。

这样得到的标注数据比单纯的静态 trace 更丰富:完整的带时间戳的轨迹、标注者的每一次介入、分支决策点,以及来自不同路径的对比数据。这些数据可以直接用于训练过程奖励模型、偏好模型和指令遵循评估器。

环境要求

  • Python 3.10+
  • Git(检查点系统基于 git 提交)
  • 以下智能体后端之一:
    • Ollama 用于本地模型推理(无需 API key)
    • ANTHROPIC_API_KEY 用于访问 Anthropic API
    • Claude Agent SDK 提供完整的 Claude Code 智能体体验

后端

Potato 支持三种运行编码智能体的后端。每种后端都在子进程中运行智能体,并把它的动作实时推送到标注界面。

1. Ollama(本地模型)

在本地运行编码智能体,不需要 API key。Ollama 对开放权重模型的推理速度不错,适合开发、测试,以及数据不能离开本机的场景。

安装:

bash
# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh
 
# Pull a coding-capable model
ollama pull qwen2.5-coder:7b
 
# Or a larger model for better performance
ollama pull deepseek-coder-v2:16b

配置:

yaml
agentic:
  enabled: true
  display_type: coding_trace
  live_agent:
    enabled: true
    backend: ollama
    model: qwen2.5-coder:7b
 
    ollama:
      host: "http://localhost:11434"    # Ollama server URL
      temperature: 0.2
      num_ctx: 8192                     # context window size
      num_predict: 2048                 # max tokens per response
      keep_alive: "5m"                  # keep model loaded in memory
 
    # Agent capabilities
    tools:
      - read_file
      - edit_file
      - write_file
      - bash
      - glob
      - grep
    max_steps: 50
    step_timeout_seconds: 60

2. Anthropic API

通过 Anthropic API 使用 Claude 模型,编码能力强并支持工具使用。需要 API key。

准备:

bash
# Set your API key
export ANTHROPIC_API_KEY="sk-ant-..."
 
# Or add to .env file
echo "ANTHROPIC_API_KEY=sk-ant-..." >> .env

配置:

yaml
agentic:
  enabled: true
  display_type: coding_trace
  live_agent:
    enabled: true
    backend: anthropic
    model: claude-sonnet-4-20250514
 
    anthropic:
      api_key: ${ANTHROPIC_API_KEY}
      max_tokens: 4096
      temperature: 0.2
      system_prompt: |
        You are a coding assistant working on a software project.
        Read files before editing them. Run tests after making changes.
        Explain your reasoning before each action.
 
    # Agent capabilities
    tools:
      - read_file
      - edit_file
      - write_file
      - bash
      - glob
      - grep
    max_steps: 100
    step_timeout_seconds: 120

3. Claude Agent SDK

Claude Agent SDK 提供完整的 Claude Code 智能体体验,包括自动工具编排、上下文管理和跨文件推理。这是能力最强的后端,但需要先安装 SDK。

准备:

bash
# Install the Claude Agent SDK
pip install claude-agent-sdk
 
# Set your API key
export ANTHROPIC_API_KEY="sk-ant-..."

配置:

yaml
agentic:
  enabled: true
  display_type: coding_trace
  live_agent:
    enabled: true
    backend: claude_agent_sdk
 
    claude_agent_sdk:
      api_key: ${ANTHROPIC_API_KEY}
      model: claude-sonnet-4-20250514
      max_turns: 100
      permission_mode: auto           # auto-approve tool use
      enable_thinking: true           # show extended thinking
 
    max_steps: 100
    step_timeout_seconds: 180

控制操作

标注界面提供四种控制操作,让标注者引导智能体的行为。

暂停 / 恢复

点击 Pause 会在两步之间让智能体停下。它做完当前这一步后等待。标注者可以查看当前状态、检查文件,再决定是让智能体继续还是介入。点击 Resume 让它继续执行。

yaml
live_agent:
  controls:
    pause_resume:
      enabled: true
      auto_pause_on_error: true      # pause when a command fails
      auto_pause_after_steps: 0      # pause after N steps (0 = disabled)
      keyboard_shortcut: "Space"

发送指令

智能体暂停期间,标注者可以发送新指令来改变它的方向。当智能体走上错误的路,或者标注者想测试它对引导的反应时,这一项很有用。

yaml
live_agent:
  controls:
    send_instructions:
      enabled: true
      placeholder: "Type instructions for the agent..."
      inject_as: system_message      # "system_message" or "user_message"
      keyboard_shortcut: "Enter"
      presets:
        - "Try a different approach"
        - "Read the error message more carefully"
        - "Check the test file for expected behavior"
        - "Revert your last change and try again"

指令会被注入智能体的对话上下文。inject_as 决定它以系统消息(权威指令)还是用户消息(对话式引导)的形式出现。

回滚

回滚会把项目恢复到之前的某个 git 检查点。智能体做的每一次文件改动都会自动提交,所以标注者可以点击时间线上任意一个先前步骤,回到那一刻的确切状态。智能体的对话上下文也会同步截断。

yaml
live_agent:
  controls:
    rollback:
      enabled: true
      show_checkpoint_diff: true     # show what will be undone
      require_confirmation: true     # "Are you sure?" dialog
      keyboard_shortcut: "Ctrl+Z"

分支与重放

分支重放把回滚和发送指令结合起来:标注者回滚到某个检查点,再发送不同的指令,从而生成一条分叉的轨迹。收集偏好数据时这很有用——你可以从同一个起点出发探索两种不同做法,再比较结果。

yaml
live_agent:
  controls:
    branch:
      enabled: true
      max_branches: 5                # maximum branches from any checkpoint
      branch_naming: auto            # "auto" or "manual"
      compare_view: true             # side-by-side branch comparison
      keyboard_shortcut: "Ctrl+B"

分支对比视图把两条分支并排显示,并高亮它们分岔的位置。标注者可以评价哪条分支的结果更好,从而产出用于 DPO 训练的偏好对。

Git 检查点系统

实时智能体模式用 git 跟踪每一次文件改动,由此提供可靠的回滚、分支和完整的变更历史。

工作方式

  1. 智能体启动前,Potato 创建一个名为 potato-session-{session_id} 的新 git 分支
  2. 每次文件改动(编辑、写入、创建、删除)之后,Potato 自动提交并附上描述性的提交信息
  3. 每个提交都被标记为一个检查点,出现在时间线上
  4. 回滚通过 git checkout 把工作目录恢复到任意检查点
  5. 分支会从检查点提交处创建一个新的 git 分支

配置

yaml
live_agent:
  git_checkpoints:
    enabled: true
    branch_prefix: "potato-session"
    commit_message_format: "Step {step}: {tool} {file_path}"
    auto_commit: true
    cleanup_on_complete: false       # delete session branches when done
    require_clean_working_dir: true  # fail if there are uncommitted changes

手动管理检查点

bash
# List all Potato session branches
git branch | grep potato-session
 
# View checkpoints for a session
git log potato-session-abc123 --oneline
 
# Clean up old session branches
python -m potato.cleanup_sessions --older-than 7d

数据格式

实时编码智能体任务的输入数据给出任务描述,以及可选的起始文件或目录:

json
{
  "id": "task_001",
  "task_description": "Fix the bug in src/parser.py where empty input causes a crash",
  "project_dir": "/path/to/project",
  "start_file": "src/parser.py",
  "test_command": "python -m pytest tests/test_parser.py -v",
  "context_files": [
    "src/parser.py",
    "tests/test_parser.py"
  ]
}
字段必填说明
id任务的唯一标识符
task_description智能体要做什么
project_dir项目目录的路径
start_file初始展示给智能体的文件
test_command用于验证修复的命令
context_files预先加载进智能体上下文的文件

配置参考

一个实时编码智能体观察任务的完整配置:

yaml
task_name: "Live Coding Agent Observation"
task_dir: "."
 
data_files:
  - "data/coding_tasks.jsonl"
 
item_properties:
  id_key: id
  text_key: task_description
 
agentic:
  enabled: true
  display_type: coding_trace
 
  coding_trace_display:
    diff_style: unified
    diff_context_lines: 3
    syntax_highlight: true
    show_line_numbers: true
    terminal_theme: dark
    file_tree:
      enabled: true
      position: left
      click_to_navigate: true
 
  live_agent:
    enabled: true
    backend: anthropic
    model: claude-sonnet-4-20250514
 
    anthropic:
      api_key: ${ANTHROPIC_API_KEY}
      max_tokens: 4096
      temperature: 0.2
 
    tools:
      - read_file
      - edit_file
      - write_file
      - bash
      - glob
      - grep
 
    max_steps: 100
    step_timeout_seconds: 120
 
    controls:
      pause_resume:
        enabled: true
        auto_pause_on_error: true
        keyboard_shortcut: "Space"
      send_instructions:
        enabled: true
        inject_as: system_message
        presets:
          - "Try a different approach"
          - "Read the error message carefully"
          - "Run the tests first"
      rollback:
        enabled: true
        require_confirmation: true
      branch:
        enabled: true
        max_branches: 5
        compare_view: true
 
    git_checkpoints:
      enabled: true
      branch_prefix: "potato-session"
      auto_commit: true
      cleanup_on_complete: false
 
annotation_schemes:
  # Per-step ratings during observation
  - annotation_type: per_turn_rating
    name: step_quality
    description: "Rate each agent step as you observe it"
    target: agentic_steps
    rating_type: radio
    labels:
      - "Good"
      - "Acceptable"
      - "Unnecessary"
      - "Incorrect"
 
  # Overall task completion after agent finishes
  - annotation_type: radio
    name: task_completion
    description: "Did the agent complete the task?"
    labels:
      - "Fully Complete"
      - "Partially Complete"
      - "Failed"
 
  # Branch comparison (when branching is used)
  - annotation_type: radio
    name: branch_preference
    description: "Which branch produced a better result?"
    labels:
      - "Branch A"
      - "Branch B"
      - "Both Equal"
      - "Both Failed"
 
  # Notes on the observation
  - annotation_type: text
    name: observation_notes
    description: "Describe what you observed and any interventions you made"
    label_requirement:
      required: false
 
output_annotation_dir: "output/"
output_annotation_format: "jsonl"

分支轨迹导出

标注者使用分支重放后,输出会包含完整的分支树。这种格式是为从对比轨迹中训练偏好模型和过程奖励模型而设计的。

json
{
  "id": "task_001",
  "annotator": "observer_01",
  "root_branch": {
    "branch_id": "main",
    "steps": [
      {"step": 0, "type": "file_read", "file": "src/parser.py", "rating": "Good"},
      {"step": 1, "type": "edit", "file": "src/parser.py", "rating": "Incorrect"}
    ],
    "children": [
      {
        "branch_id": "branch_1",
        "branch_point": 1,
        "instruction": "Try a different approach -- use a try/except block instead",
        "steps": [
          {"step": 2, "type": "edit", "file": "src/parser.py", "rating": "Good"},
          {"step": 3, "type": "terminal", "command": "pytest", "rating": "Good"}
        ],
        "outcome": "Fully Complete",
        "children": []
      },
      {
        "branch_id": "branch_2",
        "branch_point": 1,
        "instruction": "Read the test file first to understand expected behavior",
        "steps": [
          {"step": 2, "type": "file_read", "file": "tests/test_parser.py", "rating": "Good"},
          {"step": 3, "type": "edit", "file": "src/parser.py", "rating": "Good"},
          {"step": 4, "type": "terminal", "command": "pytest", "rating": "Good"}
        ],
        "outcome": "Fully Complete",
        "children": []
      }
    ]
  },
  "branch_preference": "Branch B",
  "observation_notes": "Both branches solved the problem, but branch B produced cleaner code by reading the tests first."
}

把分支轨迹导出用于偏好学习:

bash
# Export as DPO preference pairs from branch comparisons
python -m potato.export \
  -i output/ \
  -f branching_dpo \
  -o results/branch_preferences.jsonl
 
# Export full trajectory trees
python -m potato.export \
  -i output/ \
  -f trajectory_tree \
  -o results/trajectory_trees.jsonl

安全

实时智能体运行在任务数据指定的项目目录中,可以读、写和执行该目录下的文件。建议注意以下几点:

  • 沙箱隔离:面对不可信的代码或不可信的智能体模型时,把 Potato 放进 Docker 容器或虚拟机里运行。智能体可以执行任意 shell 命令,隔离很重要。
  • 只读模式:如果只想让智能体分析代码而不修改,禁用 bashwrite_file 工具。
  • 网络限制:用 Docker 的 --network none 参数阻止智能体发起网络请求。
  • 资源上限:设置 max_stepsstep_timeout_seconds,防止智能体失控跑飞。
yaml
# Restricted tool set for analysis-only tasks
live_agent:
  tools:
    - read_file
    - glob
    - grep
  # No edit_file, write_file, or bash

故障排查

Ollama 未运行

text
Error: Connection refused at http://localhost:11434

启动 Ollama 服务:

bash
ollama serve

确认它已在运行:

bash
ollama list

缺少 API Key

text
Error: ANTHROPIC_API_KEY environment variable not set

设置环境变量:

bash
export ANTHROPIC_API_KEY="sk-ant-..."

或者写进项目的 .env 文件,Potato 会自动加载 .env

Git 未初始化

text
Error: Project directory is not a git repository

检查点系统依赖 git。在项目目录中初始化一个仓库:

bash
cd /path/to/project
git init
git add -A
git commit -m "Initial commit"

智能体陷入循环

如果智能体反复做同一个动作,它可能卡住了。当同一个工具调用带同样的参数重复 3 次时,Potato 会判定为循环并自动暂停智能体。这个阈值可以配置:

yaml
live_agent:
  loop_detection:
    enabled: true
    threshold: 3                     # pause after N identical consecutive steps
    action: pause                    # "pause" or "terminate"

清理会话分支

时间久了,会话分支会越积越多,需要定期清理:

bash
# Remove branches older than 7 days
python -m potato.cleanup_sessions --older-than 7d
 
# Remove all session branches
python -m potato.cleanup_sessions --all
 
# Dry run (show what would be deleted)
python -m potato.cleanup_sessions --older-than 7d --dry-run

另请参阅

有关实现详情,请参阅源文档