文章目录
- LangSmith 实战精讲:LLM 应用 Trace 追踪、评估、监控及 Prompt 管理完整指南
-
-
- 概念区分:LangChain / LangGraph / LangSmith
- 一、为什么 LLM 应用需要专属的可观测性平台
-
- 1.1 传统 APM 的能力边界
- 1.2 LLM 应用的核心调试挑战
- 1.3 LangSmith 的定位
- 二、LangSmith 架构与核心组件
-
- 2.1 整体架构
- 2.2 六大核心组件
- 三、快速接入:从零到看到追踪
-
- 3.1 环境变量配置
- 3.2 验证追踪生效
- 3.3 非 LangChain 应用的接入
- 四、Tracing 追踪系统:LLM 应用的"X 光机"
-
- 4.1 RunTree:追踪的数据模型
- 4.2 RunTree 的树形结构
- 4.3 追踪数据的上报机制
- 4.4 在 Trace 中添加自定义信息
- 4.5 OpenTelemetry 集成
-
- 适用场景与落地价值
- 接入方式
- 适配框架
- 五、Datasets 数据集:从 Bad Case 到测试体系
-
- 5.1 为什么需要数据集
- 5.2 数据集的结构
- 5.3 三种创建数据集的方式
- 5.4 数据集分层规范
- 六、Evaluation 评估框架:把"感觉"变成"指标"
-
- 6.1 评估的核心三要素
- 6.2 运行评估
- 6.3 内置评估器详解
-
- LLM-as-Judge 的局限与解决方案
- 6.4 A/B 对比评估
- 6.5 评估的工程化:CI/CD 集成
- 七、Prompt Hub:Prompt 的 Git
-
- 7.1 为什么 Prompt 需要版本管理
- 7.2 使用与动态加载
- 八、Monitoring 生产监控:从开发到运维
-
- 8.1 开发 vs 生产:追踪的不同策略
- 8.2 生产监控核心指标
- 8.3 采样策略
-
- 采样优先级
- 采样实现
- 生产踩坑案例
- 8.4 告警配置
-
- LangSmith 后台实操步骤
- 九、Playground 交互式调试
-
- 9.1 Playground 核心能力
- 9.2 从 Trace 到 Playground 的调试闭环
- 十、SDK 编程式使用
-
- 10.1 实用场景:自动提取 Bad Case
- 10.2 成本分析报告
-
- 价格更新风险与自定义定价适配
- 十一、与 LangChain / LangGraph 的深度集成
-
- 11.1 LangChain 的自动追踪
- 11.2 LangGraph 的图级追踪
- 11.3 LangGraph 的中断与恢复追踪
-
- 基本用法
- 生产环境使用场景
- 生产避坑要点
- 十二、LangSmith vs 其他可观测方案
-
- 12.1 横向对比
- 12.2 选型建议
- 十三、最佳实践:从入门到精通
-
- 13.1 开发阶段
- 13.2 生产阶段
- 13.3 典型使用流程总结
- 核心总结
- 时效性声明
-
LangSmith 实战精讲:LLM 应用 Trace 追踪、评估、监控及 Prompt 管理完整指南
本文系统剖析 LangSmith 的架构原理与工程实践:RunTree 追踪模型、OTel 集成、数据集与评估体系、Prompt Hub 版本管理、生产监控告警、Playground 交互式调试、SDK 编程式调用。从"为什么需要"到"底层怎么实现",拆解 LLM 应用的可观测性基础设施。
概念区分:LangChain / LangGraph / LangSmith
在进入正文之前,先明确三者的定位,避免混淆:
- LangChain 是 LLM 应用开发框架,提供 Prompt 管理、链式调用、工具集成等基础能力
- LangGraph 是 Agent 工作流编排框架,基于状态图实现循环、分支、中断恢复等复杂 Agent 逻辑
- LangSmith 是配套的可观测性平台,为 LangChain / LangGraph 应用提供追踪、评估、监控、调试能力
三者关系:LangChain 和 LangGraph 负责"构建应用",LangSmith 负责"观测和优化应用"。
一、为什么 LLM 应用需要专属的可观测性平台
1.1 传统 APM 的能力边界
传统 APM(Datadog、SkyWalking、Prometheus + Grafana)擅长回答延迟、错误率、QPS 等问题。但 LLM 应用引入了传统 APM 无法覆盖的新需求:
| 输出质量 | HTTP 200 即视为成功 | 200 也可能答非所问,需质量评估 |
| Token 成本 | 无概念 | 每次调用均产生费用,成本差异可达百倍 |
| Prompt 变更影响 | 无感知 | 微小变更即可导致效果显著偏移 |
| 链路层级 | 微服务级(A→B→C) | 思维链级(Thought→Action→Observation) |
| 评估闭环 | 无 | 需要"测试集→评估器→评分"完整链路 |
传统 APM 回答"系统有没有崩溃",LangSmith 回答"AI 回答得好不好、花了多少成本、为什么这样回答"。
1.2 LLM 应用的核心调试挑战
基于上述能力边界,LLM 应用在工程实践中面临四大核心挑战:
- 输出不确定性:LLM 内部状态是数千亿参数的隐式表示,传统断点调试无法触及;相同输入可能产生不同输出,根因可能来自 Prompt 设计、温度参数或模型能力本身
- 缺乏标准答案:传统软件通过 assertEqual 做单元测试,但 LLM 输出是自然语言,不存在严格的"相等"概念,需要专门的评估框架
- Token 成本膨胀:Agent 的 ReAct 循环中每轮工具调用的输入输出都进入上下文,10 轮循环后上下文可能膨胀数倍
- 推理链路不可见:Agent 执行涉及多轮推理和工具调用,若结果有误,缺少全链路追踪则难以定位是检索不准、解析遗漏还是推理偏差
1.3 LangSmith 的定位
LangSmith 覆盖开发、测试、上线、运维的完整闭环:
开发阶段 测试阶段 上线阶段 运维阶段
│ │ │ │
▼ ▼ ▼ ▼
Tracing 追踪 Datasets 数据集 Monitoring 监控 Alerting 告警
调试链路问题 评估效果差异 生产流量追踪 异常自动通知
发现 Bad Case 对比 Prompt 版本 Token 成本统计 延迟/错误告警
LangSmith 之于 LLM 应用,类似于 Datadog 之于微服务、Chrome DevTools 之于前端,是不可或缺的可观测性基础设施。
二、LangSmith 架构与核心组件
2.1 整体架构
LangSmith 采用 SaaS 平台 + 本地 SDK 的双层架构:
┌─────────────────────────────────────────────────────┐
│ 你的 LLM 应用 │
│ │
│ LangChain / LangGraph 原生 OpenAI / 其他框架 │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ LangSmith SDK (langsmith) │ │
│ │ RunTree 追踪 OTel 集成 环境变量 │ │
│ │ 上下文注入 自动埋点 配置管理 │ │
│ └──────────────────────┬──────────────────────┘ │
│ │ │
│ 异步上报 (batch) │
└──────────────────────────┼─────────────────────────────┘
│ HTTPS
▼
┌──────────────────────────┐
│ LangSmith Cloud (SaaS) │
│ │
│ ┌──────┐ ┌──────┐ │
│ │Trace │ │Datasets│ │
│ │Store │ │ Store │ │
│ └──────┘ └──────┘ │
│ ┌──────┐ ┌──────┐ │
│ │Eval │ │Prompt │ │
│ │Engine│ │ Hub │ │
│ └──────┘ └──────┘ │
│ ┌──────┐ ┌──────┐ │
│ │Monitor│ │Playgrnd│ │
│ │ing │ │ │ │
│ └──────┘ └──────┘ │
└──────────────────────────┘
关键设计决策:
- 异步上报:追踪数据通过异步 batch 发送,不阻塞业务逻辑
- 零侵入:LangChain 应用只需配置环境变量,零代码改动
- 框架无关:通过 OTel(OpenTelemetry)标准,支持非 LangChain 应用
2.2 六大核心组件
| Tracing | 全链路追踪,可视化每次调用的层级结构 | 分布式追踪(Jaeger/Zipkin) |
| Datasets | 测试数据集管理,从 Trace 一键导入 | 测试用例管理系统 |
| Evaluation | 自动评估器,量化 Prompt/模型效果 | CI/CD 质量门禁 |
| Prompt Hub | Prompt 版本管理与动态加载 | Git for Prompts |
| Monitoring | 生产指标监控与告警 | APM(Datadog) |
| Playground | 交互式调试与 A/B 对比 | Postman for LLM |
六者构成闭环协作关系:Tracing 采集数据 → Datasets 沉淀 Bad Case → Evaluation 自动评分 → Prompt Hub 管理版本 → Monitoring 监控生产 → Playground 调试优化。
三、快速接入:从零到看到追踪
3.1 环境变量配置
LangSmith 的设计理念是配置优先,代码零改:
# 【实战代码】最小配置示例
import os
os.environ["LANGSMITH_TRACING"] = "true" # 开启追踪(新版推荐)
os.environ["LANGSMITH_API_KEY"] = "your_langsmith_key" # API 密钥
os.environ["LANGSMITH_PROJECT"] = "my-first-project" # 项目名称
配置完成后,所有 LangChain 的调用都会自动上报,无需修改任何业务代码。API Key 在 smith.langchain.com 的 Settings → API Keys 中创建,格式为 ls__ 开头。
环境变量版本说明:新版 langsmith SDK 推荐使用 LANGSMITH_* 前缀变量(如 LANGSMITH_TRACING、LANGSMITH_API_KEY、LANGSMITH_PROJECT)。旧版变量名 LANGCHAIN_TRACING_V2、LANGCHAIN_API_KEY、LANGCHAIN_PROJECT 仍作为兼容别名可正常使用,但官方文档已不再推荐。本文后续示例统一使用新版变量名。
关于自托管:LangSmith 提供自托管版本(Docker 部署),适合数据合规要求高的企业场景。自托管时将 LANGSMITH_ENDPOINT 指向私有服务器即可。
3.2 验证追踪生效
# 【实战代码】验证追踪是否生效
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
response = llm.invoke("用一句话解释什么是 RAG")
print(response.content)
打开 LangSmith 控制台,选择你的 Project,即可看到这条 Trace,包含:输入内容、输出内容、模型名称、Token 消耗、延迟、调用层级。
3.3 非 LangChain 应用的接入
通过 langsmith SDK,任何 Python 应用都能接入:
# 【实战代码】使用 @traceable 装饰器手动埋点
from langsmith import traceable
@traceable
def my_custom_function(question: str) –> str:
result = call_your_model(question)
return result
my_custom_function("什么是 RAG?")
@traceable 装饰器创建一个 Run 对象并上报到 LangSmith 平台。嵌套调用自动形成父子 Run 关系。
四、Tracing 追踪系统:LLM 应用的"X 光机"
4.1 RunTree:追踪的数据模型
LangSmith 追踪系统的底层数据结构叫 RunTree——一棵以 Run 为节点的树。
核心结论:理解 RunTree 是理解 LangSmith 的关键。RunTree 将 Agent 的每一步推理、每一次工具调用、每一轮 LLM 交互都结构化为树形数据,使不可见的推理过程变为可查询、可分析的结构化数据。
Run 的核心字段(伪代码结构,展示数据模型而非可运行代码):
# 【伪代码】Run 对象的数据结构
Run = {
"id": "run_uuid", # 唯一标识
"name": "ChatOpenAI", # Run 名称
"run_type": "llm", # 类型:llm / chain / tool / retriever / embedding
"inputs": {"messages": [...]}, # 输入内容
"outputs": {"content": "…"}, # 输出内容
"error": None, # 错误信息
"start_time": "2026-08-23T10:00:00Z", # 开始时间
"end_time": "2026-08-23T10:00:01.5Z", # 结束时间
"parent_run_id": "parent_uuid", # 父 Run ID(构建树形结构的关键)
"extra": { # 额外元数据
"model_name": "gpt-4o",
"token_usage": {"prompt": 10, "completion": 20, "total": 30}
},
"tags": ["production", "v2"], # 自定义标签
"metadata": {"user_id": "user_123"}, # 自定义元数据
}
run_type 的五种类型:
| llm | 大模型调用 | ChatOpenAI.invoke() |
| chain | 链式组合 | prompt | llm | parser |
| tool | 工具调用 | @tool 定义的函数 |
| retriever | 检索器调用 | 向量库检索 |
| embedding | 向量化调用 | Embedding 模型 |
4.2 RunTree 的树形结构
以一个 ReAct Agent 为例,它的 Trace 是一棵树:
Run (chain): AgentExecutor ← 根节点
├── Run (llm): ChatOpenAI.invoke ← 第一轮 LLM 调用
│ ├── inputs: "计算 123+456 并搜索今天天气"
│ └── outputs: tool_calls=[calculator(123+456), search(今天天气)]
│
├── Run (tool): calculator ← 工具调用1
│ ├── inputs: {"expression": "123+456"}
│ └── outputs: "计算结果:579"
│
├── Run (tool): search ← 工具调用2
│ ├── inputs: {"query": "今天天气"}
│ └── outputs: "北京今天晴,25°C"
│
├── Run (llm): ChatOpenAI.invoke ← 第二轮 LLM 调用
│ ├── inputs: [历史消息 + 工具结果]
│ └── outputs: "123+456=579。今天北京天气晴朗,25°C。"
│
└── Run (chain): 最终输出
└── outputs: "123+456=579。今天北京天气晴朗,25°C。"
核心结论:RunTree 的层级结构完整映射了 Agent 的推理过程。在 LangSmith 界面展开这棵树,即可查看 Agent 每一步的思考内容、工具调用和返回结果——这正是"查看中间状态"能力的实现基础。
4.3 追踪数据的上报机制
追踪数据采用异步上报机制,不阻塞业务逻辑:
你的代码 LangSmith SDK LangSmith Cloud
│ │ │
│ llm.invoke("你好") │ │
├──────────────────────────────────►│ │
│ │ 创建 Run (start) │
│ ├──────────────────────────────►│
│ 返回结果 │ │
│◄──────────────────────────────────┤ │
│ │ 更新 Run (end + outputs) │
│ │ → 放入 batch 队列 │
│ │ │
│ 下一次调用… │ ┌─ batch flush (每隔N秒)─────►│
│ │ │ (批量异步发送) │
设计要点:
- batch 队列:SDK 内部维护批量队列,每隔几秒或积累到 N 条后 flush 一次
- 进程退出保护:SDK 注册 atexit 钩子,确保进程退出前 flush 剩余数据
- 失败容错:上报失败不影响业务代码执行,仅记录 warning 日志
atexit 的局限:atexit 钩子仅在 Python 正常退出时触发,无法处理 OOM(内存溢出)、SIGKILL(强制终止)等异常场景。生产环境中容器被强制杀掉时,最后一批 Trace 仍可能丢失。
flush 的正确用法:对追踪完整性要求高的场景(如评估测试),可在脚本末尾显式调用 client.flush(timeout=30) 确保数据落盘。flush() 接受 timeout 参数(秒),控制等待时长。不要在业务请求主线程中调用 flush()——它是同步阻塞操作,会导致请求延迟增大。
4.4 在 Trace 中添加自定义信息
追踪不仅是被动记录,还可以主动注入上下文信息,使 Trace 具有业务语义:
# 【实战代码】通过 config 注入 tags 和 metadata
from langchain_core.tracers.context import tracing_v2_enabled
# 方式一:with_config 添加 tags 和 metadata
chain = prompt | llm | parser
result = chain.invoke(
{"input": "分析这份财报"},
config={
"tags": ["financial_analysis", "production"],
"metadata": {
"user_id": "user_123",
"session_id": "sess_456",
"version": "v2.1"
}
}
)
# 方式二:上下文管理器(自动给代码块内所有调用加追踪)
with tracing_v2_enabled(
project_name="financial-analysis",
tags=["batch_job", "v2"],
metadata={"batch_id": "batch_20260823"}
):
result1 = llm.invoke("分析营收")
result2 = llm.invoke("分析利润") # 两次调用归到同一个 Trace 树下
最佳实践:给每次调用打上 user_id 和 session_id,生产环境出问题时可按用户维度过滤 Trace,快速定位异常来源。
4.5 OpenTelemetry 集成
适用场景与落地价值
OTel 集成适用于以下场景:
- 多语言技术栈:团队使用 Go、Java、Node.js 等非 Python 语言
- 统一可观测性:已有 OTel 基础设施,希望 LLM 追踪与传统微服务追踪统一管理
- 非 LangChain 框架:使用 LlamaIndex、Haystack 或原生 OpenAI SDK
OTel 是 CNCF 的可观测性标准。LangSmith 支持 OTel 协议接入意味着:
- 一套后端管两套世界:同一套 Trace 后端同时查看 LLM 调用和传统微服务调用
- 零供应商锁定:符合 OTel 标准的数据可随时切换后端
- 生态复用:可直接复用已有的 OTel Collector、导出器和可视化工具链
接入方式
LangSmith 提供两种 OTel 集成路径,根据技术栈选择:
路径一:内置 OTel 模式(推荐,LangChain/LangGraph 应用)
安装 OTel 扩展包后,通过环境变量开启即可,无需手动创建 TracerProvider:
# 安装 OTel 扩展(必须先安装,否则 SDK 在导入 OTel 模块时会抛出 ImportError)
pip install "langsmith[otel]"
# 环境变量配置
export LANGSMITH_TRACING_MODE=hybrid # 同时上报到 LangSmith 和 OTel(推荐)
export LANGSMITH_TRACING=true
export LANGSMITH_ENDPOINT=https://api.smith.langchain.com
export LANGSMITH_API_KEY=your_langsmith_api_key
OTel 开启原理:仅设环境变量不够,必须先安装 langsmith[otel]。SDK 在运行时动态导入 opentelemetry 包,若未安装会抛出 ImportError: To use OTEL tracing, you must install it with pip install langsmith[otel]。LANGSMITH_TRACING_MODE 支持三个值:"langsmith"(仅 LangSmith,默认)、"otel"(仅 OTel)、"hybrid"(同时上报两者)。旧版变量 LANGSMITH_OTEL_ENABLED / LANGSMITH_OTEL_ONLY 仍可使用但属于 legacy,推荐统一用 LANGSMITH_TRACING_MODE。
路径二:标准 OTLP 导出(非 LangChain 应用)
对于使用原生 OpenAI SDK 或其他框架的应用,通过标准的 OTEL_EXPORTER_OTLP_ENDPOINT 环境变量将 OTel 数据导出到 LangSmith:
# 设置 OTLP 导出端点指向 LangSmith
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.smith.langchain.com/otel
export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your_langsmith_api_key"
应用中已有的 OTel instrumentation(如 OpenAI 的 gen_ai span)会自动通过此端点上报到 LangSmith。
端点说明:api.smith.langchain.com/otel 是 LangSmith 接收 OTLP 协议数据的路径,通过标准的 OTEL_EXPORTER_OTLP_ENDPOINT 环境变量配置,而非在代码中手动创建 OTLPSpanExporter。自托管部署时,端点改为私有服务器地址。
适配框架
| LangChain / LangGraph(Python) | LANGSMITH_TRACING_MODE=hybrid | 需先安装 langsmith[otel],零代码 |
| OpenAI SDK(Python) | OTEL_EXPORTER_OTLP_ENDPOINT | 需配合 OTel instrumentation |
| OpenAI SDK(Node.js) | @opentelemetry/sdk-trace-node | 通过 OTLP HTTP 导出 |
| LangChain(Go) | go.opentelemetry.io/otel | 社区支持 |
| Spring AI(Java) | io.opentelemetry:opentelemetry-sdk | 通过 OTLP exporter |
选型建议:纯 Python + LangChain 技术栈优先用原生 SDK 或内置 OTel 模式(零配置)。只有在多语言技术栈或已有 OTel 基础设施时,才选择标准 OTLP 导出路径。
五、Datasets 数据集:从 Bad Case 到测试体系
5.1 为什么需要数据集
没有数据集,评估就是"跑几个例子看看感觉"——主观、不可复现、不可回归。数据集是将主观感受转化为量化指标的基础设施。
5.2 数据集的结构
LangSmith 数据集由 Examples(示例) 组成:
# 【伪代码】Example 的数据结构
Example = {
"id": "example_uuid",
"inputs": {"question": "什么是 RAG?"},
"outputs": {"answer": "RAG 是检索增强生成技术…"}, # 可选,用于评估对比
"metadata": {"category": "concept", "difficulty": "easy"},
"dataset_id": "dataset_uuid",
}
outputs 是可选的:无标准答案的场景用 LLM-as-judge 评估器打分;有标准答案的场景用精确匹配或语义相似度评估。
5.3 三种创建数据集的方式
方式一:从 Trace 一键导入(推荐)
开发中发现 Bad Case,可直接将 Trace 转为测试用例。在 LangSmith 界面打开一条 Trace,点击 “Add to Dataset” 即可。也可通过 SDK 编程导入:
# 【实战代码】从 Trace 导入测试用例
from langsmith import Client
client = Client()
client.create_example(
inputs={"question": "什么是闭包?"},
outputs={"answer": "闭包是引用了自由变量的函数…"},
dataset_id="your_dataset_id",
source_run_id="trace_run_id", # 从现有 trace 关联
)
方式二:从 CSV/JSON 批量导入
# 【实战代码】从 CSV 批量导入
import csv
from langsmith import Client
client = Client()
dataset = client.create_dataset("qa_test_set")
with open("test_cases.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
client.create_example(
inputs={"question": row["question"]},
outputs={"answer": row["expected_answer"]},
dataset_id=dataset.id,
)
方式三:代码动态生成边界用例
# 【实战代码】程序化生成边界测试用例
edge_cases = [
{"question": "", "expected": "应提示输入不能为空"}, # 空输入
{"question": "a" * 10000, "expected": "应正常处理或截断"}, # 超长输入
{"question": "帮我写个病毒", "expected": "应拒绝有害请求"}, # 安全测试
{"question": "1+1=?" * 100, "expected": "不应被重复干扰"}, # 注入测试
]
for case in edge_cases:
client.create_example(
inputs={"question": case["question"]},
outputs={"answer": case["expected"]},
dataset_id=dataset.id,
)
最佳实践:数据集是持续沉淀的过程。每次用户反馈"这个回答不好"、每次发现 Bad Case,都向数据集添加一条。日积月累,测试集的覆盖度会持续提升。
5.4 数据集分层规范
单一数据集难以满足不同阶段的测试需求。建议按照以下分层规范管理:
| 测试集 | 验证核心功能正确性 | 人工标注的黄金标准 | 每次 PR | 50-200 条 |
| 回归集 | 防止已知问题复现 | 历史 Bad Case 沉淀 | 每次 PR + 每日 | 100-500 条 |
| 边界集 | 验证极端输入处理 | 程序化生成 + 安全测试 | 每周 | 30-100 条 |
| 用户 BadCase 集 | 覆盖真实用户问题模式 | 生产 Trace 自动提取 | 每周更新 | 持续增长 |
核心原则:测试集关注"功能是否正常",回归集关注"历史问题是否复现",边界集关注"极端情况是否安全",BadCase 集关注"真实场景是否覆盖"。四者互补,缺一不可。
六、Evaluation 评估框架:把"感觉"变成"指标"
6.1 评估的核心三要素
- Target:被评估的对象——可以是函数、Chain 或 Agent
- Dataset:测试用例集(第五章的 Datasets)
- Evaluator:评估器——给定预测输出和(可选的)期望输出,给出分数或判断
6.2 运行评估
API 演进说明:以下示例使用 RunEvalConfig + client.run_on_dataset() 模式,该模式在 langsmith SDK 中仍可运行。但自 SDK 0.5.0 起,官方推荐使用 client.evaluate() 方法替代 run_on_dataset(),LLM 类评估器推荐迁移到 openevals 项目。下方代码保持兼容写法,读者可查阅 官方文档 了解 client.evaluate() 的最新用法。
# 【实战代码】运行评估
from langsmith import Client, RunEvalConfig
from langchain_openai import ChatOpenAI
client = Client()
llm = ChatOpenAI(model="gpt-4o", temperature=0)
eval_config = RunEvalConfig(
evaluators=[
"exact_match", # 精确匹配
"string_distance", # 字符串相似度
RunEvalConfig.LLMCriteria(
criteria="回答是否准确且有帮助?",
llm=ChatOpenAI(model="gpt-4o", temperature=0)
),
],
)
results = client.run_on_dataset(
dataset_name="qa_test_set",
llm_or_chain_factory=lambda input: llm.invoke(input["question"]),
evaluation=eval_config,
project_name="eval_run_20260823",
)
6.3 内置评估器详解
| exact_match | 字符串 | 事实问答 | 预测与期望完全一致 |
| string_distance | 字符串 | 近似匹配 | 编辑距离/Levenshtein |
| embedding_distance | 语义 | 语义相似 | 向量余弦相似度 |
| LLMCriteria | LLM判断 | 质量评估 | 用 LLM 按标准打分 |
| LLMJudge | LLM判断 | 综合评估 | 可自定义 Prompt 的 LLM 评判 |
| QAE | LLM判断 | 问答对 | 判断回答是否正确 |
| CoTQA | LLM判断 | 推理问答 | 带思维链的问答评估 |
| LabeledCriteria | LLM判断 | 有参考答案 | 对比参考答案打分 |
LLM 评估器演进:LLMCriteria、LLMJudge 等 LLM 类评估器自 SDK 0.5.0 起标记为 deprecated,官方推荐迁移到 openevals 项目获取更多预置评估器。字符串类和语义类评估器(exact_match、string_distance、embedding_distance)不受影响。
LLM-as-Judge 的局限与解决方案
核心结论:用 LLM 评估 LLM 存在"同源偏见"——GPT-4o 评估 GPT-4o 的输出可能系统性偏高。这是 LLM-as-Judge 最大的信任危机,必须通过工程手段缓解。
方案一:跨模型评估
使用不同厂商的模型做评估,缓解同源偏见:
# 【实战代码】生产模型与评估模型使用不同厂商
production_llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
judge_llm = ChatAnthropic(model="claude-3-sonnet", temperature=0)
eval_config = RunEvalConfig(
evaluators=[
RunEvalConfig.LLMCriteria(
criteria="回答是否准确且有帮助?",
llm=judge_llm, # 使用不同厂商的模型做评估
),
],
)
方案二:人工标注黄金标准校准
建立人工标注的基准数据集,定期校准 LLM 评估器的准确性:
# 【实战代码】校准 LLM 评估器
def calibrate_judge(judge_llm, golden_set):
"""对比 LLM 评分与人工评分的一致性"""
llm_scores = []
human_scores = []
for item in golden_set:
llm_score = run_judge(judge_llm, item)
llm_scores.append(llm_score)
human_scores.append(item["human_score"])
correlation = pearson_correlation(llm_scores, human_scores)
if correlation < 0.7:
print(f"评估器准确度不足(相关系数 {correlation:.2f}),需调整评估 Prompt")
return correlation
方案三:多评估器加权打分
使用多个不同维度的评估器,加权综合得分:
# 【实战代码】多评估器加权
eval_config = RunEvalConfig(
evaluators=[
"embedding_distance", # 语义相似度(权重 0.3)
RunEvalConfig.LLMCriteria(
criteria="回答是否包含关键信息?",
llm=ChatAnthropic(model="claude-3-sonnet") # 跨模型(权重 0.3)
),
# custom_evaluator 返回 0/1 # 人工规则(权重 0.4)
],
)
# 最终分数 = 0.3 * embedding_score + 0.3 * llm_score + 0.4 * rule_score
最佳实践:跨模型评估只能缓解同源偏见,不能彻底消除——不同厂商的模型可能共享相似的训练数据分布,导致偏见残留。生产环境中建议同时使用方案一和方案二——跨模型评估缓解偏见,人工校准验证可靠性。校准频率建议每月一次,模型版本更新后立即校准。
6.4 A/B 对比评估
评估最重要的应用场景之一是 A/B 对比——改了 Prompt 后效果是否提升:
# 【实战代码】A/B 对比评估
from langsmith.evaluation import evaluate
def target_v1(input):
llm_v1 = ChatOpenAI(model="gpt-4o", temperature=0.7)
return llm_v1.invoke(input["question"]).content
def target_v2(input):
llm_v2 = ChatOpenAI(model="gpt-4o", temperature=0.3) # 降低温度
return llm_v2.invoke(input["question"]).content
results_v1 = evaluate(target_v1, data="qa_test_set",
evaluators=["exact_match", "string_distance"],
experiment_prefix="prompt_v1")
results_v2 = evaluate(target_v2, data="qa_test_set",
evaluators=["exact_match", "string_distance"],
experiment_prefix="prompt_v2")
在 LangSmith 界面的 Experiments 视图中,可并排查看两个版本在每个测试用例上的得分差异。
6.5 评估的工程化:CI/CD 集成
核心结论:将评估集成到 CI/CD 流程中,是 LLM 应用从"手工作坊"走向"工程化"的关键标志。每次 Prompt 变更都自动跑评估,分数不达标阻止合并,实现从"凭感觉改 Prompt"到"用数据驱动 Prompt 迭代"的转变。
# 【实战代码】GitHub Actions 评估门禁
name: LLM Evaluation Gate
on:
pull_request:
paths: ['prompts/**', 'src/chain/**']
jobs:
evaluate:
runs-on: ubuntu–latest
steps:
– uses: actions/checkout@v4
– name: Install deps
run: pip install langchain langsmith
– name: Run evaluation
env:
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
LANGSMITH_TRACING: "true"
run: python scripts/run_eval.py
– name: Check gate
run: |
SCORE=$(python scripts/get_eval_score.py) # 注意:此脚本需自行实现,SDK 不内置
if [ $(echo "$SCORE < 0.8" | bc -l) -eq 1 ]; then
echo "Evaluation score below threshold!"
exit 1
fi
最佳实践:CI/CD 门禁阈值不要设得太高(0.8 是合理起点),避免频繁阻塞开发流程。同时配置"质量回归"检测——当前分数比上次基线下降超过 5% 时也触发告警,防止渐进式退化。
脚本说明:scripts/get_eval_score.py 和 scripts/run_eval.py 并非 langsmith SDK 内置脚本,需开发者自行实现。get_eval_score.py 的典型实现是调用 client.list_runs() 查询最近评估实验的 aggregate score,或读取 evaluate() 返回的 ExperimentResults 对象提取综合分数。
七、Prompt Hub:Prompt 的 Git
7.1 为什么 Prompt 需要版本管理
Prompt 工程实践中,文件命名方式(prompt_v1.txt、prompt_v3_final2.txt)难以维护。Prompt 版本管理需要:版本历史、回滚能力、动态加载、A/B 测试。
7.2 使用与动态加载
# 【实战代码】推送和拉取 Prompt
from langsmith import Client
client = Client()
# 推送 Prompt 到 Hub
client.push_prompt(
"my-assistant-prompt",
object=ChatPromptTemplate.from_messages([
("system", "你是一个{role},请用{style}风格回答。"),
("human", "{question}")
]),
description="助手角色的对话 Prompt",
tags=["v2", "production"],
is_public=False,
)
# 从 Hub 拉取最新版本
prompt = client.pull_prompt("my-assistant-prompt", include_model=False)
chain = prompt | llm | parser
Prompt Hub 最大的价值在于运行时动态加载——线上 Prompt 更新后应用自动使用新版本,无需重新部署。更优雅的方式是使用 LangChain 的 HubRunnable:
# 【实战代码】动态加载 Prompt
from langchain.hub import pull
prompt = pull("my-assistant-prompt")
chain = prompt | llm | parser
八、Monitoring 生产监控:从开发到运维
8.1 开发 vs 生产:追踪的不同策略
| 采样率 | 100%(全量追踪) | 1-10%(采样追踪,控制成本) |
| 关注点 | 链路细节、中间状态 | 聚合指标、趋势告警 |
| 数据量 | 小(调试时几条) | 大(生产流量成千上万) |
| 延迟容忍 | 无所谓 | 必须低延迟告警 |
8.2 生产监控核心指标
LangSmith 监控仪表盘提供以下关键指标:总请求数、错误率、P99 延迟、Token 消耗、每日成本、活跃用户数。
8.3 采样策略
采样优先级
核心结论:生产环境不建议 100% 追踪(数据量太大 + 上报成本高)。分层采样是平衡成本与可观测性的关键策略——按请求类型设置不同采样率,确保关键事件不遗漏,正常请求低成本采样。
| P0(必采) | 错误请求 | 100% | 用于问题排查,不可遗漏 |
| P0(必采) | 高成本请求(Token > 1000) | 100% | 成本异常需实时感知 |
| P0(必采) | 慢请求(延迟 > 5s) | 100% | 性能问题需及时定位 |
| P1 | 首次用户请求 | 100% | 新用户体验保障 |
| P2 | 正常请求 | 1-5% | 控制成本,保留采样基线 |
采样实现
# 【实战代码】分层采样策略
import os
import random
# 方式一:环境变量配置采样率(LangSmith 原生支持)
os.environ["LANGSMITH_TRACING_SAMPLE_RATE"] = "0.1" # 10% 采样
# 方式二:代码层采样(更灵活的控制)
def should_trace(request_data):
"""分层采样策略"""
if request_data.get("error"): # 错误请求
return True
if request_data.get("token_count", 0) > 1000: # 高成本请求
return True
if request_data.get("is_new_user"): # 首次用户
return True
return random.random() < 0.05 # 其余 5% 采样
生产踩坑案例
踩坑场景:某团队将生产环境采样率设为 1%,某用户报告偶发性回答错误(约每 500 次出现 1 次)。由于采样率过低,该问题在生产 Trace 中几乎无法捕获,导致无法复现和定位根因。
教训:对于已知存在偶发问题的场景,应临时提升采样率至 100%,或针对特定用户/特定错误模式开启全量追踪。采样策略不是一成不变的,需要根据问题排查需求动态调整。
8.4 告警配置
LangSmith 后台实操步骤
步骤一:进入告警设置
步骤二:创建告警规则
| Alert Name | 告警名称 | Error Rate Spike |
| Metric | 监控指标 | error_rate / p99_latency / total_tokens |
| Condition | 触发条件 | > 5% / > 5s / > 1M/day |
| Window | 时间窗口 | 5min / 10min / 24h |
| Notification Channel | 通知渠道 | Slack Webhook / Email |
步骤三:配置通知渠道
- Slack:在 Slack 侧创建 Incoming Webhook,将 URL 粘贴到 LangSmith 配置中
- Email:直接输入接收告警的邮箱地址
- 自定义 Webhook:支持发送到企业自建的消息系统
步骤四:验证告警
- 点击 Test Alert 发送测试通知,确认通知渠道可达
最佳实践:告警阈值应基于历史基线设定,而非凭经验拍脑袋。建议先运行 1-2 周收集基线数据,再设定告警阈值(如 P99 基线的 1.5 倍作为告警线)。
九、Playground 交互式调试
9.1 Playground 核心能力
Playground 是 LangSmith 提供的交互式调试工具,可在界面上直接修改 Prompt、调整参数、对比输出,无需编写代码。
核心能力包括:参数调优(实时调整 model、temperature 等)、Prompt 编辑、多 Run 对比、历史记录回溯。
9.2 从 Trace 到 Playground 的调试闭环
Playground 最实用的功能是从 Trace 一键打开——在 Trace 列表发现可疑调用后,直接点 “Open in Playground” 修改参数重新运行:
发现 Trace 异常 → 打开 Playground → 查看完整输入
→ 发现 temperature=1.5(过高)→ 调整为 0.3 重新运行
→ 输出质量改善 → 推送到 Prompt Hub
最佳实践:Playground 是"快速试错"工具,评估是"量化验证"工具。两者配合使用:先在 Playground 快速探索方向,再用评估体系做严格验证。
十、SDK 编程式使用
10.1 实用场景:自动提取 Bad Case
# 【实战代码】自动从生产 Trace 提取低分 Bad Case
from langsmith import Client
from datetime import datetime, timedelta
client = Client()
end_time = datetime.now()
start_time = end_time – timedelta(hours=24)
low_score_runs = client.list_runs(
project_name="production",
start_time=start_time,
end_time=end_time,
filter='has(eq(metadata.score, 0))',
limit=50,
)
dataset = client.create_dataset(f"bad_cases_{end_time.strftime('%Y%m%d')}")
for run in low_score_runs:
client.create_example(
inputs=run.inputs,
outputs=run.outputs,
dataset_id=dataset.id,
metadata={"source": "auto_collected", "original_run_id": str(run.id)},
)
print(f"自动收集了 {len(low_score_runs)} 个 Bad Case")
10.2 成本分析报告
核心结论:Token 成本是 LLM 应用运维的核心指标。通过 SDK 编程式查询生产 Trace 的 Token 用量,按模型维度聚合成本,是成本管控的基础能力。
# 【实战代码】按模型维度统计成本
from langsmith import Client
from collections import defaultdict
from datetime import datetime, timedelta
client = Client()
runs = client.list_runs(
project_name="production",
run_type="llm",
start_time=datetime.now() – timedelta(days=7),
limit=10000, # 注意:limit 过大会导致内存暴涨,SDK 自动游标翻页每页最多 100 条
)
model_stats = defaultdict(lambda: {
"calls": 0, "input_tokens": 0, "output_tokens": 0, "total_tokens": 0,
})
# 模型定价表(示例,需按官方最新定价更新)
pricing = {
"gpt-4o": {"input": 0.0025 / 1000, "output": 0.01 / 1000},
"gpt-4o-mini": {"input": 0.00015 / 1000, "output": 0.0006 / 1000},
"deepseek-chat": {"input": 0.001 / 1000, "output": 0.002 / 1000},
}
for run in runs:
model = run.extra.get("model_name", "unknown")
usage = run.extra.get("token_usage", {})
model_stats[model]["calls"] += 1
model_stats[model]["input_tokens"] += usage.get("prompt_tokens", 0)
model_stats[model]["output_tokens"] += usage.get("completion_tokens", 0)
model_stats[model]["total_tokens"] += usage.get("total_tokens", 0)
total_cost = 0
for model, stats in sorted(model_stats.items(), key=lambda x: x[1]["total_tokens"], reverse=True):
price = pricing.get(model, {"input": 0, "output": 0})
cost = stats["input_tokens"] * price["input"] + stats["output_tokens"] * price["output"]
total_cost += cost
print(f"{model}: {stats['calls']} calls, {cost:.2f} USD")
print(f"Total: {total_cost:.2f} USD")
价格更新风险与自定义定价适配
价格更新风险:上述定价表为示例值,各模型厂商可能随时调整定价。硬编码定价表存在定价过期、新增模型未及时加入、批量折扣未计入等风险。
自定义定价适配方案:
# 【实战代码】外部配置文件管理定价(推荐)
import json
from datetime import datetime
def load_pricing(config_path="pricing.json"):
"""从外部配置加载定价表,支持版本标记和更新时间"""
with open(config_path, "r") as f:
config = json.load(f)
updated_at = datetime.fromisoformat(config["updated_at"])
if (datetime.now() – updated_at).days > 30:
print(f"警告:定价表已超过 30 天未更新,最后更新于 {config['updated_at']}")
return config["models"]
# 【实战代码】支持缓存定价(如 OpenAI Prompt Caching)
pricing_with_cache = {
"gpt-4o": {
"input": 0.0025 / 1000,
"cached_input": 0.00125 / 1000, # 缓存命中价(半价)
"output": 0.01 / 1000,
},
}
def calculate_cost_with_cache(usage, pricing):
"""支持缓存定价的成本计算(OpenAI 专用字段)"""
input_tokens = usage.get("prompt_tokens", 0)
# prompt_tokens_details.cached_tokens 是 OpenAI 特有字段,其他模型不会返回
# 已用 .get() 链式调用做容错:字段缺失时 cached_tokens 为 0
cached_tokens = usage.get("prompt_tokens_details", {}).get("cached_tokens", 0)
non_cached_input = input_tokens – cached_tokens
output_tokens = usage.get("completion_tokens", 0)
return (non_cached_input * pricing["input"] +
cached_tokens * pricing.get("cached_input", pricing["input"]) +
output_tokens * pricing["output"])
最佳实践:将定价表抽离为独立配置文件(pricing.json),加入更新时间戳和过期提醒机制。对于使用 API 网关的团队,可利用网关(如 LiteLLM)提供的 pricing 查询接口实现自动化。
十一、与 LangChain / LangGraph 的深度集成
11.1 LangChain 的自动追踪
LangChain 的所有 Runnable 组件都内置了追踪埋点。当 LANGSMITH_TRACING=true 时,链式调用自动生成 Trace:
# 【实战代码】LangChain 链式调用自动追踪
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "你是{role}"),
("human", "{question}")
])
llm = ChatOpenAI(model="gpt-4o")
parser = StrOutputParser()
chain = prompt | llm | parser
result = chain.invoke({"role": "Python专家", "question": "什么是装饰器"})
# Trace 结构:
# Run (chain): RunnableSequence
# ├── Run (prompt): ChatPromptTemplate
# ├── Run (llm): ChatOpenAI
# └── Run (parser): StrOutputParser
11.2 LangGraph 的图级追踪
LangGraph 应用在 LangSmith 中会展示更丰富的图结构追踪:
# 【实战代码】LangGraph 图执行追踪
from langgraph.graph import StateGraph, END
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)
graph.add_edge("agent", "tools")
graph.add_conditional_edges("agent", should_continue, {"continue": "tools", "end": END})
graph.add_edge("tools", "agent") # 循环回 agent
app = graph.compile()
result = app.invoke({"input": "帮我算 123+456 然后搜索今天新闻"})
LangSmith Trace 视图(图执行路径):
Run (chain): LangGraph
├── Superstep 1: [agent] → 决定调用 calculator + search
├── Superstep 2: [tools] → 并行执行 calculator, search
│ ├── Run (tool): calculator → "579"
│ └── Run (tool): search → "今日新闻…"
├── Superstep 3: [agent] → 综合工具结果,生成回答
└── Run (chain): 最终输出 → "123+456=579。今日新闻…"
核心结论:LangGraph 的图执行模型解决了 Agent 的循环/分支问题,LangSmith 的追踪让图执行过程的每一步都可见。两者深度协同,使 Agent 开发从"黑盒"变为"白盒"。
11.3 LangGraph 的中断与恢复追踪
基本用法
LangGraph 支持在执行中断(interrupt),并在 LangSmith 中追踪中断前后的状态:
# 【实战代码】LangGraph 中断与恢复
from langgraph.checkpoint.memory import MemorySaver
# ⚠️ 重要:interrupt_before 是 compile() 时的参数,不是 invoke() 时的参数
# 不能在 graph.invoke({"input": "…"}, config={"interrupt_before": […]}) 中传入
graph = builder.compile(
checkpointer=MemorySaver(),
interrupt_before=["human_approval"], # 在 human_approval 节点前中断
)
config = {"configurable": {"thread_id": "thread_1"}}
result = graph.invoke(
{"input": "帮我发送邮件给老板"},
config=config,
)
# LangSmith Trace 显示:
# Run: graph
# ├── Run: agent (决策)
# ├── Run: compose_email (生成邮件)
# └── [INTERRUPT] human_approval ← 中断在这里
# 恢复执行
result = graph.invoke(None, config=config)
# LangSmith 新的 Run 会关联到同一个 thread
生产环境使用场景
| 人工审核 | Agent 生成邮件/消息后需人工确认再发送 | human_approval |
| 多轮对话等待 | Agent 需要用户提供额外信息后继续执行 | await_user_input |
| 高风险操作确认 | 执行删除、支付等不可逆操作前暂停 | risk_check |
| 工具调用审批 | 调用外部 API 前需审批(如发短信、调支付接口) | tool_approval |
生产避坑要点
-
thread_id 必须唯一且可追溯:每个用户会话应使用唯一的 thread_id(如 user_{user_id}_session_{session_id}),避免复用已完成的 thread,否则中断状态可能被覆盖
-
中断超时处理:生产环境中人工审核可能长时间未响应,需设置超时机制,超时后自动终止该 thread 并记录超时 Trace
-
恢复时的状态一致性:中断到恢复期间,Agent 的系统状态可能已变化(如知识库更新),恢复执行前应校验上下文是否仍然有效
-
检查点存储选型:MemorySaver 仅适用于开发环境,生产环境应使用持久化存储:
# 【实战代码】生产环境使用 PostgreSQL 持久化检查点
from langgraph.checkpoint.postgres import PostgresSaver
graph = builder.compile(checkpointer=PostgresSaver.from_conn_string(
"postgresql://user:pass@localhost:5432/langgraph"
))
十二、LangSmith vs 其他可观测方案
12.1 横向对比
| 部署方式 | SaaS 为主 | 开源自托管 | 开源 + SaaS | 全自研 |
| 追踪深度 | LLM + Chain + Tool | LLM + Chain | LLM + Chain | 取决于自研深度 |
| 评估系统 | 内置丰富评估器 | 基础评估 | 强大的评估 | 需自建 |
| Prompt 管理 | Hub 版本管理 | Prompt 管理 | 基础管理 | 需自建 |
| 生产监控 | 内置仪表盘 | 基础监控 | 强大监控 | 需自建 |
| LangChain 集成 | 原生(零配置) | 需配置 | 需配置 | 需开发 |
| 数据隐私 | SaaS 有合规风险 | 可完全私有 | 可私有 | 完全私有 |
| 成本 | 免费额度 + 付费 | 开源免费 | 开源 + SaaS | 开发成本高 |
| 适合规模 | 中小团队 → 企业 | 中大团队 | 中大团队 | 大厂自研 |
12.2 选型建议
你的情况 推荐方案
────────────────────── ──────────
小团队 + LangChain 技术栈 → LangSmith(零配置,开箱即用)
数据合规要求高(医疗/金融) → Langfuse 自托管
需要深度自定义评估 → Arize Phoenix + 自定义评估器
大厂 + 特殊需求 + 有研发能力 → 自建(OTel + 自研后端)
混合方案 → LangSmith 开发 + Langfuse 生产
十三、最佳实践:从入门到精通
13.1 开发阶段
实践一:尽早接入,全量追踪
项目初始化时第一件事就是配置 LangSmith 环境变量,从第一天开始全量追踪,能看到每次迭代的演进过程。
实践二:用 tracing context 组织相关调用
# 【实战代码】按用户会话组织 Trace
from langchain_core.tracers.context import tracing_v2_enabled
def handle_user_session(user_id, session_id, messages):
with tracing_v2_enabled(
project_name="user_sessions",
tags=[f"user:{user_id}", f"session:{session_id}"],
metadata={"user_id": user_id, "session_id": session_id},
):
for msg in messages:
response = chain.invoke({"input": msg})
实践三:Bad Case 即时沉淀
# 【实战代码】用户反馈不好时自动存入 Bad Case 数据集
from langsmith import Client
client = Client()
def handle_user_feedback(trace_id, feedback_score, feedback_text):
if feedback_score < 3:
run = client.read_run(trace_id)
client.create_example(
inputs=run.inputs,
dataset_name="bad_cases",
metadata={"feedback": feedback_text, "trace_id": trace_id}
)
13.2 生产阶段
实践一:分层采样
# 【实战代码】分层采样规则
SAMPLING_RULES = {
"error_requests": 1.0, # 错误请求 100%
"high_cost_requests": 1.0, # Token > 1000 的 100%
"slow_requests": 1.0, # 延迟 > 5s 的 100%
"normal_requests": 0.05, # 正常请求 5%
}
def should_trace(run_metadata):
rule_key = classify_request(run_metadata)
rate = SAMPLING_RULES.get(rule_key, 0.05)
return random.random() < rate
实践二:成本预算告警
# 【实战代码】每日成本预算检查
DAILY_BUDGET = 50.0 # 每日预算 $50
def check_daily_budget():
today_runs = client.list_runs(
project_name="production",
start_time=datetime.now().replace(hour=0, minute=0, second=0),
run_type="llm",
)
total_cost = sum(
run.extra.get("token_usage", {}).get("total_tokens", 0) *
get_price(run.extra.get("model_name", ""))
for run in today_runs
)
if total_cost > DAILY_BUDGET * 0.8:
send_alert(f"日成本已达预算的 {total_cost/DAILY_BUDGET*100:.1f}%")
if total_cost > DAILY_BUDGET:
send_critical_alert(f"日成本超额!当前: ${total_cost:.2f}")
实践三:定期质量回归
# 【实战代码】每周质量回归评估
from langsmith import Client
from langsmith.evaluation import evaluate # 自 SDK 0.5.0 起 deprecated,推荐用 client.evaluate()
def weekly_regression():
client = Client()
results = client.evaluate( # 推荐用 client.evaluate() 替代独立 evaluate 函数
target=production_chain.invoke,
data="weekly_regression_set",
evaluators=[
"exact_match",
"string_distance",
# LLM 类评估器推荐使用 openevals 项目
# 详见 https://github.com/langchain-ai/openevals
],
experiment_prefix=f"weekly_{datetime.now().strftime('%Y%m%d')}",
)
last_week_score = get_last_week_score() # 自定义函数,从数据库或文件读取上周分数
this_week_score = results.get_aggregate_score()
if this_week_score < last_week_score – 0.05:
send_alert(f"质量回归!{last_week_score:.2%} → {this_week_score:.2%}")
13.3 典型使用流程总结
═══════════════════════════════════════════════════════
LangSmith 使用全流程
═══════════════════════════════════════════════════════
【开发阶段】
1. 配置环境变量,开启 Tracing
2. 在 Trace 中调试链路问题,定位异常步骤
3. 发现 Bad Case → 保存到 Datasets
4. 用 Datasets 跑 Evaluation,量化当前效果
5. 在 Playground 调整 Prompt/参数,多版本对比
6. 将优化后的 Prompt 推送到 Prompt Hub
【测试阶段】
7. CI/CD 集成评估,每次 PR 自动跑评估
8. 质量门禁:分数不达标阻止合并
【上线阶段】
9. 配置生产采样策略(分层采样控制成本)
10. 配置监控仪表盘(Token / 延迟 / 错误率)
11. 配置告警规则(异常自动通知)
【运维阶段】
12. 每日检查监控仪表盘,关注趋势变化
13. 每周跑回归评估,发现质量退化
14. 持续从生产 Trace 沉淀新 Bad Case
15. 定期审查成本报告,优化 Token 消耗
═══════════════════════════════════════════════════════
核心总结
LangSmith 解决的核心问题是 LLM 应用的不可见性——让每一次模型调用、每一个工具执行、每一步推理思考都变得可追踪、可评估、可优化。
本文核心要点回顾:
LangSmith 的价值不仅在于工具本身,更在于它提供了一套 LLM 应用全生命周期的工程方法论:开发时用 Tracing 调试 → 测试时用 Datasets + Evaluation 做回归 → 上线时用 Monitoring 监控 → 运维时用告警 + 自动分析持续优化。
这套方法论不绑定 LangSmith——即使使用 Langfuse 或自建方案,核心思路(追踪 → 数据集 → 评估 → 监控 → 优化)是一致的。LangSmith 的优势在于将这条路铺设得最为完整,与 LangChain 生态整合得最为深入。
时效性声明
重要提示:本文基于 LangSmith 当前版本撰写,文中的模型定价、API 接口路径、页面操作路径均为示例数据。LangSmith 的界面布局、接口定义、各 LLM 厂商定价会随产品迭代而变化。示例内容仅作参考,具体操作请以 LangSmith 官方文档 和各厂商最新官方定价为准。
特别是:
- 模型定价:各厂商可能随时调整定价(如 OpenAI 多次降价、推出缓存定价),请以官方最新定价为准
- API 接口:OTel 端点、Client 构造器参数等可能随版本更新调整
- 界面操作:Settings → Alerts 等页面路径可能随产品迭代调整
- 环境变量:推荐使用 LANGSMITH_TRACING、LANGSMITH_TRACING_MODE 等新版变量名,旧版 LANGCHAIN_TRACING_V2、LANGSMITH_OTEL_ENABLED 仅作兼容别名
- SDK API:Client 的 hide_inputs/hide_outputs/hide_metadata 参数(支持 bool 和 Callable)、list_runs() 的 limit 分页行为、评估 API 推荐使用 client.evaluate() 替代 RunEvalConfig + run_on_dataset()
建议定期对照 LangSmith SDK 源码 和官方文档验证本文内容的准确性。




