因果链分析 Skill
概述
因果链分析是一种系统性的问题根因分析方法。它从用户提供的原始问题(表层缺点)出发,先分析本质上需要解决的初始缺点,然后以"逐节点展开"的方式生长因果链:
- 维护一个待展开节点的优先队列
- 每次取出优先级最高的一个节点(即当前对初始缺点影响最大的)
- 拆分出它的下一层直接原因
- 把新发现的子节点按优先级放回队列,循环往复
- 直到队列中所有节点都展开完毕或被判定为末端缺点
这种"带优先级的树搜索"方式,避免了"一次性起草全文再回头检查"的弊端。
每展开一个节点,就即时确认:
- 它的表述是否规范
- 拆分是否直接且完备
- 是否与已有节点重复
发现问题立即修正,必要时甚至回退修改上层节点。因果链在生长的每一步都保持正确,而不是先长成一棵可能有错的树再去修剪。
核心输出:一个Markdown文件,包含完整的因果链分析结果,使用缩进表示层级关系。
何时使用此Skill
当用户提到以下内容时,应调用此skill:
- "分析因果链"
- "帮我做因果链分析"
- "进行因果链分析"
如果用户只是对某种情况感到不满意,希望能解决眼前的问题,却想不出好的解决办法,则:
- 先自行评估,如果对这个问题的产生机制(在理论层面)做一次完整充分的分析,是否有助于产生更多的候选方案
- 如果是,询问用户:是否愿意由 AI 助手系统地把问题出现的原因梳理一遍,这或许能帮助想出更多的解决思路
- 用户同意后,调用此skill
- 若 1、2 中任何一个的答案为否,可忽略此skill
分析流程
请先阅读 references/factor_definition.md 了解因素定义。
因果链中的每个因素(包括初始缺点、推演中间结果、展开的子节点)都必须符合这一定义:主语+谓语、明确具体、原子化、客观事实、肯定陈述。
后续步骤中不再重复列举这些要求,统一以"符合因素定义"指代。
步骤1:理解用户问题
- 仔细阅读用户描述的问题
- 识别用户提供的"表层缺点"
- 关键:分析这个表层缺点,判断它是否是"本质初始缺点",还是用户最直接看到的表面因素
步骤2:推导本质初始缺点
如果用户提供的只是一个导致不满的直接现象,而非根本上造成不满的初始缺点,需要进行推导。推演链中的每一个中间结果都应符合因素定义:
- 询问"这个表层缺点会导致什么?"
- 推演它的结果。推演仅限于客观因果(该缺点会引发什么客观后果),不讨论主观动机(使得什么功能无法实现、什么目的无法达成)
- 注意这里"原因→结果"的分析方向与步骤4相反
- 继续追问,直到找到用户本质上想避免的客观状况,即初始缺点
- 依据因素定义,调整优化初始缺点的表述
- 如果你认为这样的初始缺点不止一个,可以分别展开因果链分析,但不宜过多
- 出现场景包括左右为难情形:系统在一种设计下产生缺点 A,另一设计下产生缺点 B,可对 AB 分别分析
- 如果你识别出了 3 个或以上的初始缺点,请向用户确认,避免出现理解偏差
示例:
- 用户说"冬天开门被静电打到",这需要推导为"电流刺激神经末梢导致疼痛",而"疼痛"才是真正让用户不满的初始缺点。因为如果换用神经不敏感的手背,即使被电到,也没有明显感觉
- 用户说"感到疼痛",这已经是初始缺点(仅需按因素定义调整表述)。因为尽管它会进一步导致"心情不好",但用其他办法来解决已经意义不大
- 用户说"油漆从油漆箱中溢出",这可能是初始缺点,也可能不是。因为它确实会导致"油漆浪费"、"地面污染",但这些可能已经超出了当前项目所需要关注的范围。遇到这种情况,可以考虑向用户确认
重要:
- 初始缺点的表述应符合因素定义,如有问题立即修正
- 如果对初始缺点的理解有疑问,先向用户确认再继续分析
- 确认时需要留意,用户可能对"初始缺点"这个概念不够了解。可以考虑换成更通俗的表述,比如"本质上想解决的问题"
- 若后续分析过程中认为需重新设置初始缺点,必须取得用户同意,不得擅自修改
步骤3:初始化分析文件与待展开队列
- 立即创建一个Markdown文件(命名建议见"写入文件的时机"一节),写入初始缺点作为因果链的根
- 在记忆中维护一个待展开节点队列,初始时只包含根节点(初始缺点)
- 每个节点附带一个优先级评估:该节点因素的消除对解决初始缺点的贡献程度。贡献越大、优先级越高(参考"分析过程中的注意事项"中的"二八定律")
步骤4:逐节点展开(核心循环)
只要队列非空,重复以下流程:从队列中取出优先级最高的一个节点,对它执行展开。
如有需要,可用 scripts/check-leaves <file> --non-terminal 列出所有待展开节点。
一次完整的展开包含以下子步骤。注意别太死板:这不是一个只许前向推进的单行道。如果你发现之前做过的某个步骤做得不够好,也可以回退修改重做。
4.1 确认因素表述
- 检查当前节点是否符合因素定义。若有问题,立即修正
- 若发现问题的根源在于上一层(父节点)的展开方式本身不对,可以回退修改父节点,甚至父节点的父节点
- 若发现问题的根源在于初始缺点的表述,回到步骤2重新确认
4.2 检查是否与已有节点重复
判断当前节点如果展开,是否会导致重复展开或无限递归。
4.2.1 区分检查
检查当前节点是否与文件中某个已有节点文字表述相同或高度相似。
若存在这样的节点,先认真分析它们是否存在微妙的差异,在两个上下文中实际指向不同的因素(如对应不同的对象/时间/发生条件等):
- 如果实际不同:修改表述以区分,如可补充限定词(定语/状语),然后继续展开
- 如果确实指向同一因素或可能等价:进入 4.2.2
4.2.2 等价性判断
先判断当前节点与已有节点是否等价。等价关系分四种:
- 完全相同
- 仅限定词不同(如"(条件A)X过大" vs 已有"(条件B)X过大"),且预判后续展开方式完全一致
- 反面(如"X过大" vs 已有"X过小"),且预判后续展开子树精确对应已有节点展开子树的镜像
- 2,3 同时出现,即对应不同限定词的反面,且后续展开恰为镜像
2–4 后续展开的一致性判断可能需实际展开后才能确认。若当前无法通过预判确定,先完整展开当前节点,待子节点做 4.2 检查时自行发现等价并跳过。 非等价节点应继续展开。
4.2.3 等价性标注
确认等价后,如果等价节点位于祖先链中(可能在任意深度,不限于父节点),展开会无限递归,行末标注 :祖先节点已分析 后不再展开。
否则标注 :上方已分析 或 :下方已分析(按文件行号判断),不再重复展开。
标注时可选地追加括号说明等价类型:
(仅差限定词):仅限定词不同,且后续展开方式完全一致(反面):反面,且后续展开方式恰为镜像
例如(两者同时出现情形)::祖先节点已分析(仅差限定词,反面)
标注后该节点不再加入队列,跳过本次展开的后续子步骤。
4.3 产出正确分解
本步骤为当前节点产出一组正确的直接子因素。它把选择拆分依据、确定组合关系、验证三件事放在一个紧闭环里反复迭代,直到验证全部通过,或穷尽所有拆分方式仍失败(此时进入 4.4)。
4.3.1 目标与基本原则
最终目的,是在当前分析边界内,把初始缺点的产生条件展开为一套有助于后续发现尽可能多解决办法和干预方向的因果结构。 服务于此的一般经验原则如下:
- 直接性:每层对应紧邻的发生机制(比如由物理上直接接触的组件引起),避免跳过可干预环节
- 完备性:避免遗漏独立致因路径和必要条件
- 保留机制差异:把后续归因方向或可干预方向不同的机制分开,使后续分析覆盖更多方向
一次展开只选择一种展开依据。当前层只产出父节点的下一层直接子因素,不得顺着某个子因素继续下拆。
前置知识:子因素间的组合关系类型
一次拆分得到的若干子因素,按"它们如何共同导致父节点"可分为多种关系:
- And(与):所有子因素同时成立才导致父节点
- Or(或):任一子因素成立即导致父节点
- +(加法):父节点是各子因素的代数和(如总碳排放 = 电力碳排 + 工业碳排 + 交通碳排),是强调"可叠加的量"的 And
- ×(乘法):父节点是各子因素的乘积(如摩擦力 = 压力 × 摩擦系数),是强调"因子连乘"的 And
根据具体情况,可自行设定其他关系,如:
- ∪(并集):可恢复信息 = Git信息 ∪ 备份信息 ∪ 日志信息 ∪ 人员记忆
- 如需要,可进一步讨论各子项的重合度大小
- max(最大值):如"峰终定律"中峰值印象深度 = max(环节1印象深度, 环节2印象深度, ...)
- min(最小值):如可招聘人数 = min(招聘方可提供岗位数, 互有意向的求职者人数)
- ……
关系类型决定了完备性检验的方向:
- And / + / × 是"缺一不可",检验时问"已有子因素都成立的前提下,能否阻止父节点发生?"——若有办法,说明遗漏了某个必要前提
- Or 是"独占即可",检验时问相反的问题"假设所有已知子因素都不发生,父节点是否仍可能发生?"——若仍发生,说明还有另一条独立的致因路径
所以组合关系必须在拆分当下就明确,否则 4.3 的验证无法正确进行。这不是写入时才回头确定的事。
4.3.2 选择拆分依据并产出候选子因素
为当前节点选择一种拆分依据,按它产出候选子因素。基于 4.3.1 所述目标原则的一般实现方式,默认按以下顺序依次尝试:
- 形态完备性枚举:当父节点可以以多种形态发生,且这些形态的发生机制存在差异时,枚举这些形态,以备未来分别归因
- 例如,"钢球解体"直接原因不是"机械应力大于钢球材料强度",而应为"钢球受冲击表面断裂 or 钢球内部断裂",后者再展开时直接原因"钢球内部横向断裂 or 钢球内部纵向断裂",再后者才在未来归因为"钢球内部纵向机械应力大于钢球材料强度"
- 这种区分必要,是因为表层应力、内部横向应力、内部纵向应力的后续归因方向不同,干预方式也不同
- 同理,"Transformer 注意力计算量大"不应直接用公式
FLOPs = CLN²d,应先拆 QKᵀ、softmax、AV 等模块。这些模块计算机制不同,后续展开优先级也不同 - 选定本依据后,形态就是当前层的子因素,不再同层使用公式或其他依据继续下拆
- 例如,"钢球解体"直接原因不是"机械应力大于钢球材料强度",而应为"钢球受冲击表面断裂 or 钢球内部断裂",后者再展开时直接原因"钢球内部横向断裂 or 钢球内部纵向断裂",再后者才在未来归因为"钢球内部纵向机械应力大于钢球材料强度"
- 严格直接公式:若形态完备性枚举不适用,找出现代科学中描述当前层直接机制的严格定义或计算公式,把公式中的每一项作为独立分支展开
- 公式必须处于当前因果层,不得跨越多个形态、模块或中间因果层
- 比如,本层次缺点是"摩擦力大"时,利用"摩擦力=压力×摩擦系数",就应该在压力和摩擦系数两个方面找到下一层级的子因素
- 公式天然揭示了组合关系:加减项对应 +,相乘因子对应 ×
- 公式中的每个因素都必须作为子节点列出,不因其取值处于正常范围而省略或改用弱化表述(如用"非零""正常"替代"过大")
- "过大"/"过小"的基准是对父节点的影响:减小取值能缓解或消除父节点时记为"过大"(反向同理"过小"),即使按常规标准属正常值
- "正常"与"异常"的区分应在优先级评估和末端判定时体现,不应在拆分时预判裁剪或改述
- 同一因素在因果链的不同位置出现时,允许带有反向标记(如分别"过大"和"过小"),不过应先判断是否实际指向不同的因素(见步骤4.2)
- 同一变量多次出现时,检查每次出现是否对应不同的因果角色,若是则区分,即使当前场景下相等
- 如注意力计算
FLOPs ∝ H · L² · d_h里的两个L应写为L_Q与L_K
- 如注意力计算
- 检查公式是否依赖未显式声明的假设。若该假设本身是一个可改变的因果因素,将其显式化为一个独立节点
- 如注意力
FLOPs ∝ H · L² · d隐含假定了每个查询与全部键交互的密集模式
- 如注意力
- 公式中某量若由另一更基础量经筛选/变换等规则派生(而非直接等于该基础量),则派生规则应作为独立因果因素显式化
- 如注意力中
L_K(每查询交互的键数)并非直接等于N(总 token 数),从N到L_K经过了"密集交互"这一派生规则——选什么 token 为键、每查询覆盖多少键,都是独立的因果因素
- 如注意力中
- 公式推导链中的每一步变换都构成一个因果层,不可因"数学等价"而跳过
- 即使前后两步在数学上等价(如
a = b与b = c),"因 a 取某值导致 b 取某值"仍是因果步骤,应独立为一层 - 高手的分析可达 20+ 层、500+ 节点——每一步都不应被"等价"的理由省略
- 即使前后两步在数学上等价(如
- 用当前层的直接公式,不得把多层公式经代入合并后作为本层的拆分依据
- 如
F = ma是直接公式,而合并m = ρV后所得F = ρVa是推导合成公式,用后者拆出的原因不属于直接原因
- 如
- 直观公式:若没有严格直接公式,尝试构造一个在抽象直觉层面成立的关系式(不一定严谨),用它来拆解
- 直接拆分要素:既无严格公式也无直观公式时,直接按物理组成或逻辑构成拆分要素
- 建议枚举所有可能与当前因素存在交互的实体,并对每个相关实体枚举所有交互方式,逐一确认所有可能的贡献是否已在拆分中体现——非主要关注对象的贡献容易被忽略。
4.3.3 确定组合关系
拆分得到子因素后,判断它们属于 And / Or / + / × 中的哪一种(见上方"前置知识")。这一步在拆分当下完成。
4.3.4 验证拆分
对 4.3.2 得到的拆分,逐项验证:
- 是否客观规律:每个子因素必须是客观因果(为什么发生),不能是主观动机(为什么这么做)。诸如"需要xx"、"为了xx"的表述不是缺点,不能作为子因素。违反则回到 4.3.2 重新拆分
- 是否直接原因:每个子因素必须是父节点的直接原因,不能跳步。
- 比如,对于"(端起热水杯子时)手感觉烫",不能想当然地说"杯子中水的温度太高",因为它不是造成缺点的直接原因
- 应该分解成:手感觉烫 → 手部温度感觉神经受刺激 → 手表面温度太高
- 而"杯子中的水温度太高"属于更底层的缺点
- 如果某子因素其实是通过一个中间原因才导致父节点,说明跳步了,应在中间补一层(A → B 补成 A → C → B)
- 是否发生机制而非使能条件:问自己"该子因素成立后,父节点是立即发生,还是需要经过一连串中间效应才发生?"
- 如果是一连串中间效应,说明你写的是使能条件(enabling condition),而非发生机制(mechanism),违反了直接原因原则
- 使能条件的特征:它是系统的一个属性、参数或设计事实,描述了"允许某事发生"而非"某事如何发生"
- 此时应沿着中间效应链路继续展开:从使能条件出发,找出它在此场景下实际产生的具体物理/逻辑效应,直到找到父节点前的那一步
- 若拆分基于公式,同样检查公式是否为直接公式(见 4.3.2):若公式中某项需经中间量才能影响父节点,该公式为整合公式,违反直接原因原则
- 违反则回到 4.3.2 重新拆分
- 比如,对于"(端起热水杯子时)手感觉烫",不能想当然地说"杯子中水的温度太高",因为它不是造成缺点的直接原因
- 是否完备:按 4.3.3 确定的组合关系选择对应的检验逻辑(见"前置知识")。
- And / + / ×:勇敢想象,反复问"在已有子因素都成立的前提下,我就是希望阻止父节点发生,到底有没有办法?"。如果有办法,说明还遗漏了某个必要前提,把它补充进来,重新想象,直到再也想不出遗漏的因素
- Or:反复问"假设所有已知子因素都不发生,父节点是否仍可能发生?"。如果仍可能,说明还有另一条独立的致因路径,把它补充进来
- 如果 4.3.2 没有用公式拆分,或即使用了仍不确定是否完备,可以回头用公式(严格公式或直观公式)交叉检查父节点。公式是避免遗漏的强大手段
- 完备性不足则补充后重新验证
子 agent 辅助:在验证"是否完备"或"是否跳步"时,如有必要,可以启动一个子 agent,让它只回答这一个节点的拆分是否完备、是否直接,不要让它展开整个因果链。 可让它读本 SKILL.md(给完整路径)了解分析原则。 给它提供父节点、当前拆分方案、相关背景即可;回答用于辅助你下一步的判断,是否采纳由你决定。
4.3.5 失败回退与成功出口
- 若验证全部通过:进入 4.5 写入子节点
- 若某项验证不通过,尝试修复,并重新验证拆分方案
- 若修复失败,且 4.3.2 还有未试的拆分方式,则回到 4.3.2 换下一种方式重新尝试
- 若 4.3.2 的四种方式都已穷尽且仍未通过验证:进入 4.4 判断是否末端
4.4 判断是否末端
对照"末端缺点判定标准"一节,判断当前节点是否为末端缺点。
- 若是末端:在该节点行末标注
:末端(判定理由),判定理由简要注明属于"末端缺点判定标准"中的哪一条(如"物理极限"、"自然现象"等)。不再展开,不把子节点加入队列,结束本次展开 - 若不是末端但拆分失败:回到 4.3 重新尝试拆分(可能需要换一种拆分思路,或重新查阅公式)。4.3 的四种拆分依据可以循环尝试
4.5 写入子节点
拆分成功且非末端时,把通过 4.3 验证的子因素落盘并加入队列。
重要:
- 一次展开只产出当前节点的直接子节点。不允许顺手写出子节点的下层原因
- 对子节点的展开,必须等它入队后,单独取出、完整执行 4.1~4.5 的流程
- 写入前,对每个子因素执行 4.1 的表述检查,确保表述符合规范
- 所有新增节点必须来自当前节点的公式拆分或直接分解,不得基于外部参考材料中的论点或其他动机主动添加
- 若某因素无法从当前节点的任何拆分方式中自然得出,应检查已有分析是否有遗漏或错误
- 若仍未找合适位置,不应强行加入
定期落盘:展开过程中,每当新增一定量的分析结果(如每执行 3 到 5 次展开,或完成一个子树后),及时编辑文件写入新内容,以避免遗忘;不建议汇总大量结果后才统一写入。详见"写入文件的时机"一节。
书写约定:
- And 关系不标注,默认即是 And
- Or / + / × 在父节点文字描述后标注
:or/:+/:× - 建议(非必须):若补充拆分依据能让文档更清晰,可在行末追加
(拆分依据:描述),如:×(公式:σ = ρ × a × D)。仅在确有帮助时添加
写入步骤:
- 按上述约定在父节点行末标注组合关系
- 把子因素写入文件:默认缩进下一层;若满足"箭头简写"前提(单因链,见"输出格式规范"),可改用 ← 简写在同一层级写入(不是必须)
- 对每个子因素评估优先级(对初始缺点的影响/贡献程度),加入待展开队列
4.6 中期结构扫描
因果链持续膨胀,建议每新增约 20-30 节点或每完成一个主要分支后,做一次中期结构扫描。
1. 因素表述预检:按 references/factor_definition.md 的检查方法,
运行 scripts/check-notation <file> 粗筛疑似违规表述。
逐条做语义复核,修正真实问题并重跑,忽略误报。
2. 重构子树:检查因果链中是否有缩进层级过深、内容特别复杂的子树。 这样的子树可以独立出来,在下方另起一个段落单独分析,从而降低缩进层级、提高可读性。 例如:
* A
* B:or
* D:单独深入分析
* E
* C
# 单独分析:D
* D:×
* F
* H
* I
* G
在原先的位置用 :单独深入分析 标记,并引用下方独立段落的标题。
3. 子 agent 扫描:完成子树重构后,启动一个子 agent 扫描分析文件。它只提建议、不修改文件。 让它阅读本 SKILL.md(给完整路径)以了解所有规范要求,一方面检查这些要求,另一方面额外关注以下 SKILL.md 未专门覆盖的结构性检查:
- 缩进结构是否正确(每层严格 +1 tab),是否存在孤儿节点
- 非终端但无子节点的叶子节点,判断是否应继续展开
- 过早标记为末端的节点(重言式、逻辑不充分的终端理由)
- 语义重复或可合并的节点
- 缺失的桥接公式(如本应存在但未显式写出的公式节点)
- 按优先级给出改进建议
你或子 agent 均可用 scripts/check-leaves <file> 列出所有叶节点。
额外加 --non-terminal 只显示待展开节点,加 --terminal 只显示已标记节点。
4. 重读规范:你自己重新使用 read 工具读一遍本 SKILL.md 以及 references/ 下的辅助文档。 因果链分析到这一步,上下文中已积累大量分析历史,早期读入的规范要求可能被冲淡。 重新加载规范,使其在上下文中多次重复出现,有助于在后续分析中保持对各项要求的准确遵循。 如果重新加载后意识到之前已进行的分析存在不符合要求的迹象,考虑返工修复。
步骤5:因果链收尾检查(6项全局复盘)
当待展开队列为空(所有节点都已展开或被判定为末端)时,进入收尾检查。
虽然每次展开时已经做过表述、跳步、遗漏的即时检查,仍然需要把以下 6 项检查完整反复确认多遍,重复多轮直到改不动为止。
重要:对每一项检查,如果发现错误就立即修改文件,不能等 6 项都检查完才一起修改。
工具使用:到这一步,因果链分析文件通常已经较长,且使用 tab 缩进表示层级,逐行通读不易把握整体结构。 如果环境中有 outline-read skill 可用,可加载它来读取已编写的分析文件,以便按层级折叠展开,辅助在 6 项检查中快速定位和浏览各节点。
检查一:每个缺点因素的表述是否满足要求
复查全文档,每个缺点因素分别核对是否符合因素定义。
详细标准见 references/factor_definition.md,包括可利用的检查脚本。
检查二:是否有跳步
复查全文档,逐节点检查每个因果关系是否符合"直接原因"标准(标准与示例见步骤4.3.4 验证 2)。 在此基础上,额外关注逐节点检查时不易发现的跨节点、跨子树逻辑跳跃,发现问题立即补上中间层。
检查三:是否有遗漏因素
复查全文档,逐节点核对是否有步骤4.3.4 验证 3 中遗漏的因素。 同时关注单个节点展开时局部看似完备,但从全局角度看(结合其他子树的信息交叉验证)才发现缺少的必要前提。 发现遗漏则补充到相应层级下。
检查四:是否提前终止
检查各个因素节点在之前的分析中是否过早终止,即缩进层级到此为止,但其实现在看看它好像并不是末端缺点,可以继续展开出下一层的原因。
检查方法:对于每个叶节点(无论是否已标注 :末端),问自己"这个原因还能继续追问'它发生的机制是什么'吗?"
可用 scripts/check-leaves <file> 列出所有叶节点。
注意别跑偏:追问涉及的所有因果关系仅限于客观规律(为什么发生),不讨论主观动机(为什么这么做)。不要分析系统为什么这么设计、参数为什么这么选取。如果出现了这样的分析,请把它删除。
检查五:你能想到的所有解决方案,是否都对应末端缺点?
目的:通过反向验证检查分解完备性,不是要做方案设计。
- 先别管你做过的分析,直接看用户的原始问题,或者识别出的初始缺点,设想一些可能的解决方案
- 再回头检查你的分析:对每个这样的解决方案,检查它为何有效,是否是因为它解决了至少一个末端缺点
- 如果有它所解决的中间缺点,但没有直接对应的末端缺点,检查这是否意味着你的分析出现了:
- 跳步,展开的原因不是直接原因
- 某一层展开有遗漏因素
- 有的中间缺点之前错误地展开了设计动机(应作为末端缺点,或改按客观机制重新展开)
- 其他不合理之处
- 如果你认为它确实不应该对应任何末端缺点,需要有明确的理由
检查六:是否有其他你觉得不合理之处?
一切你觉得不合理的地方都算:前后矛盾,不构成原因,等等。
检查流程
- 完整做一轮 6 项检查
- 如有错误,立即编辑文件修正(不要等 6 项都完成再改)
- 修正后重新从检查一开始做下一轮
- 若某轮检查无任何修改,改变视角再做一轮检查,例如逆向(从末端到根,或从后往前)
- 连续两轮检查都没有发现需要修改的地方,才确认收尾检查通过
- 确认通过后,进入步骤6
步骤6:子 Agent 改进审查
开始前提:只有完成步骤5,且确认连续两轮(共 2×6 项)检查都没发现问题后,才允许进入这一步
执行条件:如果你负责的是从头执行一次完整的因果链分析(而不是改进一个已有的分析结果文档),并且没有被告知"不要创建子 agent",则执行以下操作:
- 创建一个子 agent(需有文件读写能力),让它:
- 加载本 SKILL.md 全文(给完整文件路径)以了解所有规范要求
- 读取你生成的因果链分析结果文档(给完整路径)
- 首先执行步骤5,反复进行六项检查并修改,直到连续两轮都没发现要改的地方
- 确认无误后,关注中期扫描所列的结构性检查(缩进、孤儿节点、未展开叶子、过早终端、重复节点、缺失桥接公式)
- 直接编辑文件进行修改改进
- 检查是否有其他不合理、或应重新考虑之处,若有,在汇报时告知
- 命令它绝对不要再创建子 agent
目的:通过独立的、上下文无污染的子 agent 审查,发现主 agent 可能遗漏的问题,进一步提升因果链分析的质量。 步骤6 的 agent 与步骤4 中期扫描 agent 的区别:前者直接动手修改,后者只提建议。
子 agent 完成后,检查它的修改处数:
- 如果修改超过 5 处,说明可能仍有改进空间,请再创建一个新的子 agent 做相同任务
- 重复此过程,直到某次修改少于 5 处,或当前步骤6 已累计启动 3 次子 agent(含第 1 步的那一次)
前一步终止条件满足后,根据最终版因果链分析文档,重新执行一轮步骤5 的 6 项检查,发现新问题就接着修改。再也找不出更多问题后,可以结束分析。
因素定义
详细的因素定义(主语+谓语形式、明确具体、原子化、客观事实、肯定陈述、必要时补充状语)见 references/factor_definition.md。
末端缺点判定标准
当满足以下任一条件时,该节点即为末端缺点,不再展开。在行末标注 :末端(判定理由),判定理由简要注明属于哪一条标准。
这些标准在步骤4.4(展开时即时判断)和步骤5检查四(收尾复查)中都要用到。
- 达到物理、化学、生物或几何等领域的极限
- 达到自然现象(如惯性、引力、人体生理机制等,它们是导致问题的缺点,但无法干预改变)
- 避免扩大解读:例如"钢球材料强度有限"不是末端,应进一步归因为"材料为钢"(设计决策),有时还包括"钢球温度高"(可继续展开)
- 达到系统设计决策(如"油漆箱容量太小",不应分析为何这么设计;正确的做法是继续分析"长/宽/高/形状")
- 只有当继续追问必然会转向"为什么选择这种设计"时,才按系统设计决策终止
- 若还能分析该设计在当前事件中通过什么客观机制产生错误,则应继续展开
- 达到法规、国家或行业标准限制
- 无法继续找到下一层原因
- 达到成本极限或人的本性
- 继续分析将与本项目无关
输出格式规范
Markdown 文件结构
# 因果链分析:[问题概括]
[使用缩进表示层级的因果链]
[同级缺点的关系区分 And / Or / + / ×]
[Or 关系在父节点后标记 `:or`,+/× 同理,And 无需标记]
[拆分依据可在行末用括号注明,非必须]
[末端缺点在行末标记 `:末端(判定理由)`]
[重复/等价因素标注 `:上方/下方/祖先节点已分析`,可选追加 `(仅差限定词)` 和/或 `(反面)`]
- 初始缺点
- 直接原因1
- 下一层原因
- 下一层原因
- 直接原因2:or(形态枚举:…)
- 次级原因A
- 次级原因B
- 直接原因3(公式:…)
- ...
缩进表示规则
- 使用
-或*开头表示因果节点 - 每往下一层增加 一个 tab的缩进
- 不需要编号(如 1.1.1.2),纯缩进即可
- 父子关系:缩进在下一层的因素是上一层因素的原因
- 同级关系:同一缩进层级的多个因素,默认是 And 关系(共同出现时使上一级因素出现)
- 其他关系:如果是 Or 关系,在它们所导致的父节点行末标记
:or,+/× 类似
结构示例:完整的因果链输出样例见 examples/static_electricity.md,展示了 tab 缩进表示层级、父子与同级关系的实际写法。
箭头简写(单因链折叠)
连续的"唯一子节点"链可用 ← 简写压平到同一缩进层级,避免缩进过深。 简写并非必须,沿用原有基于缩进的展开方式也完全没有问题。
前提条件(X 欲对 Y 使用简写时,以下均须满足):
- X 是 Y 的唯一直接子节点
- Y 也是其父节点的唯一直接子节点
条件 2 是硬前提:若 Y 有兄弟节点,即便 X 是 Y 的唯一子节点,也不得使用简写。
写法:* ← X,与上一行 Y 同级缩进。链可连续延伸,遇到多子节点处恢复正常缩进。
示例:
* 初始缺点:loss 上升
* ← 正确类输出 logit 降低
* ← 模型权重变化大
* ← Adam 更新量大
* 学习率大
* 累积动量大
* 当前梯度大
* 反传梯度系数非零
* ← 正确类预测概率与 1 距离大于浮点舍入误差
* ← 正确类预测概率低
…
使用前必验:单因情形不常见,需重新检验拆分逻辑,确认两层均为唯一的直接子节点。一旦发现遗漏的并列因素,前提破坏,改用正常缩进。
分析过程中的注意事项
优先级评估与二八定律
待展开队列的优先级排序遵循二八定律(帕累托原则):优先展开对初始缺点影响最大、贡献最显著的少数关键因素节点。
判断一个节点优先级的高低,可以从这些角度考虑:
- 该因素的消除能在多大程度上缓解或解决初始缺点
- 该因素在科学公式中对应的项,其量级或变化幅度是否显著(例如分析注意力计算量时,优先展开复杂度高的子组件)
- 该因素是否处于因果链的主干路径上
优先级无需精确量化,凭分析者的判断给出相对排序即可。目的是把分析精力投入到最可能产生关键缺点的分支上,而非平均分配到每个节点。
努力细化分析
- 努力把分析做得更细致:从本以为的"直接原因"中剥离出更直接的原因(更少跳步),从本以为的"充分条件"后挖掘出更多的隐藏前提(更少遗漏),把本以为的"末端缺点"分解出更底层的末端缺点(深入拆解)
- 高手的分析经常可以达到 20+ 层,拆解出 500+ 个因素节点。尽管不是所有问题都确实能拆解出这么多的因素节点,但你应该有对分析精细程度的极致追求
- 如果你觉得有必要,可以启动子 agent 对某个子因素再展开专门的深入分析
- 分析结果质量属于关键核心追求。只要对质量提升有益,请坚决避免任何形式的控制成本的企图(例如 token 消耗、子 agent 创建)
验证逻辑
- 每找到一个因果关系问自己:"这些原因真的保证会导致这个结果吗?有没有其他依赖的前提条件?"
- 检查是否有逻辑跳跃(跳过了中间层级的直接原因)
与用户互动
- 初始缺点不确定时:先确认再分析
- 分析方向迷茫时:可以简要说明你的思路,询问用户意见
- 用户有新信息时:及时更新分析
- 检查过程中有疑问时:也可以询问用户
使用网络搜索
- 使用条件:除非用户明确提及,否则一般不需要使用网络搜索,缺失的背景信息可以直接询问用户。如果你确实认为需要,请向用户确认
- 使用时机:只有在独立完成相当一部分分析之后,才允许调用网络搜索。不允许一上来就搜索网络信息。展开到某个节点需要确认公式或机制时,可以查询
- 使用方式:务必注意,网上找到的原因分析通常极度不专业、不可靠。请仅仅用它来完善你的因果链分析,帮助发现更多之前没有意识到的因素。绝对不要被别人的结论主导你的分析过程
写入文件的时机
- 创建文件:步骤3 开始时立即创建Markdown文件,写入初始缺点
- 迭代编辑:步骤4 展开过程中,每新增一定量分析结果(如每展开 3 到 5 个节点,或完成一个子树后),及时把新内容写入文件,避免后续遗忘
- 即时修正:步骤4.1 发现表述问题时、步骤5 检查发现问题时,立即编辑文件修正
文件命名建议:
因果链分析_问题名称.mdcausal_chain_analysis_xxx.md
位置:由 AI 根据上下文自行决定,除非用户指定了特定位置。
案例参考
案例:静电问题
用户输入:"冬天开门总是被静电打到"
分析过程(以逐节点展开的方式):
- 理解问题:表层缺点是"被静电打到"
- 推导本质初始缺点:静电产生电流 → 电流刺激神经末梢 → 疼痛产生。按因素定义规范调整措辞后,确认初始缺点为"手指痛觉明显"(可与用户确认)
- 初始化文件与队列:写入"手指痛觉明显"作为根,加入队列
- 逐节点展开(示意):
- 展开"手指痛觉明显":
- 确认表述符合规范,不重复,尝试拆分
- 直接原因 = 痛觉神经末梢受到的刺激强度大 and 痛觉感知通路功能正常
- 检验通过,两个子节点入队("刺激强度大"优先级最高)
- 展开"刺激强度大":拆为 通过手指的放电电流大 and 手指痛觉神经末梢分布密集 and 痛觉感受器对电流刺激敏感
- 展开"放电电流大":用公式 I=U/R 拆分为 人体与门把手间电位差大 × 放电通路电阻小
- 展开"电位差大":用公式 ΔU=U_人体−U_门把手 拆分为 人体电位偏离地电位多 + 门把手电位低
- ……继续展开,直到队列为空
- 展开"手指痛觉明显":
- 因果链收尾检查:完整做 6 项检查,连续两轮无问题
- 外部审查:启动独立的子 agent 进一步检查,改进因果链分析结果
完整分析结果见 examples/static_electricity.md。
开始分析
当用户请求因果链分析时:
- 首先理解用户的问题(步骤1)
- 判断是否需要推导本质初始缺点,如需要则向用户确认推导结果(步骤2)
- 创建Markdown文件,写入初始缺点,建立待展开队列(步骤3)
- 进入逐节点展开的核心循环,每次取优先级最高的节点展开,即时确认表述、检查重复、尝试拆分、检验拆分、判断末端、登记子节点,定期写入文件,适时中期检查(步骤4)
- 队列空后,做 6 项收尾检查,连续两轮无问题才通过(步骤5)
- 检查通过后启动子 agent 做全局改进审查,审查后再做一轮 6 项检查(步骤6)