课程0基础Agent开发课 / LangChain / LangSmith-LLM应用的全链路可观测性
— 14 min read

LangSmith-LLM应用的全链路可观测性

一个 RAG 链给出了错误的回答,原因可能有十种:检索到的文档不相关、Prompt 指令被误解、模型在某个步骤幻觉、格式化出错……用 print 语句排查,要在代码里插入几十个断点,重跑十几次才能定位。这是 LLM 应用开发的特有痛点:传统的 logging 对文本输入输出有效,对"模型在哪一步开始偏离"无能为力。

LangSmith:LLM 应用的全链路可观测性

一个 RAG 链给出了错误的回答,原因可能有十种:检索到的文档不相关、Prompt 指令被误解、模型在某个步骤幻觉、格式化出错……用 print 语句排查,要在代码里插入几十个断点,重跑十几次才能定位。这是 LLM 应用开发的特有痛点:传统的 logging 对文本输入输出有效,对"模型在哪一步开始偏离"无能为力。

LangSmith 是 LangChain 官方推出的追踪和评估平台,专门解决 LLM 应用的可观测性问题。

1.1 为什么 print/logging 不够用

LangChain 应用
(自动埋点)

Trace 追踪
记录每次调用
完整链路

Run 分析
延迟/Token/费用
统计分析

Dataset 评估集
构建黄金测试集
批量评估

Feedback 反馈
人工标注 + 自动
评分闭环

LangSmith 持续改进闭环

LangSmith全链路可观测性——Trace追踪、Run分析、Dataset评估、Feedback反馈形成持续改进闭环

传统应用的可观测性关注:请求耗时、错误率、资源占用。LLM 应用在这之上还需要:

中间状态可见性:一条 RAG 链有 5 个步骤,每步的输入输出都可能导致最终结果偏差。传统 logging 可以记录输入输出,但无法结构化地展示"步骤 3 的 Prompt 注入了哪些文档、模型实际看到的是什么"。

Token 成本归因(归因:找出谁消耗了多少):整体账单在增长,但哪条链、哪个 Prompt 消耗最多 Token?不追踪到链级别,成本优化无从下手。

版本对比:改了 Prompt 后,新版本在哪些案例上变好了、哪些变差了?没有历史记录就无法对比。

评估数据沉淀:线上标注"这个回答不好",要能自动沉淀成评估数据集,用于离线评估。这不是 logging 能做到的。

问题 传统 logging LangSmith
记录输入输出 能(手动写) 自动(零代码)
中间步骤可视化 不能 Trace 树状图
Token 用量统计 不能 自动统计,按步骤
版本 A/B 对比 不能 Run 对比视图
在线标注 不能 Feedback API
构建评估数据集 不能 从 Trace 一键添加

1.2 LangSmith 是什么

LangSmith 是 LangChain 的官方可观测性平台,与 LangChain 和 LCEL 原生集成。核心能力:

  • Tracing:自动追踪每个 Runnable 的输入、输出、耗时、Token 用量,以树状结构展示调用链路
  • Datasets:从线上 Trace 收集数据,构建离线评估数据集
  • Evaluations:批量在数据集上运行链,自动评估输出质量
  • Prompt Hub:版本化管理 Prompt,支持 pull/push

1.3 5 分钟接入:零代码改动启用追踪

LangSmith 的接入成本极低,只需设置环境变量:

bash
# 1. 注册 LangSmith(https://smith.langchain.com)并获取 API Key
# 2. 设置环境变量

export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=ls__your_api_key_here
export LANGCHAIN_PROJECT=my-rag-project  # 可选,默认 "default"

或者在 Python 代码中设置(在任何 LangChain 代码之前):

python
import os

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls__your_api_key_here"
os.environ["LANGCHAIN_PROJECT"] = "my-rag-project"

# 之后的所有 LangChain 调用都会自动上报到 LangSmith
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

llm = ChatOpenAI(model="gpt-4o")
chain = ChatPromptTemplate.from_template("解释{concept}") | llm

# 这次调用会自动出现在 LangSmith 的 Traces 页面
result = chain.invoke({"concept": "向量数据库"})

就这么简单。不需要修改任何业务代码,不需要添加任何 try/except,LangSmith 通过 LangChain 的回调系统自动捕获所有信息。

1.4 LangSmith UI 核心功能

1.4.1 Trace 详情

每次链调用都会生成一条 Trace,以树状结构展示完整的调用链路:

code
RAG Chain (3.2s | 1,847 tokens | $0.009)
├── Retriever (0.4s)
│   └── VectorSearch
│       Input:  "什么是向量数据库?"
│       Output: [doc1, doc2, doc3, doc4]
├── PromptTemplate (0ms)
│   Input:  {question: "...", context: "doc1\ndoc2..."}
│   Output: [SystemMessage, HumanMessage]
└── ChatOpenAI (2.8s | 1,847 tokens)
    Input:  [SystemMessage("你是..."), HumanMessage("...")]
    Output: AIMessage("向量数据库是...")
    Tokens: prompt=1,243, completion=604
    Cost:   $0.009

点击任意节点,可以看到完整的输入输出内容,以及该步骤的 Token 用量和耗时。

1.4.2 Run 对比

修改了 Prompt 版本后,可以选择两次运行进行 side-by-side 对比,清晰看到哪些地方输出不同。

1.4.3 Feedback:标注好坏回答

在 UI 或代码中标注某次运行的质量:

python
from langsmith import Client

client = Client()

# 给某次运行打分
client.create_feedback(
    run_id="run_id_from_trace",   # 从 Trace 页面复制
    key="quality",
    score=0.8,                    # 0-1
    comment="回答准确,但语气稍显生硬"
)

