mcpField
A
analyzing-mlflow-trace

analyzing-mlflow-trace

github.com/mlflow测试与质量821.0k 次安装2 天前更新
代码仓库

关于 analyzing-mlflow-trace

用于检查和排查单条 MLflow 追踪的技能,指导读取跨度、评估结果、状态、耗时和令牌数据。它还说明如何将追踪证据与应用代码关联,以定位错误输出或性能问题的原因。

主要功能

  1. 01检查追踪 JSON 和跨度树
  2. 02解读评估结果及其理由
  3. 03查找错误和耗时瓶颈
  4. 04将跨度与应用代码关联
  5. 05检查令牌使用元数据

适用场景

  1. 01排查 Agent 的错误回答
  2. 02定位故障工具或检索步骤
  3. 03识别追踪中的延迟瓶颈

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mlflow/skills --skill analyzing-mlflow-trace

安装后在 Claude Code 中输入/analyzing-mlflow-trace确认已加载。

附带文件references/cross-trace-analysis.mdreferences/trace-structure.md

详细介绍

分析单条 MLflow 追踪

追踪结构

追踪会以 span 树的形式记录 AI/ML 应用的完整执行过程。每个 span 代表一项操作(LLM 调用、工具调用、检索步骤等),并记录其输入、输出、耗时和状态。追踪还包含 评估结果——来自人工或 LLM 评审者的质量反馈。

分析追踪前,建议先阅读 references/trace-structure.md——其中涵盖完整的数据模型、所有字段和类型、分析指南,以及 OpenTelemetry 兼容性说明。

对于一批追踪、组件瓶颈或反复出现的错误模式,在使用 retrieving-mlflow-traces 选取有界样本后,请阅读 references/cross-trace-analysis.md。

处理 CLI 输出

复杂的 Agent 执行过程可能会生成 100KB 以上的追踪。始终将输出重定向到文件——不要将 mlflow traces get 的输出直接管道传递给 jq、head 或其他命令,因为管道可能会悄无声息地不产生任何输出。

# Fetch full trace to a file (traces get always outputs JSON, no --output flag needed)
mlflow traces get --trace-id <ID> > /tmp/trace.json

# Then process the file
jq '.info.state' /tmp/trace.json
jq '.data.spans | length' /tmp/trace.json

优先获取完整追踪并直接解析 JSON,而不是使用 --extract-fields。--extract-fields 标志对嵌套 span 数据的支持有限(例如,span 的输入/输出可能会返回空对象)。获取一次完整追踪,并根据需要进行解析。

JSON 结构

追踪 JSON 包含两个顶层键:info(元数据、评估结果)和 data(spans)。

{
  "info": { "trace_id", "state", "request_time", "assessments", ... },
  "data": { "spans": [ { "span_id", "name", "status", "attributes", ... } ] }
}

关键路径(已根据实际 CLI 输出验证):

内容jq 路径
追踪状态.info.state
所有 spans.data.spans
根 span.data.spans[] | select(.parent_span_id == null)
Span 状态码.data.spans[].status.code(值:STATUS_CODE_OK、STATUS_CODE_ERROR、STATUS_CODE_UNSET)
Span 状态消息.data.spans[].status.message
Span 输入.data.spans[].attributes["mlflow.spanInputs"]
Span 输出.data.spans[].attributes["mlflow.spanOutputs"]
评估结果.info.assessments
评估名称.info.assessments[].assessment_name
反馈值.info.assessments[].feedback.value
反馈错误.info.assessments[].feedback.error
评估理由.info.assessments[].rationale

重要:Span 输入和输出以序列化 JSON 字符串的形式存储在 attributes 中,而不是 span 的顶层字段中。来自第三方 OpenTelemetry 客户端的追踪可能会使用不同的属性名称(例如 GenAI Semantic Conventions、OpenInference 或自定义键)——请检查原始 attributes 字典,找到对应字段。

如果路径不匹配(结构可能因 MLflow 版本而异),请按以下方法查找:

# Top-level keys
jq 'keys' /tmp/trace.json

# Span keys
jq '.data.spans[0] | keys' /tmp/trace.json

# Status structure
jq '.data.spans[0].status' /tmp/trace.json

快速健康检查

将追踪获取到文件后,运行以下命令以获取摘要:

jq '{
  state: .info.state,
  span_count: (.data.spans | length),
  error_spans: [.data.spans[] | select(.status.code == "STATUS_CODE_ERROR") | .name],
  assessment_errors: [.info.assessments[] | select(.feedback.error) | .assessment_name]
}' /tmp/trace.json

