Diagnose
昇腾问题的核心诊断循环。你是辅助定位工具——fix 是你给的建议,由人手动应用到客户环境,你不自动改生产。
何时用
出现训练或推理问题(中断 / 精度 / 性能),且你在能执行 bash 的 agent 中。被打断后续接 → /skill:resume-diagnosis。
紧急情况(生产中断)
客户说“紧急 / 生产挂了 / 先恢复”时,诊断目标从“查根因”变成“先 stabilize”:
- 还是先查知识库——如果有匹配的 case(比如已知的安全回滚),直接给,这最快。知识库里的具体解药永远优于通用急救口诀。
- 没有快速匹配时,根据客户已提供的信息,一步步给 stabilize 建议:
- 问客户最近 24-48h 改过什么(脚本/配置、框架版本、驱动/固件/CANN、数据、模型代码)——事故多半源于最近的改动
- 基础健康检查:
npu-smi info(卡活着吗)、hccl top(通信拓扑正常吗) - 看日志栈尾,定位哪层炸的
- 能否先恢复:回滚上个 checkpoint 重启 / 降配(关 EP、降 batch)/ 重启 daemon
- 不钻深度排查、不写 postmortem——事后用
/skill:to-postmortem补。
流程(核心循环详见 references/diagnosis-procedure.md)
执行模型:你不访问任何环境。所有信息——日志、版本、报错、环境变量——都由工程师从客户那提供(粘贴进来)。你的主动角色是信息不够时,明确提示工程师需要向客户要什么。case 里的
command是“要确认的检查”:对照已提供的信息判断,或让客户跑后把输出贴回来——不是你直接执行pip/env/grep。续接:若存在未完成的
diagnosis_state-*.yaml(每个并发诊断一个文件),先问“有未完成的诊断,要/skill:resume-diagnosis续接吗?”——别让工程师自己记着跑 resume。
-
收集症状 + 确认框架(全部来自工程师提供的信息)
- 错误信息、
HCCL_*/ASCEND_*/NPU_*环境变量值、版本组合(引擎版本 + CANN + HDK/驱动 + 架构 A2/A3/A5)——都从客户那要来 - 信息不全就主动问:若没说清,主动问——①症状(什么报错/什么时候挂)②客户的版本组合(引擎/CANN/HDK/架构)③日志/profiler 在哪(贴相关 rank + 栈尾)。别干等
- 框架从提供的信息/报错判断(日志里 mindspeed/vllm 字样等);判断不了就直接问工程师“客户跑的什么框架”,不要跑
pip list(那是你本地环境,跟客户无关) - 主动裁剪日志:让工程师只贴失败 rank + 报错栈尾,绝不灌全量 profiler——诊断 session 的 context 八成是日志,全量灌进来会滑出 smart zone(~120K token 推理最锐利),推理质量暴跌
- 错误信息、
-
分类 → 加载
triage-tree.yaml(Tier 1)- 症状匹配分支 → 路由到 namespace(先
training|inference/<framework>/,再common/) - triage 决策记进 trace(命中哪个分支、路由到哪些 namespace、category)
- triage 多分支弱匹配/置信度低 → 优雅退化:加载所有 namespace 索引让 quickly_check 筛(索引便宜,退化成本可控)
- 框架未检测到 → 只搜
common/;无法分类 → 直接 Tier 3
- 症状匹配分支 → 路由到 namespace(先
-
两阶段加载 Tier 2
- 阶段一:加载命中 namespace 的索引(
id/title/symptoms/quickly_check/category/confidence),用quickly_check(primary→fallback)对照已提供的信息过滤候选 ≤5;检查项缺信息时,记下要向客户补要什么 - 空库提示(冷启动):若命中 namespace 为空(还没 case),不要静默退化——告诉用户“当前
knowledge/<ns>/还没有验证过的 case,你可以:①继续深度排查(步骤 5)②诊断完跑/skill:to-postmortem沉淀成第一条 case ③转人工”。别让空库的体感是“这玩意啥也不会”。 - primary 不匹配但 fallback 匹配 → 仍进验证,标记
low_confidence - category 决定 quickly_check 形态:interrupt 用 grep 错误签名、precision 用数值阈值(
loss>1e3、has_nan)、performance 用 profiler 指标(comm_ratio>0.4)——别混用 - 阶段二:全量加载候选,按
confidence.score降序进入验证。多条候选时明示:“匹配到 N 条候选,先验证最可能的<id>(confidence<score>)”,让工程师有数;工程师可说“跳过这条试下一条”
- 阶段一:加载命中 namespace 的索引(
-
验证 diagnosis checks
- 顺序验证候选 case 的
diagnosis检查项(对照已提供的信息,不跳步);某步缺信息 → 提示工程师向客户要(或让客户跑该 command 贴回输出);mismatch 且有fix_on_mismatch→ 提示 fix(先看 severity,见下) - 版本软匹配:把候选 case 的
compat(framework/cann/hdk,填了的维度)逐维对照客户的版本组合——任一维不匹配 → 标version_mismatch、confidence 临时下调,case 仍是候选(不硬排除);没填的维度跳过 - 命中 → 输出 root cause + fix,进入步骤 6
- 所有候选未命中 → 深度排查(步骤 5)
- 顺序验证候选 case 的
-
深度排查(Tier 2 未命中)
- 若 Script 工具已接入(见 references/script-integration.md),按 category 用:interrupt→日志/core dump、precision→
mem-analyze、performance→ascend-profile-analyze/bench-run。当前骨架阶段这些 Script 多半还没接——别假装能调,诚实告诉工程师。 - Tier 3 关键词检索
postmortems/(rg -l '<keyword>' postmortems/,top-3 读片段)——这是骨架阶段真正能用的兜底 - 都没有 → 诚实说“知识库没覆盖这个问题,需手动排查;定位完用
/skill:to-postmortem沉淀,下次就能命中”。人 + agent 联合分析
- 若 Script 工具已接入(见 references/script-integration.md),按 category 用:interrupt→日志/core dump、precision→
-
产出
resolution: resolved | escalated | unknown- Tier-2 命中:常规 postmortem 草稿
- Tier-2 未命中但最终解决:postmortem 含一段你起草的候选 case(quickly_check + diagnosis + confidence 低),交
/skill:knowledge-groom验证 - 完整 trace 随
diagnosis_state-<session_id>.yaml留存(每并发诊断一文件;模板见diagnosis_state.yaml.example) - 结果反馈闭环(闭合学习环,关键):给完 fix 后,等工程师应用并回来报告结果——问“应用后解决了吗?(解决 / 没解决 / 部分解决)”。结果回写该 case 的 confidence:解决 →
hits += 1;没解决 →misdiagnoses += 1、更新last_hit。不问这步,confidence/误诊率永远是初始值,整个学习机制空转。 - 沉淀已含在本步骤:命中=常规 postmortem、未命中=含候选 case 的 postmortem,本步骤已生成。只有当本次不是经 /diagnose 定位的(如用 Kimi/手工查的、或没配 session-end hook 导致 postmortem 没生成),才需
/skill:to-postmortem手动沉淀。
命中时的输出格式
命中一条 case 后,给工程师结构化、可追溯的输出(别只甩一句 fix):
命中 <CASE-ID>(confidence <score>,历史命中 <hits> 次 / 误诊 <misdiagnoses> 次)
版本匹配:<完全匹配 | version_mismatch:本 case 在 <versions> 验证、客户是 <customer versions>——慎用>
匹配症状:<本轮匹配到的 symptoms>
root cause:<root_cause>
fix:<fix>(fix_type: <env-var|config-change|code-patch|pending-investigation>,severity: <benign|service-affecting|data-loss-risk>,<fix_side_effects>)
→ fix_type 决定呈现:env-var/config-change 直接给可执行命令;code-patch 给改动文件+diff 要点(不可直接执行);pending-investigation 给排查建议
rollback:<rollback>
应用后检查:<怎么验证 fix 生效>
confidence 校准(给工程师判断该多信):>0.8 高可信,直接应用;0.5–0.8 中可信,应用同时准备 plan B;<0.5 仅作提示,重点靠手动排查。把标尺讲出来,别让工程师猜 0.86 是高还是中等。
severity 闸门(命中后先看这个)
读候选 case 的 severity 字段,决定输出策略:
benign→ 直接给 fixservice-affecting→ 给 fix,但标注fix_side_effects(如 requires-restart),让人协调窗口data-loss-risk(如"checkpoint 可能被污染")→ 不直接给 fix,输出"先停训练、保留现场、通知 owner"。高危 root cause 的正确动作是 halt 不是 patch
每个 fix_on_mismatch 都带 rollback——人应用失败时能回退。
每步必写 trace(硬要求)
每个 step 后往 diagnosis_state-<session_id>.yaml(每个并发诊断一个独立文件,按 session_id 区分)的 trace 数组追加一条:
- {step: N, action: triage|load_index|quickly_check|load_full|run_check|hit|miss, ...}
trace 是误诊归因的唯一依据(见 references/diagnosis-procedure.md 末段"误诊归因"):误诊时先读 trace 判断是 case 错(改库)还是执行错(改 skill)。不写 trace = 无法归因 = 可能改坏正确的 case。
不要做
- 不要替人决定 root cause——给结构化清单,人执行后贴回结果
- 不要连续尝试第三个 case——两次未解决即转人工(误诊保护的串联保护,见 references/diagnosis-procedure.md)
- 不要把全量 profiler 灌进 context——裁剪到相关 rank + 栈尾
- 不要用 interrupt 的 grep 思路建 precision 的 quickly_check(category 形态不同)
- 被打断 →
/skill:resume-diagnosis