RAG 2026-07-15 105 次浏览

从黑盒到可量化:基于 Langfuse + RAGAS 构建生产级 RAG 可观测与评测体系

系统拆解 Langfuse 全链路可观测与 RAGAS 量化评测的组合方案,覆盖 RAG 分层埋点、Dataset、Bad Case、回归评测、发布门禁与生产安全。

从黑盒到可量化:基于 Langfuse + RAGAS 构建生产级 RAG 可观测与评测体系

RAG 系统最难处理的问题,往往不是“模型能不能回答”,而是当答案出现错误时,我们无法快速说清:究竟是问题改写偏了、知识没有召回、重排丢掉了关键文档、Prompt 约束不足,还是模型在脱离上下文自由发挥。

Demo 阶段可以靠开发者逐条查看答案,生产阶段却不能继续依赖“感觉不错”。真实流量会带来长尾问题、复杂会话、成本波动和不可重复的偶发故障。如果系统只有接口日志和最终答案,就仍然是一个黑盒。

一套真正可用的 RAG 工程体系,需要同时回答两个问题:

  • 发生了什么?——通过 Langfuse 记录完整调用链,定位问题所在环节。
  • 回答得怎么样?——通过 RAGAS 将检索与生成质量转化为可比较的指标。

本文围绕这两个问题,给出一套从在线观测、Bad Case 沉淀到离线回归评测的生产级设计。

一、为什么传统监控不够

Prometheus、Grafana 和常规 APM 非常适合观察 QPS、错误率、数据库耗时和 HTTP 延迟,但 RAG 的故障通常具有明显的语义属性。

例如,一次请求返回 200、总耗时 1.8 秒,从传统监控看一切正常,但实际可能发生了以下问题:

  • Query 改写改变了用户原意;
  • 向量检索没有召回关键资料;
  • TopK 中混入大量相似但无关的文档;
  • Reranker 把真正有价值的文档排到了后面;
  • 上下文超过预算被截断;
  • 模型生成了检索材料中不存在的事实;
  • Prompt 或模型版本变化导致效果回退;
  • Token 消耗突然增加,但无法定位增加在哪一步。

这些问题仅靠 CPU、接口延迟和错误码无法解释。LLM 应用需要额外观测 Prompt、Completion、Context、Token、模型参数、检索结果、语义评分以及每个业务步骤的父子关系。

二、总体设计:可观测与评测分工

Langfuse 与 RAGAS 解决的是两个相互衔接、但并不相同的问题。

组件核心职责主要产物
Langfuse记录和还原一次请求的执行过程Trace、Span、Generation、Token、成本、异常和业务标签
RAGAS判断检索与生成结果的质量Faithfulness、Answer Relevancy、Context Precision、Context Recall 等分数

两者组合后的数据流如下:

线上 RAG 请求
  → Langfuse 记录完整 Trace
  → 发现低分、投诉或异常样本
  → 沉淀为 Dataset
  → RAGAS 批量评测候选版本
  → 分数回写并比较
  → 达到门禁后发布

Langfuse 让问题“看得见”,RAGAS 让效果“比得出”。真正的价值不在于两个工具分别部署成功,而在于它们形成同一条数据闭环。

三、RAG 全链路应该怎样埋点

Langfuse 通常使用三层观测模型:

  • Trace:一次完整用户请求或 Agent 任务;
  • Span:请求中的一个业务步骤,可以继续嵌套;
  • Generation:真正调用大模型的叶子节点。

对标准 RAG 流程,可以采用下面的分层方式。

RAG 全链路与 Trace 分层

1. 根 Trace:记录完整请求

根 Trace 应当承担全局索引作用,至少包含:

  • user_idsession_id
  • 环境、应用、租户和渠道;
  • RAG 版本、Prompt 版本、模型版本;
  • 原始问题、最终答案;
  • 总耗时、总 Token、总成本;
  • 请求状态、异常类型、用户反馈和最终评分。

这些字段决定了后续能否按照用户、会话、版本和环境进行筛选与对比。

2. Query 改写 Span

记录原始问题、改写后问题、改写策略、意图识别结果和耗时。

出现检索偏差时,第一步应确认改写后的 Query 是否仍然忠于用户意图。很多“向量库检索不准”,根因其实发生在检索之前。

