← 工程化与 LLMOps

如何为多步骤 LLM 工作流设计端到端 Trace?

高频 困难 调用日志与链路追踪 · 第 2 / 3 问 更新于 2026/09/30
LLMOpsDistributed TracingSpan异步工作流
本题落地项目AI Agent智能会议纪要辅助系统

简化版

LLM Trace 的目标是还原一次任务如何经过输入治理、检索、模型、工具、校验、重试和 Fallback,而不是把所有 Prompt 塞进日志。根 Trace 表示一个用户任务,每次实际尝试建独立 Span;Span 记录版本、阶段耗时、Token、结果码和输入输出的受控引用。

异步队列和人工审批要传播 trace_id、span_id/link、operation_id 与 baggage 中的低敏路由信息;重试是新 Span,不覆盖旧 Span。采样采用错误/高风险全保留、普通成功按比例或尾部采样,并把敏感原文放受限证据库。llm-observability-fields 讲字段字典,本题重点是 Span 拓扑、上下文传播与采样完整性。

详细版

先按责任边界划 Span:网关、上下文构造、Retriever、Reranker、每次模型调用、工具、验证器。并行工具是兄弟 Span,Fallback 是同一逻辑阶段下的新 attempt,缓存命中也要有短 Span 说明为什么绕过模型。

root task
├─ guard
├─ retrieve -> rerank
├─ model attempt=1 (timeout)
├─ model attempt=2 release=fallback
├─ tool operation_id=...
└─ validate -> response stream

Trace 不等于审计日志:Trace 为诊断可采样,审计证据通常不可按普通比例丢弃。验收时用故障注入验证跨队列、回调和流式连接仍能串联,父子时长合理,失败 attempt 没有被成功结果覆盖,且无 Prompt/Secret 意外进入属性。

完整版教学

字段决定“记录什么”,Trace 设计决定“这些事件如何组成因果链”;没有因果关系,一堆完整日志仍无法解释一次失败。

一、Trace 的根应该是什么

根 Trace 应对应用户可理解的一个逻辑任务,而非单个 HTTP 请求。一次任务可能经历客户端重试、多个模型调用和异步工具,若每段各自创建无关联 Trace,就无法计算端到端成功与成本。

根属性保存任务类型、租户受控 ID、release_id 和最终状态。高基数 request_id 用于查询,不直接作为指标标签。

二、Span 边界怎样划分

Span 应对应有独立所有者、耗时和失败语义的组件。一次模型调用、一次检索、一次工具执行和一次校验分别建 Span,而不是给每个内部函数都打点。

Span关键事件结束状态
retrievalquery built、candidateshit/empty/error
model_callqueued、first token、finishstop/length/error
tool_callvalidated、sent、committedsuccess/failed/unknown
validationschema、grounding、安全pass/block/unavailable

边界太粗无法定位,太细则成本和噪声过高。

三、重试与 Fallback 如何表示

每次网络尝试建立新的 Span,带 attempt、provider、release 与触发原因。不能复用同一个 Span 并把最终状态改成成功,否则会丢失第一次超时和真实成本。

Fallback Span 与主尝试共享逻辑 operation,但使用不同 release_id。根 Trace 汇总全部 attempt 的 Token 和费用,才能计算每次成功任务成本。

四、异步消息如何传播上下文

生产者把标准 Trace Context 注入消息 Header,消费者提取后创建子 Span。若消息在很久以后由独立工作流处理,可用 Span Link 表达因果关系,避免伪造一个持续数小时的同步父子调用。

enqueue span --context/link--> worker span --link--> callback span

消息重投递沿用同一 message_id,但每次处理建新 attempt Span。Header 只携带必要 ID,不能传播 Prompt、密钥或大块业务状态。

五、并行分支与聚合怎样画

多个独立工具并行调用时使用兄弟 Span,聚合节点记录等待哪些分支、哪些超时以及采取何种部分成功策略。简单串成父子会让时间轴误导为顺序执行。