# 标注为正面/负面
client.create_feedback(
    run_id="run_id_from_trace",
    key="user_rating",
    value="positive"  # 或 "negative"
)

被标注的运行可以直接添加到 Dataset,形成有标注的评估数据集。

1.5 Dataset 与评估:批量测试 RAG 质量

python
from langsmith import Client
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langsmith.evaluation import evaluate, LangChainStringEvaluator

client = Client()

# 1. 创建评估数据集
dataset = client.create_dataset(
    dataset_name="rag-quality-v1",
    description="RAG 问答质量评估数据集"
)

# 添加测试案例
examples = [
    {
        "inputs": {"question": "LangChain 的 LCEL 是什么?"},
        "outputs": {"answer": "LCEL 是 LangChain Expression Language,用于声明式构建链..."}
    },
    {
        "inputs": {"question": "如何给 LangChain 添加记忆?"},
        "outputs": {"answer": "可以使用 ConversationBufferMemory 或 ChatMessageHistory..."}
    },
]

client.create_examples(
    inputs=[e["inputs"] for e in examples],
    outputs=[e["outputs"] for e in examples],
    dataset_id=dataset.id
)

# 2. 定义被评估的链
def rag_chain_fn(inputs: dict) -> dict:
    """待评估的 RAG 链"""
    chain = (
        ChatPromptTemplate.from_template("基于你的知识回答:{question}")
        | ChatOpenAI(model="gpt-4o")
        | StrOutputParser()
    )
    answer = chain.invoke(inputs)
    return {"answer": answer}

# 3. 定义评估器
# 使用 LangChain 内置的 QA 评估器
qa_evaluator = LangChainStringEvaluator("qa")

# 自定义评估器:检查关键词
from langsmith.evaluation import run_evaluator

@run_evaluator
def keyword_evaluator(run, example) -> dict:
    """检查关键词是否在回答中"""
    answer = run.outputs.get("answer", "")
    reference = example.outputs.get("answer", "")

    # 提取参考答案中的关键词(简化版)
    keywords = [w for w in reference.split() if len(w) > 3][:5]
    hits = sum(1 for kw in keywords if kw in answer)
    score = hits / len(keywords) if keywords else 0.0

    return {"key": "keyword_recall", "score": score}

# 4. 运行批量评估
results = evaluate(
    rag_chain_fn,
    data=dataset.name,
    evaluators=[qa_evaluator, keyword_evaluator],
    experiment_prefix="gpt-4o-baseline",
    num_repetitions=1
)

print(results.to_pandas())

1.6 Prompt Hub:版本化管理 Prompt

LangSmith 提供 Prompt Hub,支持把 Prompt 模板推送到云端,在代码中 pull 使用,实现 Prompt 与代码的解耦:

python
from langchain import hub

# 从 Hub 拉取社区 Prompt(无需 LangSmith 账号)
rag_prompt = hub.pull("rlm/rag-prompt")
print(rag_prompt.messages[0].prompt.template)

# 从 Hub 拉取自己的 Prompt(需要登录)
my_prompt = hub.pull("my-username/customer-service-v2")

# 在链中使用
chain = my_prompt | llm | StrOutputParser()

# 推送 Prompt 到 Hub
from langchain_core.prompts import ChatPromptTemplate

new_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是专业的客服助手,版本 3.0"),
    ("human", "{question}")
])

hub.push("my-username/customer-service-v3", new_prompt)

1.7 手动记录自定义 Span

对于不经过 LangChain 的自定义逻辑,可以手动创建 Span(追踪单元:在链路追踪中代表一段操作的记录,包含开始时间、结束时间和相关数据,多个 Span 组合成完整的 Trace 树):

python
from langsmith import traceable, Client
from langsmith.run_helpers import get_current_run_tree

# 方法 1:@traceable 装饰器
@traceable(name="custom-preprocessing", run_type="chain")
def preprocess_query(query: str) -> str:
    """自定义预处理逻辑"""
    # 清理、规范化、扩展查询
    cleaned = query.strip().lower()
    expanded = f"{cleaned} 相关内容 技术文档"  # 查询扩展
    return expanded

@traceable(name="rerank-results", run_type="retriever")
def rerank_documents(query: str, docs: list) -> list:
    """文档重排序(自定义逻辑)"""
    # 用关键词相关性重排
    scored_docs = [
        (doc, sum(1 for kw in query.split() if kw in doc.page_content))
        for doc in docs
    ]
    return [doc for doc, _ in sorted(scored_docs, key=lambda x: -x[1])]

# 方法 2:上下文管理器
from langsmith.run_helpers import langsmith_trace

def complex_pipeline(query: str) -> str:
    with langsmith_trace(name="query-expansion") as run:
        expanded_query = preprocess_query(query)
        run.metadata["expansion_ratio"] = len(expanded_query) / len(query)

    docs = retriever.invoke(expanded_query)

    with langsmith_trace(name="reranking") as run:
        reranked_docs = rerank_documents(query, docs)
        run.metadata["docs_before"] = len(docs)
        run.metadata["docs_after"] = len(reranked_docs)

    return generate_answer(query, reranked_docs)

1.8 LangSmith 追踪链路完整图

自动上报

发现差回答

一键添加

批量运行

生成报告

hub.pull

hub.push

UI 标注

查看分析

查看趋势

LangChain 应用
链调用

LangSmith 平台

Traces 追踪
每次调用的完整链路

Datasets 数据集
测试案例管理

Evaluations 评估
批量质量测试

Prompt Hub
Prompt 版本管理

Feedback 标注
好/坏/评分

评估报告
指标趋势图

开发者

LangSmith 把"黑盒"变成"白盒"——从线上 Trace 发现问题,到标注数据集,到离线评估验证修复,这条链路建起来,LLM 应用的质量就有了可追溯的依据,而不是靠猜。

本页目录