主题
观测与评测
定位:一条 trace 从产生、消费到门禁的完整路径。
一句话:可观测回答“这次为什么这样”,评测回答“下一版能不能上”,门禁回答“谁批准它上”;三者共用同一条 trace 链和同一批数据(轨迹、事件、版本、成本),拆成三套系统就会三套口径互相打架。
整合说明:本篇合并吸收旧 14 篇(信号体系与 span 语义)、40 篇(Langfuse 选型决策与落地推演)、42 篇(OpenJudge 实跑记录)、43 篇(观测接口 17 端点契约实跑)四篇重写,并以
C:\Users\Administrator\Desktop\02-项目代码\OpenJudge\openjudge\graders\本地源码复核为主线修正旧文口径。全文用两类标记区分证据强度:源码坐实=读本地源码确认(附文件行号);实测=本机对真实服务实跑闭环(附日期 2026-10-26)。通用方法论见 可观测与评测 与 BadCase 与质量运营;调优数据链见 26-调优闭环落地设计;审计管道见 08 专栏《10-安全体系与全链路审计》。版本适用:AgentScope Java 2.x / agentscope-service 2.1.0-BETA1 / Langfuse v4.x(自托管)/ py-openjudge 0.2.4。
§一 为什么需要统一观测视图
平台上线后,证据问题以三类故障形式暴露:
- 分不清慢在哪:一次任务跨网关、控制面、队列、内核、工具,指标只报“Turn P95 涨了 3 秒”——是模型变慢、工具超时、审批等待还是排队?没有按语义拆开的 span,四种原因的 owner 和处置动作完全不同,最后只能人工翻日志。
- 说不清为什么失败:日志按服务分散,一次任务出问题时只能按时间戳猜顺序;被拒绝的工具调用、被中断的 turn 在可观测里干脆是空白——“没记录”比“有错误”更难归因。
- 发布门禁拍脑袋:离线跑分不错,上线仍然退化——评测集和真实流量不是同一分布,也没有人规定“降到多少必须回滚”;门禁没有接在发布流水线上,就只是一份没人看的报告。
根因是把观测、评测、治理当成三个系统。六类信号各有分工,但只有 Trace 能跨组件串起来,其余都挂靠在这条链上:
| 信号 | 来源 | 关键属性 | 回答什么问题 | 成本 |
|---|---|---|---|---|
| Trace | 网关、内核、工具、数据面 | trace_id、span 名、模型、工具、版本 | 这次为什么走这条分支 | 中,需采样 |
| 事件流 | Service 事件日志(43 篇契约) | 单调 seq/游标、会话、Turn、审批 | 执行到哪一步、谁批准 | 高,需保留策略 |
| 指标 | OTel SDK / 网关 | 模型、Agent、工具、状态码 | 趋势与告警 | 低,但基数敏感 |
| 成本账 | 网关计量 + Token 用量 + budget ledger | 租户、应用、模型、输入/输出/缓存 | 钱花在哪 | 中,需对账 |
| 评测分 | 黄金集 + OpenJudge grader | 用例、版本、评分维度 | 这一版是否更好 | 高,需标注 |
| 审计 | 控制面 + 网关 | 主体、动作、对象、结果 | 谁改了什么、谁调用了什么 | 高,需不可改 |
一条必须分清的边界:Session 是交互容器,Trace 是因果链。session_id 可跨天、跨多次执行,顺序靠事件游标;trace_id 是一次执行,结构靠父子 span。不要把 session_id 当 trace_id;不要从 trace 结束推断任务完成(完成看任务账本与证据);子 Agent 或跨队列执行另起 trace 时必须用 Span Link 指回父执行,不能变成孤岛。
本篇的展开顺序即一条 trace 的生命周期:§二定信号(span 语义、指标、采样)→ §三定归宿(Langfuse 后端)→ §四定接口(观测契约怎么调)→ §五定消费(评测与门禁)→ §六给链路(四条端到端时序)。
§二 信号体系
2.1 十二类 span 语义
Trace 能串起来不等于能读懂。一次 Agent 执行里混着模型调用、检索、记忆、工具、策略检查、压缩、人工审批与中断;如果都记成 chat 或 execute_tool,“慢在哪、钱花在哪、哪一步被拦下”就无从回答。按语义动作建 span,共十二类:
| Span 类型 | 何时产生 | 必带属性 | 常见错误 |
|---|---|---|---|
ENTRY | 请求进入平台 | 入口类型、认证结果、租户、路由 | 与网关 HTTP span 混成一个 |
AGENT | 一次 Agent 调用 | agent_key、release_id、会话 | 缺发布单元,无法复现 |
WORKFLOW | 工作流整体执行 | workflow_revision、触发方式 | 把每次节点执行都记成 workflow |
STEP | 工作流节点 | node_id、join_type、分支 | 节点与工具调用混层 |
LLM | 一次模型请求 | 模型、参数、输入/输出/缓存 Token、finish_reason | 只记总 Token,不记缓存 |
RETRIEVAL | 知识检索 | 索引版本、top_k、命中 ID、分数 | 只记耗时,无法解释召回变化 |
MEMORY | 记忆读或写 | 作用域、操作、文档版本 | 把记忆写当成普通工具调用 |
TOOL | 一次工具执行 | 工具名、版本、side_effect、action_id、结果 | 缺 action_id,接不上审批与审计 |
GUARDRAIL | 策略/内容检查 | 策略 ID、决定、原因码 | 只记放行,拒绝的检查完全消失 |
COMPACTION | 上下文压缩 | 压缩前后 Token、丢弃的引用 | 不记丢了什么,事后无法解释 |
HITL | 等待人工 | 等待类型、审批 ID、决定、等待时长 | 把等待时间算进模型时延 |
INTERRUPT | 取消、超时、中断 | 原因、未完成项数量、补偿状态 | 非正常退出没有 span |
四条落地规则:同一次动作只产生一个语义 span;拒绝也要留 span(否则越权尝试在可观测里是空白);等待与执行分开计时(HITL 与 task.wait 的时长不能混进模型延迟);重试开新 Trace 并用 Span Link 指回上一次,不复用 trace_id 造两个根 span。
每个 span 至少带四类属性:版本(Agent、提示词、模型、工具)、用量(输入/输出/缓存 Token)、结果(状态码、错误类型)、归属(租户、应用、会话)。缺版本无法回放,缺归属无法计费,缺结果无法聚合。
2.2 采集管道:OTel SDK → Collector → OTLP
AgentScope Java 的 OtelTracingMiddleware 默认覆盖 invoke_agent、chat、execute_tool 三类 span,并通过 Reactor 上下文传播 traceparent。整条链的采集管道分三段:
三处 traceparent 续接是硬要求(网关、调度/队列、Runtime Host),否则链路断成截;RAGFlow 走官方 connector 直投 Langfuse(06 专栏实测端点 POST /api/v1/langfuse/api-key 可用)。非官方框架只要产出 OTel GenAI 语义 span(llm/tool/retrieval/embedding/pipeline)即可经 Collector 汇入,无第二套 SDK。
2.3 指标表(Instrument 类型标注)
| 指标 | Instrument | 维度 | 用途 | 告警思路 |
|---|---|---|---|---|
| Turn 时延 P95 | Histogram(agent.turn.duration_ms) | Agent、模型 | 体验 | 连续 5 分钟超过基线 1.5 倍 |
| Token 用量 | Counter(gen_ai.client.token.usage,按 input/output/cache 分) | 租户、模型 | 成本 | 单租户日环比突增 50% |
| Token 成本 | Counter(金额累加) | 应用、模型 | 分摊 | 预算消耗达 80% / 100% |
| 工具错误率 | Counter(调用数,按状态码/错误类型分桶),率值告警端派生 | 工具、错误类型 | 稳定性 | 5xx 与超时分开统计 |
| 任务成功率 / 重试率 | Counter(终态计数) | 任务类型 | 可靠性 | 重试率连续上升 |
| 队列等待 | Histogram(queue.wait_ms)+ Gauge(“最后消息时间”滞后) | LiteTopic 通道 | 容量 | 自建滞后指标 |
| 审批等待 | Histogram(hitl.wait_ms) | 审批类型 | 流程瓶颈 | 超 SLA 未处理 |
| 任务等待(按类型) | Histogram(task.wait.duration_ms,wait_type 维度) | wait_type、任务类型 | 区分审批/工具/输入/外部/排队 | 按类型设 SLA,不混成“处理中” |
| 上下文压缩次数 | Counter | Agent | 质量风险 | 单会话频繁压缩 |
| 决策一致率 | Gauge(周期重算写入) | 用例 | Jev 校准 | 影子建议与实际结果偏差扩大 |
两条纪律:指标标签只放低基数字段(模型、Agent、工具、状态码),会话 ID、用户 ID、任务 ID 放 Trace 与事件;成本以网关计量与 budget ledger 为准,内核自报 Token 只用于排障。等待必须按 wait_reason.type 拆开——审批慢、工具慢、模型限流、排队、等外部回调的处置 owner 完全不同;等待分类约定见 22-架构评审与任务闭环 §三、§十四。
2.4 采样策略
采样在 Collector 的 tail-based 处理器完成(按 trace 尾部决策,不做头部采样,保证错误 trace 完整):
- 错误与高风险全采:含错误状态码的 trace、
GUARDRAIL拒绝、预算超限、审批拒绝——一条不丢; - 正常请求按比例采:初始 10%,按存储容量与排障需求调整;采样率变更要记录版本,否则跨版本错误率对比失真;
- 决策窗口:tail-sampling 按 trace 完成后 30s 窗口决策,需为长任务放宽 policy 生命周期;
- 审计不走采样:审计记录与 Trace 分开存储、写后不可改、保留期按合规单独设定(衔接 08 专栏管道:网关+控制面+实例审计 → OTel → MinIO 归档 180 天)。有事件不等于有审计——事件是运行记录,审计要求完整性、不可改与保留期。
§三 后端选型(Langfuse)
3.1 为什么是 Langfuse
选型面对六条硬约束:数据不出域、MIT/Apache 开源许可、企业 SSO、按 user_id/实例隔离审计、RAGFlow 端点已就绪、AgentScope 官方接入证据。候选九家(Langfuse、Arize Phoenix、Comet Opik、W&B Weave、LangSmith、Helicone、OpenLIT、Traceloop OpenLLMetry、AgentOps)逐一对照后的否决链:
| 候选 | 否决点 |
|---|---|
| LangSmith | 平台闭源 SaaS,自托管锁 Enterprise 许可——许可与成本双杀 |
| W&B Weave | 服务端不开源,自托管需付费 license,非 OTel 原生 |
| Comet Opik | 评估指标库最强(30+ LLM-judge),但自托管 OSS 无认证/无用户管理,违反隔离审计 |
| Arize Phoenix | 技术能力强、OSS 自带 OIDC+LDAP,但 ELv2 非 OSI 开源、RAGFlow 无官方集成——备选观察位 |
| OpenLIT | Apache-2.0 全栈最接近的挑战者,但双生态集成与 SSO 证据弱——第二备选 |
| Helicone / AgentOps | 无企业 SSO 文档、评估体系弱 |
| OpenLLMetry | 只是埋点 SDK 不是后端,主仓库已放缓 |
Langfuse 胜出的结构:核心 MIT、可完全自托管;trace/span/generation 三层数据模型 + usage/cost + userId/sessionId/tags/prompt 版本为一等属性;社区版自带 OIDC SSO 与告警;评估器(scores/datasets/experiments/LLM-as-judge)内置,judge 经 LiteLLM 可接本地开源模型;RAGFlow 官方内置 connector(≥0.18.0,端点已实测)+ AgentScope Python/Java 官方接入文档——双官方集成全场仅一家。
复合形态是一主多辅,不引第二套 trace:
Langfuse(观测主干,唯一 trace 归宿)
├── 评估模块:Langfuse 原生 evaluator + OpenJudge/Judge 服务(域内模型打分,见 §五)
├── 告警模块:Langfuse Alerts(v4+ 社区版可用)+ Grafana 兜底(邮件渠道)
├── 回流模块:datasets 导出管道(RAGFlow 回灌 / 微调数据 SFT/DPO/CPT)
└── 门户皮:HiMarket 统一入口 + 观测面 API 聚合3.2 十二类 span → Langfuse 数据模型映射
agentscope-service 观测面(§四 17 端点实证)与 OTel GenAI 语义的汇入映射。generation 是 Langfuse 的模型调用专用对象(带 model/prompt/output/token/cost),span 是通用观察对象,metadata tag 承载非树状语义:
| # | span/观测对象 | 来源契约 | Langfuse 汇入对象 | 说明 |
|---|---|---|---|---|
| 1 | session | GET .../snapshot | trace(会话 root) | 一次会话一条 trace,user_id/session_id 属性打标 |
| 2 | turn | events type=turn(单调 seq) | observation(子 span) | turn 级,agent_version 属性 |
| 3 | run | events type=run | observation(子 span) | run 级,含 execution_attempts 重试语义 |
| 4 | item | events type=item / GET .../items | observation | 消息/工具 item,type=message 属性 |
| 5 | tool | events type=tool / GET .../tools | observation(name=tool_call) | 工具调用(arguments/input/model_call_id) |
| 6 | usage | GET .../usage | Langfuse 内置 usage/cost | model_calls/tokens 汇入 generation 计量 |
| 7 | llm/generation | OTel GenAI gen_ai.* span | generation 对象 | 模型调用(qwen3.8-max 等),prompt/output/token |
| 8 | retrieval | OTel GenAI retrieval span(RAGFlow 链路) | observation(type=retrieval) | RAGFlow connector 已就绪(实测) |
| 9 | embedding | OTel GenAI embedding span | generation(type=embedding) | 向量化调用 |
| 10 | pipeline | 网关/调度/编排链路 | span(父上下文) | 端到端链路对标百炼“大模型/MCP/向量检索” |
| 11 | budget | GET | PUT .../budget | 平台侧(Langfuse 无原生 budget) | ledger 与 cost 双源对照,见 §4.4 |
| 12 | hands/worker | GET /api/hands/status | 平台侧 metadata/Gauge(不入 trace) | 执行体健康走 Grafana |
汇入规则:1–10 走 OTLP(traceparent 三处续接照常生效);11–12 为平台侧指标面,不混入 Langfuse trace 语义。首 Token 耗时需埋点补 span attribute(小项缺口)。
3.3 最小部署足迹
六件套(官方最小足迹合计约 9C/21.5GiB,需 K8s 承载;Docker Compose 单机快速起步建议 ≥4C/16GiB/100GiB):
| 组件 | 资源 | 职责 |
|---|---|---|
| langfuse-web | 2C/4Gi | UI + Ingestion/Public API |
| langfuse-worker | 2C/4Gi | 异步评估任务、回填 |
| PostgreSQL | 2C/4Gi | 元数据(项目/用户/dataset/prompt 定义) |
| ClickHouse | 2C/8Gi | trace/observation/score 事实数据,单分片可到 TB 级 |
| Redis | 1C/1.5Gi | ingestion 队列与缓存 |
| S3 / MinIO | 按量 | 附件与 blob 存储 |
版本现状:v4.70.0(2026-10-24),月均约 23 个 release;v4 于 2026-08-17 GA,v3 安全补丁维持到 2027-01。所有投递为异步——观测面故障不阻塞业务主链路(RAGFlow connector 与 SDK 侧均为失败不影响响应的语义)。
3.4 社区版 RBAC 限制与缓解
企业 license key 才解锁的能力:项目级 RBAC、审计日志、服务端脱敏、数据保留策略、SCIM。平台侧缓解:
- API 隔离成立:每租户/每实例独立 Langfuse project + 独立 pk/sk,API key 按项目鉴权(数据隔离由项目模型原生支撑);trace 强制携带
userId/sessionId一等属性,Observations API、告警过滤器均支持按 user 过滤——“按 user_id/实例隔离审计”在 API 层闭环。 - UI 隔离不成立:社区版登录用户可访问所加入组织下的项目,无项目级角色细分。收敛路径:门户观测面只读、按角色(平台 admin / 租户 owner / 普通用户)在 HiMarket 聚合页收敛数据范围(走 Public API 而非直放 UI);写操作(evaluator/dataset 管理)走平台后台。iframe 直嵌官方无证据(X-Frame-Options 未文档化),按“网关反代 + 观测面 API”落地。
- 其余自建:脱敏用 SDK 侧 client-side masking;数据保留用 ClickHouse TTL + 归档任务(对齐 08 专栏 180 天审计保留);SSO 社区版 OIDC 覆盖 Keycloak/AzureAD/Okta 等,纯 SAML 场景由前置 IdP 做 SAML→OIDC 桥接;告警渠道 Slack/Webhook/GitHub Actions,邮件由 Grafana 或自有通知中心兜底。
§四 观测接口契约
agentscope-service 观测面 17 端点全部实跑(2026-10-26,主链会话 d57377bc-...,454 事件;以下均为实测)。接入点 gateway :18080;鉴权三件套:Authorization: Bearer <jwt> + X-AgentScope-Tenant + X-AgentScope-Namespace。
4.1 端点清单
| # | 端点(前缀 /api/v1/agent-sessions/{id}) | 实测 | 用途 |
|---|---|---|---|
| 1 | GET /events?after=&limit= | 200 | 事件游标分页 {data,next_cursor,has_more} |
| 2 | GET /events/stream?after= | 200(SSE) | 15s keepalive 实时流,支持 Last-Event-ID |
| 3 | GET /snapshot | 200 | views+session+usage 一致快照(as_of 水位) |
| 4 | GET /tools | 200 | 工具调用记录(arguments/input/model_call_id) |
| 5 | GET /items?limit= | 200 | 消息/工具 item 分页(消息正文载体) |
| 6 | GET /inputs | 200 | 输入应用记录(input_id→run_id→turn_id) |
| 7 | GET /subagents | 200 | 子代理列表 |
| 8 | GET /artifacts | 200 | 产物列表 |
| 9 | GET /required-actions | 200 | HITL 待办(Inbox 聚合数据源) |
| 10 | GET /usage?include_children= | 200 | 用量聚合(model_calls/tokens/估算成本) |
| 11 | GET | PUT /budget | 200 | 预算读写(GET 先 reconcile 自愈,revision 递增) |
| 12 | GET /checkpoints | 200 | checkpoint 清单(cp_ id+turn_id+reason) |
| 13 | POST /checkpoints/restore | — | 回滚(body checkpoint_id+reason,需 Idempotency-Key) |
| 14 | POST /fork | — | 派生新会话 |
| 15 | GET /export | 200 NDJSON | 全量导出(Content-Disposition: session-events.jsonl) |
| 16 | GET /trace(+subagents/recovery/POST reconcile) | 404 | 敏感对账面默认关,需 trace-enabled=true |
| 17 | GET /api/hands/status | 200 | worker/租约健康(心跳+认领度量) |
4.2 关键端点语义
events 游标分页:cursor 是 SessionEventCursor 的 base64 编码,不透明、不外泄内部 seq;limit 上限 1000(实测 454 事件一页取全);data[] 按事件时间升序。坑:游标超前当前水位返回 409,需重拉最新页;GET /events/{eventId} 按事件自身 id(evt_*/id 字段)查询——传 item id 实测 404,不是消息 id。
SSE 事件流:Accept: text/event-stream,每 15s 输出 :keepalive 注释行防代理超时;public 过滤——只推公共事件(turn/run/item/tool/usage),不推内部 journal 事件;durable subscribe:断线带 Last-Event-ID 重连不丢事件(链路见 §六.3)。
snapshot:as_of 为快照一致水位(events 游标语义),inputs/artifacts/action_commands 等分视图各带独立 item cursor——一次读取即得一致视图,报表侧不用拼多次分页。
export:NDJSON 每行一个事件(含 session_id/schema_version/type/cursor),适合归档与评测集回放(§五数据源);原子导出走 Lua 脚本。
trace 敏感面:builder.agent-api.trace-enabled=false(默认)时 trace/trace-subagents/trace-recovery 全部 404 且响应体 {"error":"not found"}——是“默认关”而非接口不存在;开启需配置项翻转 + ROLE_ADMIN 或 ROLE_SESSION_TRACE。内部 journal 级对账接口,生产默认不暴露是正确姿势。
4.3 usage 与 budget:两个“看起来缺数据”的实测结论
usage 面不承担单价换算(实测):
json
{"data":{"cost_complete":false,"currency":null,"estimated_cost":0,"model_calls":4,
"models":[{"model":"qwen3.8-max","scope":"session_only",
"usage":{"inputTokens":6698,"outputTokens":233,"reasoningTokens":151,"totalTokens":6931}}]}}currency=null、estimated_cost=0 不是缺陷——Service 记录的是原始 token 用量,单价化换算在 Langfuse 侧配置(见 4.4)。含子代理走 include_children=true。
budget 默认不限(实测):
json
{"enforcement":"before_model_call","limits":{},"revision":8,"scope":"session_tree",
"usage":{"total_tokens":29293,"unpriced_calls":4,"unreported_calls":0}}limits:{} 即默认无上限——预算不 PUT 就等于没有;revision 每次 reconcile/写入递增(实测 8 = 4 次模型调用 × 2 类事件对账);GET 先 reconcile 自愈的语义意味着读操作也可作对账触发器。
4.4 配置方法:让成本与预算数字真实
- 成本单价表(Langfuse 侧):在 Langfuse
model definition按模型名(如qwen3.8-max)登记 input/output 单价,trace 汇入 generation 后自动推算美元成本。注意unpriced_calls>0时任何成本门禁都失真——先配价,再谈预算。 - 预算限制(Service 侧):
PUT .../budget设置limits。生产推荐初值:max_tokens= 单会话稳态用量 2–3 倍(实测会话树 P50≈6.9k tokens、四调用合计 29,293 total_tokens,起步建议 100k);max_cost必须等第 1 步定价就绪后再设;enforcement=before_model_call保持默认——拦在调用前,防超额产生费用。 - 对账口径:
usage+budget → 成本看板,与 Langfuse cost 双源对照;不一致时以 budget ledger(实测态)为准排查,网关计量为账单权威(14 篇纪律:Trace 不是账单,采样、重试、缓存都会让 Token 统计偏离真实计费)。
4.5 调用注意事项汇总(踩过/实测确认)
| 注意点 | 说明 |
|---|---|
| 409 | events 游标超前水位,重拉最新页 |
| Idempotency-Key | 写操作(turns/restore/fork)必带且唯一,否则 400/重复执行 |
| 中文 body | 必须显式 UTF-8 bytes(坑位 K16:PowerShell 默认 GBK 编码丢汉字) |
| events/ | 按事件 id 查,不是 item/message id |
| trace 404 | 默认关而非不存在,开面走 admin 角色 |
| limit 上限 | events ≤1000,超限按 1000 截断 |
§五 评测与门禁
5.1 评测框架选型:OpenJudge
- 官方生态:AgentScope 官方评测框架(
agentscope-ai/OpenJudge,Apache-2.0)——与 agentscope-service 同源,随官方演进,不是第三方拼装; - grader 覆盖面:本地源码复核计得 58 个 grader 类(源码坐实,清单见 5.2),Agent 族按 action/memory/observation/plan/reasoning/reflection/response/tool/trajectory 九个子域组织;
- judge 模型复用:grader 用 OpenAI 兼容模型当 judge,直接复用 token-plan 网关(qwen3.8-max)——零新增模型成本;
- 评测即训练奖励:输出同时适配训练 reward,评估结果可回流强化。
两条口径修正(相对旧 42 篇,均以本地源码为准):
TrajectoryComprehensiveGrader不是误称——类真实存在(源码坐实:graders/agent/trajectory/trajectory_comprehensive.py:276,LLMGrader,逐 step 评 contribution/relevance/accuracy/efficiency 四维 1–5 分再平均归一)。42 篇实跑 0.0 分、“No steps to evaluate”的根因是输入 schema 适配:该 grader 期望 agent 级 step 轨迹,drill 级合并出的 messages 没被提取出可评步骤。落地结论不变但依据改写:门禁主力用ToolSelectionGrader(源码坐实:agent/tool/tool_selection.py:158,aevaluate(query, tool_definitions, tool_calls)输入契约极简,与 §四 tools 端点的arguments/input/model_call_id直接吻合,无需轨迹重排)+ToolCallSuccessGrader(agent/tool/tool_call_success.py:170,执行成功判定)作补充;TrajectoryComprehensiveGrader保留给已完成 step 级 schema 对齐的深度评估。RelevanceGrader的真实来源是graders/common/relevance.py:196(源码坐实:通用相关性 grader,1–5 分制、threshold默认 3、支持 ZH 评估模板,输入 query+response(+对话历史))——42 篇实跑用的即此。skills/relevance.py:275定义的是SkillRelevanceGrader,评的是 Skill 定义与用途的相关性,属技能供给面评估,两者不可混用。
5.2 可用 grader 矩阵(源码坐实)
按目录全量清点;类型区分 LLM(judge 模型驱动)与规则(确定性计算,零模型成本,适合 L0/L1 快检):
| 族 | grader | 类型 |
|---|---|---|
| agent/action | ActionAlignmentGrader · ActionLoopDetectionGrader | LLM · 规则 |
| agent/memory | MemoryAccuracyGrader · MemoryDetailPreservationGrader · MemoryRetrievalEffectivenessGrader | LLM |
| agent/observation | ObservationInformationGainGrader | 规则 |
| agent/plan | PlanDecompositionGrader · PlanFeasibilityGrader | LLM |
| agent/reasoning | ReasoningCoherenceGrader · ReasoningGroundednessGrader | LLM |
| agent/reflection | ReflectionAccuracyGrader · ReflectionOutcomeUnderstandingGrader · ReflectionProgressAwarenessGrader | LLM |
| agent/response | ResponseCompletenessGrader · ResponseHelpfulnessGrader | LLM |
| agent/tool | ToolCallAccuracyGrader · ToolCallSuccessGrader · ToolParameterCheckGrader · ToolSelectionGrader(LLM);ToolCallPrecisionRecallMatchGrader · ToolCallStepSequenceMatchGrader · ToolUsageEfficiencyGrader(规则) | LLM+规则 |
| agent/trajectory | TrajectoryAccuracyGrader · TrajectoryComprehensiveGrader · TrajectoryErrorRecoveryGrader(LLM);TrajectoryStepEfficiencyGrader(规则) | LLM+规则 |
| skills | SkillCompletenessGrader · SkillDeclarationAlignmentGrader · SkillDesignGrader · SkillRelevanceGrader · SkillThreatAnalysisGrader | LLM |
| text | NumberAccuracyGrader · SimilarityGrader · StringMatchGrader | 规则 |
| code | CodeBugDetectionGrader · CodeComplexityGrader · CodeSecurityGrader(LLM);CodeExecutionGrader · CodeStyleGrader · PatchSimilarityGrader · SyntaxCheckGrader(规则) | LLM+规则 |
| format | JsonMatchGrader · JsonValidatorGrader · LengthPenaltyGrader · NgramRepetitionPenaltyGrader · ReasoningFormatGrader · ReasoningToolCallFormatGrader | 规则 |
| math | MathExpressionVerifyGrader | 规则 |
| multi_turn | AnaphoraResolutionGrader · ContextMemoryGrader · InstructionClarificationGrader · ProactiveInteractionGrader · ResponseRepetitionGrader · SelfCorrectionGrader · TopicSwitchGrader | LLM |
| multimodal | ImageCoherenceGrader · ImageHelpfulnessGrader(LLM);TextToImageGrader(规则) | LLM+规则 |
对百炼 8 类预置轨迹评估器的映射(旧 40 篇把这块全列为“自建”,OpenJudge 到位后大部分降级为“配置即用”):
| 百炼预置轨迹评估器 | OpenJudge 对应(源码坐实) | 判定 |
|---|---|---|
| 轨迹准确性 | TrajectoryAccuracyGrader | 直接覆盖 |
| 动作循环检测(ATIF) | ActionLoopDetectionGrader(规则) | 直接覆盖 |
| 回答忠实度 | ReasoningGroundednessGrader | 直接覆盖 |
| 执行成功性与错误定位 | ToolCallSuccessGrader + TrajectoryErrorRecoveryGrader | 组合覆盖 |
| 观察信息增益 | ObservationInformationGainGrader(规则) | 直接覆盖 |
| 工具调用成功率 | ToolCallSuccessGrader + ToolUsageEfficiencyGrader | 组合覆盖 |
| 最终回答有害性 | 无对应类 | 仍需自建安全 judge |
| 检索有效性 | MemoryRetrievalEffectivenessGrader 只覆盖记忆检索;RAG 检索命中率仍需规则自建 | 部分覆盖 |
5.3 实跑结论
链路实测(2026-10-26,全链路闭环):events 游标分页取 454 真实事件 → 轨迹构造(item.completed message → OpenAI messages;tool.requested+tool.completed → tool_calls)→ OpenJudge grader → token-plan 网关 qwen3.8-max 作 judge → score+reason 产出。结果:
| Grader | 输入 | 得分 | judge 理由(节选) |
|---|---|---|---|
| RelevanceGrader(common) | query=USER 首条 / response=assistant 末条 | 5.0 | judge 自主识别出链路的中文编码事故(汉字变 ?,非 UTF-8 转换丢字),并给出可操作步骤 |
| RelevanceGrader(common) | 中文验证回合 | 3.0 | 违反“请简短回复”显式指令——多余细节、泄露 sess_* 内部 ID 与环境信息,均被 reason 点名 |
| TrajectoryComprehensiveGrader | 12 条 messages(drill 级合并) | 0.0 | “No steps to evaluate”——schema 适配问题(见 5.1 修正 1),非类不存在 |
关键结论:judge 评分质量足以精准诊断真实缺陷并当质量门禁——5.0 例识别编码事故、3.0 例抓指令违背与信息泄露;缺陷→修链路→重跑回归的迭代闭环已完成一轮(编码修复后重跑中文回合,ENCODING_OK + Relevance 出分)。
5.4 评测集管理
评测不是“跑一遍 benchmark”,而是维护三样东西:
- 黄金集:按业务域与任务类型分层,覆盖正常、边界、对抗与历史 BadCase;每条用例带输入、期望、评分标准与版本;数据源即 §四 契约——
exportNDJSON 归档、events游标回放历史会话轨迹批量评分; - 评分器组合:规则断言(
text/string_match、format/json_validator、agent/tool规则系——工具是否调用、参数是否正确、是否越权)+ LLM judge(Relevance/ToolSelection/Response 系)+ 人工复核(高风险样本);新 grader 上线前要先在自己样本上验证与人工判断的一致性; - 采样与回流:线上按成功率、成本、时延分层抽样、脱敏后入集;只抽失败样本会让评测集越来越偏。
对照必须按维度看,不只看总分:总分持平但成本翻倍,同样不能上。评测集、grader 配置、阈值随发布冻结——改评测集要像改代码一样评审(LLM-as-Judge 本身会漂移,高风险结论必须人工复核或规则兜底)。
5.5 门禁分级与发布流水线集成
| 级别 | 检查 | 执行者 | 通过条件 | 失败动作 |
|---|---|---|---|---|
| L0 静态 | 配置 schema、链接、许可、禁用词 + format/text 规则 grader | CI 构建阶段 | 全部通过 | 阻止合并 |
| L1 离线 | 黄金集回归(RelevanceGrader + ToolSelectionGrader + ToolCallSuccessGrader + 规则断言) | CI/发布前批跑,score+reason 入库(Postgres/Redis) | 关键维度不退化;阈值门禁(如 Relevance < 3 阻断);成本增幅在阈值内 | 阻止发布 |
| L2 影子 | 真实流量旁路 | Langfuse 指标面 | 决策一致率、错误率无异常 | 只观察,不切流 |
| L3 灰度 | 1% → 10% → 50% | Langfuse Alerts + Grafana | 成功率、时延、成本、投诉率达标 | 自动回滚上一 revision |
| L4 全量 | 持续监控 | 告警规则(错误率 2%/延迟 p95 15s/成本日环比 50%/faithfulness 均值 <0.7 持续 30min) | 稳定窗口内无回归 | 手动或自动回滚 |
门禁是递进关系而非并列清单:每级只解决“上一级看不见的风险”,任一级不过就退回,且退回路径必须比前进路径短。
三级递进的依据:L0/L1 拦“已知会错的东西”(规则断言 + 黄金集,跑在 CI 里,成本可控);L2 拦“评测集分布外的问题”,只观察不切流,产出的是决策一致率而不是分数;L3/L4 拦“真实流量才暴露的问题”,判据换成成功率、时延、成本与投诉率。B2/RB 两条退回边都指向 L1,而不是指向 L0——改完必须重新跑离线回归,静态检查通过不代表质量没退化。
与发布流水线的三个集成点:
- 触发点:Agent 定义的发布工单绑定
release_id,CI 在 promote 到 staging 前调 §六.2 的门禁链路(历史会话轨迹回放 + 黄金集评分),评测产物不可变归档; - 判定与留证:score+reason 入库并回写 Langfuse(numeric score 挂 trace),按 agent/skill/模型版本出对比看板——门禁结论必须可回放,不接受“报告说过了”;
- 回滚能力是门禁成立的前提:Agent 定义用版本切换、Endpoint 用 release 切换、Workflow 用 revision 固定,回滚十分钟内一键完成(checkpoint/restore 契约在 §四 #13);如果回滚需要改代码,门禁就只是形式。
评测还差接入层补齐的部分(控制台范围):数据集/任务/报告 UI 归 HiMarket 门户皮;这与百炼“评测任务状态机/综合得分仪表盘/5 模型对比”对齐,结构上 Langfuse experiments + 自建报告聚合已覆盖。
§六 已支持场景链路
6.1 一次对话的 trace 上报全链路(内核 → OTel Collector → Langfuse)
6.2 评测门禁触发(CI → 黄金集 → 评分 → 放行/阻断)
6.3 SSE 事件流续传(断线 → Last-Event-ID → 不丢不重)
6.4 预算观测(usage → 成本计算 → 阈值告警)
边界与验收
六条边界:Trace 不是账单(采样/重试/缓存使 Token 统计偏离计费,账单以网关与供应商为准);指标不是根因(指标只说“哪里变了”,定位靠 trace 与事件);评测集不是真实分布(黄金集永远滞后线上,必须持续回流);LLM-as-Judge 不是裁判(评分器会漂移,高风险结论人工复核或规则兜底);有事件不等于有审计(审计要完整性、不可改、保留期,单独管道);Span 不是越细越好(按语义动作建,工具内部重试与分页是属性不是几十个同级 span)。
五条验收判据(判断证据体系是否成立):任取一条线上回答能还原完整 span 树,且被拒绝的工具调用也有 GUARDRAIL 或 TOOL span;等待审批的时长不计入模型时延;指标能按租户与 Agent 聚合;黄金集能复现至少一个历史 BadCase;回滚在十分钟内完成、审计与 Trace 分开且不可改。
整合自旧 14/40/42/43 篇 | OpenTelemetry GenAI 语义约定 / Langfuse v4.x / py-openjudge 0.2.4 / agentscope-service 2.1.0-BETA1 | 2026-10