三大平台定位对比
| 平台 | 定位 | 强项 | 弱项 |
|---|---|---|---|
| Braintrust | 商业化评估平台,SaaS | UI 对比最清晰;trace/eval 一体化;实验版本管理优秀 | 收费,国内访问慢 |
| LangSmith | LangChain 同门,偏可观测 | Trace 观测强;与 LangChain 生态无缝 | Evaluation 相对轻;绑定 LC 生态较深 |
| Promptfoo | 开源 CLI,本地优先 | 完全本地;YAML 配置;CI 最友好;免费 | UI 相对朴素;scale 到大团队需自建 |
选型决策树
你要什么?
│
┌────────────┼────────────┐
▼ ▼ ▼
开源本地 团队协作 已用 LangChain
│ │ │
▼ ▼ ▼
Promptfoo Braintrust LangSmith
│
预算有限?
│
Promptfoo + 自建看板
实用建议
小团队/个人:Promptfoo 起步,CI 集成,本地可控。
中大团队:Braintrust 做协作,对比/回归/分享有完整 workflow。
LangChain 重度用户:LangSmith,省掉对接成本。
三者可共存:Promptfoo 跑 CI 冒烟 + Braintrust 做主评估库。
中大团队:Braintrust 做协作,对比/回归/分享有完整 workflow。
LangChain 重度用户:LangSmith,省掉对接成本。
三者可共存:Promptfoo 跑 CI 冒烟 + Braintrust 做主评估库。
Promptfoo 实战
最小例子
# promptfooconfig.yaml description: "客服意图分类评估" prompts: - "你是一个客服意图分类器,把下面的用户输入归类为:query/complaint/refund/other。只返回标签。\n\n用户: {{input}}" providers: - openai:gpt-4o-mini - openai:gpt-4o tests: - vars: { input: "我的订单怎么还没到?" } assert: - type: equals value: "query" - vars: { input: "这质量也太差了吧!" } assert: - type: equals value: "complaint" - vars: { input: "我想退货" } assert: - type: equals value: "refund" - vars: { input: "能给我推荐点好吃的吗" } assert: - type: equals value: "other" # 运行: npx promptfoo eval # 可视化: npx promptfoo view
断言类型(assertions)
assert: - type: equals # 精确匹配 value: "positive" - type: contains # 包含子串 value: "发票" - type: regex # 正则 value: "^\\{.*\\}$" - type: is-json # JSON 合法 - type: contains-json # 包含合法 JSON - type: similar # 语义相似 value: "退款流程说明" threshold: 0.8 - type: llm-rubric # LLM 裁判 value: "回答是否专业且简洁" - type: latency # 延迟 threshold: 2000 - type: cost # 成本 threshold: 0.01 - type: javascript # 自定义 JS value: "output.length < 500 && !output.includes('竞品')"
CI 集成
# .github/workflows/evals.yml name: Evals on: [pull_request] jobs: eval: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: "20" } - run: npx promptfoo eval --no-progress-bar --max-concurrency 4 env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - run: npx promptfoo share # 生成可分享链接
Braintrust 实战
核心概念
Dataset
评估集。在 UI 或 API 里管理 input/expected 字段,支持版本和 tag。
Experiment
一次跑 eval 的结果。每次跑生成新的 experiment,与历史对比 diff。
Scorer
打分函数。内置 ExactMatch、Levenshtein、Factuality、Moderation,也支持自定义。
Project
组织维度。一个应用一个 project,内含多个 dataset/experiment/log。
SDK 例子
from braintrust import Eval, init_dataset from autoevals import Factuality, LevenshteinScorer # 评估集可以本地,也可以从 Braintrust 拉 dataset = init_dataset(project="customer-support", name="prod-samples-v3") def my_agent(input: str) -> str: # 你的 LLM 应用 rsp = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": input}], ) return rsp.choices[0].message.content Eval( "customer-support", data=dataset, task=my_agent, scores=[Factuality(), LevenshteinScorer()], experiment_name="gpt4o-mini-v7-tone-tweak", metadata={"model": "gpt-4o-mini", "prompt_version": "v7"}, )
运行完,Braintrust UI 会显示:
- 每条样本的 input / output / expected / 分数
- 本次实验 vs 上次实验的差异(hover diff,哪些变好、哪些退步)
- 按 metadata 筛选(如只看 prompt_version=v7)
- 按 tag 分层看分
自定义 Scorer
from autoevals import Score def has_citation(output, expected=None): score = 1.0 if "[source:" in output else 0.0 return Score( name="HasCitation", score=score, metadata={"output_length": len(output)}, )
LangSmith 实战
起点:观测再评估
LangSmith 最强的是 trace 观测。接入即送全链路记录:
import os os.environ["LANGSMITH_TRACING"] = "true" os.environ["LANGSMITH_API_KEY"] = "ls_..." os.environ["LANGSMITH_PROJECT"] = "customer-support" from langsmith import traceable @traceable(run_type="chain") def my_agent(q): # 每次调用自动记录到 LangSmith return llm_call(q)
从 trace 构建评估集
LangSmith 的独特工作流:先观测生产流量,挑代表性/问题 case 一键加入 dataset,然后跑评估。
from langsmith import Client from langsmith.evaluation import evaluate client = Client() def my_agent(inputs): return {"output": llm_call(inputs["question"])} def correctness_evaluator(run, example): pred = run.outputs["output"] ref = example.outputs["answer"] score = llm_judge(pred, ref) return {"key": "correctness", "score": score} evaluate( my_agent, data="customer-support-v3", # 数据集名 evaluators=[correctness_evaluator], experiment_prefix="sonnet-4-6-v2", max_concurrency=8, )
三个平台的 diff 视图对比
对比"同一条 case 在 v6 vs v7 的输出"是日常最高频操作:
Braintrust
- 列表模式:左右两列横向 diff,直接看哪些红哪些绿
- 关注"regressions"视图:只看退步 case
- 带 metadata 筛选(按 model、prompt_version)
LangSmith / Promptfoo
- LangSmith:实验对比页,按 score 差值排序
- Promptfoo:表格模式,多 provider 并列同一行
- Promptfoo CLI 可直接生成 HTML 报告
多平台混用模式
# 典型架构
Dev 本地: Promptfoo (快速迭代 prompt)
CI (每 PR): Promptfoo (快跑 50 条冒烟)
主评估 (每晚): Braintrust (全量 1000 条,带 Judge)
生产 trace: LangSmith (持续观测)
本地自建方案
如果因为合规/成本/网络不能用 SaaS,最小本地栈:
# 用 SQLite + Streamlit 搭一个最小评估看板 import sqlite3, json from datetime import datetime conn = sqlite3.connect("evals.db") conn.execute(""" CREATE TABLE IF NOT EXISTS runs ( id INTEGER PRIMARY KEY, ts TEXT, experiment TEXT, case_id TEXT, input TEXT, output TEXT, expected TEXT, scores TEXT, -- JSON metadata TEXT -- JSON )""") def log_run(exp, case_id, inp, out, expected, scores, meta): conn.execute( "INSERT INTO runs (ts, experiment, case_id, input, output, expected, scores, metadata) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (datetime.utcnow().isoformat(), exp, case_id, inp, out, expected, json.dumps(scores), json.dumps(meta)), ) conn.commit()
搭配 Streamlit 做看板,200 行能做出"能用的 mini Braintrust"。
选型的 5 个判断题
- 合规:数据能不能出境?能 → 三个都行;不能 → Promptfoo 本地 + 自建
- 团队规模:个人/2-3 人 → Promptfoo;5+ → Braintrust
- 是否用 LangChain:深度使用 → LangSmith;否则 → Braintrust
- 是否需要和 trace 深度集成:需要 → LangSmith / Braintrust;只做离线 eval → Promptfoo
- 预算:可花 → 选付费;零预算 → Promptfoo + LangSmith 免费额度
本章小结
- Promptfoo:开源 CLI + YAML,CI 友好,个人/小团队起步
- Braintrust:商业 SaaS,UI 对比最强,中大团队协作
- LangSmith:observability 优先,LangChain 生态原生
- 三者常共存:本地 Promptfoo 冒烟 + 主库 Braintrust + 生产 trace LangSmith
- 合规/数据出境限制 → 本地自建方案可用 SQLite + Streamlit,200 行起步