Langfuse部署与实践:构建大模型智能体可观测与评估闭环
2026/9/5 12:19:22 网站建设 项目流程

大模型应用能从 demo 走到生产,关键往往不是模型选得不好,而是没人能说清楚线上一次回答到底经历了几轮工具调用、Prompt 用的是哪个版本、Token 烧在哪一步。Langfuse 就是解决这类问题的开源可观测平台,它把 Trace、Span、Generation、Score、数据集和 Prompt 版本管理放在同一个 Web 控制台里,适合做大模型 Agent 的调试、评估和性能优化。

这篇文章会从一个真实可跑的落地路径展开:先快速过一遍 Langfuse 的核心能力和部署门槛,然后演示自托管部署、SDK 接入、Agent 链路追踪、提示词版本管理、基于数据集的批量评估,再到 REST API 和自动化回归。全文以本地测试环境为准,代码会尽量贴近官方 SDK 写法,版本差异会单独说明。

在开始之前先给结论:Langfuse 不需要 GPU,也不吃显存,它主要做观测和分析,实际资源消耗在数据库和 Web 服务上。对个人开发者和中小团队来说,最轻量的用法是 Docker 一键拉起一个自托管实例,然后通过 Python SDK 把业务代码里的关键调用接进去,剩下的事情都交给控制台。

1. Langfuse 核心能力速览

能力项说明
项目性质开源的 LLM 可观测性与评估平台
核心功能Trace 链路追踪、Prompt 版本管理、数据集管理、离线/在线评估、成本与延迟分析
支持接入方式Python SDK、TypeScript SDK、REST API、OpenTelemetry、LangChain 等框架回调
部署方式Docker Compose 自托管、官方云服务、本地开发模式
硬件要求无 GPU 要求,普通服务器或开发机即可运行
主要存储组件PostgreSQL(事件数据)、ClickHouse(分析数据)、Redis(队列缓存)
适合场景智能体评估、线上问题定位、Prompt 调优、成本与 Token 监控、批量回归测试

Langfuse 的定位不是模型部署工具,而是一个应用层观测和分析底座。你不需要把自己的模型注册进去,只需要在应用的推理调用前后上报数据,它就能把这些数据串成结构化链路。

从技术选型的角度,Langfuse 的价值在于把“调试”从日志里解放出来。普通日志只能看到一条一条孤立文本,而 Langfuse 可以看到一次任务里从用户输入到 Agent 规划、工具返回、再到大模型最终生成的全过程。

2. 为什么智能体落地后必须做可观测与评估

传统 Web 服务的问题定位很简单,接口报错了看状态码和堆栈基本就能定位。智能体的失败方式完全不同,即使整个调用链 HTTP 状态都是 200,Agnet 仍然可能因为检索结果不好、工具参数传错、模型过度推理而给出一个错误答案。

这时候就需要三类数据:

第一类是调用链路数据。一次智能体任务可能包含 Intent 识别、知识库检索、工具调用、回答生成多个环节。没有链路追踪,出问题之后根本不知道应该优化哪一个环节。

第二类是版本数据。同一个 Prompt 改过三次,线上跑的是第二版,离线实验用的是第三版,最后表现不一致,这在实际开发中非常常见。Langfuse 的 Prompt 版本管理正好能把版本和 Trace 绑定在一起,后续复盘时可以精确还原某一次生成使用的是哪个版本。

第三类是评估结果数据。大模型输出没有确定性的断言可以参考,必须用评分函数或 LLM-as-a-Judge 来做质量度量。评估不能只跑一次,要把评估结果沉淀下来,形成样本库,每次 Prompt 或模型变化后重新跑一遍回归。

Langfuse 的设计本质上是把这三种数据统一存储,并提供了 UI、API 和 SDK 三个维度的使用入口。接下来先从部署开始,把服务先跑起来。

3. Langfuse 本地部署与启动

3.1 环境准备

