news 2026/9/11 20:46:24

Langfuse Evaluators v2 数据模型深度解析:从 eval_templates 到 Evaluator / Rule / Rule Assignment 的架构演进

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Langfuse Evaluators v2 数据模型深度解析:从 eval_templates 到 Evaluator / Rule / Rule Assignment 的架构演进

Langfuse Evaluators v2 数据模型深度解析:从 eval_templates 到 Evaluator / Rule / Rule Assignment 的架构演进

【免费下载链接】langfuse🪢 Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. 🍊YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse

本指南以 web/src/features/evals/v2/CLAUDE.md 为骨架,深入剖析 Langfuse 新一代评测系统(Evaluators v2)的数据模型设计、迁移路径与工程实践。读者将掌握新旧两代数据模型的差异、Evaluator/Rule/Rule Assignment三者间的 n:m 关联结构、评测执行元数据的兼容策略,以及该模块的测试规范与源码组织方式。

为什么需要 Evaluators v2

Langfuse 的评测(Evals)能力早期依赖一套"模板 + 作业配置"的模型。在旧设计中,一个可复用的评测器定义与它的运行规则被拆散在不同表中,导致"评测器"这一核心业务实体缺乏一等公民地位:

  • eval_templates:负责存放评测器的定义(提示词、模型、输出 schema、源码等);
  • job_configurations:负责存放"变量映射(variable mapping)"以及"该评测器要跑在哪些事件上(which events it runs against)"。

这种拆分带来的问题是:模板与运行配置是一对多、却又通过外部引用强耦合的关系,当需要把"一个评测器"同时挂到多条运行规则上、并为每条规则定制变量映射时,关系表达不够自然,也难以在 UI 中形成清晰的"评测器详情"视图。

Evaluators v2 用三个实体重构了这一领域模型(参见 packages/shared/prisma/schema.prisma):

  • Evaluator(评测器):评测能力的定义本体;
  • Rule(规则):旧job_configuration的继承者,负责描述"在什么条件下跑、按什么采样率跑";
  • Rule Assignment(规则关联):处理 Evaluator 与 Rule 之间 n:m 关系的关联表。

新数据模型详解

Evaluator:评测器定义本体

Evaluator模型(schema.prisma)落库为evaluators表,字段包括:

字段说明
name评测器名称
type评测类型,取值见EvalTemplateType枚举:LLM_AS_JUDGE(LLM 作为裁判)或CODE(代码评测)
description可选描述
createdByUserId创建者,删除用户时置空(onDelete: SetNull
blockedAt/blockReason/blockMessage阻断状态:当 LLM 连接鉴权失败、账单耗尽、端点不可达、默认评测模型缺失或模型配置无效时,评测器会被标记为BLOCKED

评测器的"定义内容"本身是可版本化的,存放在evaluator_versions表(EvaluatorVersion,schema.prisma)中。每个版本通过@@unique([evaluatorId, version(sort: Desc)])约束实现单调递增的版本号,并保存:

  • prompt/promptMessages/vars:LLM-as-Judge 的提示词体系;
  • provider/model/modelParams:模型配置;
  • outputDefinition:输出(评分)定义;
  • variableMapping:变量映射(JSON);
  • sourceCode/sourceCodeLanguage:代码评测的源码,sourceCodeVarChar(262144),语言枚举PYTHON/TYPESCRIPT

在服务端,评测器定义通过 discriminated union 进行强校验(web/src/features/evals/v2/server/evaluators/evaluatorTypes.ts):LLM_AS_JUDGE分支要求promptMessagesmodelConfigoutputDefinition,并会从提示词中自动抽取变量(extractVariables)写入varsCODE分支则要求sourceCodesourceCodeLanguage,且不允许携带variableMappingz.never().optional()),因为代码评测的变量映射语义与 LLM 评测不同。

Rule:旧 job_configuration 的继承者

EvaluationRule(schema.prisma)落库为evaluation_rules表,保留了JobConfiguration的核心运行时语义:

字段说明
name规则名称
statusJobConfigState枚举:ACTIVE/INACTIVE
targetObject目标对象类型,v2 中通过过滤器表达,规则的targetObject字段已被标记为 deprecated
filterJSON 形式的条件过滤器,决定"哪些事件会被评估"
samplingDecimal 采样率,取值范围 0..1,控制作业实际执行的比例
delay执行延迟(毫秒)
timeScope时间范围,默认["NEW"]

