尧图精选

Langfuse实战:构建LLM应用的可观测性中枢

🕒 发布时间:2026/10/1 4:04:55 📁 来源:尧图网络
1. 这不是又一个“安装教程”而是大模型工程落地的观测中枢实战手记Langfuse 这个名字过去两年在 LLM 工程圈子里出现的频率已经不亚于 LangChain 或 LlamaIndex。但很多人第一次接触它是在调试一个 RAG 流程时发现明明 prompt 写得没问题embedding 模型也换了三轮为什么 top-k 检索结果还是错得离谱或者在上线一个 Agent 服务后用户反馈“回答很慢但又说不出哪里慢”日志里只有零星几行 HTTP 状态码根本没法定位是 tool call 卡在了数据库、还是 LLM 回复被流式中断、抑或是 memory 缓存失效导致重复计算——这时候你才真正意识到LLM 应用不是写完代码就能跑通的黑盒它是一套需要可观测性的新基础设施。我从 2023 年底开始把 Langfuse 接入团队三个核心项目一个面向医疗知识库的 RAG 助手、一个调度多工具的金融风控 Agent、还有一个基于本地 Ollama Chroma 的政务文档摘要系统。不是为了“跟风上 Observability”而是被真实问题逼出来的——我们花了 3 天时间排查一个看似简单的“检索命中率低”问题最后发现根源是 embedding 模型在 batch inference 时对长文本做了截断而这个行为在原始 API 文档里只用一行小字标注没有任何 warning 日志。Langfuse 让我们第一次看清了 LLM 调用链路上每个环节的输入、输出、耗时、token 消耗、甚至中间状态比如 RAG 中 retrieval 结果、re-rank 排序分数、prompt template 渲染后的完整字符串。它不是替代 Prometheus 或 Grafana而是专门为 LLM 场景设计的“神经突触成像仪”你能看到 token 是怎么一层层流动的context 是如何被拼接的agent 的 decision tree 是怎样分支的。这篇内容不讲概念定义不列功能清单也不做版本对比。它完全基于我在生产环境踩过的坑、调过的参数、改过的 SDK 配置、重写的 trace hook以及和运维同事一起压测自托管集群时的真实数据。你会看到如何用不到 20 行代码让 Langfuse 自动捕获 LangChain 的 chain 执行全过程包括每个 Runnable 的输入输出、metadata 标签、error 堆栈怎样在 RAG pipeline 中插入 custom span精准测量 retrieval latency、rerank 开销、LLM 生成耗时的占比而不是笼统地看整个 endpoint 的 P95Agent 开发中最容易被忽略的“状态漂移”问题——当同一个 user_id 在不同 session 中触发不同 toolLangfuse 的 trace lineage 如何帮你快速回溯决策路径自托管部署时PostgreSQL 连接池配置不当导致的 trace 写入堆积以及如何用 pg_stat_activity 实时诊断V4 版本评估闭环的核心变化从“人工打分表”到“自动评估 workflow”的迁移实操包括如何定义 custom evaluator、如何接入 GPT-4-turbo 作为 judge model、如何设置 threshold 触发告警。适合谁读如果你正在用 LangChain / LlamaIndex / Ollama / vLLM 构建真实业务系统而不是跑 demo如果你的团队已经开始讨论“LLM 成本优化”“RAG 准确率提升”“Agent 可靠性 SLA”而不是还在纠结“该选哪个开源模型”如果你的监控面板上还只有 CPU 和内存曲线而没有 token usage heatmap 或 retrieval hit rate trendline——那么这篇就是为你写的。它不假设你熟悉 OpenTelemetry也不要求你部署过 Jaeger所有操作都从最简路径出发每一步都有参数依据、效果验证和避坑提示。2. Langfuse 的本质不是日志收集器而是 LLM 应用的“手术显微镜”2.1 它解决的不是“有没有日志”而是“日志能不能回答关键问题”传统 APM 工具如 Datadog、New Relic能告诉你某个 API 请求耗时 2.3sHTTP 状态码 200但无法告诉你这 2.3s 里LLM 生成占了多少RAG 检索占了多少tool call 占了多少输入给 LLM 的 prompt 是什么是否包含了预期的 contextcontext 里有没有混入无关文档LLM 输出的 response 是否被 post-process 截断是否触发了 safety guard 导致 fallback如果是 Agent它调用了哪些 tool每个 tool 的 input/output 是什么decision 的依据是什么Langfuse 的设计哲学就是把 LLM 应用的执行过程拆解成可观察、可度量、可关联的原子单元。它的核心抽象不是 “trace”虽然底层兼容 OpenTelemetry而是observation—— 一个 observation 可以是Generation一次 LLM 调用记录 model、input、output、usageprompt_tokens/completion_tokens、latency、temperature 等Span一个逻辑执行单元比如 “retrieval step”、“rerank step”、“tool execution”可以嵌套、可以标记 metadataTrace一个用户请求的完整生命周期由多个 observation 组成支持跨 service 关联比如前端 → API gateway → RAG service → LLM serviceDataset EvaluationV4 引入的核心能力把测试样本、评估指标、judge model 封装成可复用、可版本化的评估 workflow。提示不要把 Langfuse 当作“另一个日志平台”。它的价值不在存储量而在结构化深度。一个 Generation observation 存储的不只是字符串而是带 schema 的 JSON{ input: { messages: [...] }, output: { content: ..., tool_calls: [...] }, usage: { prompt_tokens: 1280, completion_tokens: 245 } }。这意味着你可以直接用 SQL 查询“找出所有 completion_tokens 1000 且 prompt_tokens 500 的 generation它们的 output.content 是否包含‘请参考’字样”——这种查询在纯文本日志里几乎不可能高效实现。2.2 为什么必须自托管公有云版的三大硬伤Langfuse 提供 SaaS 版本langfuse.com对个人开发者或 PoC 项目确实方便。但在企业级 LLM 应用中我们最终全部切换到了自托管。原因很实际第一数据主权与合规红线。我们的医疗 RAG 系统处理的是脱敏后的患者检验报告和药品说明书虽然不包含身份证号、手机号等 PII但根据《医疗卫生机构信息系统安全管理办法》所有涉及健康数据的系统日志必须本地留存、不可外传。SaaS 版本的数据传输路径client → Langfuse cloud → your DB意味着原始 prompt、retrieved documents、LLM output 全部经过第三方服务器。即使启用 encryption at rest也无法规避传输过程中的潜在风险。自托管后所有流量只在内网流转DB 连接走 private subnetaudit log 可对接公司 SIEM 系统。第二性能瓶颈与 trace 写入延迟。SaaS 版本的 ingestion endpoint 有明确的 rate limit免费版 100 req/minPro 版 1000 req/min。在压测阶段我们的 Agent 服务单节点 QPS 达到 80每个请求产生 5~8 个 observationretrieval span 2x tool call spans 1x generation瞬间就触发限流。更严重的是当网络抖动时Langfuse SDK 的默认 retry 策略会阻塞主线程导致整个 LLM 请求超时。自托管后我们把 PostgreSQL 部署在同 AZwrite latency 稳定在 8~12msSDK 的 batch flush 机制默认 100ms 或 10 items完全满足高并发需求。第三定制化与集成深度受限。SaaS 版本的 UI 和 API 是标准化的无法添加 custom field、无法修改 evaluation result schema、无法对接内部 auth system如 LDAP。而我们的风控 Agent 需要按业务线打标business_line: credit_risk、按审批等级打标approval_level: L2这些 metadata 必须在 trace 创建时注入并在 dashboard 上做下钻分析。自托管版本允许我们直接修改langfuse-server的 GraphQL schema新增字段并同步到 frontend。注意自托管不等于“自己编译源码”。Langfuse 官方提供 Docker Compose 部署脚本https://github.com/langfuse/langfuse/tree/main/docker支持 PostgreSQL Redis Next.js frontend 一键启动。我们线上用的是 Kubernetes Helm chart官方维护但初期验证完全可以用docker-compose up -d在一台 8C16G 的机器上跑通全链路。2.3 V4 版本评估闭环从“人工抽查”到“自动质量门禁”V4 最大的变革是把“评估”从一个独立模块变成了 trace 生命周期的内置环节。旧版V3的评估流程是导出 trace 数据 → 人工挑选样本 → 用 Excel 打分 → 汇总统计。这导致两个问题评估滞后、标准不一、无法回溯。V4 的评估闭环Evaluation Workflow解决了这个问题Dataset不再是 CSV 文件而是数据库里的 first-class entity。你可以为不同场景创建 dataset比如medical_qa_testset_v2、finance_agent_benchmark_2024q3。每个 sample 包含inputuser query、expected_outputgolden answer、metadata如 difficulty level, domain tag。Evaluator支持三种类型Rule-based用正则、关键词匹配、Jinja2 模板判断例如{{ output | contains(contraindication) }}LLM-as-a-judge调用外部 LLM如 GPT-4-turbo、Claude-3-haiku作为裁判输入 prompt 定义评分标准例如 “请根据以下 criteria 给 response 打分1. 准确性0-52. 完整性0-53. 无害性0-5”Custom Python写一个函数接收trace,dataset_item,output返回score和reason。Evaluation Run绑定 dataset evaluator target traces可按 filter 条件筛选如tags [rag_v2] AND start_time 2024-06-01一键触发。结果实时写入evaluations表并自动关联到 source trace。我们用这套机制实现了“质量门禁”每次 RAG pipeline 发布新版本前CI/CD 流水线自动触发 evaluation run如果accuracy_score 0.85或harm_score 0.1则阻断发布。这比人工 review 效率高 10 倍且保证了每次迭代都有可量化的效果验证。3. 实战四步法从零搭建可观测性基座含 LangChain/Ollama/Agent 全场景适配3.1 环境准备与自托管部署避开 PostgreSQL 连接池陷阱自托管部署的核心是 Langfuse ServerNode.js PostgreSQL存储 Redis缓存/队列。我们采用 Helm Chart 部署到阿里云 ACK 集群但这里先给出最简 Docker Compose 方案确保你能 10 分钟跑通# docker-compose.yml version: 3.8 services: langfuse-postgres: image: postgres:15-alpine environment: POSTGRES_DB: langfuse POSTGRES_USER: langfuse POSTGRES_PASSWORD: langfuse_password volumes: - ./postgres-data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U langfuse] interval: 30s timeout: 10s retries: 5 langfuse-redis: image: redis:7-alpine command: redis-server --save 60 1 --loglevel warning healthcheck: test: [CMD, redis-cli, ping] interval: 30s timeout: 10s retries: 5 langfuse-server: image: langfuse/langfuse:latest environment: DATABASE_URL: postgresql://langfuse:langfuse_passwordlangfuse-postgres:5432/langfuse REDIS_URL: redis://langfuse-redis:6379 NEXT_PUBLIC_LANGFUSE_CLOUD_REGION: LANGFUSE_SECRET_KEY: sk-lf-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx NEXT_PUBLIC_LANGFUSE_PUBLIC_KEY: pk-lf-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # 关键配置避免连接池耗尽 DATABASE_POOL_MAX: 20 # 默认是 10高并发需调大 DATABASE_POOL_MIN: 5 # 启用批量写入降低 I/O 压力 LANGFUSE_FLUSH_INTERVAL_MS: 100 LANGFUSE_FLUSH_QUEUE_SIZE: 10 depends_on: langfuse-postgres: condition: service_healthy langfuse-redis: condition: service_healthy ports: - 3000:3000关键参数解析与避坑DATABASE_POOL_MAX这是最容易被忽略的致命参数。PostgreSQL 默认 max_connections100但 Langfuse Server 的 connection pool 会占用一部分。如果设为默认 10在 QPS 50 时pool exhaustion 会导致 trace 写入失败错误日志显示Error: connect ECONNREFUSED。我们线上设为 20配合pgbouncer做连接池复用。LANGFUSE_FLUSH_*Langfuse SDK 默认使用内存 buffer 批量写入。FLUSH_INTERVAL_MS100意味着最多等待 100ms 或积累 10 个 observation 才 flush。这能显著降低 DB write QPS但会引入最多 100ms 的观测延迟。对于 debug 场景可设为10对于生产监控100是平衡点。REDIS_URLRedis 不仅用于 cache还用于 background job queue如 async evaluation run。如果省略evaluation 会同步执行拖慢 API 响应。部署后访问http://localhost:3000用初始账号adminlangfuse.com/password登录。首次登录会引导创建 project记住生成的public_key和secret_key——这是后续 SDK 初始化的凭证。3.2 LangChain 集成自动捕获 Chain 执行细节无需修改业务代码LangChain 是目前最主流的 LLM orchestration 框架Langfuse 提供了开箱即用的LangchainCallbackHandler。但直接使用官方示例往往捕获不到关键信息。以下是经过生产验证的配置from langfuse import Langfuse from langfuse.langchain import LangchainCallbackHandler from langchain_core.runnables import RunnableConfig from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA # 初始化 Langfuse client注意不是 SDK 的 Langfuse()而是 Langfuse 对象 langfuse Langfuse( public_keypk-lf-xxx, secret_keysk-lf-xxx, hosthttp://localhost:3000 ) # 创建 callback handler关键参数 handler LangchainCallbackHandler( langfuse_clientlangfuse, # 必须开启否则不会捕获 intermediate steps releaseTrue, # 为每个 trace 添加业务标签便于 dashboard 过滤 tags[rag_v2, prod], # 设置 trace name避免默认的 langchain 太泛 session_iduser_12345, # 可动态传入 # 重要启用 metadata 透传让 custom metadata 可见 update_stateTrue ) # 构建你的 chain以 RetrievalQA 为例 llm ChatOpenAI(model_namegpt-3.5-turbo, temperature0) qa_chain RetrievalQA.from_chain_type( llmllm, retrievervectorstore.as_retriever(), chain_typestuff, return_source_documentsTrue # 确保 retrieval 结果被捕获 ) # 调用时传入 handler result qa_chain.invoke( {query: 高血压患者服用阿司匹林的禁忌症有哪些}, configRunnableConfig(callbacks[handler]) # 关键必须通过 config 传入 )实操心得return_source_documentsTrue是 RAG 可观测性的基石。Langfuse 会自动将source_documents解析为retrievalspan并记录每个 document 的page_content、metadata如 source file、chunk id。没有它你就只能看到 LLM 的 input/output看不到 retrieval 的质量。session_id不要硬编码。建议从 request header如X-Request-ID或 JWT token 中提取这样同一个用户会话的所有 trace 会自动聚合成一条 lineage。tags是 dashboard 分组的灵魂。我们按[model:gpt-4, pipeline:rag, env:staging]打标dashboard 上就能一键筛选“所有 staging 环境的 gpt-4 RAG trace”。部署后访问 Langfuse dashboard → Traces你会看到一条 trace展开后有清晰的 hierarchyRetrievalQA(root span)Retriever(span, typeretrieval, inputquery, outputdocuments)StuffDocumentsChain(span, typellm, inputprompt, outputanswer)每个 span 都有 duration、input/output preview、metadata。3.3 RAG 调试排错用 retrieval hit rate 和 context relevance 定位瓶颈RAG 的最大痛点是“黑盒检索”——你不知道为什么召回结果不准。Langfuse 让你把 retrieval 拆解成可度量的环节Step 1测量 retrieval hit rateHit rate query 的 golden answer 在 retrieved docs 中出现的次数/ 总 query 数。这不是 Langfuse 内置指标但你可以用 SQL 计算-- 查询所有 retrieval span提取 retrieved doc ids 和 golden answer source SELECT t.id as trace_id, s.input as query, s.output-document_ids as retrieved_ids, d.expected_output-source_doc_id as golden_doc_id, CASE WHEN s.output-document_ids LIKE % || d.expected_output-source_doc_id || % THEN 1 ELSE 0 END as is_hit FROM traces t JOIN observations s ON t.id s.trace_id AND s.type SPAN AND s.name Retriever JOIN datasets_items d ON d.input-query s.input WHERE t.tags ARRAY[rag_v2];我们发现 hit rate 从 0.62 提升到 0.89是因为把 embedding model 从text-embedding-ada-002换成了bge-m3并在 chunking 时增加了 overlap50。Step 2评估 context relevance即使 hit rate 高retrieved context 也可能 irrelevant。我们用 LLM-as-judge evaluator# 定义 evaluator prompt relevance_prompt 你是一个专业的医疗信息评估员。请根据以下 criteria 评估 retrieved context 对 user query 的相关性 - 相关性context 是否直接回答 query 的核心问题0-5分 - 精准性context 是否包含 query 所需的具体事实如药物名、剂量、禁忌0-5分 - 冗余度context 是否包含大量无关的背景描述0-5分分数越低越冗余 user query: {{ input.query }} retrieved context: {{ output.retrieved_context }} 请只输出 JSON{relevance_score: x, precision_score: y, redundancy_score: z, reason: ... } # 创建 evaluator evaluator LangfuseEvaluator( namemedical_context_relevance, promptrelevance_prompt, modelgpt-4-turbo, score_mapping{ relevance_score: lambda x: x.get(relevance_score, 0), precision_score: lambda x: x.get(precision_score, 0), redundancy_score: lambda x: 5 - x.get(redundancy_score, 0) # 取反 } )运行 evaluation 后dashboard 上会出现context_relevance_score指标。我们发现 precision_score 低原因是 chunk size 太大512 tokens导致一个 chunk 包含了“阿司匹林适应症”和“禁忌症”两部分内容LLM 在生成时混淆了重点。解决方案将 chunk size 降到 256并用semantic_chunker基于句子边界分割。3.4 Agent 调试追踪 decision tree 与 state driftAgent 的复杂性在于其非线性执行路径。一个 query 可能触发search_web→read_pdf→summarize→generate_report也可能只触发search_web。Langfuse 的 trace lineage 能清晰展示这条路径from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain.tools import Tool # 定义 tools def search_web(query: str) - str: # 模拟搜索 return fWeb results for {query} def read_pdf(pdf_path: str) - str: # 模拟读取 return fContent of {pdf_path} web_search_tool Tool( nameweb_search, funcsearch_web, descriptionSearch the web for current information ) pdf_reader_tool Tool( namepdf_reader, funcread_pdf, descriptionRead and extract text from a PDF file ) # 创建 agent agent create_tool_calling_agent( llmllm, tools[web_search_tool, pdf_reader_tool], promptagent_prompt ) agent_executor AgentExecutor(agentagent, tools[web_search_tool, pdf_reader_tool], verboseTrue) # 调用时传入 handler result agent_executor.invoke( {input: 请分析这份财报/data/q2_2024.pdf中的营收增长原因并对比去年Q2数据}, configRunnableConfig(callbacks[handler]) )在 Langfuse dashboard 的 trace 中你会看到AgentExecutor(root)Agent(span, typellm, inputprompt, outputtool_calls)web_search(span, typetool, inputquery, outputresults)pdf_reader(span, typetool, inputpath, outputcontent)Agent(span, typellm, inputfinal_prompt, outputanswer)关键洞察state drift问题同一个 user_id 在不同 session 中agent 可能因 memory 不一致而选择不同 tool。Langfuse 的session_id关联所有 trace你可以对比session_idA和session_idB的 decision path发现session_idA的 memory 包含了“用户偏好简洁回答”所以跳过了web_search直接pdf_reader而session_idB的 memory 为空所以先web_search。解决方案在 agent memory 初始化时强制注入 user profile。tool call failure定位如果pdf_readerspan 的 status 是ERRORoutput 会显示FileNotFoundError而 input 是/data/q2_2024.pdf——这说明文件路径配置错误而非 LLM 问题。4. V4 评估闭环实战构建自动化质量门禁含 GPT-4-turbo judge 配置4.1 Dataset 构建从 CSV 到结构化测试集V4 的 Dataset 不再是静态文件而是数据库实体。创建方式有两种UI 创建Dashboard → Datasets → Create Dataset → Upload CSV。CSV 格式必须包含inputJSON string和expected_outputJSON string。例如inputexpected_output{query: 糖尿病患者可以吃芒果吗, user_profile: {age: 52, complications: [retinopathy]}}{answer: 可以适量食用但需控制总量..., sources: [diabetes_diet_guideline_v3.pdf]}API 创建推荐便于 CI/CDcurl -X POST http://localhost:3000/api/datasets \ -H Authorization: Bearer sk-lf-xxx \ -H Content-Type: application/json \ -d { name: medical_qa_testset_v2, description: Test set for diabetes and hypertension queries, items: [ { input: {query: 糖尿病患者可以吃芒果吗}, expected_output: {answer: 可以适量食用...} } ] }经验技巧input字段必须是 JSON object不能是纯 string。因为 evaluator 需要解析input.query。expected_output不必完美但必须包含关键事实。我们用diff工具比对 LLM output 和 expected_output 的语义相似度而非 exact match。4.2 LLM-as-Judge 配置用 GPT-4-turbo 实现低成本高精度评估Rule-based evaluator 适合简单规则如“是否包含关键词”但对“答案准确性”“逻辑连贯性”等复杂维度LLM-as-judge 更可靠。我们选择 GPT-4-turbogpt-4-turbo-2024-04-09因为它 cost 低$0.01/1K input tokens、响应快 2s、且支持 128K context能容纳长 prompt 和长 output。Prompt 设计要点角色定义清晰你是一个资深医疗编辑负责审核 AI 生成的患者教育内容。评分标准具体避免模糊表述。例如不写“回答是否准确”而写“回答是否包含以下三个事实1. 芒果升糖指数为 512. 单日摄入不超过 100g3. 需监测餐后血糖”。输出格式严格强制 JSON便于 parser 解析。防幻觉指令如果 output 中包含未在 input 或 expected_output 中提及的信息请在 reason 中指出并给 accuracy_score 扣分。完整 prompt 示例你是一个资深医疗编辑负责审核 AI 生成的患者教育内容。请根据以下 criteria 严格评估 output 的质量 1. 准确性0-5分output 是否包含 input query 的所有关键事实是否与 expected_output 一致是否存在虚构信息 2. 完整性0-5分output 是否覆盖了 query 的所有子问题是否遗漏重要细节如剂量、禁忌、监测指标 3. 可读性0-5分output 是否使用患者能理解的语言是否避免专业术语是否分段清晰 input query: {{ input.query }} expected_output: {{ expected_output.answer }} output: {{ output.answer }} 请只输出 JSON格式如下 { accuracy_score: 4, completeness_score: 5, readability_score: 4, reason: 准确提到了芒果GI值和摄入量但未提及餐后血糖监测... }成本与性能权衡GPT-4-turbo 的 input token cost 是 $0.01/1K一个评估 prompt input output 约 1200 tokens单次 cost ≈ $0.012。我们设置batch_size5即每次 API call 评估 5 个 samplescost 降至 $0.06latency 仍 5s。为防 rate limit我们在 Langfuse server 的evaluator配置中设置了concurrency_limit3。4.3 Evaluation Run 与质量门禁CI/CD 中的自动拦截Evaluation Run 是 V4 的核心 workflow。创建方式Dashboard → Evaluations → Create Evaluation → Select Dataset Evaluator Filter。Filter 配置实战trace_filter:tags ARRAY[rag_v2] AND start_time 2024-06-01—— 只评估新版本的 trace。sample_rate:0.3—— 随机采样 30% 的 trace避免全量评估压力过大。thresholds:{ accuracy_score: { min: 4.2 } }—— 如果平均 accuracy_score 4.2则 evaluation run status 为FAILED。CI/CD 集成GitHub Actions 示例# .github/workflows/eval.yml name: RAG Evaluation on: push: branches: [main] paths: [rag_pipeline/**] jobs: evaluate: runs-on: ubuntu-latest steps: - name: Trigger Langfuse Evaluation run: | curl -X POST http://langfuse.internal/api/evaluations \ -H Authorization: Bearer ${{ secrets.LANGFUSE_SECRET_KEY }} \ -H Content-Type: application/json \ -d { datasetName: medical_qa_testset_v2, evaluatorName: medical_accuracy_judge, traceFilter: tags ARRAY[rag_v2], thresholds: {accuracy_score: {min: 4.2}} } - name: Check Evaluation Result run: | # 轮询 evaluation run status STATUS$(curl -s http://langfuse.internal/api/evaluations/latest?datasetNamemedical_qa_testset_v2 \ -H Authorization: Bearer ${{ secrets.LANGFUSE_SECRET_KEY }} | jq -r .status) if [ $STATUS ! SUCCESS ]; then echo Evaluation FAILED. Blocking deployment. exit 1 fi这个 workflow 让我们把“质量验收”从发布后移到了发布前每次迭代都有客观数据支撑。5. 常见问题与独家排错指南那些官方文档没写的坑5.1 Trace 丢失的五大原因及诊断方法Trace 丢失是最常见的问题表现是 dashboard 上看不到任何数据。按发生概率排序原因现象诊断命令解决方案SDK 初始化失败langfuse.log显示Failed to initialize Langfuse clientkubectl logs -f langfuse-server-xxx | grep -i init检查hostURL 是否可达curl -v http://langfuse.internal:3000/health确认public_key/secret_key正确PostgreSQL 连接池耗尽langfuse-server日志频繁出现Error: connect ECONNREFUSED或timeoutkubectl exec -it postgres-pod -- psql -U langfuse -c SELECT * FROM pg_stat_activity WHERE state idle in transaction;增加DATABASE_POOL_MAX或在 Langfuse Server 前加pgbouncerRedis 连接超时evaluation run 卡住status 一直是RUNNINGkubectl exec -it redis-pod -- redis-cli ping检查 Redismaxmemory配置增加maxmemory-policy allkeys-lruBatch flush 配置不当trace 延迟高达数分钟kubectl logs -f langfuse-server-xxx | grep -i flush将LANGFUSE_FLUSH_INTERVAL_MS从1000改为100LANGFUSE_FLUSH_QUEUE_SIZE从100改为10LangChain config 未传递只有 root trace没有 spans在 chain invoke 时加print(handler)确认 handler 被创建必须通过configRunnableConfig(callbacks[handler])传入不能只callbacks[handler]提示Langfuse Server 的/healthendpoint 返回详细状态。一个健康的响应是{status:ok,database:ok,redis:ok,queue:ok}。任何一项为error都对应上述问题。5.2 RAG 观测中的“幽灵 context”为什么 retrieved documents 显示为空现象trace 中Retrieverspan 的output字段是空数组[]但业务代码明确调用了retriever.invoke()并返回了 documents。根因分析LangchainCallbackHandler 默认只捕获retriever.get_relevant_documents()的返回而某些 retriever如MultiQueryRetriever的执行逻辑在invoke()方法里且get_relevant_documents()是空实现。解决方案方法一推荐强制使用as_retriever()并指定search_typesimilarityretriever vectorstore.as_retriever( search_typesimilarity, search_kwargs{k: 5} )方法二自定义 retriever wrapperclass ObservableRetriever: def __init__(self, retriever): self.retriever retriever def get_relevant_documents(self, query: str): docs self.retriever.get_relevant_documents(query) # 手动创建 span langfuse.trace( namecustom_retrieval, inputquery, output[doc.page_content for doc in docs] ) return docs5.3 Agent 的 tool call 参数混淆
上一篇/下一篇内容由系统自动关联 返回资讯列表 →