3. 向量检索 Span

建议记录:

  • 实际检索 Query;
  • 知识库和索引版本;
  • Embedding 模型版本;
  • TopK、相似度阈值;
  • 召回文档 ID、标题、片段和分数;
  • 检索耗时。

生产环境不要无节制地保存完整敏感文档。可以根据数据等级保存摘要、Hash、文档 ID 或经过脱敏的片段,并配置访问控制与留存周期。

4. 重排与过滤 Span

记录重排模型、过滤规则、重排前后数量、各文档分数,以及最终送入模型的 Context 列表。

这个节点能回答两个关键问题:关键文档是否被错误过滤,以及噪声文档是否占用了上下文窗口。

5. Generation 节点

Generation 专门描述模型调用,应记录:

  • Prompt 模板及版本;
  • 实际输入的 Context;
  • 模型、温度、最大输出长度等参数;
  • 模型输出;
  • Input、Output Token;
  • 首 Token 延迟、总推理耗时;
  • 重试、限流和异常信息。

如果使用的模型 SDK 不能自动返回 Token Usage,需要在适配层补充,否则成本分析会出现数据缺口。

四、上下文传播:从 Demo 走向生产

原型项目可以直接在关键函数上增加 @observe 装饰器。嵌套调用时,SDK 会自动建立父子关系,接入成本很低。

生产系统还需要动态注入用户、会话、版本和租户信息。这时应利用 OpenTelemetry Context,在入口处写入 Trace 属性,让下游 Span 自动继承。

@observe(as_type="chain")
def rag_pipeline(question, user_id, session_id):
    span = trace.get_current_span()
    span.set_attribute("langfuse.user.id", user_id)
    span.set_attribute("langfuse.session.id", session_id)
    span.set_attribute("app.rag.version", "rag-2026-07")

    rewritten = rewrite_query(question)
    docs = retrieve(rewritten)
    contexts = rerank(docs)
    return generate_answer(question, contexts)

进程内通常通过 contextvars 隐式传播;跨服务调用则应使用 W3C Trace Context,通过 traceparent Header 传递 Trace ID 和父 Span ID。这样,网关、RAG 服务、模型网关和工具服务才能串成一条完整链路。

如果系统基于 LangGraph 构建 Agent,可以在 graph.invoke() 外层建立根节点,每个 Node 建立 Span,每次模型调用建立 Generation。条件分支、循环重试和工具调用因此都会呈现在同一棵链路树中。

五、RAGAS 如何量化 RAG 质量

仅仅记录链路还不够。我们还需要将“这次回答好不好”转化为稳定指标。

Faithfulness:是否忠于上下文

用于判断答案中的事实是否能够从检索 Context 中得到支持。分数低通常意味着模型产生了幻觉,或者上下文本身不足以支撑回答。

Answer Relevancy:是否回答了问题

用于判断答案与用户问题是否相关。它可以发现答非所问、过度发散或大量无关内容。

Context Precision:召回内容是否有效

用于观察召回结果中真正有用的信息占比。分数低说明检索噪声过多,可能需要调整 Query、TopK、Chunk、Embedding 或 Reranker。

Context Recall:需要的信息是否被召回

用于判断回答问题所需的关键信息是否出现在 Context 中。分数低通常意味着知识缺失或漏召回。

需要注意:不同 RAGAS 版本对数据字段和指标定义可能存在变化;部分指标可以在没有标准答案时运行,部分指标则需要 Reference 或 Ground Truth。升级版本时应固定依赖、校验输入 Schema,并用一小批已知样本检查评分口径是否变化。

六、Dataset 是整套体系的枢纽

线上 Trace 只是事实记录,Dataset 才能把一次事故转化为可重复验证的资产。

建议从以下渠道持续收集样本:

  • 用户明确点踩或投诉;
  • 人工审核发现的典型错误;
  • RAGAS 自动评分低于阈值;
  • 线上异常、超时或高成本请求;
  • 新业务场景和高风险问题;
  • 历史版本曾经修复过的缺陷。

Dataset 中至少保留 questionanswercontexts,并根据指标需要补充 reference。同时保存业务分类、难度、风险等级、语言、数据来源和脱敏状态。

一个常见误区是直接把模型的实际回答当成 expected_output。实际回答不等于标准答案。如果某项指标依赖参考答案,应由业务专家修正,或者从可信数据源构造 Reference。

