课程0基础Agent开发课 / 生产化部署 / LangSmith与Langfuse-AI应用的可观测性
— 10 min read

LangSmith与Langfuse-AI应用的可观测性

传统 Web 应用的监控日志包含足够的调试信息:HTTP 状态码、响应时间、报错堆栈。但对于 AI 应用,当用户反馈"回答质量很差,完全答非所问"时,HTTP 日志里只有 `200 OK`,响应时间 3.2 秒。服务正常在跑,没有报错,但问题到底出在哪一步?是向量检索没找到相关文档?是找到了但 Prompt 写得不好?还是 LLM 本身的问题?

LangSmith 与 Langfuse:AI 应用的可观测性

传统 Web 应用的监控日志包含足够的调试信息:HTTP 状态码、响应时间、报错堆栈。但对于 AI 应用,当用户反馈"回答质量很差,完全答非所问"时,HTTP 日志里只有 200 OK,响应时间 3.2 秒。服务正常在跑,没有报错,但问题到底出在哪一步?是向量检索没找到相关文档?是找到了但 Prompt 写得不好?还是 LLM 本身的问题?

传统日志回答不了这个问题。


1.1 为什么 AI 应用需要可观测性

AI应用可观测性架构图
AI应用可观测性三层架构及LangSmith与Langfuse工具对比

传统 Web 应用的调试逻辑很简单:看日志,找报错,定位代码行,修复。业务逻辑是确定性的,同样的输入永远得到同样的输出。

AI 应用不一样。一个 RAG 问答系统内部的调用链路可能是这样的:

用户问题

问题改写/扩展

向量检索

文档重排序

构建Prompt

LLM推理

输出后处理

最终答案

检索结果1

检索结果2

检索结果3

每个节点都可能出问题,而且是概率性的问题:同一个问题,今天回答得好,明天可能因为检索到了不同的文档而回答得差。

调试 AI 应用需要能看到每次请求的完整链路:用户问了什么 → 改写成了什么 → 检索到了哪些文档(完整内容)→ 实际发给 LLM 的 Prompt 是什么 → LLM 返回了什么 → 最终输出是什么 → 花了多少 token → 每个环节耗时多少。

这就是 AI 应用的可观测性。


1.2 LangSmith:官方解决方案

LangSmith 是 LangChain 官方提供的可观测性平台,和 LangChain 生态无缝集成。

1.2.1 接入方式

零代码侵入,设置环境变量就自动开启追踪:

bash
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_ENDPOINT="https://api.smith.langchain.com"
export LANGCHAIN_API_KEY="ls__your_api_key"
export LANGCHAIN_PROJECT="my-rag-app"

这四行环境变量设置完成后,所有 LangChain 调用会自动被追踪,不需要修改任何代码。

1.2.2 核心功能

Trace(链路追踪)

每次请求都会生成一条完整的 Trace,展示整个调用链路的树状结构。可以看到:

  • 每个 LLM 调用的完整输入(System Prompt + Human Message)
  • LLM 的完整输出
  • 每个环节的耗时
  • token 消耗(input tokens、output tokens、总费用)
  • 如果用了工具,工具的入参和返回值

这对调试来说价值极大。用户反馈某次回答质量差,找到那条 Trace,一眼就能看到是检索到的文档完全不相关,还是 Prompt 有问题,还是 LLM 输出就歪了。

Evaluate(评估)

可以对历史 Trace 打分,也可以配置自动评估器(用另一个 LLM 来评估输出质量)。评估结果会聚合成指标,让你看到整体质量趋势。

Dataset(测试集管理)

从生产 Trace 里挑选典型问题,构建测试集。每次改了 Prompt 或换了模型,在测试集上跑一遍,对比指标变化,确保没有回退。

Playground

直接在 LangSmith 界面上修改 Prompt,用保存的输入测试,不需要改代码重新部署。这对快速迭代 Prompt 非常有用。

1.2.3 核心指标

LangSmith 会自动收集:

  • 延迟:p50/p95/p99 分位数,识别慢请求
  • Token 消耗:input tokens、output tokens,控制成本
  • 成功率:是否有报错或超时
  • 每次调用的完整输入输出

1.2.4 接入代码示例

python
# 只需设置环境变量,其余代码不需要改动
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls__your_api_key"
os.environ["LANGCHAIN_PROJECT"] = "rag-production"

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage

llm = ChatOpenAI(model="gpt-4o-mini")

# 这次调用会被自动追踪,LangSmith 里能看到完整记录
response = llm.invoke([
    SystemMessage(content="你是一个技术助手"),
    HumanMessage(content="什么是向量数据库")
])
print(response.content)

如果想手动添加自定义 metadata,用 @traceable 装饰器:

python
from langsmith import traceable