总耗时也不能把并行 Span 时长直接相加。墙钟延迟看关键路径,资源成本才对各调用求和;Trace 分析需明确两种口径。

六、流式响应记录哪些事件

模型 Span 记录请求发送、首个有效内容 token、最后 token、Finish Reason 和上游取消;响应 Span 记录首字节成功写给客户端、背压和断连。服务端拿到 token 不等于客户端已收到。

工具等待期间不应算进模型 TPOT。可把工具阶段拆为独立 Span,并同时报告端到端相邻事件间隔,避免指标口径混淆。

七、内容怎样最小化

Span 属性优先存 Token 数、内容哈希、Prompt/文档版本、风险分类和受控 artifact_id。原始 Prompt、输出、工具参数或文档正文只在合法必要的受限证据库中保存。

脱敏要在数据离开业务进程前完成。Trace 后端访问也需权限与审计,调试开关必须自动过期。

八、采样策略如何兼顾成本与问题发现

头部采样在请求开始时决定,简单便宜但可能丢掉后来才出现的错误;尾部采样在知道状态、延迟和风险后决定,更适合保留失败与长尾,但需要缓存 Trace 数据。

可采用:安全/写操作与错误 100% 保留,P99 和未知状态高比例保留,普通成功按 1% 抽样。审计事件另走不可随诊断采样丢弃的通道。

九、Baggage 为什么要谨慎

Baggage 会随跨服务请求传播,适合低敏、低基数的租户等级、实验 ID 或 release_id。把用户文本、完整 tenant 权限或 Secret 放入 Baggage,会在每个下游复制并扩大泄露面。

传播字段要有白名单、大小上限和信任来源。下游不能把客户端自带 Baggage 直接当授权依据。

十、怎样从 Trace 生成指标

从 Span 聚合 QPS、错误、阶段时长、Fallback 率、工具未知状态和 Token 成本;标签只选模型、区域、稳定错误码等受控维度。Trace ID、Prompt Hash 等高基数字段留作查询。

若 8 秒总延迟中 Retriever 0.3 秒、Reranker 0.7 秒、排队 1.5 秒、Decode 5 秒、校验 0.5 秒,优化优先级明显不同于只有 total_ms=8000 的日志。

十一、如何验证 Trace 没有断链

注入 Provider 超时后 Fallback、队列重投递、并行工具部分失败、客户端取消和审批回调。检查根 Trace 是否包含所有 attempt、最终状态、关键路径与总成本。

监控 orphan span、缺失 release_id、负时长、时钟偏差、采样丢失和属性超限。部署新组件时用契约测试确认它正确传播上下文。

十二、常见误区与追问

  • 误区:一次 HTTP 就是一条完整 Trace。 异步任务和重试可能跨多个请求,根应对应逻辑任务。
  • 误区:重试成功后覆盖第一次失败即可。 会丢失故障、成本与重试放大证据。
  • 误区:把所有原文存进 Span 最利于排障。 会扩大隐私与安全风险,应保存引用和受控采样。
  • 误区:并行 Span 的时长应全部相加得到延迟。 墙钟延迟看关键路径,成本才对资源求和。
  • 误区:Trace 可以替代审计日志。 Trace 可采样,审计对完整性和防篡改要求不同。
  • 追问:队列消费者算子 Span 还是 Link? 短生命周期同一操作可继承父子;长延迟独立工作流更适合 Link。
  • 追问:怎样保留罕见错误? 使用尾部采样规则按错误、风险和长尾时延优先保留。

十三、加强记忆

端到端 Trace 记“任务为根、责任为 Span、重试不覆盖、异步靠 Context/Link”。并行看关键路径,成本汇总全部 attempt;流式区分模型首 token 与客户端写出。内容只存最小字段和受控引用,错误与高风险优先尾采样,审计证据走独立通道。最终用故障注入证明链路不断、口径不乱、敏感数据不泄露。

