Skip to content
公告阅读约需 7 分钟

Potato 2.3:智能体标注、Solo Mode 与 Best-Worst Scaling

Potato 2.3.0 带来了人机协同标注的 Solo Mode、智能体轨迹标注、Best-Worst Scaling、SSO 与 OAuth 登录、Parquet 导出,以及 15 个演示项目。

Potato Team

**注意:**本文描述的是 Potato 2.3 在 2026 年 3 月发布时的样子。下文中的若干配置键在后续版本里被改名或替换,当前的语法见文档。不要把这些配置块直接复制到运行当前版本 Potato 的项目里。

Potato 2.3.0 带来了 Solo Mode——一套贯穿十个书面阶段的人机协同标注流程——以及带十一个已注册轨迹转换器的智能体轨迹标注、提供三种打分方法的 Best-Worst Scaling、面向 Google、GitHub 和通用 OIDC 提供商的 SSO 与 OAuth 登录、Parquet 导出和 15 个演示项目。发布说明记录了自 2.2.0 以来 50 多次提交,以及横跨 8 个模块的 12 个安全漏洞修复。

这次发布跟随的是人们标注对象的变化。两年前还在标注情感和命名实体的研究者,现在在拆解多步骤的智能体轨迹、批量比较模型输出,并为 Potato 的方案集当初设计时还不存在的任务构建数据集。Solo Mode 和智能体轨迹这两块工作,针对的都是这个转变。

升级

bash
pip install --upgrade potato-annotation==2.3.0

Parquet 导出需要 PyArrow 12.0.0 或更新的版本,要单独安装:

bash
pip install "pyarrow>=12.0.0"

智能体轨迹标注

一次智能体运行是一串工具调用、推理步骤和中间输出,把它压平成纯文本,就丢掉了评估者需要看到的结构。Potato 2.3 改为通过显示系统来渲染轨迹,于是轨迹被排布成一段对话,评分挂在单独的轮次上。

显示在 instance_display 中声明,逐轮评分方案嵌套在存放对话的那个字段下面:

yaml
instance_display:
  layout:
    direction: vertical
    gap: 16px
  fields:
    - key: task_description
      type: text
      label: "Task"
    - key: conversation
      type: dialogue
      label: "Agent Trace"
      span_target: true
      display_options:
        show_turn_numbers: true
        alternating_shading: true

2.3 中有两种显示类型承载智能体的工作。dialogue 显示把轨迹渲染成轮次并支持在其上做跨度标注,interactive_chat 则用于标注者亲自参与而非事后回看的对话。设置 span_target: true 正是让标注者能在一轮内部高亮某一段文字的开关,幻觉和无依据的说法就是这样在它们出现的位置被标出来的。

其他框架的轨迹通过转换器进入,本次发布注册了十一种格式:openai、anthropic、swebench、otel、mcp、multi_agent、langchain、langfuse、react、webarena 和 atif。

bash
python -m potato.trace_converter -i traces.json -f react -o data/traces.jsonl

Solo Mode

多标注者标注需要招人、培训、协调,在许多研究项目上,瓶颈是这套后勤而不是标注界面。Solo Mode 改为让一位领域专家和一个大模型搭档。人来标注,模型来提议,每一次纠正都反馈回提示词里,随着两者逐渐收敛,人把队列里越来越多的部分交给模型。

这套流程贯穿十个书面阶段:初始设置、提示词审查、边缘案例合成、边缘案例标注、提示词验证、并行标注、分歧解决、定期复查、自主标注和最终验证。并不是每个项目都会经过每个阶段。

yaml
solo_mode:
  enabled: true
 
  labeling_models:
    - endpoint_type: "ollama"
      model: "qwen3:4b"
      endpoint_url: "http://localhost:11434"
      max_tokens: 256
      temperature: 0.1
 
  revision_models:
    - endpoint_type: "ollama"
      model: "qwen3:4b"
      endpoint_url: "http://localhost:11434"
 
  uncertainty:
    strategy: "direct_confidence"
 
  thresholds:
    end_human_annotation_agreement: 0.90
    minimum_validation_sample: 20
    confidence_low: 0.5
    periodic_review_interval: 50
 
  instance_selection:
    low_confidence_weight: 0.4
    diversity_weight: 0.3
    random_weight: 0.2
    disagreement_weight: 0.1
 
  state_dir: "solo_state"

instance_selection 这四个权重决定哪些条目值得占用人的注意力。把低置信度权重设为 0.4、多样性设为 0.3,就把人的大部分时间送到模型没把握的实例上,同时对分布的其余部分保持足够覆盖,好发现系统性错误。随机采样上的那 0.2,是让 end_human_annotation_agreement 里的一致性估计有意义的东西,因为只在困难实例上算出来的一致率,并不是你在整个语料上会得到的那个数。