从类型层看(ruleTypes.ts),RuleMetadataSchemasampling约束为z.number().min(0).max(1)filtersingleFilter数组;CreateRuleSchematargetObject的默认值为EVENT,并明确注释:"modern rules are event rules and experiment scope is expressed through filters"(现代规则即事件规则,实验(experiment)范围通过过滤器表达)。

Rule Assignment:n:m 关联表

EvaluationRuleEvaluatorAssignment(schema.prisma)落库为evaluation_rule_evaluator_assignments表,是 v2 数据模型相对旧版最关键的结构性变化:

  • 同时持有evaluationRuleIdevaluatorId两个外键,均级联删除;
  • @@unique([evaluationRuleId, evaluatorId])保证同一规则下每个评测器只出现一次;
  • 每个关联可以携带独立的variableMapping(JSON),这意味着"同一个评测器挂在多条规则上时,每条规则都能有各自的变量映射";
  • 额外的evaluatorId索引用于支撑"按评测器反查其关联的所有规则"。

这套设计把旧模型中"模板定义 + 作业配置"的一对多耦合,升级为"评测器 ⇄ 规则"的干净多对多关系,也正是文档中"association table handling the n:m relationship"所指的内容。

新旧数据模型对照

维度v1(旧版)v2(新版)
评测器定义EvalTemplate(eval_templates)Evaluator+EvaluatorVersion(evaluators / evaluator_versions)
运行配置JobConfiguration(job_configurations)EvaluationRule(evaluation_rules)
关联方式JobConfiguration 通过evalTemplateId外键指向模板EvaluationRuleEvaluatorAssignment关联表(n:m)
变量映射存放在 JobConfiguration.variableMapping存放在 Assignment.variableMapping,可逐规则定制
版本管理EvalTemplate 以@@unique([projectId, name, version])约束版本EvaluatorVersion 以@@unique([evaluatorId, version])约束版本
执行元数据仅记录job_configuration_id记录evaluator_id+evaluation_rule_id(+ assignment id)

需要说明的是,旧表并未被删除:EvalTemplateJobConfigurationJobExecution仍保留在 schema.prisma 中,用于支撑存量数据与兼容旧执行链路。

评测执行的元数据:job_configuration_id 与 evaluator_id 的兼容

原文档特别强调了一个向后兼容细节:过去捕获的评测执行 trace 只记录了job_configuration_id,只有新的运行才会记录evaluator_idevaluation_rule_id

在源码中,这一元数据约定被集中定义在 packages/shared/src/features/evals/evalExecutionMetadata.ts,完整键集合包括:

EVALUATOR_ID: "evaluator_id", EVALUATOR_VERSION_ID: "evaluator_version_id", EVALUATOR_TEST: "evaluator_test", EVALUATION_RULE_ID: "evaluation_rule_id", EVALUATION_RULE_ASSIGNMENT_ID: "evaluation_rule_assignment_id", JOB_EXECUTION_ID: "job_execution_id", JOB_CONFIGURATION_ID: "job_configuration_id", TARGET_TRACE_ID: "target_trace_id", TARGET_OBSERVATION_ID: "target_observation_id", TARGET_DATASET_ITEM_ID: "target_dataset_item_id",

其中evaluator_test标记该次执行是否为测试运行,evaluator_version_id精确到版本,evaluation_rule_assignment_id精确到关联记录——这些字段共同支撑"这次评分是由哪个评测器、哪个版本、哪条规则、哪个关联产生的"完整追溯链。

为了让新旧执行记录在查询层面统一可检索,事件表为两者都暴露了过滤列:Evaluator IDe.evaluator_id)与Rule IDe.evaluation_rule_id),见 packages/shared/src/eventsTable.ts。而查询层(packages/shared/src/features/query/dataModel.ts)使用coalesce(nullIf(evaluator_id, ''), evaluation_rule_id)将新字段回退到旧字段:当某条记录缺少新的evaluator_id(即旧运行)时,自动用evaluation_rule_id兜底,从而让新旧执行在同一个过滤器下都能被命中。

评测器版本管理与创建/更新流程

v2 将"评测器定义"与"评测器元信息"分层:Evaluator表保存name/type/description等元数据与阻断状态,而EvaluatorVersion表保存每一版定义内容。创建与更新的入参 schema 定义在 evaluatorTypes.ts:

  • CreateEvaluatorSchemaprojectId+ 可选evaluatorId(用于从已存在评测器创建新版本)+definition
  • UpdateEvaluatorSchemaprojectId+evaluatorId+definition,同时支持部分更新(PatchEvaluatorInput)。

