
先说一个让我抓狂过的场景:
Agent 跑完了,结果不对。你盯着最后那条输出,完全不知道它在中间干了什么——调了哪些工具、检索出来什么、模型脑子里经过了几次转弯、哪一步开始走偏的。你只能猜。
这不是小概率事件,这是大模型应用的日常。
模型本身是黑盒,加上 RAG 的检索过程、多步 tool call、多轮对话上下文——一次请求打进去,里面发生了什么,默认你是完全看不见的。出了问题,你能做的就是改 prompt 重跑,然后再猜。
Langfuse 就是专门解决这件事的。
YC W23 出来的开源项目,做 LLM 应用可观测性(Observability)。用我之前讲 Harness Engineering 的框架来放——它正好补上了那块最容易被忽视的「Observability」组件:把你 Agent 的整条推理链路,从黑盒变成透明盒。
Langfuse 最核心的能力叫 Tracing(链路追踪)。
概念很简单:把一次请求的完整过程,记成一棵「树」。
每一次 LLM 调用,每一次 tool call,每一步 RAG 检索,耗时、输入、输出、中间状态——全部嵌套挂在这棵树上。你不只能看到最终结果,还能点进任意一个节点,看到那个时刻模型收到了什么、吐出了什么、花了多少时间。
举个例子:你的 Agent 有一步检索失败,召回了一堆不相关的文档,然后模型基于这堆垃圾给了一个看起来很合理但完全错误的答案。
没有 Tracing 的世界:你看到错误答案,改 prompt,重跑,结果还是错,你继续猜。
有 Tracing 的世界:你打开 Langfuse,点进这条请求,找到检索那一层,看到召回的 top-5 文档——哦,原来是 embedding 的问题,检索根本没拿到正确上下文,跟 prompt 没关系。两分钟定位,不是两小时瞎猜。
这就是行车记录仪的价值:不是防止你出事故,是出了事故能找到责任人。
光看得见还不够,得能打分。
Langfuse 的第二块能力叫 Evaluation(评估),解决的问题是:你手里积累了一堆 trace,怎么知道 Agent 的整体质量是在变好还是变差?
它支持几种方式:
LLM-as-a-judge:用另一个模型当裁判,自动对每条 trace 的输出打分——相关性够不够、有没有幻觉、回答完整吗。成本低,可以大规模跑。
代码规则评估:简单粗暴,但有时候最有效。比如检查输出里有没有包含必要字段、格式对不对、有没有超长。
用户反馈:把线上用户的点赞/踩动作,直接关联回对应的 trace,让真实使用数据反哺评估。
人工标注:对于高价值、高风险的场景,标注团队可以在 Langfuse 的界面里直接给 trace 打标签,构建 golden dataset。
这几种方式组合起来,能建立一套持续评估管线:每次你改了 prompt 或者换了模型,能有数据说话,而不是靠感觉说「感觉好像变好了?」
这一点我说过很多次:Prompt 是你 Agent 最重要的配置,不应该跟代码耦合在一起。
Langfuse 的 Prompt Management 做的就是把这件事系统化:
特别是最后这个——A/B + 评估打分的组合,才是真正的数据驱动 prompt 优化,而不是凭直觉改了又改。

上线之前每个人都说:「AI 成本可以接受。」
上线之后:token 账单比预期高了三倍,但你不知道是哪条链路吃掉的。
Langfuse 自动统计每条 trace 的 token 用量、对应成本、端到端延迟,汇总成 dashboard。你能一眼看出来:是某个特别长的 system prompt 在吃钱,还是某个 tool call 被调了太多次,还是某个用户的对话轮次远超平均。
更重要的是,这些数据能帮你做成本优化决策——哪些场景可以换便宜模型,哪些地方可以压缩上下文,有数据支撑,不是瞎猜。
Langfuse 支持 Python 和 JavaScript/TypeScript SDK,也有 OpenTelemetry 集成。接入门槛很低,我拆成三种场景说。
场景一:直接用 OpenAI SDK,加一行 drop-in 替换
pip install langfusefrom langfuse.openai import openai # 换掉原来的 import,其他不动
client = openai.OpenAI()
# 用法完全一样,Langfuse 自动把每次调用 trace 记下来
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "帮我总结这份合同"}],
)就这一行 import 替换,所有调用自动被追踪。不需要改业务代码。
场景二:手动打点,精确控制 trace 结构
如果你的 Agent 有多步骤,想看清每一步的边界,用 @observe 装饰器:
from langfuse.decorators import observe, langfuse_context
@observe() # 这个函数的输入输出、耗时自动记录
def retrieve_context(query: str) -> list[str]:
# 你的 RAG 检索逻辑
chunks = vector_db.search(query, top_k=5)
return chunks
@observe()
def generate_answer(question: str, context: list[str]) -> str:
# 你的 LLM 调用逻辑
prompt = build_prompt(question, context)
return llm.call(prompt)
@observe(name="contract-analysis-agent") # 最外层是整条 trace 的根节点
def run_agent(user_input: str) -> str:
# 给这条 trace 打个自定义标签,方便后面过滤
langfuse_context.update_current_trace(
user_id="user_123",
tags=["contract", "production"],
)
context = retrieve_context(user_input)
answer = generate_answer(user_input, context)
return answer这样跑完,Langfuse 里就能看到一棵树:根节点是 contract-analysis-agent,下面挂着 retrieve_context 和 generate_answer 两个子节点,各自的耗时、输入、输出都在。
场景三:LangChain 一行 callback 接入
from langfuse.callback import CallbackHandler
handler = CallbackHandler() # 自动读环境变量里的 API Key
chain.invoke(
{"input": "帮我分析这份合同"},
config={"callbacks": [handler]}, # 加这一行
)LangChain 里每一步——LLM call、tool call、retriever——全部自动被 callback 捕获,不需要手动打点。
环境变量配置:
LANGFUSE_SECRET_KEY="sk-lf-..."
LANGFUSE_PUBLIC_KEY="pk-lf-..."
LANGFUSE_HOST="https://cloud.langfuse.com" # 或者你自托管的地址自托管的话,官方提供 Docker Compose 一键部署,数据留在自己手里:
# 克隆仓库,复制环境变量模板,一键启动
git clone https://github.com/langfuse/langfuse.git
cd langfuse
cp .env.example .env
docker compose up -d
# 访问 http://localhost:3000三分钟跑起来,数据不出内网,对有合规要求的场景很友好。
我之前讲过,生产级 Agent 需要一套完整的 Harness 工程脚手架,其中 Observability 是最容易被跳过、但出了问题最难补的一层。
Langfuse 就是这层的标准答案:
如果你现在有 Agent 在跑、或者准备上线,接入 Langfuse 应该是优先级最高的基础设施动作之一。
没有 Observability 的 Agent,就是在用开了眼睛但没有仪表盘的方式开车。
你的应用可能跑得很好,但你不知道为什么好。一旦出问题,你也不知道为什么坏。
先把灯打开,再聊优化。
你现在有在用什么 LLM 可观测性工具吗?评论区聊聊。
— 完 —