先这样答
回答时可以从层级拆分、特有字段和存储策略三个方面展开。在 span 层级设计上,一次完整的用户请求作为根 span,代表用户的原始意图。在根节点之下,按照实际执行步骤拆分出子 span,常见的子过程包括 query 改写、知识库检索、结果重排、外部工具调用以及大模型调用。无论是哪一层 span,都必须记录基础的输入输出内容、执行耗时、消耗的 token 数与对应费用,以及当前使用的模型名称和具体参数。
在记录字段时,大模型应用有其特有的信息需要留存。模型调用环节要记录 prompt 版本和温度参数。检索环节要记录命中的 chunk id。如果是工具调用,则记录传入的参数和返回结果的摘要。排障与评测回流都靠这些核心字段,它们是后续复现问题和优化效果的直接依据。
在实际落地时需要处理存储成本和数据安全的取舍。全量记录通常只保留在低成本的元数据层,而具体的长文本内容需要按照采样率或数据敏感级别进行留存过滤。为了把各系统串联起来,会生成一个 trace id 贯穿日志与业务单据。
这套设计在满足线上问题定位的同时,也为后续的模型微调和效果评测准备了结构化的真实数据。
面试官会怎么追问
- 「如果发现某个请求的整体耗时很长,你会通过 trace 里的哪些信息来定位问题?」 先通过根 span 确认整体延迟,接着下钻查看各个子 span 的耗时占比。如果是检索 span 耗时过长,会检查数据库响应状态。如果是大模型调用 span 耗时异常,则结合记录的 token 数量和模型名称,判断是输入上下文过长还是模型本身的生成速度下降。
- 「大模型生成的文本通常很长,全部存入 trace 系统会导致成本过高,怎么解决?」 主要依靠分层存储和采样机制来控制成本。将基础的元数据如 token 数、耗时、模型配置进行全量记录,存入低成本层。对于输入输出的长文本内容,设置采样率进行部分留存,或者在检测到发生错误等异常情况时才触发全量文本记录。
- 「为什么在检索 span 里强调要记录命中的 chunk id,而不是直接记检索出来的文本?」 记录 chunk id 的存储成本远低于记录完整的文本片段,且通过 id 可以随时回溯到知识库中查看具体内容。这在排查幻觉问题或进行检索质量评测时已经足够。同时,记录 id 也能避免在 trace 日志中直接暴露敏感的业务数据。
回答的坑
- 认为 trace 只是用来记录耗时和报错,忽略了 prompt 版本、温度和检索 chunk id 等大模型特有字段对排障与评测回流的价值。
- 试图把所有的输入输出长文本和工具返回细节都不加限制地塞进 span 属性里,没有考虑数据脱敏以及按采样率留存的低成本存储策略。
同系列的题
—— 本题完 ——