Solo Mode 附带 85 个集成测试和端到端测试、一份开发者指南,以及 examples/advanced/solo-mode/ 和 examples/advanced/simple-solo-mode/ 两个示例项目。从简单的那个开始,它跑在本地的 Ollama 模型上,不需要 API key,所以你首先评估的是这套流程适不适合你的任务,而不是这个模型值不值它的价钱。

Best-Worst Scaling

Best-Worst Scaling 给标注者看一组条目,通常是四个,只要求按某一个标准挑出最好的和最差的。这两次选择隐含了一批成对比较,而在许多互相重叠的组之间,分数会落在一个真实的量表上,且这些判断比打分更快做出。

yaml
annotation_schemes:
  - annotation_type: bws
    name: sentiment_bws
    description: "Sentiment Intensity"
    best_description: "Which sentence expresses the MOST positive sentiment?"
    worst_description: "Which sentence expresses the LEAST positive sentiment?"
    tuple_size: 4
    sequential_key_binding: true

收集到的组上可以跑三种打分方法。counting 是透明的基线,算法是 (best_count - worst_count) / appearances,不需要额外依赖,而且结果确定。bradley_terry 拟合一个成对比较模型,产出对数尺度的强度参数。plackett_luce 拟合完整的排序模型。两种基于模型的方法都需要 pip install choix。

bash
python -m potato.bws_scoring --config config.yaml --method bradley_terry

分数落在输出目录下的 bws_scores.tsv 里,包含每个条目的分数、排名、最好和最差的次数,以及出现次数。管理面板有一个 BWS Scoring 标签页,可以用一个按钮跑同样的计算,并把结果显示成表格。

SSO 与 OAuth

标注者要通过互联网访问的部署需要真正的账号,2.3 加入了 OAuth 2.0 和 OpenID Connect,让他们可以用已有的身份登录。支持 Google、GitHub 和任何通用 OIDC 提供商,并且可以按邮箱域名或 GitHub 组织限制访问。

yaml
authentication:
  method: "oauth"
  providers:
    google:
      client_id: ${GOOGLE_CLIENT_ID}
      client_secret: ${GOOGLE_CLIENT_SECRET}
  user_identity_field: "email"
 
secret_key: ${POTATO_SECRET_KEY}

把这个配置块加到你的配置里。随之而来有两个要求。OAuth 需要 HTTPS 部署,开发时 localhost 除外;它还需要一个稳定的 secret_key,因为每次重启都变的签名密钥会让登录已经发出的会话全部失效。在你的提供商那里把重定向 URI 注册为 https://your-domain.com/auth/callback/google,其中的提供商名字按实际替换。

Parquet 导出

标注数据越来越多地流向想要列式格式的分析工具,所以 2.3 把 Parquet 加进了导出注册表。一次导出最多产出三张表:annotations.parquet,每个实例、每个标注者一行;spans.parquet,每条跨度标注一行;以及 items.parquet,存放源数据。

bash
python -m potato.export -c config.yaml -f parquet -o ./export/

选项在命令行上传递,而不是在项目里配置,压缩编码可选 snappy(默认)、gzip、zstd、lz4 或 none:

bash
python -m potato.export -c config.yaml -f parquet -o ./export/ \
    --option compression=gzip --option include_items=false

这三张表用 instance_id 连接,这也是为什么不必先把任何东西读进 pandas 就能从 DuckDB 里用上这批导出:

python
import duckdb
duckdb.sql("""
  SELECT i.item_id, a.user_id, a.*
  FROM './export/annotations.parquet' a
  JOIN './export/items.parquet' i ON a.instance_id = i.item_id
""")

安全修复

本次发布修复了横跨 8 个模块的 12 个安全漏洞,以及分布在 25 个文件里的 XSS、健壮性和数据完整性问题,还有一处跨度删除的级联操作——它遍历的是字典的键而不是值,因而留下了没清掉的链接记录。一次依赖审计把 Python 和 JavaScript 依赖都升到了当前版本。

其他修复里有两个可能影响到你已经收集的数据。一个 has_free_response 布尔值崩溃(issue #111)和一个全阶段导航循环都影响了标注是否按预期被记录下来,而动态 multirate 的引号处理影响了这些值是怎么写出去的。如果你在 2.2 上跑过用到自由文本选项或 multirate 方案的研究,在把输出当作最终结果之前先检查一遍。

演示项目

本次发布在 demo/ 下附带 15 个演示项目,按彼此叠加的顺序编号,从 01-sentiment-admin 到 15-agentic-chat,涵盖跨度、自定义审核布局、图像分类、音频情感、视频、多模态条目、裁定、滑块、边界框、依存树、分层 ELAN 标注和智能体聊天。每个演示目录里有一个 config.yaml 和它的 data/,整套演示共用一个脚本,为基于媒体的那几个演示生成所需的素材。

bash
# From the repository root: generates the demo data, then starts all 15 servers
bash demo/launch.sh

完整的变更日志,包括上面提到的每一项修复,见仓库中的 v2.3.0 发布说明。请到 GitHub 提 issue,或者在 GitHub Discussions 里开个话题。

链接