【智能体开发】《LangChain核心技术与LLM项目实践》_67.[第7章 表达式语言] LangSmith集成实战:追踪调试你的应用

为什么你的LangChain应用总是"薛定谔的能跑"?因为你在用瞎子摸象的方式调试LLM! 本文将手把手教你用LangSmith给LCEL装上"透视眼",从黑盒调试迈向全链路追踪,让每个Prompt、每次Token消耗、每个中间变量都无所遁形。读完这篇文章,你将掌握企业级LLM应用的可观测性实战方案,从此告别"本地能跑线上崩"的尴尬局面。
文章目录:
- 为什么LCEL需要LangSmith:从盲人摸象到透视一切
- 环境配置:避开API Key和项目初始化的那些坑
- 基础追踪:让你的链式调用"可视化"
- Prompt调试:不再做"黑盒程序员"
- 性能监控:LLM应用的"体检报告"
- 回归测试:用数据集守护你的Prompt版本
- 生产环境最佳实践:从玩具到企业级
嗨,大家好呀,我是你的老朋友精通代码大仙。接下来我们一起学习 《LangChain核心技术与LLM项目实践》,震撼你的学习轨迹!
“本地能跑,线上就崩”,这应该是每个程序员深夜改bug时最想砸键盘的瞬间。学LangChain的时候,你是不是也这样:本地跑个问答机器人挺顺畅,一部署到生产环境,用户反馈"答非所问"、“响应慢得像蜗牛”,而你对着满屏的print日志一脸懵逼,根本不知道哪一步出了问题?
更扎心的是,LLM应用跟你以前写的CRUD完全不一样。传统的API调用,输入输出明确,错了就是404或者500。但大模型呢?同样的Prompt,GPT-4和GPT-3.5输出可能天差地别; temperature调高一点,回答就从"严谨教授"变成"胡言乱语患者"。你用LCEL(LangChain Expression Language)写了一长串-processing chain,中间某个Runnable出了问题,你根本不知道是哪一环在"作妖"。
这种无力感,就像你蒙着眼走迷宫,还指望能一口气走到终点。但好在,LangSmith就是给我们准备的"夜视仪"和"GPS"。这节课,咱们不玩虚的,直接上手把LangSmith焊进你的LCEL项目里,让你从此做LLM应用的"透视者"。
1. 为什么LCEL需要LangSmith:从盲人摸象到透视一切
点题:
LangSmith既不是简单的日志库,也不是普通的调试工具。它是LangChain官方推出的全生命周期LLM应用开发平台,核心能力就是可观测性(Observability)。当你的应用用LCEL写成管道式的处理流(Retriever → Prompt → LLM → Parser),LangSmith能把这个管道完全透明化,让你看到每一步的输入输出、Token消耗、延迟耗时,甚至Prompt的精确版本。
用个比喻,LCEL是你的高速公路,车(数据)在上面飞驰,而LangSmith就是沿途的监控摄像头+ETC计费系统+路况显示屏,三合一。
痛点分析:
新手最容易犯的错,就是以为print()大法能搞定LLM调试。比如下面这段典型的"作死"代码:
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
chain = (
RunnableParallel({
"context": retriever,
"question": RunnablePassthrough()
})
| prompt
| ChatOpenAI()
| parser
)
result = chain.invoke("什么是RAG?")
print(f"结果:{result}") # 就打印个最终结果?
痛点一:中间态黑盒。如果最终输出错了,是Retriever搜错了文档,还是Prompt模板填充有问题,或者是LLM理解错了?你完全不知道。
痛点二:性能盲区。用户说"好慢啊",你猜是网络问题还是模型问题?没有数据支撑,优化就是瞎折腾。
痛点三:Prompt版本混乱。你改了Prompt上线,发现效果变差了,想回滚,却发现根本不知道上一版Prompt长啥样。
解决方案/正确做法:
接入LangSmith只需要三步,但这一步能让你后期的调试效率提升十倍:
import os
from langchain_core.callbacks.manager import tracing_v2_enabled
# 1. 配置环境变量(后续详细讲)
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key"
os.environ["LANGCHAIN_PROJECT"] = "rag-debug-project"
# 2. 运行追踪(上下文管理器方式)
with tracing_v2_enabled(project_name="rag-debug-project"):
result = chain.invoke("什么是RAG?")
# 3. 或者直接在链上配置(推荐)
chain_with_tracing = chain.with_config({"run_name": "my_rag_chain"})
这样做的好处是,每一次调用都会在LangSmith的后台生成一个完整的Trace(追踪记录)。你可以像看瀑布流一样,看到:
- Retriever返回了哪些文档(带相似度分数)
- 最终送到LLM的Prompt全文(填充后的真实内容)
- LLM的原始输出(不是解析后的)
- 每一步的执行时间(毫秒级)
小结:
别再当"print调试工程师"了,LLM应用的复杂度远超传统软件。LangSmith不是可选项,而是生产环境的必需品。早接入,早解脱。
2. 环境配置:避开API Key和项目初始化的那些坑
点题:
万事开头难,LangSmith的初始化配置虽然只要几行代码,但新手在这里踩的坑能绕地球三圈。从API Key的获取到项目的隔离,从环境变量的管理到多环境中的切换,这一步做不对,后面全白搭。
痛点分析:
坑一:Key到处飞,安全没保障。我见过太多同学直接把LANGCHAIN_API_KEY硬编码在代码里,然后不小心commit到GitHub,第二天收到邮件:“您的API Key已泄露,已被禁用”。
坑二:项目混用,数据污染。测试环境的调用跑到生产项目的Dashboard里,调试记录和真实用户请求混在一起,分析起来像在大海捞针。
坑三:Tracing开关忘记关。本地开发时开了追踪,跑单元测试时也在往LangSmith发数据,结果免费额度瞬间用完(LangSmith有免费Tier,但有次数限制)。
坑四:代理和网络问题。有些公司网络有代理,直接调用LangSmith API timeout,报错信息还不明显,新手以为是代码问题,折腾半天。
解决方案/正确做法:
正确的环境配置应该像洋葱一样,分层管理:
# config.py - 配置分离,永不硬编码
import os
from dotenv import load_dotenv
load_dotenv()
class Settings:
# LangSmith配置
LANGCHAIN_TRACING_V2 = os.getenv("LANGCHAIN_TRACING_V2", "false").lower() == "true"
LANGCHAIN_API_KEY = os.getenv("LANGCHAIN_API_KEY")
LANGCHAIN_ENDPOINT = os.getenv("LANGCHAIN_ENDPOINT", "https://api.smith.langchain.com")
LANGCHAIN_PROJECT = os.getenv("LANGCHAIN_PROJECT", "default-project")
# 环境区分
ENV = os.getenv("APP_ENV", "development")
settings = Settings()
# 使用示例
if settings.LANGCHAIN_TRACING_V2:
print(f"✅ 已开启LangSmith追踪,项目:{settings.LANGCHAIN_PROJECT}")
else:
print("⚠️ 追踪已关闭,生产环境请开启")
.env文件示例(记得加进.gitignore!):
# 开发环境
APP_ENV=development
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=ls-xxx...
LANGCHAIN_PROJECT=rag-dev-v2
# 生产环境另外配置,或用不同的.env.production
进阶技巧:条件追踪
不要用"全或无"的方式控制追踪,要学会按条件开启:
from langchain_core.runnables import RunnableConfig
def get_chain_with_tracing(chain, user_query: str, enable_trace: bool = True):
"""只在需要时开启追踪,比如只追踪10%的生产流量"""
config = RunnableConfig(
run_name="qa_chain",
tags=["production", "v1.2.0"],
metadata={
"user_id": "user_123",
"feature_flag": "new_prompt"
}
)
if enable_trace and settings.LANGCHAIN_TRACING_V2:
return chain.with_config(config)
return chain
# 采样追踪:每10个请求追踪1个
import random
should_trace = random.random() < 0.1
result = get_chain_with_tracing(chain, query, should_trace).invoke(query)
这样做的好处:
- 安全:Key在环境变量,代码干净
- 隔离:开发/测试/生产完全分开
- 成本控制:采样追踪,既保留观测性,又不烧钱
小结:
配置是地基,地基歪了楼就塌。记住口诀:Key进环境变量,项目要隔离,追踪可采样,代理要配置。
3. 基础追踪:让你的链式调用"可视化"
点题:
现在进入实战核心。我们要让LCEL的每一个Runnable都"发光",让你能在浏览器里像看监控大屏一样观察数据流。LangSmith的Trace由Run组成,每个Run对应一个可执行单元,形成树状结构。
痛点分析:
痛点:链条太长,找不到北。比如一个复杂的RAG应用:
如果最终答案错了,是B重写坏了Query,还是C检索出了无关文档?没有可视化追踪,你得在每个节点加print,代码瞬间变成"打印地狱":
# 错误示范:打印地狱
def rewrite_query(q):
new_q = llm.invoke(f"改写:{q}")
print(f"改写后:{new_q}") # 恶心!
return new_q
def retrieve_docs(q):
docs = vectorstore.similarity_search(q)
print(f"检索到:{len(docs)}篇") # 更恶心!
return docs
代码里充斥着print,既难看又影响性能,最重要的是,生产环境你根本看不到print输出(除非看日志,但日志是文本,不是结构化数据)。
解决方案/正确做法:
使用@traceable装饰器或LCEL原生集成(LangChain 0.1.x后自动集成):
from langsmith import traceable
from langchain_core.runnables import RunnableLambda
# 方式一:装饰器(适合自定义函数)
@traceable(run_type="chain", name="query_rewriter")
def rewrite_query(query: str) -> str:
"""查询重写模块"""
prompt = f"优化以下搜索查询:{query}"
response = llm.invoke(prompt)
return response.content
# 方式二:LCEL原生(推荐)
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
template = """基于以下上下文回答问题:
{context}
问题:{question}
"""
prompt = ChatPromptTemplate.from_template(template)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 自动追踪,无需额外代码
rag_chain = (
{"context": retriever | (lambda docs: "\n\n".join(doc.page_content for doc in docs)),
"question": RunnablePassthrough()}
| prompt
| ChatOpenAI(model="gpt-4")
| StrOutputParser()
)
# 运行后,去LangSmith后台看Trace树
response = rag_chain.invoke("什么是量子计算?")
在LangSmith的Web界面,你会看到:
Run: RunnableSequence (总耗时2.3s)
├── Run: VectorStoreRetriever (800ms)
│ └── 输出:3个Document对象(内容可见)
├── Run: ChatPromptTemplate (5ms)
│ └── 输出:填充后的完整Prompt(可查看)
├── Run: ChatOpenAI (1.4s)
│ ├── 输入:Messages(完整可见)
│ ├── 输出:AIMessage
│ └── Token使用:Input 450 / Output 120
└── Run: StrOutputParser (1ms)
实战技巧:自定义Metadata
给追踪添加标签,方便后续筛选:
config = {
"tags": ["rag", "v2.0", "customer_support"],
"metadata": {
"user_id": "customer_456",
"session_id": "sess_789",
"feature_flag": "hybrid_search"
}
}
result = rag_chain.invoke(query, config=config)
这样你可以在LangSmith里按标签过滤,只看"customer_support"相关的调用,或者对比"v1.0"和"v2.0"的性能差异。
小结:
可视化不是奢侈品,是LLM开发的必需品。关掉print,打开Trace,让数据流动看得见、摸得着。
4. Prompt调试:不再做"黑盒程序员"
点题:
Prompt是LLM应用的"源代码",但很多人管理Prompt就像管理一团乱麻。LangSmith的Prompt Hub和Playground功能,让你能像Git管理代码一样管理Prompt,还能在浏览器里实时调试。
痛点分析:
痛点一:Prompt版本灾难。你在代码里改了Prompt,上线后发现效果变差,想回滚?不好意思,Git里只记录了代码变更,Prompt的具体文本早就随着部署被覆盖了。
痛点二:变量注入错误。LCEL的PromptTemplate经常需要注入变量,比如:
template = "基于{context}回答问题:{question}"
如果context里包含了特殊字符(比如大括号、引号),导致Prompt格式错乱,LLM输出混乱,你很难在生产环境重现当时的具体Prompt长啥样。
痛点三:无法A/B测试。你想试试不同的Prompt写法,但不知道哪个效果更好,只能凭感觉,没有数据支撑。
解决方案/正确做法:
第一步:Prompt版本化管理
把Prompt从代码里抽离,使用LangSmith Prompt Hub:
from langsmith import Client
client = Client()
# 将当前Prompt推送到Hub(版本化管理)
prompt = ChatPromptTemplate.from_template("""你是一个专业的客服助手。
用户问题:{question}
相关文档:{context}
请用友好的语气回答,如果不知道就说不知道。""")
# 保存到Hub,获得一个可以引用的commit hash
prompt_url = client.push_prompt("my-project/customer-service-v1",
object=prompt)
print(f"Prompt已保存:{prompt_url}")
在代码里引用Hub中的Prompt:
from langchain import hub
# 总是拉取最新版本,或用特定版本
prompt = hub.pull("my-project/customer-service-v1:latest")
# 或固定版本,确保可复现
prompt = hub.pull("my-project/customer-service-v1:abc123")
第二步:查看实际渲染后的Prompt
在LangSmith的Trace详情页,点击Prompt节点,你能看到最终送到LLM的完整文本,包括所有变量填充后的样子。如果发现输出了"我不知道"(明明文档里有答案),一看Prompt,发现context变量是空的!瞬间定位问题。
第三步:Playground调试
在LangSmith网页端,你可以拿历史Trace中的输入,直接在Playground里修改Prompt,换不同的模型(比如从GPT-3.5换成Claude),实时查看输出差异,无需修改代码。
# 在Trace中标记某个Run为"需要调试"
from langsmith.run_trees import RunTree
run = RunTree(
name="debug_run",
run_type="chain",
inputs={"question": "如何退款?"}
)
进阶:Prompt对比实验
# 同时测试两个Prompt版本
prompt_v1 = hub.pull("my-project/prompt:v1")
prompt_v2 = hub.pull("my-project/prompt:v2")
chain_v1 = prompt_v1 | llm | parser
chain_v2 = prompt_v2 | llm | parser
# 用同样的测试集跑两边,在LangSmith比较结果
test_queries = ["如何退款?", "怎么开发票?", "客服电话是多少?"]
for q in test_queries:
r1 = chain_v1.invoke(q)
r2 = chain_v2.invoke(q)
# LangSmith会自动记录两次调用的差异
这样做的好处:
- 可复现:每个Prompt版本都有hash,永远能回到过去的状态
- 可调试:看到实际渲染的Prompt,不再猜变量注入结果
- 可优化:Playground里快速迭代,找到最佳Prompt
小结:
Prompt不是字符串,是资产。用管理代码的方式管理Prompt,用调试前端的方式调试Prompt,这才是专业LLM工程师的素养。
5. 性能监控:LLM应用的"体检报告"
点题:
LLM调用是昂贵的,无论是时间成本还是金钱成本。LangSmith提供详细的性能指标:Token使用量、首Token延迟(TTFT)、总耗时、成本估算。这些数据是优化应用的金矿。
痛点分析:
痛点一:成本失控。你接入了GPT-4,用户疯狂使用,月底收到账单吓傻了,但根本不知道哪一步最烧钱。
痛点二:延迟黑洞。用户抱怨"卡顿",你知道是LLM慢,但不知道慢在哪个环节。是检索慢?还是生成慢?还是Prompt太长导致输入处理慢?
痛点三:无法量化优化效果。你把检索从k=10改成k=3,感觉快了点,但不确定;你换了更小的模型,感觉 cost 降了,但用户体验是否变差了?没有数据,优化就是盲人摸象。
解决方案/正确做法:
成本监控实战:
在LangSmith的Dashboard里,你可以看到:
- Total Tokens:总体消耗
- Prompt Tokens vs Completion Tokens:输入输出比例(如果输入远大于输出,说明你在浪费钱传输无关上下文)
- Cost per Run:单次调用成本
代码里获取精确指标:
from langchain.callbacks.manager import tracing_v2_enabled
with tracing_v2_enabled() as cb:
result = chain.invoke("复杂的问题...")
# 运行完成后,LangSmith后台会记录详细指标
# 如果你需要在代码里实时获取(用于动态限流)
from langchain.callbacks import get_callback_manager
callback = get_callback_manager().get_callback("langsmith")
# 注意:实际API可能变化,以最新文档为准
性能优化实战案例:
假设你发现某个Trace总耗时5秒,LangSmith显示:
- Retriever:3.5秒(瓶颈!)
- LLM:1.2秒
- 其他:0.3秒
优化方案:
- 检索优化:把向量数据库从CPU版换成GPU加速版,或加缓存
- Prompt压缩:如果Prompt Tokens太多(比如塞了10篇长文档),用Map-Reduce策略,或者先用小模型做摘要
# 优化前:直接塞全文
def old_retriever(q):
return vectorstore.similarity_search(q, k=10) # 10篇长文,Token爆炸
# 优化后:先摘要再填充
@traceable(name="smart_retriever")
def smart_retriever(q):
docs = vectorstore.similarity_search(q, k=5)
# 用小模型快速摘要,减少Token
summaries = [summarize_chain.invoke(doc.page_content) for doc in docs]
return summaries
设置监控告警(结合LangSmith API):
# 定期检查高成本调用
from langsmith import Client
client = Client()
runs = client.list_runs(
project_name="production",
filter='gt(total_tokens, 4000)', # 找出Token使用超过4k的调用
start_time=datetime.now() - timedelta(days=1)
)
# 分析这些"胖调用",优化Prompt设计
for run in runs:
print(f"高成本调用:{run.name}, Tokens: {run.total_tokens}")
# 发送告警到钉钉/Slack
A/B测试性能:
# 测试两个模型的成本/质量平衡
gpt4_chain = prompt | ChatOpenAI(model="gpt-4") | parser
gpt35_chain = prompt | ChatOpenAI(model="gpt-3.5-turbo") | parser
# 同样的问题,对比两者的Token消耗和延迟
# LangSmith会自动生成对比报告
这样做的好处:
- 省钱:一眼看出哪里在浪费Token,针对性压缩Prompt
- 提速:精确找到性能瓶颈,不是盲目优化
- 可控:设置Token上限,防止用户输入超长文本导致账单爆炸
小结:
不监控成本的LLM应用,就像不开油表开跑车,迟早要抛锚。用数据驱动优化,让每一分钱都花在刀刃上。
6. 回归测试:用数据集守护你的Prompt版本
点题:
LLM应用最大的噩梦就是"负优化"——你改了个Prompt想提升效果,结果把原本好的case搞砸了。LangSmith的Dataset和Evaluation功能,让你能像单元测试一样测试你的Chain,确保每次改动都是正向优化。
痛点分析:
痛点一:** regressions(回归错误)**。你加了个新功能(比如支持多轮对话),结果导致单轮问答质量下降。上线后才发现,用户投诉不断。
痛点二:主观评估。你看了10个例子,觉得新Prompt更好,但样本量太小,上线后发现有20%的case变差了,只是你碰巧没测试到。
痛点三:无法自动化。每次改Prompt都手动测十几个问题,累死人,还容易遗漏。
解决方案/正确做法:
构建测试数据集:
在LangSmith中创建Dataset,包含输入和期望输出(或评估标准):
from langsmith import Client
from langsmith.schemas import Example
client = Client()
# 创建数据集
dataset = client.create_dataset(
dataset_name="qa_test_set",
description="客服场景关键问题测试集"
)
# 添加测试用例(包括边界情况)
examples = [
Example(
inputs={"question": "如何退款?"},
outputs={"answer": "您可以在订单页面点击申请退款..."}, # 期望输出
metadata={"category": "售后", "difficulty": "easy"}
),
Example(
inputs={"question": "你们CEO是谁?"},
outputs={"answer": "我不知道"}, # 期望拒绝回答
metadata={"category": "隐私", "difficulty": "hard"}
),
Example(
inputs={"question": "用Python写个冒泡排序"}, # 边界:无关问题
outputs={"answer": "我只处理客服问题..."},
metadata={"category": "边界", "difficulty": "medium"}
)
]
client.create_examples(
dataset_id=dataset.id,
examples=examples
)
自动化评估:
定义评估函数,自动对比输出与期望:
from langsmith.evaluation import evaluate, LangChainStringEvaluator
# 方式一:用LLM作为评委(LLM-as-a-judge)
qa_evaluator = LangChainStringEvaluator(
"qa",
config={"llm": ChatOpenAI(model="gpt-4", temperature=0)}
)
# 方式二:自定义评估逻辑
def correctness_evaluator(run, example):
"""检查是否包含关键信息点"""
prediction = run.outputs["output"]
expected = example.outputs["answer"]
# 简单包含检查,实际可用更复杂的语义相似度
score = 1.0 if expected in prediction else 0.0
return {
"key": "correctness",
"score": score,
"comment": f"Expected: {expected}, Got: {prediction[:100]}..."
}
# 运行评估实验
results = evaluate(
rag_chain.invoke, # 你的链
data="qa_test_set", # 数据集名称
evaluators=[qa_evaluator, correctness_evaluator],
experiment_prefix="prompt-v2-test" # 实验名称
)
对比实验(A/B Test):
运行两个版本的Prompt,LangSmith会自动对比指标:
实验A (Baseline):
- 平均Correctness: 0.85
- 平均Latency: 2.1s
- 失败Case: 退款流程说明不完整
实验B (New Prompt):
- 平均Correctness: 0.92 (↑)
- 平均Latency: 2.3s (↑ 可接受)
- 失败Case: 隐私问题回答过于详细
基于数据决策:虽然B慢一点,但准确率高,而且隐私问题那个case可以单独修复。
CI/CD集成:
在GitHub Actions里跑评估:
# .github/workflows/eval.yml
name: LLM Eval
on: [pull_request]
jobs:
evaluate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run LangSmith Eval
run: |
python -m pytest tests/test_prompts.py
python scripts/evaluate_chain.py # 调用上面的evaluate代码
env:
LANGCHAIN_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
回归测试实战技巧:
- 黄金数据集:保留20个最难的case,每次改Prompt必须全过
- 对抗测试:专门准备"攻击性"输入(Prompt Injection、超长输入、乱码),确保系统不崩溃
- 影子模式:新Prompt上线前,先在Shadow Mode跑(处理真实请求但不返回给用户),在LangSmith对比新旧版本结果
这样做的好处:
- 防回退:确保新代码不会破坏旧功能
- 可量化:用分数说话,不用"我觉得"
- 自动化:解放双手,专注开发
小结:
没有测试的Prompt修改是赌博。用数据集构建安全网,让每次上线都心里有底。
7. 生产环境最佳实践:从玩具到企业级
点题:
最后,咱们聊聊怎么把LangSmith用到真实的企业环境。包括多租户隔离、隐私合规、成本控制、与现有监控体系的集成。这一步决定了你的LLM应用是"Demo"还是"产品"。
痛点分析:
痛点一:数据隐私。用户输入可能包含手机号、地址等PII(个人身份信息),直接发送到LangSmith云端可能违反GDPR或公司政策。
痛点二:规模问题。每天百万级调用,LangSmith的存储和查询会不会成为瓶颈?费用会不会爆炸?
痛点三:信息孤岛。LangSmith的数据如何与现有的APM(如Datadog、New Relic)打通?团队已经习惯看Grafana大盘了。
解决方案/正确做法:
隐私保护:数据脱敏
import re
from langchain_core.runnables import RunnableLambda
def mask_pii(text: str) -> str:
"""脱敏处理"""
# 手机号
text = re.sub(r'\d{3}-\d{4}-\d{4}', '[PHONE]', text)
# 邮箱
text = re.sub(r'\S+@\S+\.\S+', '[EMAIL]', text)
return text
# 在送进LangSmith前脱敏
sanitized_chain = (
RunnablePassthrough() |
RunnableLambda(lambda x: {**x, "question": mask_pii(x["question"])})
| rag_chain
)
# 或者使用LangSmith的隐藏输入功能(更推荐)
config = {
"metadata": {"sensitive": True},
# 某些版本支持在配置中标记不记录输入
}
分级追踪策略:
不是所有调用都需要详细追踪,分级处理:
def should_trace(query: str, user_tier: str) -> bool:
"""根据策略决定是否追踪"""
# 1. 付费用户全量追踪(服务好金主)
if user_tier == "premium":
return True
# 2. 包含错误关键词的追踪(用于发现bug)
if any(word in query for word in ["error", "bug", "坏了"]):
return True
# 3. 采样:普通用户只追踪5%
return random.random() < 0.05
# 动态开关
if should_trace(query, user.tier):
result = chain.with_config({"run_name": "production"}).invoke(query)
else:
# 不追踪,节省额度
result = chain.invoke(query)
自建追踪后端(可选):
如果对数据隐私极度敏感,LangSmith支持私有化部署(Enterprise版),或者你可以用开源替代方案(如Langfuse、Phoenix)作为后端,但保持LangChain的追踪接口不变。
集成现有监控体系:
把LangSmith数据导出到你的监控平台:
# 定期同步关键指标到Prometheus/Grafana
from prometheus_client import Counter, Histogram
llm_calls = Counter('llm_calls_total', 'Total LLM calls')
llm_latency = Histogram('llm_latency_seconds', 'LLM latency')
# 在Callback中上报
class MyCallbackHandler(BaseCallbackHandler):
def on_llm_end(self, response, **kwargs):
llm_calls.inc()
# 同时LangSmith也记录一份,双保险
错误追踪与告警:
from langsmith.run_trees import RunTree
try:
result = chain.invoke(query)
except Exception as e:
# 记录失败Run
run = RunTree(
name="failed_run",
run_type="chain",
error=str(e),
inputs={"query": query}
)
run.end()
# 发送告警
send_alert(f"Chain failed: {e}")
raise
团队协作规范:
- 命名规范:
project_name用{team}-{env}-{app}格式,如nlp-prod-customer-bot - Tag规范:必须加
version、env、model标签,方便筛选 - Review机制:像Review代码一样Review Trace,特别是失败案例
这样做的好处:
- 合规:满足企业数据安全要求
- 可持续:成本控制,避免追踪费用超过LLM调用费用
- 融合:不打破现有DevOps体系,平滑接入
小结:
生产环境无小事。隐私、成本、监控、协作,四手抓四手都要硬。LangSmith不是银弹,但用对了就是瑞士军刀。
写在最后
编程之路不易,但每一步成长都算数。回想我们刚开始学LangChain的时候,是不是觉得LCEL的管道语法很酷,但一旦出错就抓瞎?今天咱们给这套系统装上了LangSmith这个"透视镜",从配置到追踪,从调试到测试,从开发到生产,构建了一整套LLM应用的可观测性体系。
记住,写LLM应用和写传统软件最大的区别就是不确定性。你无法像控制数据库查询一样精确控制大模型的输出,但你可以控制的是观察它、理解它、测试它的能力。LangSmith给你的就是这种掌控感。
保持好奇,持续学习,你也能成为LLM应用开发的高手。无论你现在是在为Debug而头秃,还是在为优化Prompt而失眠,都是成长的必经之路。利用好工具,相信数据,保持对技术的敬畏和热爱,你写的每一行代码,都会在未来给你回报。
加油,咱们下节课见!
获取更多学习资料请加威信:caogenzhishi 推荐朋友B占UP:个人快速成长/精进学习资料
+微辛备注:“资料代找获取”,全网计算机学习资料代找:例如:
《课程:2026 年多模态大模型实战训练营》
《课程:AI 大模型工程师系统课程 (22 章完整版 持续更新)》
《课程:AI 大模型系统实战课第四期 (2026 年开课 持续更新)》
《课程:2026 年 AGI 大模型系统课 23 期》
《课程:2026 年 AGI 大模型系统课 21 期》
《课程:AI 大模型实战课 8 期 (2026 年 2 月最新完结版)》
《课程:AI 大模型系统实战课三期》
《课程:AI 大模型系统课程 (2026 年 2 月开课 持续更新)》
《课程:AI 大模型全阶课程 (2025 年 12 月开课 2026 年 6 月结课)》
《课程:AI 大模型工程师全阶课程 (2025 年 10 月开课 2026 年 4 月结课)》
《课程:2026 年最新大模型 Agent 开发系统课 (持续更新)》
《课程:LLM 多模态视觉大模型系统课》
《课程:大模型 AI 应用开发企业级项目实战课 (2026 年 1 月开课)》
《课程:大模型智能体线上速成班 V2.0》
《课程:Java+AI 大模型智能应用开发全阶课》
《课程:Python+AI 大模型实战视频教程》
《书籍:软件工程 3.0: 大模型驱动的研发新范式.pdf》
《课程:人工智能大模型系统课 (2026 年 1 月底完结版)》
《课程:AI 大模型零基础到商业实战全栈课第五期》
《课程:Vue3.5+Electron + 大模型跨平台 AI 桌面聊天应用实战 (2025)》
《课程:AI 大模型实战训练营 从入门到实战轻松上手》
《课程:2026 年 AI 大模型 RAG 与 Agent 智能体项目实战开发课》
《课程:大模型训练营配套补充资料》
更多推荐
所有评论(0)