自托管 Langfuse 的硬件要求不高,一台 2 核 4G 内存的 Linux 服务器或者本机 Docker 环境都可以,磁盘取决于你的数据量。日常测试预留 20G 以上更稳妥。

部署前确认环境里已经安装:

  • Docker 20.10 以上
  • Docker Compose 2.x
  • 可访问的浏览器

Windows 环境建议直接使用 Docker Desktop,Linux 环境直接安装 Docker Engine 即可。以下命令以 Linux 和 macOS 终端为准。

3.2 通过 Docker Compose 启动

Langfuse 官方仓库提供了完整的 Docker Compose 编排文件,包含 Web 服务、PostgreSQL、ClickHouse、Redis 和反向代理等组件。

git clone https://github.com/langfuse/langfuse.git cd langfuse docker compose up -d

首次启动会拉取镜像并初始化数据库,耗时取决于网络状况,通常在几分钟内完成。启动完成后:

docker compose ps

看到服务状态为 running 后,在浏览器访问:

http://localhost:3000

首次进入页面时会要求注册一个管理员账号,这个账号用于登录控制台。如果端口 3000 被占用,可以修改 docker-compose 中 Web 服务的端口映射,比如把3000:3000改成13000:3000

3.3 创建 API 密钥

登录控制台之后,在项目设置中创建 API Key,会得到两个关键值:

  • Public Key,作为请求标识
  • Secret Key,作为请求签名

这两个值不要提交到 Git 仓库。SDK 和 REST API 调用时都会用到,建议放到本地环境变量或配置中心里。

到这里服务已经可用,接下来要做的就是让业务应用开始向 Langfuse 上报 Trace 数据。

4. SDK 接入:让 Langfuse 开始记录智能体调用

4.1 安装依赖

Python 项目安装 SDK:

pip install langfuse

如果你的智能体基于 LangChain,还需要额外安装:

pip install langchain langchain-openai

4.2 初始化客户端

SDK 初始化时需要三个配置项:

import os from langfuse import Langfuse langfuse = Langfuse( public_key=os.getenv("LANGFUSE_PUBLIC_KEY", "pk-lf-xxxx"), secret_key=os.getenv("LANGFUSE_SECRET_KEY", "sk-lf-xxxx"), host=os.getenv("LANGFUSE_HOST", "http://localhost:3000") )

如果是云服务版本,host 换成 Langfuse 控制台对应的 API 地址即可。

4.3 使用装饰器追踪代码

Langfuse Python SDK 提供了一个非常轻量的装饰器@observe。在函数上加上装饰器后,每次函数调用会自动生成一个 span,一个完整调用链最外层就是 trace。

from langfuse.decorators import observe import openai client = openai.OpenAI() @observe() def ask_llm(question: str) -> str: response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "你是一个智能助手。"}, {"role": "user", "content": question} ] ) return response.choices[0].message.content

@observe()装饰的函数内部调用 openai SDK 时,Langfuse 会自动捕获大模型调用,并以 generation 的形式挂到当前 trace 下。运行一次后去 Langfuse 控制台刷新 Trace 页面,就能看到本次调用记录。

4.4 为 Agent 任务增加业务信息

纯装饰器只能记录函数名和参数,生产环境还要记录用户 ID、会话 ID、任务类型等业务信息。Langfuse 提供了运行时上下文,可以在@observe函数内额外写入元数据。

from langfuse.decorators import observe, langfuse_context @observe() def run_agent(user_id: str, question: str) -> str: langfuse_context.update_current_trace( name="customer-service-agent", user_id=user_id, session_id="session-2026-001", metadata={ "scene": "after_sales", "env": "test" } ) return ask_llm(question)

这样在控制台的 Trace 详情页里,可以按用户 ID、会话 ID 或 metadata 内容筛选,问题定位效率会高很多。

5. 复杂 Agent 链路追踪:LangChain 场景接入