分析洞察

  • state: OK 不代表输出正确。 它只表示没有未处理的异常。请检查评估结果中是否有质量信号;如果没有,请直接分析跟踪记录的输入、输出和中间 Span 数据,查找问题。
  • 解读评估值时,务必查看 rationale。 单看 value 可能会产生误导——例如,user_frustration 评估结果的 value: "no" 可能表示“未检测到挫败感”,也可能表示“挫败感检查未通过”(也就是说,确实存在挫败感),具体取决于评分器的配置方式。.rationale 字段(评估结果的顶层字段,不嵌套在 .feedback 下)会解释该值在当前语境中的含义,通常会先用直白的语言描述问题,无需检查任何 Span。
  • 评估结果告诉你出了什么问题;Span 告诉你问题出在哪里。 如果存在评估结果,请根据反馈/预期形成假设,然后在 Span 树中确认。如果没有评估结果,请检查 Span 的输入/输出,确定执行过程从何处偏离预期行为。
  • 评估错误不等于跟踪错误。 如果评估结果包含 error 字段,表示评估该跟踪记录的评分器或判定器出错了,而不是跟踪记录本身有问题。跟踪记录可能完全正常;评估结果的 value 只是不可靠。这可能是评分器崩溃导致的(例如超时、返回无法解析的输出),也可能是评分器被用于其设计范围之外的跟踪类型(例如,将检索相关性评分器用于没有检索步骤的跟踪记录)。后一种情况属于评分器配置问题,而不是跟踪记录问题。
  • Span 耗时可以揭示性能问题。 父 Span 与子 Span 之间的间隔表示开销;重复的 Span 名称可能表示发生了重试;比较各个 Span 的耗时可以找出瓶颈。
  • 令牌用量有助于解释延迟和成本。 请在跟踪元数据(例如,mlflow.trace.tokenUsage)或 Span 属性(例如,mlflow.chat.tokenUsage)中查找令牌用量。并非所有客户端都会设置这些字段——请检查原始的 attributes 字典,查看是否有等效字段。输入令牌突然增加可能表示提示词注入或上下文过大。

与代码库关联

MLflow Tracing 会捕获应用程序调用栈不同部分的输入、输出和元数据。将跟踪记录内容与源代码关联起来,能比仅凭跟踪记录更准确地定位根本原因。

  • Span 名称对应函数。 Span 名称通常与使用 @mlflow.trace 装饰的函数或由 mlflow.start_span() 包装的函数相同。对于自动记录的 Span(LangChain、OpenAI 等),名称则遵循相应框架的惯例(例如,ChatOpenAI、RetrievalQA)。
  • Span 树映射调用栈。 如果 Span A 是 Span B 的父级,则函数 A 调用了函数 B。
  • Span 输入/输出对应函数的参数/返回值。 将它们与代码逻辑进行比较,可以看出函数是否按设计运行,或是否产生了意外结果。
  • 跟踪记录展示发生了什么;代码揭示为什么。 检索器返回无关结果,可能是因为相似度阈值设置错误。Span 输入不正确,可能表明代码中设置了错误的模型参数,或缺少环境变量。

示例:调查错误答案

一位用户报告称,其客户支持 Agent 在回答查询“我们的退款政策是什么?”时给出了错误答案。该跟踪记录没有评估结果。

1. 获取跟踪记录并检查高层信号。

该跟踪记录的 state: OK,表示没有发生崩溃。由于没有评估结果,请直接检查跟踪记录的输入和输出。response_preview 显示 “我们的配送政策规定,订单会在 3-5 个工作日内送达……”,这回答的是与用户提问不同的问题。

2. 检查跨度以定位问题。

跨度树如下所示:

customer_support_agent (AGENT) — OK
├── plan_action (LLM) — OK
│   outputs: {"tool_call": "search_knowledge_base", "args": {"query": "refund policy"}}
├── search_knowledge_base (TOOL) — OK
│   inputs: {"query": "refund policy"}
│   outputs: [{"doc": "Shipping takes 3-5 business days...", "score": 0.82}]
├── generate_response (LLM) — OK
│   inputs: {"messages": [..., {"role": "user", "content": "Context: Shipping takes 3-5 business days..."}]}
│   outputs: {"content": "Our shipping policy states..."}

Agent 正确地决定搜索“退款政策”,但 search_knowledge_base 工具返回了一份配送文档。随后,大模型根据错误的上下文如实作答。问题出在工具的检索,而不是 Agent 的推理或大模型的生成。

3. 与代码库关联。

跨度 search_knowledge_base 对应应用代码中的一个函数。调查后发现,向量索引仅根据配送常见问题构建,退款政策文档从未被编入索引。

4. 建议。

  • 重新建立知识库索引,将退款政策文档纳入其中。
  • 添加检索相关性评分器,以检测检索到的上下文是否与查询主题不匹配。
  • 考虑为常见查询添加包含正确答案的预期评估,以支持回归测试。

评论

支持 Markdown