项目实战落地

项目里怎么做的

《AI Agent智能会议纪要辅助系统》没有接入 Trace 系统,但一次任务里的每一步都能串起来,靠的是三张表和两个字段:

ai_call_log   每次模型调用一行
  request_id  AIC 前缀加随机串,唯一,标识这一次调用
  call_type   TRANSCRIPTION 转写、SPEAKER_MATCH 说话人匹配、MINUTES_CHUNK 纪要分段、
              MINUTES_MERGE 纪要合并、AGENT_REVIEW 自检审查、AGENT_REFINE 自检重写
  biz_id      按 call_type 指向不同的业务记录:
              转写和说话人匹配 → 转写任务,纪要分段和合并 → 纪要,自检审查和重写 → 自检运行
agent_run     一次纪要自检一行:状态、轮次、修订稿、开始和结束时间
agent_step    自检的每一步一行:步骤类型(审查、重写、汇总)、状态、耗时

自检审查和自检重写两类日志的 biz_id 存的就是自检运行的主键,和 agent_step.run_id 是同一个值,所以一次自检的步骤和这次自检里的每一次模型调用,都能按运行 ID 对上。纪要生成、纪要自检、说话人匹配三处文本模型调用走同一个 invoke_json,转写走转写服务,两条路径成功和失败都写一条日志,失败的 usage_json 为空。

运行观测页按同一套关系判断员工能看哪些日志:先查出员工名下的转写任务、纪要和自检运行的 ID,再按 call_type 选对应的集合,比对日志的 biz_id,落在集合里才算他的调用。

《AI企业流程编排系统》的面试文档把它叫「三级可观测」:workflow_run 记一次运行的初始输入、最终上下文、状态和耗时;workflow_run_step 按执行顺序记每个节点执行前的完整上下文、节点输出、状态、耗时和错误原因,节点名称和类型存执行时的快照;ai_usage_log 记大模型节点的每次模型调用。前两层靠运行 ID 关联;模型调用日志带的是流程 ID 和节点 ID,没有运行 ID,要对到某一次运行只能靠流程、节点和调用时间。文档给的排查顺序是:先看运行记录的整体状态,再按步骤日志定位出错的节点,大模型节点再结合调用日志看模型调用详情。

为什么这样取舍

  • biz_id 按 call_type 解释。 一张日志表承接转写、纪要、自检三种业务,用「类型 + 业务 ID」两个字段就能回到具体的那条业务记录,不用为每种业务加一列。
  • 运行和步骤单独成表。 自检是一个多轮的反思环,步骤的类型、状态和耗时是按运行看的;模型调用日志只记调用本身,两张表各管一层,靠运行 ID 对上。
  • 归属判断复用同一关系。 员工能看哪些日志,不在日志表里另存用户,而是顺着 biz_id 回到业务表看是谁发起的,权限和业务数据保持一致。

和正文说的端到端 Trace 相比,这套做法串得起「一条业务记录下的所有调用」,但没有父子 Span 和跨服务传播;链路本身怎么设计 Span,还是看正文。检索链路那一段记什么,见「RAG 链路 Trace 应该记录哪些信息?」。

面试官还会追问

  • 运行观测页的「最近失败记录」把失败的模型调用和失败的自检运行合在一张表里,两类记录怎么排序、最多保留几条?
  • 自检运行的「平均轮次」为什么只统计至少完成过一轮审查的运行?

学完《AI Agent智能会议纪要辅助系统》,上面这些追问你都会迎刃而解。

本题落地项目地狱锤炼AI Agent智能会议纪要辅助系统基于LangChain+LangGraph的AI Agent智能会议纪要辅助系统 包括会议管理 资料管理 音视频转写 说话人分离 会议纪要生成 Agent自检更正 Agent运行观测等。FastAPILangChainLangGraphAgent多模态源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目 也可以学AI企业流程编排系统地狱锤炼 查看项目