如果你的智能体已经基于 LangChain / LangGraph 实现,通常不需要自己手写 span,Langfuse 提供了对应回调处理器,能自动捕获 Agent 的每一步执行过程。

5.1 标准回调方式

以 LangChain 的 AgentExecutor 为例:

from langfuse.callback import CallbackHandler from langchain_openai import ChatOpenAI from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain.tools import tool lanfuse_handler = CallbackHandler( public_key="pk-lf-xxxx", secret_key="sk-lf-xxxx", host="http://localhost:3000" ) @tool def get_weather(city: str) -> str: """获取指定城市的天气信息。""" return f"{city} 今日天气晴朗,温度 20 摄氏度。" llm = ChatOpenAI(model="gpt-4o-mini", temperature=0) agent = create_tool_calling_agent(llm, [get_weather]) executor = AgentExecutor(agent=agent, tools=[get_weather]) result = executor.invoke( {"input": "北京今天天气如何?适合穿什么出门?"}, config={"callbacks": [lanfuse_handler]} )

执行完成后,打开 Langfuse 控制台,就能看到整个 Agent 的 Trace 结构:

  • Agent 的规划过程
  • 工具名称和输入输出
  • 大模型推理的 Token 消耗
  • 每步执行耗时
  • 最终回答内容

如果某一个工具返回了异常内容,直接在 UI 中点击对应 span 就能看到完整的原始输出,不需要再去翻日志。对多工具 Agent 来说,这是最高效的手段。

5.2 多轮对话与 Session 绑定

多轮对话场景下,不要把每一轮用户输入都当成独立 trace,而是尽量让它们属于同一个 session。LangChain 场景可以在 invoke 配置中带上 session_id:

executor.invoke( {"input": "那明天呢?"}, config={ "callbacks": [lanfuse_handler], "run_id": "session-2026-001" } )

Langfuse 控制台会把同一 session 下的多次 trace 组织起来,方便按会话维度回放用户和智能体的完整交互。

6. 大模型观测:不是只看日志,而是看指标

接入 Trace 之后,Langfuse 的观测页面会持续积累几类指标:

  • 调用总量:按模型、按操作类型、按用户维度统计
  • Token 消耗:输入 Token、输出 Token、总量和对应成本
  • 推理延迟:单次生成耗时和端到端耗时
  • 错误率:SDK 上报时的错误状态和异常信息
  • 评分分布:人工打标和自动评估的分数变化

这些指标可以在控制台直接看,也可以把筛选结果导出。排查线上问题时,可以先看错误率和大延迟集中在哪个 Agent 环节,再进入相应 Trace 查看具体输入输出,最后定位到 Prompt 或工具参数问题。

这与传统 APM 的用法类似,区别是大模型观测需要结合文本内容和语义信息才能判断问题,所以 Langfuse 把 trace、prompt、token、score 放在同一个详情页,尽可能减少跳转成本。

7. 提示词版本管理:Prompt 调试与变更追踪

Prompt 调优是智能体迭代过程中最频繁的操作。Langfuse 的 Prompt Management 提供了在线编辑、版本发布、版本对比和代码拉取能力。

7.1 在控制台创建 Prompt

在 Langfuse UI 的 Prompts 页面中新建一个 Prompt,命名为agent-system-prompt,填写系统提示词内容,并发布为 v1。后续再次编辑并发布,版本号自动变更。

7.2 代码中获取 Prompt

Python SDK 获取指定名称 Prompt,并读取其最新版本:

prompt = langfuse.get_prompt("agent-system-prompt") messages = [ { "role": "system", "content": prompt.compile(variables={"user_name": "张三"}) }, { "role": "user", "content": question } ]

Prompt 支持变量模板,prompt.compile()方法会把模板变量渲染成最终文本。

7.3 让 Trace 关联 Prompt 版本

在调用大模型时,最好把 Prompt 版本信息同步写入 generation:

@observe(as_type="generation") def call_with_prompt(question: str): prompt = langfuse.get_prompt("agent-system-prompt", version=None) response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": prompt.compile()}, {"role": "user", "content": question} ] ) return response

之后在 Trace 详情里,可以看到这条 generation 引用的 Prompt 名称和版本号。一旦发现某个版本上线后结果变差,可以直接对比旧版本的输出,快速回滚。

8. 智能体评估落地:从评估函数到批量评测

Langfuse 的价值不只是观测历史调用,还能推动质量回归。智能体评估可以理解为把一批“输入 + 期望输出”放到数据集里,然后用评分规则批量打分。

8.1 创建评估数据集

dataset = langfuse.create_dataset( name="customer-service-eval", description="售后客服智能体回归数据集" ) dataset.create_item( input={"question": "我的订单还没收到,应该怎么办?"}, expected_output="回答中应包含查询物流状态的建议或操作步骤。" ) dataset.create_item( input={"question": "产品有问题想退货,流程是什么?"}, expected_output="回答中应包含退货申请的方式、时限和注意事项。" )

数据集里的每一个 item 会保留独立版本,后续更新数据不会影响历史结果。

8.2 实现简单评估函数

最简单的评估函数可以检查输出文本中是否包含期望关键词,也可以写一个基于规则的打分函数:

def contains_key_points(output: str, expected_output: str) -> dict: output_clean = output.replace(",", "").replace("。", "") expected_clean = expected_output.replace(",", "").replace("。", "") matched = sum(1 for point in expected_clean if point in output_clean) total = max(len(expected_clean), 1) return { "score": matched / total, "label": "pass" if matched / total > 0.6 else "fail", "metadata": { "matched_count": matched, "expected_length": len(expected_clean) } }

这种函数的好处是脱离大模型依赖,执行速度快,适合在 CI 或批量任务中每天跑。

8.3 执行批量评估

在 Langfuse SDK 中执行评估,需要把 dataset 与评估函数关联。不同 SDK 版本对evaluate入口的写法有差异,建议使用前先查看当前版本的官方示例。下面是一种接近官方 API 的写法:

from langfuse.evaluations import evaluate evaluate( dataset=dataset, evaluation=contains_key_points, run_name="rule-based-regression", )

执行完成后,控制台的 Dataset 页面会显示本次 run 的评分结果,包括每个样本的详细分数、标注信息和整体均分。

8.4 用 LLM-as-a-Judge 做更细粒度的评估

规则评估无法覆盖生成内容质量。更常见的做法是让一个强大的模型扮演评委,对智能体输出打分。这里用一个通用示例:

def llm_as_judge(output: str, expected_output: str) -> dict: judge_prompt = f""" 你是一个智能体评估专家。 请根据以下标准判断回答是否合格: 标准:{expected_output} 智能体回答: {output} 请只返回 JSON,格式为: {{"score": 0 到 1 之间的数字, "reason": "评分理由"}} """ judge_response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": judge_prompt}], response_format={"type": "json_object"} ) content = judge_response.choices[0].message.content import json result = json.loads(content) return { "score": result.get("score", 0), "label": "pass" if result.get("score", 0) >= 0.7 else "fail", "metadata": {"reason": result.get("reason", "")} }

LLM-as-a-Judge 更适合评估回答的相关性、完整性和语气。执行时会消耗一定 Token,建议批量任务控制在合理规模内,并且在跑批量之前先手动验证 5 到 10 条样本,避免评委 Prompt 本身产生系统性偏差。

8.5 线上分数采集

除了离线评估集,Langfuse 还支持人工评分。在控制台 Trace 详情页可以直接给某一条回答打分,也可以把人工评分结果与线上反馈同步。后续分析时可以同时看自动评估和人工评分,两者一致性高说明自动评估可信,两者差异大则需要重新校准评估标准。

9. 接口 API 与自动化批量任务

