标注引擎配置
labeling_engine 块中的每一个键,涵盖来源和置信度方法、人工标注池、众包花费、预算、运行时限制、功能开关,以及校验会拒绝哪些写法。
标注引擎所做的一切都在一个 labeling_engine 块中设置。无效的块会让服务器在启动时停下,并一次性列出所有问题。要让标注者拿到引擎的请求,还需要设置 assignment_strategy: engine。设置了这个策略却没有启用引擎,属于校验错误。
这个块包含以下几个部分,下文逐一说明:
assignment_strategy: engine
labeling_engine:
enabled: true
schemas: [sentiment] # default: every scheme a source can label
sources: []
cascade: [laya, gemma] # default: the first source alone
contracts: []
humans: {}
crowd: {}
budgets: {}
runtime: {}
features: {}
redaction: {}
distill: {}顶层键
直接位于 labeling_engine 下的键有五个:
| 键 | 默认值 | 含义 |
|---|---|---|
enabled | false | 开启引擎。启用的引擎至少需要一个来源。 |
schemas | 全部 | 引擎负责标注的标注方案。在 assignment_strategy: engine 下,没有列入的方案只会在引擎为自己的方案交给人的那些条目上得到回答,而不是在每个条目上,校验会对此发出警告。没有任何来源能标注的方案(例如自由文本)不能放进引擎,所以在这个策略下它永远不会在每个条目上得到回答。如果必须如此,请改用其他分配策略。 |
sources | [] | 模型。参见来源。 |
cascade | 第一个来源 | 按尝试顺序排列的来源 id。最后一个之后是人。 |
contracts | [] | 标签必须满足的条件。参见契约。 |
来源
来源是一个模型或一组已有标签,它为每个条目提出一个标签和一个置信度。每个来源都有唯一的 id 和一个 kind,来源上出现未知的键属于错误:
| 键 | 默认值 | 含义 |
|---|---|---|
id | 必填 | 在 cascade、调用日志和证书中使用的名称。 |
kind | 必填 | llm、vlm、decision、detector、judge、jury、trained、static、fixture、asr、lf、simulator 之一。 |
endpoint_type | llm、vlm、decision、judge 必填 | AI 端点,例如 vllm、openai、anthropic、gemini、ollama、openrouter、openai_vision、ollama_vision、laya 或 systemone。detector 默认为 yolo。 |
model | 端点默认值 | 模型名称。 |
base_url | 无 | 自托管或兼容 OpenAI 的端点的服务器 URL。 |
api_key | 无 | 永远不会被哈希进版本,也永远不会被导出。${ENV_VAR} 会被替换。 |
temperature | 0.0 | 0 到 2。 |
max_tokens | 256 | 每次调用的输出 token 上限。 |
timeout | 端点默认值 | 每次调用的秒数。 |
prompt | 根据方案生成 | 提示词模板。更改它会产生一个新的来源版本。 |
confidence | {method: auto} | 来源如何给出置信度。参见置信度方法。 |
concurrency | runtime.concurrency | 对这个来源的并行调用数。 |
schemas | 引擎的全部方案 | 把来源限定在这些方案上。 |
options | {} | 特定类型的选项,见下文。 |
judge | {} | 仅限 judge。与 options 相同的选项,放在自己的键下;两处都设置了同一选项时以 options 为准。 |
members | 无 | 仅限 jury。至少两个其他来源的 id。 |
aggregation | plurality | 仅限 jury。相对多数是唯一的规则。 |
field / predictions_file | 无 | 仅限 static。已有标签所在的位置。该字段存放 {scheme: label},来源只标注一个方案时也可以是单独的标签。如果每个条目上的该字段形状都不对,运行会失败,并给出指明该字段的消息。 |
error_rate, seed | 无 | 仅限 fixture。一个已知错误率的合成来源,用于测试。 |
revision | 无 | 要记录进版本的模型修订号,例如检查点的哈希值。 |
凡是可能改变答案的东西(模型、提示词、温度、选项)都会计入来源的版本哈希。新版本会让依赖该来源的每份契约变为 stale。
不是方案可取值的答案,例如不在列表中的标签、不是数字的数值字段,或单选方案上的一个列表,会被记录为错误,永远不会被当作标签,运行的消息会统计这些错误。调用失败的条目会在之后的运行中再次请求,每个来源版本最多三次,之后它会等待来源发生变化(修好的密钥或提示词就是一个新版本)。某个来源失败的运行不会让其他层停下。下一层会为每个条目打标签,potato label run 以状态码 1 退出,并指出失败的来源。
置信度方法
引擎的接受规则是对每条预测的置信度设阈值,所以来源如何给出置信度,决定了引擎能接受多少。confidence.method 取以下五个值之一:
confidence.method | 适用于 | 作用 |
|---|---|---|
verbalized | llm、vlm、judge | 模型在回复中给出 0-100 的数值。一次调用,是最不可靠的方法。 |
k_sample | llm | 以 sample_temperature(默认 0.7)取得 samples 个回复(默认 5 个)。标签是最常见的答案,置信度是它所占的比例。花费 k 次调用。 |
logprob | llm | 给标签编上字母,模型用一个字母作答,置信度从第一个 token 的概率中读出。一次调用,通常校准得最好。需要能返回 logprob 的后端(vLLM、兼容 OpenAI 的服务),并且标签不超过 20 个,标签更多的方案属于校验错误。 |
native | decision、detector、trained | 模型自身的概率。用在 llm 来源上属于校验错误。 |
auto | 全部 | 来源支持时用 native,否则用 verbalized。 |
特定类型的选项
有五种来源类型读取自己的选项:
decision涵盖进程内的 Laya,或任何/v1/systemone服务器,例如托管的 Jev 或 OpenJev。一次前向计算就为每个选项返回一个概率,适用于radio、select、likert和slider方案。endpoint_type必须是laya或systemone,systemone需要base_url,即服务器根地址(以/v1/systemone结尾的 URL 也可以)。两种情况下状态都以{"text": ...}发送,所以同一个检查点在进程内和在laya-serve后面给出的答案相同;options: {state_key: ""}则改为发送裸字符串。在评分量表(likert、slider)上,Laya 的分数几乎跟不上量表,所以在依赖它之前先检查几个条目。进程内的laya端点需要pip install 'potato-annotation[decision]'。detector在image_annotation方案上读取目标检测器给出的边界框。keep_threshold(0.35)设定分数达到多少的框才算作预测的一部分。分数介于candidate_threshold(0.05)和keep_threshold之间的框会降低这张图像的置信度。label_map把检测器的类别映射到方案的标签,未映射的类别会被忽略。image_field指定存放图像路径或 URL 的条目字段。路径的解析方式与标注页面相同:/media/x.jpg位于任务的media_directory下,相对路径位于task_dir下。judge接受rubric(默认为方案的描述)、fields(按顺序展示给评审的条目字段)和swap_order,后者会把标签顺序反过来再问一次,前后翻转的判定变为弃权。在智能体轨迹方案(process_reward、trajectory_eval……)上,评审为每一步打标签。vlm使用视觉端点(openai_vision、anthropic_vision、ollama_vision)。对于部署在兼容 OpenAI 的服务器后面的自托管模型,使用openai_vision并设置base_url。trained接受artifact_dir、trainer(默认sklearn-text)和run_id。这个来源通常由蒸馏生成,而不是手写配置。
humans
humans 块设定由谁来标注,以及引擎如何向他们抽样:
| 键 | 默认值 | 含义 |
|---|---|---|
pools | [team] | 由谁标注:team、crowd、solo。 |
calibration_rate | auto | 抽取用于盲态校准的条目比例。auto 根据契约的预估选择比例,保证每个类别有足够的标签可供检验,小型研究最多一半,超过 1,000 个条目的研究最多五分之一。 |
dev_fraction | 0.5 | 用于选定阈值的校准标签比例。其余的用来检验。 |
min_calibration_per_class | 10 | 检验按类别的契约之前,每个类别的最低数量。 |
audit_rate | 0.02 | 新接受的机器标签中以盲态送回给人、用于监控漂移的比例。 |
overlap | 0.0 | 由多人标注的校准条目比例。 |
overlap_k | 3 | 每个重叠条目的标注人数。no_worse_than_human 契约需要 3 人。 |
distribution_k | 5 | distributional 契约中每个条目的标注人数。 |
truth | majority | 多人在同一条目上的标签如何合成为契约用来检验的标签,取 majority 或 dawid_skene。 |
verify_visibility | shown | 核验请求显示机器的答案(shown)还是不显示(blind)。 |
crowd
当 crowd 在 humans.pools 中时,crowd 块才生效,Prolific 是引擎唯一能驱动的众包平台:
| 键 | 默认值 | 含义 |
|---|---|---|
provider | prolific | 众包平台。 |
study_id | 无 | 要调整规模的 Prolific 研究。 |
reward_usd | 无 | 每个名额的报酬,用于成本预估。 |
per_worker_quota | 20 | 每位工作者的请求数。名额数为 ceil(open requests / quota)。 |
众包招募默认是演练,规划器只报告它会做什么。要真正花钱,需要 features.crowd_live_spend: true 和 budgets.human_usd 上限,开启实际花费却没有上限的配置会被拒绝。众包介绍了如何设置 Prolific 研究本身。
budgets
budgets 块在超出限额之前停止花费:
| 键 | 含义 |
|---|---|
model_usd | 花费达到这个数额后,停止调用计价模型。每次调用会先预留它的预估成本。没有价格的模型以及 localhost 上的自托管模型不受此限制。 |
human_usd | 众包花费的上限。实际众包花费必须设置。 |
human_labels | 引擎最多可以发出的人工请求数,在每个请求发出时计数。 |
runtime
runtime 块控制分批、并发,以及一个人可以持有请求多久:
| 键 | 默认值 | 含义 |
|---|---|---|
batch_size | 32 | 每个提交块的条目数。被终止的运行会从下一个块继续,不会重复调用。 |
concurrency | 4 | 每个来源的并行调用数,可被来源自己的 concurrency 覆盖。 |
cache | true | 复用同一来源版本对相同请求的回复。 |
retries | 2 | 遇到超时、连接错误、429 或 5xx 后额外尝试的次数。每次尝试都会记入日志。 |
planner_interval | 30 | 服务器中两次规划器运行之间的秒数。 |
hold_minutes | 60 | 一个人持有请求而不作答的最长分钟数,超过后请求回到池中。该条目也会从他的页面上移除,所以开着不管的标签页之后无法再回答它。 |
features
除 drift 外,所有功能默认关闭:
| 键 | 开启什么 |
|---|---|
drift | 默认开启。根据抽查结果采取行动。当抽查显示已接受标签的错误率高于目标时,契约显示为 violated,该方案上的机器标签不再被接受,并抽取新的校准标签。每次认证都会开始一个新的抽查序列,所以修复后重新认证就能恢复接受。设为 false 时只报告违规,契约显示为 "met, audits breached"。 |
distill | 用本研究的标签训练一个模型,并把它放在级联的第一位(参见 distill)。 |
optimize | 让规划器每次运行时在 dev 标签上为级联的每个子集打分,并在 GET /api/engine/v1/schemes/<name>/optimize 报告保持契约覆盖率的最便宜子集。不会自动应用任何结果,因为采用一个级联意味着修改配置并重新认证。 |
crowd_recruit | 让规划器调整 Prolific 研究的规模,除非开启 crowd_live_spend,否则只是演练。 |
crowd_live_spend | 真正修改 Prolific 研究。需要 crowd 池和 budgets.human_usd。 |
pii_redaction | 在文本发往第三方 API 之前,遮盖电子邮件、URL、IP 地址、卡号、SSN、电话号码和 @用户名。调用日志以类别和哈希值记录遮盖了什么,从不记录文本本身。 |
payload_capture | 在 <task_dir>/engine_payloads/ 下保留完整的提示词和回复。默认关闭,调用日志只保留哈希值。 |
redaction
redaction.categories 列出要遮盖 email、url、ip、card、ssn、phone 和 handle 中的哪些,默认全部遮盖。只有开启 features.pii_redaction 时才会遮盖,并且只针对第三方 API。自托管的端点类型(vllm、ollama、laya、yolo……)无论在哪里运行都不遮盖,base_url 位于同一台机器上的任何端点也不遮盖。
distill
开启 features.distill 后,引擎会用本研究的标签训练一个便宜的模型,并把它放在级联的第一位:
| 键 | 默认值 | 含义 |
|---|---|---|
trainer | sklearn-text | 来自 potato/training 的训练器。 |
min_labels | 200 | 标签达到这个数量后才开始训练。 |
include_silver | true | 同时用契约认证过的机器标签训练,标记为银标准。 |
every | 2.0 | 标签数量增长到这个倍数时重新训练。 |
cert 和抽查划分中的条目永远不会进入训练集,所以蒸馏模型永远不会在它训练过的标签上接受检验。
校验
potato validate config.yaml 会连同配置的其余部分一起检查 labeling_engine 块,每条错误都会指出对应的键,例如 labeling_engine.sources[1].kind must be one of ... 或 labeling_engine.contracts[0].error is required for selective_risk。校验还会拒绝:
- 契约类型不读取的契约键,例如
error的拼写错误; - 位于级联中没有任何来源能标注的方案上的契约,并给出每个来源的原因;
- 位于引擎无法评分的方案(自由文本、成对比较)上的契约;
endpoint_type不是决策模型的decision来源,以及endpoint_type是决策模型的llm、vlm或judge来源;以及humans.overlap_k低于 3 的no_worse_than_human。
当 budgets.human_labels 小到即使每个机器答案都正确也无法认证一份 selective_risk 契约时,校验也会发出警告。请提高预算或放宽 error,直到这条警告消失。
延伸阅读
- 标注引擎
- 标注引擎契约
- 命令行、REST API、MCP 工具和 SDK
- AI 支持,介绍来源与 Potato 其他部分共用的端点类型
实现细节见源文档。