跳到主要内容

评测↔可观测闭环、巧妙之处、边界与对比

本章讲什么: 前三章把评测和可观测分别讲透了。它们不是两座孤岛——CozeLoop 用两条桥把"线上发生的事"和"离线评测的事"接成一个闭环。本章讲清这两条桥,再统一收口全局的巧妙之处、边界与横向对比。

1. 闭环全景:为什么要接起来

光有评测:你只能评"自己造的测试集",脱离真实流量。 光有可观测:你只能看"线上发生了什么",但没有"好不好"的判断。

接起来才完整:用真实线上 trace 当评测数据,用评测打分给线上质量做体检。两条桥:

可观测(线上 trace) 评测(离线/在线)
│ │
│ 桥①:trace_export │
│ 选中一批 span ─导成─▶ 评测数据集 ─────▶ 拿去跑实验
│ │
│ 桥②:在线评测 task │
│ 采样线上 span ─触发评估器打分─┐ │
│ ▼ │
└◀── auto_evaluate annotation 回写 span ┘(分数贴回 trace)

2. 桥① trace → 评测数据集

ITraceExportService.ExportTracesToDatasettrace_export_service.go:95)。

输入是一批 SpanID{TraceID, SpanID} + 字段映射(FieldMappings)+ 目标数据集配置(新建或追加)。它把选中 span 的输入/输出按映射抽成数据集的列,写入评测数据集。请求结构 ExportTracesToDatasetRequest:44)里 ExportType(append/overwrite,:39-42)和 FieldMappings:54)是关键——用 trace 的真实字段对齐数据集 schema,和评测侧的 FieldConf 映射思路一脉相承。

还有 PreviewExportTracesToDataset:96)让你导之前先看几条,避免映射错了批量污染数据集。

这条桥的价值:把"线上真实失败 case"一键沉淀成回归测试集——这是 LLM 应用迭代的核心工作流。

3. 桥② 在线评测 → annotation 回写

这是更深的耦合。在线评测(observability 的 task 域)对线上 span 持续采样并触发评估器,结果写回 span。

流程

TaskCallbackServiceImpl.AutoEvalCallbacktask_callback.go:59)是回调落点:评估器对某 span 打完分后,回调拿着 AutoEvalEvent(含 trace_id/span_id/score/reason/evaluator_record_id/expt_id)做三件事:

// 示意,非源码:AutoEvalCallback 主干(语义取自 task_callback.go:59-139)
for _, turn := range event.TurnEvalResults {
span := getSpan(turn.traceID, turn.spanID) // ① 把原始 span 捞回来
updateTaskRunDetailsCount(...) // ② Redis 计数(成功/失败统计)
span.AddAutoEvalAnnotation(taskID, evaluatorRecordID,
evaluatorVersionID, score, reasoning, ..., exptID) // ③ 造一条 auto_evaluate 标注
traceRepo.InsertAnnotations(... AnnotationTypeAutoEvaluate) // 落库
}

annotation 是什么

annotationloop_span/annotation.go)是"贴在 span 上的结构化标签"。类型枚举(annotation.go:42-48)很说明问题:

AnnotationType来源
auto_evaluate自动评测分数(桥②写的)
manual_feedback人工反馈
manual_evaluation_set / manual_dataset人工标注入集
coze_feedback / openapi_feedback平台/接口反馈

AutoEvaluateMetadataannotation.go:78)把这条标注反向连回评测世界:带 EvaluatorRecordIDEvaluatorVersionIDExptIDExptTemplateID。于是在 trace 详情页看到一个自动评分,能一路点回"是哪个实验、哪个评估器版本、哪条评估记录"打的。

还能修正

AutoEvalCorrectiontask_callback.go:143)+ AnnotationCorrectionannotation.go:64,类型 llm/manual)支持对自动评分做人工纠偏,纠偏值带 UpdatedBy/UpdateAt。这和第一章"行分优先取 Correction"前后呼应——人工修正在评测与可观测两侧是统一的一等公民

4. 全局巧妙之处(跨子系统)