很多团队的评估流程希望接入自己的任务系统,比如每天晚上从业务库拉取一批样本,调用评估函数后把结果写回 Langfuse。这时候可以使用 REST API。

9.1 API 认证方式

Langfuse REST API 使用 HTTP Basic Auth,用户名是 Public Key,密码是 Secret Key。请求地址为部署实例的/api/public路径。

LANGFUSE_PUBLIC_KEY="pk-lf-xxxx" LANGFUSE_SECRET_KEY="sk-lf-xxxx" LANGFUSE_HOST="http://localhost:3000"

9.2 使用 curl 创建 Generation

curl -X POST "$LANGFUSE_HOST/api/public/generations" \ -u "$LANGFUSE_PUBLIC_KEY:$LANGFUSE_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "llm-call", "model": "gpt-4o-mini", "input": "用户问题:我的订单还没收到", "output": "建议您先查看物流轨迹,并联系客服获取最新状态。", "usage": { "input": 120, "output": 80, "unit": "TOKENS" } }'

创建成功后,接口会返回该 generation 的 ID,可以在后续请求中用于追加 score。

9.3 创建 Score

curl -X POST "$LANGFUSE_HOST/api/public/scores" \ -u "$LANGFUSE_PUBLIC_KEY:$LANGFUSE_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "traceId": "对应 trace id", "name": "quality", "value": 0.9, "comment": "回答完整,步骤清晰" }'

9.4 Python 批量评估流水线

下面给出一个可扩展的批量评估骨架,读取本地 JSONL 测试集,逐条调用大模型,然后把 generation 和 score 写入 Langfuse:

import json import time import requests from requests.auth import HTTPBasicAuth LANGFUSE_HOST = "http://localhost:3000" AUTH = HTTPBasicAuth("pk-lf-xxxx", "sk-lf-xxxx") def run_eval_line(line: dict): question = line["question"] expected = line["expected"] import openai client = openai.OpenAI() resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "你是售后客服助手。"}, {"role": "user", "content": question} ] ) output = resp.choices[0].message.content score = 1.0 if expected.strip() in output else 0.0 langfuse_payload = { "name": "batch-eval", "model": "gpt-4o-mini", "input": question, "output": output, "metadata": {"dataset_line": line.get("id")} } resp = requests.post( f"{LANGFUSE_HOST}/api/public/generations", auth=AUTH, json=langfuse_payload, timeout=30 ) resp.raise_for_status() return output, score if __name__ == "__main__": with open("./eval_samples.jsonl", encoding="utf-8") as f: lines = [json.loads(line) for line in f if line.strip()] for idx, line in enumerate(lines[:20]): try: output, score = run_eval_line(line) print(f"{idx}: score={score}") except Exception as exc: print(f"{idx}: failed, {exc}") time.sleep(1)

批量任务建议分三块:样本准备、调用执行、结果回写。 Langfuse 的 API 本身不限制写入数量,但过多并发请求可能影响自托管服务端性能,因此在开发阶段先限制并发数。

10. 性能优化与成本优化建议

Langfuse 本身不会提升模型响应速度,但观测数据能帮助你找到最值得优化的部分。

10.1 延迟优化

从 Trace 中看每一步耗时,如果发现工具调用是瓶颈,就优化工具接口;如果发现上下文太长,就减少历史消息数量或做上下文压缩;如果发现模型本身响应慢,可以尝试降低输出 Token 上限或换一个更快的轻量模型。

10.2 Token 成本优化

Langfuse 会对每个 generation 统计输入 Token 和输出 Token。当某个环节的输入 Token 异常高时,往往是因为把大量无关文档塞进了上下文。可以基于这些数据调整检索策略,比如限制每个知识块大小、提高检索阈值、在进入大模型前过滤低分文档。

10.3 错误与重试策略

当 Trace 页面出现大量超时或异常 generation 时,不建议直接调高重试次数,而是先看异常原因。如果是上游模型限流,增加指数退避;如果是工具输出格式错误,需要检查工具描述和参数解析逻辑;如果是上下文超长,优先压缩输入而不是盲目增加 max_tokens。