七、建立可持续的质量闭环

RAG 监控、评测与发布闭环

推荐将整个流程固化为五个阶段。

阶段一:线上观测

Langfuse 实时记录调用链、成本、延迟和异常。监控系统对高错误率、高 Token、低评分和关键字段缺失建立告警。

阶段二:Bad Case 沉淀

将具有代表性的失败样本加入 Dataset,并标注根因:改写、检索、重排、上下文、Prompt、模型或数据问题。

阶段三:离线批量评测

使用同一份 Dataset 对不同候选方案执行 RAGAS:

  • Prompt A 与 Prompt B;
  • Embedding 模型 A 与模型 B;
  • 不同 Chunk Size 和 Chunk Overlap;
  • 不同 TopK、相似度阈值和 Reranker;
  • 不同生成模型与参数。

阶段四:发布门禁

不要只比较平均分。至少同时观察:

  • 各指标均值与 P10 等低分位;
  • 严重失败率;
  • 核心场景通过率;
  • 延迟与成本变化;
  • 相对上一版本的回退样本数量。

只有质量、性能和成本共同达标,候选版本才允许进入灰度。

阶段五:灰度验证与回写

线上按版本 Tag 区分流量,将 RAGAS 分数、人工反馈和业务结果回写原始 Trace,比较离线评测与真实用户反馈是否一致。如果偏差明显,需要调整 Dataset 的样本分布和评分标准。

八、生产环境不能忽略的工程细节

1. 异步上报与 Flush

Langfuse SDK 通常使用本地缓冲和异步批量上报。短生命周期脚本退出前应显式 flush();常驻服务应在优雅退出阶段刷新缓冲区。不要在每个请求中无条件执行阻塞式 Flush,否则观测组件可能反过来增加业务延迟。

2. 采样与留存

低风险正常流量可以采样,高风险请求、异常请求和低分样本应尽量全量保存。Prompt、Context 和模型输出体积较大,应分别设置热数据、冷数据和删除周期。

3. 数据安全

在 SDK 或模型网关入口统一进行脱敏,避免身份证号、手机号、密钥和企业机密进入观测平台。生产环境应配置项目隔离、最小权限、审计日志和数据删除能力。

4. 版本可追溯

每条 Trace 都应携带应用、Prompt、模型、知识库、Embedding、Reranker 和配置版本。没有版本信息,即使发现指标下降,也很难确定究竟是哪项变化造成的。

5. 观测系统自身降级

Langfuse 上报失败不能阻断主业务。SDK 应设置合理超时、批量大小、队列上限和失败降级策略,并对“观测数据丢失率”本身进行监控。

九、落地检查清单

上线前可以快速检查以下问题:

  • 是否能通过一个 Trace 还原完整 RAG 请求?
  • Query、召回文档、重排结果和最终 Context 是否可追溯?
  • 是否记录 Prompt、模型、知识库和检索策略版本?
  • Token、成本、延迟和异常是否完整?
  • 用户、会话、环境和租户维度是否可筛选?
  • 敏感字段是否在上报前完成脱敏?
  • Bad Case 是否能够一键进入 Dataset?
  • RAGAS 输入字段是否与当前版本匹配?
  • 候选版本是否使用同一 Dataset 回归测试?
  • 发布门禁是否同时考虑质量、成本和延迟?
  • 短任务退出、服务重启和上报失败时是否有兜底?

十、总结

生产级 RAG 的关键,不是再增加几个日志,而是建立一套能够解释、衡量和持续改进系统质量的数据机制。

Langfuse 负责保存一次请求“经历了什么”,RAGAS 负责判断结果“做得怎么样”,Dataset 则把线上问题沉淀成长期可复用的回归资产。三者连接起来,RAG 才能从人工抽查和主观判断,升级为可观测、可评测、可比较、可回归的工程系统。

最终应该形成这样的闭环:

监控发现问题 → Trace 定位根因 → Dataset 沉淀样本 → RAGAS 量化评测 → 发布门禁验证 → 线上反馈继续反哺。

Demo 阶段可以靠手感,生产阶段必须靠数据。


延伸阅读:滴滴面试:如何设计一个 Langfuse + RAGAS 可观测、评测生产级基建?