版本分页使用 base64url 编码的游标(evaluatorTypes.ts):游标 JSON 形如{ v: 1, version: 42 },解码失败会抛出InvalidRequestErrorEvaluatorVersionsSchema默认limit = 50。定义内容在持久化时会区分数据库 NULL 与 JSON null(Prisma.DbNullvsPrisma.InputJsonValue),参见 evaluatorRepository.ts 的versionData函数。

前端对应的版本体验组件包括 EvaluatorVersionHistorySheet(版本历史抽屉)与 EvaluatorVersionConflictDialog(版本冲突提示);评测器创建/编辑走 EvaluatorSetupEditor 的三步向导:DefinitionStep(定义)→NameStep(命名)→VariableMappingStep(变量映射),每一步都有独立的 Container 组件负责状态管理。

Rule 的生命周期与激活语义

规则模块的 tRPC 路由(web/src/features/evals/v2/server/rules/ruleRouter.ts)覆盖了规则的完整生命周期:

  • list/get/filterOptions/reusableFilters:规则的查询与筛选;
  • create/update/delete/deleteMany:增删改;
  • setEnabled/setManyEnabled:启用/停用(JobConfigState.ACTIVE/INACTIVE);
  • attach/detach:为规则挂载/卸载评测器(写入关联表);
  • createOrAttachFromEvaluatorFilters:从一个评测器的过滤器一键派生规则;
  • recentExecutions/costByRuleIds:最近执行与成本估算;
  • suggestName:根据过滤器与采样率自动生成规则名。

规则激活是 v2 的一个设计亮点。SetRuleEnabledSchema(ruleTypes.ts)允许在确认激活时一并调整采样率,注释说明了原因:激活对话框可以在确认时微调采样,二者落在同一个事务与同一条审计日志中。与之配套的前端是 ActivationConfirmationDialog 及其成本估算视图 ActivationCostEstimateView;激活前的成本预估由服务端 activationCostService.ts 计算,其入参 schema(evaluatorTypes.ts)包含过滤器、采样率、是否扣除已知测试运行成本(knownTestRunCostUsd),并对时间范围做了约束:起始不能早于 6 个月前,结束不能晚于今天。

规则的过滤器还支持"复用":reusableFilters过程返回可复用的过滤器预设;ruleFilterMatching.ts 提供filterStateKey/filtersMatch,通过稳定序列化(数组排序 +stableJsonStringify)实现两个过滤器状态的等价比较,以及fallbackRuleName将过滤器渲染为可读的默认规则名(空过滤器时返回 "All observations",多条件用·连接并截断到 200 字符)。

n:m 关联在前端与批量操作中的体现

关联表的存在直接影响了 UI 与批量操作的设计:

  • 按规则视角:RuleSetup 向导依次引导用户完成RuleNameStep(命名)→RuleFilterStep(过滤器)→RuleEvaluatorsStep(选择评测器并逐一配置变量映射),并通过 RuleEvaluatorCostEstimate 展示成本估算;
  • 按评测器视角:EvaluatorRuleRelationships 展示某个评测器被哪些规则引用,对应服务端listRulesForEvaluator过程;
  • 批量删除限制:仓库中的batchEligibleEvaluatorWhere(evaluatorRepository.ts)明确规定,带有TRACE/DATASET目标对象规则的评测器不能参与观察级批量删除,因为"trace/dataset 关联携带规则特定的映射,仅凭评测器 ID 无法在观察批量中解析"。

这种"一个评测器可挂多条规则、每条规则可挂多个评测器"的能力,正是 n:m 关联表相比旧版外键设计的价值所在。

API 层:权限、审计与测试运行

权限与审计

服务端路由全部基于 tRPC 的protectedProjectProcedure构建(evaluatorRouter.ts),每个过程先调用throwIfNoProjectAccess校验 RBAC scope:评测器使用evaluator:read等 scope,规则使用evaluationRule:read等 scope。审计日志方面,评测器写操作沿用旧的evalTemplate资源类型(evaluatorRouter.ts),而规则写操作使用JOB_CONFIGURATION_AUDIT_LOG_RESOURCE_TYPE(ruleRouter.ts),可以看到审计资源类型上同样保留了新旧迁移的痕迹。

测试运行

