Langfuse 里的分数:Score
Langfuse 把所有评分统一成 Score 对象,挂在 trace 或 observation(span/generation)上:
{
"name": "answer_relevancy",
"value": 0.83, // 数值(默认), 也可以是 enum 或 boolean
"data_type": "NUMERIC", // NUMERIC | CATEGORICAL | BOOLEAN
"comment": "答案相关但遗漏了关键时间信息",
"source": "API" | "ANNOTATION" | "EVAL",
"author": "gpt-4o-judge" | "qa-zhang" | "rule:length-ok",
"trace_id": "trc_abc",
"observation_id": null | "obs_xxx"
}
三种 data_type 适应不同场景:
NUMERIC
0-1 分数、BLEU、延迟 ms。趋势图、均值、分位都能直接画。最常用。
CATEGORICAL
good / mediocre / bad、safe / risky。避免强行把类别塞成数字。UI 按类别分布展示。BOOLEAN
pass / fail 类的检查。用"通过率"曲线看趋势,特别适合 guardrail。
三种评分通道
| 通道 | 谁打分 | 典型指标 | 时机 |
|---|---|---|---|
| ① LLM-as-Judge | 裁判模型 | relevancy / faithfulness / tone | 离线 / 在线采样 |
| ② 代码 evaluator | 脚本 | 长度、关键词、JSON schema、引用率 | 离线 + 在线 100% |
| ③ 人工标注 | QA / 用户 | 真实相关性、品牌感、踩赞 | 离线抽样 + 产品内反馈 |
真实项目一般三种都用。代码 evaluator 兜底便宜,LLM-as-Judge 量产可用,人工标注校准前两者。
① LLM-as-Judge
UI 内配置(最简单)
- Settings → LLM Connections 添加裁判模型(OpenAI/Azure/Anthropic/自建 vLLM 都行)
- Evaluators → New Evaluator 选模板或空白
- 写 prompt,用
{{input}}{{output}}{{expected_output}}做占位 - 定义返回 schema:
score (0-1)+reasoning - 配触发范围:trace 的 tag 匹配某模式 / 某个 dataset / 线上采样率
一个 answer relevancy 的 prompt 范本:
你是一位严格的评估员。给定:
User query:
{{input}}
Model answer:
{{output}}
请从 0 到 1 评分 answer 与 query 的相关程度:
- 1.0 完全相关且回答了问题
- 0.5 相关但遗漏关键信息, 或部分跑题
- 0.0 完全无关或拒答
严格按 JSON 返回:
{"score": 0.0-1.0, "reasoning": "一句话说明理由"}
SDK 打分(自己发)
UI evaluator 是 Worker 侧跑的,方便但有延迟。要在业务流里实时出评分,直接 SDK:
from langfuse import Langfuse import json, openai lf = Langfuse() def judge(trace_id: str, query: str, answer: str): rsp = openai.chat.completions.create( model="gpt-4o-mini", # 裁判模型可以比主模型便宜 response_format={"type": "json_object"}, messages=[ {"role": "system", "content": judge_prompt}, {"role": "user", "content": json.dumps({"query": query, "answer": answer})}, ], ) result = json.loads(rsp.choices[0].message.content) lf.score( trace_id=trace_id, name="answer_relevancy", value=float(result["score"]), comment=result["reasoning"], )
裁判不是越大越好
gpt-4o-mini / claude-haiku / qwen-72b 做裁判通常够用。用 o1 / opus 当裁判会让评估成本反超被评估的生成成本。选择裁判模型的标准是和人工标注的一致性,先拿 100 条人工样本 calibrate,再决定。
gpt-4o-mini / claude-haiku / qwen-72b 做裁判通常够用。用 o1 / opus 当裁判会让评估成本反超被评估的生成成本。选择裁判模型的标准是和人工标注的一致性,先拿 100 条人工样本 calibrate,再决定。
Pairwise 对比(A/B 场景专用)
比较两个版本 A / B 的输出时,直接让 LLM 选"哪个更好"比单独打分稳得多——绝对分数偏差大,但相对排序相对一致:
下面两个回答哪个更好地回应了用户提问?
User: {{query}}
Answer A: {{output_a}}
Answer B: {{output_b}}
返回 JSON: {"winner": "A" | "B" | "tie", "reasoning": "..."}
注意: 评判时不要被回答长度 / 语气 / 格式干扰,只看是否正确、是否切题。
② 代码 evaluator
一大类指标根本不需要 LLM——写两行代码搞定,又快又便宜:
def evaluate_trace(trace, output: str, expected: str): lf.score(trace_id=trace.id, name="length_ok", value=1.0 if 10 <= len(output) <= 500 else 0.0, data_type="BOOLEAN") lf.score(trace_id=trace.id, name="has_citation", value=1.0 if "[1]" in output else 0.0, data_type="BOOLEAN") # JSON schema 合规 try: schema.validate(json.loads(output)) valid = 1.0 except: valid = 0.0 lf.score(trace_id=trace.id, name="json_valid", value=valid, data_type="BOOLEAN") # BLEU / ROUGE / 编辑距离等 if expected: lf.score(trace_id=trace.id, name="rouge_l", value=rouge_l(output, expected))
代码 evaluator 的优势:100% 覆盖(不用采样)、成本接近 0、结果确定。所有"客观可判定"的指标全放这里,LLM-as-Judge 只做"主观+语义"的部分。
③ 人工标注(Annotation Queue)
有两个人工标注场景:
QA 队列
专人定期审 50-200 条 trace,给真实相关性打分。用于 calibrate 裁判模型、补充 dataset expected_output。
最终用户反馈
产品界面的👍/👎按钮,点击直接发 Score 给 Langfuse。量大但噪声也大,适合长期趋势。
配置 Annotation Queue
- UI 进 Annotation Queues → New Queue,起名
qa-daily-review - 定义 score config:比如
overall_quality: CATEGORICAL (good/mediocre/bad)+faithfulness: NUMERIC 0-1 - 配入队规则:每天从符合 tag 的 trace 随机抽 50 条,或挑 LLM-judge score < 0.5 的
- 给 QA 组配权限,他们进 UI 就能看到待标注列表,点 trace → 评分 → 下一条
用户反馈 API
# 前端拿到 trace_id, 用户点👍/👎 时: @app.post("/feedback") def feedback(trace_id: str, thumbs: str, comment: str | None): lf.score( trace_id=trace_id, name="user_feedback", value=1.0 if thumbs == "up" else 0.0, data_type="BOOLEAN", comment=comment, source="ANNOTATION", )
在线 vs 离线:两种运行模式
在线(生产采样)
- Evaluator 配 "Run on production traces, sample 10%"
- 新 trace 进来 Worker 异步打分
- 跟趋势、告警用
- 代码 evaluator 可以 100% 覆盖,LLM evaluator 10-20% 足够
离线(dataset 回归)
- Evaluator 配 "Run on dataset runs"
- CI 跑 dataset run,evaluator 对所有 run 里的 trace 打分
- prompt/模型升级决策用
- 100% 覆盖,没必要采样
成本控制:最容易翻车的点
LLM-as-Judge 如果 100% 打线上流量,评估成本能轻松超过生成成本。几个必备手段:
- 采样:在线只打 5-20% 流量。Evaluator 配置里直接设 sample rate
- 分级触发:先跑代码 evaluator,再对可疑 case 才调 LLM-judge(比如 length < 20 字的可疑短答案才送去判 relevancy)
- 裁判模型降档:gpt-4o-mini / claude-haiku / Qwen-72B 基本够用,特殊 case 再升档
- cache 裁判结果:query + answer 哈希相同的重复 trace,直接复用上次分数
- 按 tag 限域:只对
env:prod且tier:paid的 trace 跑高级评估
给评估模型单独设预算
Langfuse Settings 里 LLM Connection 可以配月度预算上限。超过直接停,不会炸成天文数字。生产上一定要配。
Langfuse Settings 里 LLM Connection 可以配月度预算上限。超过直接停,不会炸成天文数字。生产上一定要配。
把分数转换成告警
Langfuse 支持基于 score 的通知(UI 里 Alerts 面板)。常见的几个:
- 日均 answer_relevancy < 0.75 → 发 Slack 到 @llm-oncall
- 小时内 user_feedback 赞率 < 60% → PagerDuty
- 任一 trace 的 toxicity > 0.9 → 立刻发邮件 + 锁定该 user_id
- dataset regression 均分较上周 -5% → Issue 自动建
本章小结
- 分数统一 Score 对象,三种 data_type (NUMERIC / CATEGORICAL / BOOLEAN)
- 三通道:LLM-as-Judge / 代码 evaluator / 人工标注,都要用
- 裁判模型选型先 calibrate 再用,不是越大越好
- Pairwise 比单独打分更稳,适合 A/B 排序
- 成本手段:采样、分级触发、裁判降档、cache、按 tag 限域
- Annotation Queue 做 QA 审核,产品侧👍/👎 做用户反馈
- 关键分数跌破阈值一定要配告警,不然 dashboard 变"事后尸检"