Langfuse落地指南:从Docker部署到Python/Java接入与Trace排查 📅 发布时间:2026/8/30 6:13:41 👁 浏览次数: Langfuse 是当前做 LLM 应用可观测性最常用的一套开源方案核心能力是把每一次大模型请求从输入、输出、模型调用、工具调用、token 消耗到延迟和报错完整记录下来然后在网页里统一查看。这篇按 2026 年最新版的落地路径来写先用 Docker 把服务跑起来再分别接入 Python 和 Java 项目最后讲怎么用 trace 页面定位 prompt 问题、模型选型问题和资源瓶颈。适合正在做 LLM 应用、但上线后还不知道怎么追踪一次请求全链路的人。最值得先关注的一点是Langfuse 不是模型网关而是模型调用之上的观测层接入成本并不高大多数项目半天就能拉通。1. 先搞清楚 Langfuse 到底帮你解决什么问题1.1 传统日志和 LLM 调用之间缺了什么做过传统后端服务的人都知道排查问题最常用的手段就是看日志请求进来打一条调外部接口打一条返回结果打一条。这条链路在普通 Web 服务里足够用因为每一步的输入输出都是结构化的参数和返回值也稳定。但换成大模型应用之后事情变得不一样。你调用一次 OpenAI 或本地模型拿到的不是单纯一个 JSON而是一段需要二次解析的文本中间还可能穿插了 prompt 模板拼接、检索增强生成、工具调用、多轮记忆拼接。问题一旦出现比如用户问了一句奇怪的话模型返回了一段空内容或者整个请求耗时突然从 2 秒变到 20 秒传统日志很难快速定位是 prompt 没拼对还是模型本身抽风是检索阶段慢还是生成阶段慢这次调用花了多少 token对应多少钱用户重试相同问题为什么结果不一样这些问题靠 print、log 和数据库表格都能回答一部分但要把它们串成一条完整链路非常费劲。Langfuse 解决的就是这个“串起来”的问题。1.2 Langfuse 的定位Trace、监控、评估三层能力Langfuse 的核心模型是 trace也就是把一次完整的业务请求当成一条调用链记录下来。一条 trace 里可以包含 span、generation、event 这些子节点分别对应一次检索操作、一次模型生成调用、一条调试日志。这样你在页面上看到的不是一个孤立的日志条目而是一整棵调用树。除了记录调用链Langfuse 还做了几件对 LLM 应用特别重要的事自动统计每个模型的 token 消耗和成本按项目、用户、会话维度聚合记录每次生成的实际输入输出方便事后回放和对比提供 prompt 版本管理能直接看到同一个问题在 prompt 改动前后的结果差异支持数据集和评估可以把测试用例跑完后再统一打分。这些能力组合起来Langfuse 实际上承担了“监控 调试 评估”三件事。它不帮你调模型参数也不帮你优化 prompt但它能让你知道问题出在哪一层。1.3 选 Langfuse 而不是只用云平台市面上做 LLM 可观测的不只有 LangfuseLangSmith、Helicone、Arize Phoenix 也都是常见选择。LangSmith 在 LangChain 生态里集成度很高但它是托管平台数据要传到外部服务Arize Phoenix 也开源生态偏评估方向。Langfuse 最容易打动团队的一点是它是开源项目可以完全自托管数据库和代码都在自己机器上业务数据的隐私边界更可控。对于大多数团队来说选择 Langfuse 的理由通常有两条一是数据不出内网二是接入方式足够通用不绑定某个具体框架。这也是我为什么推荐先学它因为它的 trace 模型几乎可以套用到任何 LLM 应用上。2. 安装和初始化优先走 Docker 自托管路线2.1 安装前的环境确认Langfuse 的安装方式最推荐的是 Docker Compose 自托管因为官方把 Web 服务、Worker、PostgreSQL、ClickHouse、Redis 这些都准备好了一条命令就能启动整套服务。先确认几个前置条件一台 Linux 服务器或本地开发机建议至少 4 核 8G 内存。小团队内部试用这个配置够用生产环境再往上加。已经安装 Docker 和 Docker ComposeDocker Compose 尽量用 v2 版本。磁盘预留 20GB 以上因为要存数据库和 trace 数据。确认 3000 端口没有被占用这是 Langfuse Web 界面的默认入口。如果你的机器配置比较低也可以跑起来但页面加载和查询速度会明显慢尤其是 trace 多到几万条之后。原始文档没有给硬性配置标准我的建议是先按 4 核 8G 起步不够再扩。2.2 用 Docker Compose 启动整套服务从官方仓库或官方文档拿到最新的 docker-compose.yml放到一个独立目录比如/opt/langfuse下。然后在同目录创建.env文件把数据库密码、加密密钥这些变量填好再执行启动命令docker compose pull docker compose up -d docker compose ps第一次启动会比较久因为要拉镜像还要等数据库迁移完成。迁移完成后Langfuse 的 Web 容器和 Worker 容器会稳定运行。这里要解释一下为什么是这么几个组件PostgreSQL 存核心业务数据比如项目、用户、API Key、trace 的索引信息ClickHouse 存分析型数据主要用来做大量 trace 的查询和聚合Redis 承担 Worker 的任务队列Worker 负责异步处理上报的数据避免上报请求本身拖慢业务接口。最新版本的 Docker Compose 里可能还会看到对象存储相关容器用来保存文件类输入输出具体以你拉下来的镜像版本为准。启动后查看日志确认没有报错docker compose logs -f langfuse-web如果看到类似服务已监听和数据库迁移完成的日志就可以打开浏览器访问了。2.3 环境变量和数据库初始化部署 Langfuse 时有几个环境变量是必须认真对待的我这里列一下常见的几个实际以官方 docker-compose 模板为准环境变量作用建议DATABASE_URLPostgres 连接串改成自己的数据库地址和强密码SALT用于生成 ID 的盐值必须设置且不要用默认值ENCRYPTION_KEY敏感数据加密密钥必须设置生产环境用强随机值NEXTAUTH_URLWeb 访问的基础地址改成实际访问域名或 IPNEXTAUTH_SECRET登录会话签名密钥必须设置不能默认SALT 和 ENCRYPTION_KEY 这两个最容易忽略。SALT 影响 ID 的生成方式如果部署到一半改了 SALT可能导致旧数据和新请求的关联对不上ENCRYPTION_KEY 负责加密库里存的一些敏感字段丢了密钥加密数据就无法解密。所以在生产环境里这两个值要妥善备份不能随手贴到公开配置里。2.4 首次登录、创建项目、生成 API Key服务启动后打开http://localhost:3000。第一次访问会让你注册一个账号这个账号就是管理员。如果是生产环境注册完要尽快关闭公开注册避免别人注册进来看到你的项目数据。登录进去之后界面其实很简单先创建一个 Project也就是项目。进入项目的 Settings找到 API Keys。点击创建系统会生成一对密钥Public Key 和 Secret Key。记下来后面 SDK 初始化需要。Public Key 和 Secret Key 的关系有点像用户名和密码。Public Key 可以出现在客户端配置里但 Secret Key 绝对不能泄露一旦泄露别人就能往你的项目里传数据或读取 trace。所以这两个密钥要放到服务端环境变量或配置中心里不能硬编码在代码仓库。创建好项目、拿到 API KeyLangfuse 服务端基本就绪了。接下来进入真正重要的部分让业务代码把 trace 上报上来。3. 用 Python 跑通第一条 trace才算真正接入3.1 核心概念先理清Trace、Span、Generation、Session在写代码之前我建议先把几个概念搞清楚不然后面看页面会一头雾水。概念含义对应到业务场景Trace一次完整的业务请求用户问一个问题到系统返回最终答案Span一次内部操作检索知识库、拼接 prompt、调用工具Generation一次模型生成调用真正调用 OpenAI 或本地模型的这一次请求Event一条调试事件记录某个中间状态的日志Session多次 trace 的聚合同一个用户的连续多轮对话打个比方Trace 是一条完整流水线Span 是流水线上每个工位Generation 是工位上最核心的那台机器。页面展示的时候你会看到一个层级关系最外层是 Trace里面嵌套 Span 和 GenerationEvent 可能挂在任意节点上。这里有个容易混淆的点不是每次模型调用都要单独建一个 Trace。如果你的业务是一个完整问答流程遇到多次模型调用应该放在同一个 Trace 下的多个 Generation 节点里如果每个请求互相独立再考虑每个请求建一个 Trace。3.2 安装 SDK 并初始化 ClientPython 是 Langfuse 支持最完整的语言官方 SDK 可以直接用 pip 安装pip install langfuse安装完初始化一个 Langfuse 客户端from langfuse import Langfuse langfuse Langfuse( public_keypk-lf-xxxx, secret_keysk-lf-xxxx, hosthttp://localhost:3000 )host 是你部署 Langfuse 的地址本地部署就是 localhost:3000。公钥和私钥要按前面生成的内容替换不要直接用本文的占位符。我通常会建议把这段初始化代码放到一个单独模块里比如langfuse_client.py统一导出避免每个调用方各自初始化不然以后要改 host 或者调整采样配置就得全局搜代码改一遍。3.3 最小接入示例手动创建一条 Trace最简单的接入方式是手动创建 Trace在关键步骤上记录输入输出prompt 请用一句话解释大模型可观测性 trace langfuse.trace(namedemo-question, input{prompt: prompt}) # 模拟一次模型调用 generation trace.generation( namechat-completion, modelgpt-4o-mini, input{messages: [{role: user, content: prompt}]}, output{content: 大模型可观测性是记录和追踪模型调用过程的能力。}, usage{input: 18, output: 24, total: 42} ) generation.end() trace.update(output{answer: 大模型可观测性是记录和追踪模型调用过程的能力。})这段代码跑完后去 Langfuse 页面的 Traces 列表刷新一下应该能看到一条名称为demo-question的 trace点进去能看到一个 generation 节点以及输入输出。如果嫌手动记录麻烦官方也提供了装饰器方式适合把某个函数整体变成一条 tracefrom langfuse.decorators import observe observe() def handle_question(question: str): result call_llm(question) return result装饰器方式的好处是少写很多样板代码坏处是粒度不够细。如果函数内部有多次模型调用你可能还是在函数内部单独创建 generation。我的建议是先用手动方式跑通一条确认链路没问题的前提下再考虑装饰器简化代码。3.4 验证是否真的上报成功写完了发现页面上没有 trace这是新手最常遇到的情况。先别急着改业务代码按这个顺序检查看 host 是否正确。本地部署没问题但如果业务服务在另一个容器里就不能写 localhost要写宿主机 IP 或容器网络里的服务名。看公钥私钥是否是同一个项目下生成的。很多人复制了另一个项目的密钥导致数据写到了别的项目里。看网络是否通。在运行代码的机器上试一下能不能访问http://localhost:3000。看进程是否正常退出。如果脚本跑完就结束了异步上报可能还没来得及发送。这时可以在脚本末尾调用langfuse.flush()或langfuse.shutdown()强制刷新缓冲区。看 SDK 日志。在初始化时设置debugTrue会打印一些上报细节能快速判断请求是否发出去。注意本地测试时建议显式调用langfuse.flush()确认数据已经写入再关掉进程。否则你会以为接入失败实际只是数据还没发出去这个问题非常常见。4. 常见框架和语言怎么接入OpenAI、LangChain、Java4.1 OpenAI SDK 自动埋点Python SDK 提供了一个langfuse.openai入口直接替换原来的 OpenAI 客户端就能自动把模型调用记录成 generationfrom langfuse.openai import openai response openai.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: 你好}] )如果你把它放在一个被observe()装饰的函数里这次模型调用会自动挂在当前 trace 下。如果不在任何 trace 上下文中SDK 会为它单独创建一个 trace。这个模式适合大多数直接调用 OpenAI 接口的项目。它的原理很简单SDK 对 OpenAI 客户端做了一层包装在请求前后把参数和结果截获然后异步上报。对你来说业务代码基本不用改。4.2 LangChain 和 LlamaIndex 的接入方式用 LangChain 的项目通常是用官方提供的回调解法。创建一个 CallbackHandler把它传给 chain 或 LLM 调用即可from langfuse.langchain import CallbackHandler handler CallbackHandler( public_keypk-lf-xxxx, secret_keysk-lf-xxxx, hosthttp://localhost:3000 ) # 在 LangChain 调用时传入回调 llm_response chain.invoke( {question: 你好}, config{callbacks: [handler]} )LangChain 内部会通过回调把每一步的操作反馈给 Langfuse包括使用的模型、prompt、检索结果、最终输出。这样可以降低埋点成本但页面上的 trace 结构会更复杂因为 LangChain 本身的调用链就很深会有很多中间节点。刚开始看会觉得乱习惯之后反而更容易定位问题。LlamaIndex 的接入思路类似也是注册一个 Langfuse callback handler。如果你用其他框架原则是一样的框架有没有官方集成包看文档没有就用手动方式在关键调用前后创建节点。4.3 Java / Spring Boot 的接入思路Java 方向的资料没有 Python 全但官方也提供了 Java SDK 和 Spring Boot 集成包。核心思路仍然是创建一个客户端然后创建 trace 和 generation。大致结构如下LangfuseClient client LangfuseClient.builder() .publicKey(pk-lf-xxxx) .secretKey(sk-lf-xxxx) .baseUrl(http://localhost:3000) .build(); LangfuseTrace trace client.trace() .name(java-demo) .input(Map.of(question, 你好)) .start(); LangfuseGeneration generation trace.generation() .name(chat) .model(gpt-4o-mini) .start(); // 调用模型获取结果 generation.end(); trace.end();这里要注意Java 版本的具体 Maven 坐标和 Spring Boot starter 名称要以 Maven Central 上最新的包名为准。引入依赖后关键是确认版本和你的 JDK 版本匹配。常见坑是 JDK 8 项目遇到只支持 JDK 11 以上的包或者 Spring Boot 2 和 starter 的自动配置不兼容。如果不想引入 SDKLangfuse 也提供 REST 上报接口任何语言都能直接调用。在业务代码里组织好 trace 结构按照接口文档把数据 POST 到/api/public/traces或/api/public/generations鉴权用项目的公钥和私钥。这种方式的优势是通用劣势是需要自己维护 trace 结构和请求逻辑适合特殊场景兜底。4.4 批量任务场景下如何组织 trace很多人一开始只测单条调用觉得很顺等真正跑批量任务时才发现问题。批量任务和单条任务的关注点完全不同单条任务只看能不能跑通批量任务要看输入输出是否一一对应、失败重试是否正常、结果命名是否清晰、占用的上报资源会不会把 Langfuse 打垮。建议这样组织批量场景每个业务样本创建一个独立 trace不要把所有样本塞进一个 trace。虽然 Langfuse 也能在一个 trace 下挂很多节点但页面会非常难读而且一挂一整天排查时根本找不到目标样本。给每个 trace 设置sessionId和userId方便后期按维度筛选。在metadata里带上业务标识比如订单号、任务批次号、文件名称这样在列表页能快速检索。大批量上报时不要循环创建一千个同步请求最好使用 SDK 的批量接口或者调低 SDK 的 flush 间隔让它异步消费。吞吐量这块没有固定标准但你可以观察 Langfuse Worker 容器的 CPU 和内存如果上报速度跟不上业务速度就要考虑扩大 Worker 并发或增加实例。5. 在 trace 页面里调试和优化大模型的思路5.1 先看 trace 详情的水流图Langfuse 的 trace 详情页会把整条调用链以瀑布图形式展开。每个 span 和 generation 从左到右排开宽度表示耗时上下层级表示嵌套关系。我第一次用的时候第一反应是看每条链路的整体耗时然后看哪个节点最宽。如果最宽的是检索节点说明瓶颈在向量库或上下文加载如果最宽的是 generation 节点说明模型生成本身就是耗时大头如果大量时间花在一个不起眼的format节点上那可能只是后处理逻辑写得低效。排查建议是先看链路结构再看节点耗时最后看节点输入输出。不要一上来就怀疑模型很多慢请求其实是检索、重试或格式化造成的。5.2 用 token、成本和延迟定位瓶颈Traces 列表页每一行都会展示 token 消耗、成本和延迟。这里有几个常见观察方式同一个用户反复提问token 总量持续增长说明上下文没有截断多轮记忆把所有历史都塞进去了该清理了。输出 token 占比异常高但回答质量一般可以尝试在 prompt 里限制输出长度或者换一个更便宜的模型。延迟高且集中在 generation 节点优先看模型服务本身的负载再看是不是多次串行调用能并行就并行。成本突然飙升看是不是某个新版本 prompt 引入了大量重复内容或者 embedding 调用次数变多了。这些判断不是 Langfuse 自动给你的而是它提供了数据你需要结合业务逻辑去理解。刚开始跑测试时我会先固定一个问题集每改一次 prompt 或模型就跑一遍然后对比成本和延迟这样能快速筛选出性价比更高的方案。5.3 对比 prompt 版本和单次输出质量优化大模型应用最常做的事情就是改 prompt。改完 prompt怎么知道效果变好了肉眼看不靠谱要能回放同一批问题在不同版本下的输出。Langfuse 的做法是给 trace 和 generation 打上版本标签。比如在 metadata 里写prompt_version: v2或者用它的 prompt 管理功能维护一套版本。之后在详情页里你能直接对比两次相同输入下的输出内容。单独看一两条输出还不够要批量对比。这时可以结合数据集功能把测试问题整理成数据集跑完后在评估列表里逐条看输出。如果只是内部快速验证也可以把 trace 列表按 prompt 版本筛出来一条条翻输出注意观察这几个点是否存在空输出、截断、格式不正确是否对同义问题有一致性token 消耗是否稳定有没有某些问题导致输出特别长是否在特定输入下频繁报错。5.4 全量采集和隐私字段处理接入稳定之后你会发现 trace 数据增长速度非常快。每条 trace 都存完整的输入输出一天可能产生几十万条记录。这时候要考虑两件事采样和敏感信息过滤。Langfuse 支持采样配置你可以只上报一部分请求比如 10%用于监控稳定性和抽样分析但需要注意采样会丢失单条问题排查能力所以生产系统通常按两种策略结合错误请求或慢请求全量上报正常请求按比例采样。在 SDK 初始化时可以按这个思路写逻辑判断当前请求是否要走全量路径。敏感信息是另一个大坑。用户的问题里可能包含手机号、身份证、姓名模型的输出里也可能带出内部数据。如果这些内容直接存进 Langfuse等于把隐私数据复制了一份。处理方式有几种在上报前对输入输出做脱敏替换对某些字段使用 Langfuse 提供的加密存储能力直接不采集内容只保留 token、成本和延迟等运行指标。这个问题越早想越好。等数据量大了再回头清洗成本非常高。6. 生产化落地要关注的配置和排查顺序6.1 该修改的环境变量和鉴权策略如果你只是本地测试用默认配置没有问题。但如果要让团队内多人使用或者部署到公司服务器下面几项必须处理NEXTAUTH_URL改成真实的访问地址否则登录跳转可能异常生成强随机数的SALT、ENCRYPTION_KEY、NEXTAUTH_SECRET不要用示例值初始化完成后关闭公开注册避免外部人员创建账号如果用域名访问在 Nginx 或网关层配置 HTTPSAPI Key 定期轮换轮换时给新 Key 设置合适的权限范围。这几个配置里密钥轮换最容易踩坑。轮换 API Key 之后业务服务的 SDK 配置也要同步更新否则上报会一直报 401。建议把 Key 放到配置中心或环境变量里统一管理而不是散落在每个服务配置文件中。6.2 数据保留与清理trace 数据是无限增长的。按天清数据不现实但至少要做到几点设置合理的日志和数据保留期限比如只保留最近 90 天对历史数据做归档归档到对象存储或单独的分析库定期检查磁盘占用尤其是 ClickHouse 的数据目录明确哪些项目需要长期保存哪些只是临时实验。这个问题现在不处理等日志文件写满磁盘Langfuse 页面查询会变慢甚至影响上报。不要因为只是自托管就忽略运维数据总要有人管。6.3 高可用和多实例小团队内部使用单机部署就够了。但生产环境长期跑我建议至少做到PostgreSQL、ClickHouse、Redis 都使用独立的持久化存储备份数据库备份策略至少覆盖 SALT 和 ENCRYPTION_KEYWeb 和 Worker 可以独立扩容上报量大了就加 Worker 实例升级版本前先备份再按照官方迁移文档操作不要直接跳大版本。如果你发现上报延迟越来越高优先看 Worker 是否积压而不是上来就加 Web 实例。Worker 处理不过来加再多 Web 也没用队列只会越积越长。6.4 常见问题排查顺序最后整理一份我平时排查 Langfuse 问题时最常用的顺序表现象优先检查点页面打不开容器是否启动、3000 端口是否冲突、日志里是否有迁移报错登录后看不到项目当前账号是否是项目成员、是否创建过项目上报了但 trace 列表为空host、公钥私钥、项目选择、是否需要 flush上报返回 401API Key 是否正确、是否过期、是否属于同一项目trace 出现但数据不全SDK 版本和 Langfuse 服务端版本是否兼容查询速度变慢数据量是否过大、ClickHouse 是否正常、磁盘是否快满批量任务偶发丢失Worker 是否积压、批量接口是否有失败重试排查的时候顺序很重要先看现象再看配置再看日志最后看数据。不要一上来就重装服务很多问题只是 Key 配错或者网络不通。注意升级 Langfuse 时先查官方变更说明再备份数据库最后操作。尤其要留意数据库迁移脚本不要跨大版本直接升级容易出现未知兼容问题。最后留一个整体建议。Langfuse 这类工具真正落地时最值得盯住的不是功能列表而是输入输出格式、密钥权限和失败重试。先把单条 trace 跑稳再上批量再谈采样和告警。很多人一开始就把所有调用全部埋点上报结果自己先被日志噪音淹没。按这篇的顺序从一条 trace 开始把监控体系慢慢建完整。