妙在哪一句话锚点
统一"大字段外移"span 与评估输入都用 omitted/对象存储策略控制主表行宽与消息体span.go:195expt_run_item_turn_impl.go:655
评测自身可观测Prompt 评估器执行时也开 trace span,打分链路在 ob 里能回放evaluator_source_prompt_impl.go:84
容错优先于洁癖LLM 输出四级降级解析、CK 写入重试容许重复,都选"尽量出结果"evaluator_source_prompt_impl.go:373spans.go:54
人工修正贯通两端Correction 在评测聚合与 annotation 两侧都覆盖模型分expt_score_calculator.go:190annotation.go:64
复用成熟抽象trace 落库直接套 OTel Collector 管道形态ingestion.go:33
仅记录型 target在线评测不重跑被测对象,复用 trace 里已有输出target.go:85
事件驱动 + 幂等实验调度与 span 落库都走 MQ + 幂等键,可中断可重试expt_run_scheduler_mode_impl.go

5. 边界与局限(诚实)

  • 两模块不直接互调(根 ARCHITECTURE.md 不变量:模块间不直接互调)。评测↔可观测的耦合走 RPC + MQ + annotation,而非进程内调用——好处是边界清晰,代价是闭环链路更长、最终一致而非强一致。
  • 强依赖外部组件:MySQL/ClickHouse/Redis/RocketMQ 缺一不可;Code 评估器还需独立 FaaS 服务(python-faas/js-faas 镜像)。本地最小化跑不起来。
  • 落库异步:trace 上报成功不代表立即可查;在线评测分数回写也有延迟。
  • LLM-as-judge 固有不确定性:四级解析能兜底"取到分",但兜不了"分对不对"——裁判模型本身的偏差是方法论边界,非工程能解。
  • 开源版 vs 商业版:代码里大量 Commercial* 错误码与 adapter(根 ARCHITECTURE.md 的 adapter 模式)暗示部分能力在商业版;开源版是核心子集。

6. 横向对比(同 shelf 兄弟项目)

CozeLoop 在 evals-observability 这一格的定位,相对常见兄弟项目:

维度CozeLoop典型纯评测框架(如 evals/promptfoo 类)典型纯 trace 平台(如 Langfuse/Phoenix 类)
评测✅ 四类评估器 + 实验调度引擎 + 加权聚合✅ 核心弱/无
可观测✅ OTel 风格管道 + CK 存储弱/无✅ 核心
闭环✅ trace↔数据集↔annotation 双向部分(trace→dataset 有,自动评测回写不一定)
形态平台(Go 后端 + React 前端 + 部署件)多为库/CLI平台
在线评测✅ 采样线上 span 自动打分回写部分

一句话取舍:CozeLoop 不是"最轻的评测库"也不是"最专的 trace 平台",它的差异化是把两者做进同一平台并打通闭环——代价是重(依赖多、部署复杂),收益是"线上→评测→改进"的工作流不出系统。

7. 全局代码地图(总导航)

子系统主题文件符号
评测实验聚合根modules/evaluation/domain/entity/expt.goExperimentExptStatus_*
评测执行引擎modules/evaluation/domain/service/expt_run_item_turn_impl.goDefaultExptTurnEvaluationImpl.Eval
评测调度器modules/evaluation/domain/service/expt_run_scheduler_mode_impl.goNewSchedulerModeExptSubmitExec
评测行分聚合modules/evaluation/domain/service/expt_score_calculator.goCalculateWeightedScore
评测LLM 裁判解析modules/evaluation/domain/service/evaluator_source_prompt_impl.goparseContentOutput 四策略
评测Code 沙箱modules/evaluation/infra/runtime/http_faas_runtime.go
可观测上报/查询modules/observability/domain/trace/service/trace_service.goIngestTracesGetTraceGetMetrics
可观测落库管道modules/observability/domain/trace/service/ingestion.goIngestionService
可观测span 实体modules/observability/domain/trace/entity/loop_span/span.goSpan
可观测CK 存储modules/observability/infra/repo/ck/spans.goSpansCkDaoImpl
闭环trace→数据集modules/observability/domain/trace/service/trace_export_service.goExportTracesToDataset
闭环评分回写modules/observability/domain/task/service/task_callback.goAutoEvalCallbackAutoEvalCorrection
闭环annotationmodules/observability/domain/trace/entity/loop_span/annotation.goAnnotationType*AutoEvaluateMetadataAnnotationCorrection

至此,CozeLoop 的 evals-observability 全貌已闭环:评测把 target×evaluator 跑遍数据集出分(ch.1-2),可观测把线上链路记成 trace 存查(ch.3),两条桥让线上与离线互相喂养(ch.4)。