@traceable(name="RAG问答", metadata={"version": "v2"})
def rag_answer(question: str, user_id: str) -> str:
    # 这个函数的完整调用会被追踪
    # metadata 里可以加业务信息,比如 user_id、AB 测试分组
    docs = retriever.invoke(question)
    context = "\n".join([d.page_content for d in docs])

    prompt = f"""基于以下文档回答问题:
{context}

问题:{question}"""

    response = llm.invoke([HumanMessage(content=prompt)])
    return response.content

1.2.5 缺点

LangSmith 的主要问题:

闭源,数据在境外。 所有 Prompt、用户问题、LLM 输出都会发到 LangChain 的服务器(美国)。对于企业内部知识库或者涉及敏感信息的场景,这是硬伤。

免费额度有限。 免费版每月 5000 条 Trace,超过要付费。


1.3 Langfuse:开源替代方案

Langfuse 是 LangSmith 的开源替代,功能高度类似,但支持自部署。

1.3.1 和 LangSmith 的功能对比

功能 LangSmith Langfuse
链路追踪
评估
测试集
Prompt 管理
自部署 不支持 支持(Docker)
开源
免费额度 5000 条/月 自部署无限制

1.3.2 接入方式

bash
pip install langfuse

两种接入方式:

方式一:通过 LangChain CallbackHandler(零代码侵入)

python
import os
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..."
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..."
os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com"  # 或自部署地址

from langfuse.callback import CallbackHandler

langfuse_handler = CallbackHandler()

# 在 invoke 时传入 callback
response = llm.invoke(
    [HumanMessage(content="什么是RAG")],
    config={"callbacks": [langfuse_handler]}
)

方式二:手动 Trace(更灵活,可以追踪非 LangChain 代码)

python
from langfuse import Langfuse

langfuse = Langfuse()

def rag_answer(question: str) -> str:
    # 创建一个 Trace
    trace = langfuse.trace(
        name="rag-question",
        input={"question": question},
        metadata={"user_id": "user123"}
    )

    # 追踪检索步骤
    retrieval_span = trace.span(name="vector-retrieval")
    docs = retriever.invoke(question)
    retrieval_span.end(output={"doc_count": len(docs)})

    # 追踪 LLM 步骤
    generation = trace.generation(
        name="llm-call",
        model="gpt-4o-mini",
        input=[{"role": "user", "content": question}]
    )
    response = llm.invoke([HumanMessage(content=question)])
    generation.end(
        output=response.content,
        usage={
            "input": response.response_metadata["token_usage"]["prompt_tokens"],
            "output": response.response_metadata["token_usage"]["completion_tokens"]
        }
    )

    # 关闭 Trace
    trace.update(output={"answer": response.content})
    return response.content

1.3.3 自部署

用 Docker Compose 在自己服务器上跑 Langfuse:

bash
# 下载 docker-compose 配置
git clone https://github.com/langfuse/langfuse.git
cd langfuse

# 配置环境变量
cp .env.example .env
# 编辑 .env,设置 NEXTAUTH_SECRET、SALT 等

# 启动
docker compose up -d

然后把 LANGFUSE_HOST 改成自己的服务器地址,数据就不出内网了。


1.4 关键指标怎么看

有了可观测性工具,需要关注以下几个指标:

延迟分位数

不要只看平均值,要看 p95 和 p99。平均延迟 3 秒,但 p99 是 20 秒,说明有少部分请求非常慢,这些慢请求往往对应着检索质量很差(召回了大量无关文档,Prompt 变得很长)的情况。

Token 消耗趋势

每次调用消耗的 token 突然增加,说明可能是 Prompt 变长了(比如检索到的文档更多或更长),或者有 Prompt 注入攻击(用户输入了超长内容)。

Faithfulness 低的请求

结合 RAGAS 评估,把 Faithfulness 分数低的请求找出来,看完整链路,通常能发现检索问题或 Prompt 问题。

错误类型分布

超时、上下文过长(token limit exceeded)、内容过滤触发,这些错误的分布能帮助确定优化方向。


1.5 一个实际的调试场景

用户反馈:"问关于退款政策的问题,给出了一个完全错误的答案。"

有了 LangSmith,调试步骤:

  1. 在 LangSmith 里搜索关键词"退款",找到那条 Trace
  2. 查看检索结果:系统找到了 3 个文档,但其中 2 个是关于"退货"的,1 个是关于"发货"的,没有一个是关于"退款政策"的
  3. 根本原因确认:向量检索的语义理解有问题,"退款"和"退货"被当成了相似文本

没有可观测性,可能会误判为 Prompt 问题,花了几天调整 Prompt,而真正的根本原因是 embedding 模型对这两个词的区分不够精细。


1.6 上线前就要接好

可观测性接入的成本很低:LangSmith 设置 4 个环境变量,Langfuse 多装一个包,代码几乎不用改。这个成本在上线前就花掉,上线后的排查效率会高很多。

AI 应用的调试和传统应用不一样,不能只靠直觉和经验,需要数据。可观测性工具提供的就是这些数据:完整的链路追踪、token 消耗、延迟分布、质量评估。上线后遇到问题时,有了这些数据才能快速定位根因。

本页目录