11. Langfuse 常见问题与排查方法

问题现象可能原因排查方式解决方案
安装后无法访问 3000 端口Docker 服务未启动或端口冲突执行docker compose ps查看状态修改端口映射后重启服务
SDK 上报后控制台看不到 TracePublic Key / Secret Key 配置错误查看应用日志中是否有 401/403重新生成 API Key 并更新环境变量
Trace 能看到,但内部没有 generation大模型 SDK 未被当前环境自动捕获在函数里手动创建 generation 或升级 SDK 版本使用@observe(as_type="generation")显式包装
控制台时间范围选择后数据为空服务器时区与浏览器时区不一致调整时间范围或用 UTC 时间查看在代码中统一上报 UTC 时间戳
Docker 重启后数据丢失Docker Volume 未挂载或误删容器检查 compose 文件中的 volume 配置确保数据目录持久化到宿主机
批量评估任务卡住单条调用超时或外部 API 限流检查日志中的阻塞点增加超时时间和失败重试机制
数据分析页响应慢数据量增长过快或查询范围过大缩短时间范围或减少字段定期归档历史数据,避免无限制增长

如果你在接入过程中遇到 SDK 函数签名差异,最直接的方法是去查看当前安装版本的官方文档。

pip show langfuse

根据返回的版本号,再搜索对应版本的 API 说明。Langfuse 新版迭代速度较快,不同小版本的评估接口入口确实有变化。

12. 最佳实践与部署建议

12.1 开发阶段就接入

不要等到线上出问题再补观测。开发一个 Agent 后的第一件事不是跑完整流程,而是先接入 Langfuse,保证每个环节的输入输出都能被追踪。

12.2 字段脱敏

线上 Trace 中可能包含用户手机号、地址等敏感信息。Langfuse 默认会记录原始输入输出,在接生产流量前,需要在 SDK 层面对上报字段做脱敏或过滤,避免个人信息落库。

12.3 控制数据保留周期

Langfuse 的 ClickHouse 会存储大量明细数据,长期运行后磁盘占用会持续增加。建议在部署时配置数据保留策略,例如只保留最近 90 天的原始 Trace,分析报表可以单独导出归档。

12.4 建立评估回归基线

维护一个评估数据集本身就是一项长期投入。数据集不需要特别大,但必须覆盖高频场景和曾经出过错的案例。每次修改 Prompt、切换模型、调整工具后,都跑一次同样的评估集,用分数变化做回归判断。

12.5 权限与访问边界

如果 Langfuse 部署在公司内网,控制台不要默认开放到公网。可以在反向代理层增加身份认证,只允许开发和运维人员访问。API Key 也要按环境隔离,测试环境和生产环境使用不同的 Key。

13. 总结与下一步实际操作建议

Langfuse 最值得尝试的核心点不是单一的 Trace 追踪,而是 Prompt 版本管理、Trace 关联和数据集评估这三块拼在一起形成的闭环能力。真正用它调试一次线上 Agent 问题后,你会明显感觉到排查路径比翻日志直观得多。

第一次上手时,不用急着把所有代码都接入。建议先部署一个本地测试实例,用一个小型回收客服或知识问答 Agent 跑通以下链路:

  • 先接入一个@observe函数,确认控制台能看到 Trace
  • 为整个 Agent 增加用户 ID 和 session 关联,确认过滤可用
  • 然后在控制台发布一个 Prompt v1,代码里使用get_prompt拉取
  • 最后准备 10 到 20 条测试用例,执行一次批量评估

跑通这条链路之后,你就具备了一套基础的大模型应用可观测与智能体评估体系。后面可以考虑继续扩展的方向有三个:接入更多框架的自动埋点、建立每天自动跑评估的 CI 流水线、把评估结果与线上告警打通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询