test过程(evaluatorRouter.ts)接受observationId/traceId/startTime与一份完整的评测器定义,针对真实样本执行一次评测,无需先落库正式版本。前端对应 EvaluatorTestPanel 与 TestSection,支持选取样本观察(SampleObservationSelectorBase)、过滤样本(ObservationFilterBuilder)、重跑(TestRerunButton)与查看结果 trace(TestResultTraceActions)。测试执行的元数据中EVALUATOR_TEST标记会区分测试运行与正式运行。

列表与筛选

评测器列表支持按name/creator/model进行字符串过滤,按status/type进行选项过滤,并支持分页与排序(name/type/createdAt/updatedAt),schema 校验在 evaluatorTypes.ts;规则列表则支持name/creator/enabled/upgradeRequired过滤,见 ruleTypes.ts。评测器画廊(listGallery)采用基于createdAt + id的游标分页,便于在 EvaluatorGalleryView 中无限滚动浏览模板。

测试规范:避免无意义的 tautological 测试

原文档在 Testing 一节给出了两条明确约束,这也是 v2 模块工程规范的核心:

  1. 不要编写同义反复(tautological)的 React 客户端测试:即测试逻辑只是在重复实现本身,例如断言"点击按钮后 state 变成了按钮 onClick 里写死的值"这类不验证真实行为的用例;
  2. 不要测试像素定位:避免对布局坐标、样式位移这类与业务行为无关的断言;
  3. 只有当组件测试能约束有意义的行为时才添加:测试的价值在于守护真实业务规则,而非凑覆盖率。

从 v2 目录中已有的测试文件可以看到这一规范的落地形态:行为导向的测试如 EvaluatorSavedDialog.clienttest.tsx(校验保存对话框的交互行为)、RuleNameStep.clienttest.tsx、EvaluatorVersionHistorySheet.clienttest.tsx;纯函数逻辑则有配套的单元测试,如 prepareModernRuleVariableMapping.clienttest.ts、buildSampleQueryFilters.clienttest.ts、managedTemplatesCatalog.clienttest.ts。服务端侧则通过 servertest 覆盖事务与成本计算等关键路径,例如 activationCostService.servertest.ts。

小结

Evaluators v2 是 Langfuse 评测体系的一次数据模型重构:用Evaluator(含版本化定义)、Rule(运行条件与采样)和Rule Assignment(n:m 关联,逐关联变量映射)替换旧的EvalTemplate+JobConfiguration组合,同时通过执行元数据双写(evaluator_id/evaluation_rule_id与兼容旧记录的job_configuration_id)和查询层coalesce兜底,保证了新旧执行记录的统一可观测。如果你需要深入某一部分,建议从 web/src/features/evals/v2/server/evaluators/evaluatorTypes.ts 与 web/src/features/evals/v2/server/rules/ruleTypes.ts 两份 schema 定义入手,再对照 packages/shared/prisma/schema.prisma 的物理表结构与 packages/shared/src/features/evals/evalExecutionMetadata.ts 的元数据约定,即可完整还原这套模型的实现全貌。

【免费下载链接】langfuse🪢 Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. 🍊YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 20:43:34

IC烧录:从原理到量产的隐形门槛

芯片从流片到真正跑起来,中间还有一道常被人忽略的关卡,就是IC烧录。很多人觉得烧录不过是把固件写进去,接上编程器点一下“烧写”就完事,但实际上,这颗芯片能不能稳定工作、产线良率高不高、返修率低不低,…

作者头像 李华
网站建设 2026/9/11 20:42:03

依赖库大版本升级:借助大模型批量迁移废弃 API 调用

依赖库大版本升级:借助大模型批量迁移废弃 API 调用在大型软件系统的长期维护中,第三方开源依赖库的大版本升级(如 Go-Redis 从 v8 升至 v9、Spring Boot 2 升至 3、或 Pydantic 从 v1 升至 v2)往往是一项令开发团队极其头疼的苦力…

作者头像 李华
网站建设 2026/9/11 20:41:59

AD7124-8工业ADC实战:从Σ-Δ原理到多通道采集设计要点

做工业采集、变送器和仪器仪表的工程师,十有八九会跟AD7124-8BCPZ这颗片子打交道。24位Σ-Δ架构,8通道输入,内部自带PGA和可编程激励电流源,一颗芯片就能把RTD、热电偶、电桥、压力传感器这些常见的工业信号采集都包圆。我最早接…

作者头像 李华
网站建设 2026/9/11 20:41:18

SpringBoot2+Vue3+MySQL8.0构建企业级在线教育系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华