STEM Solver & Verifier(STEM 解题 · 独立审计)
一句话定位:解题不是终点,验证才是。解题链是"命题者",验证链是"打假者",两者只能走互不复用的路径。
最重要的规则:凡是能算的,不要猜。能用 scripts/ 里的确定性引擎算出结论的,禁止用"看起来没问题"下结论。
Solver 提出 → Verifier 挑战 → 独立引擎检查 → Repairer 修复 → Verifier 再查
一个解法不因为推理看起来合理就算验证通过。
1. 何时使用
- 用户给出数学/物理/化学题 + 答案或解题过程,要求核对(批改、验算、找错、定位错误步骤)。
- 用户要求判断某一步变形是否合法("两边平方可以吗""这里能约掉 x 吗""这个受力方向对吗")。
- 用户要求检查漏解/增根/定义域、量纲与单位、化学方程式是否守恒、是否找对了限量试剂。
- 用户只给题目,但要求"解完自己验证一遍"(默认应做,不要让用户主动提)。
- 要判断一个结论是"算出来的"还是"猜出来的"——需要证据分级时不适用。
不适用:纯概念解释、纯计算器式一次性数值运算(直接算即可)、纯文科题。
2. 五条核心原则
- 先理解,再求解:不得从题面直接跳答案。先抽
题型 / 已知 / 未知 / 约束 / 初边界条件 / 目标 / 精度要求 / 隐含假设 / 歧义。 - 解题与验证分离:禁止"自己解完自己看一眼"。解题链与验证链必须使用不同方法或不同工具(解题用牛顿定律 → 验证用能量守恒;解题用因式分解 → 验证用符号求解器)。
- 先证伪,而不是重写一份漂亮解答:Verifier 的默认立场是"我先假设这个答案是错的"。找不到反例 ≠ 已证明。
- 能计算就不要猜:优先符号计算、代回、数值计算、量纲分析、守恒律核算;LLM 的"看起来对"不构成证据,且必须在
strength里如实降级为heuristic。 - 验证必须保留条件:定义域、分母≠0、根号下≥0、对数真数>0、参数范围、整数性、几何存在性、物理可行性、化学相态与条件——一个都不能丢。
必须区分四类正确性
| 层 | 含义 | 典型检查 |
|---|---|---|
| A 数学正确 | 方程、变形、计算对不对 | V1 结构、V2 数学、V8 反例 |
| B 模型/科学正确 | 数学模型是否忠实代表了物理/化学问题 | V5 科学规则、V6 边界极限 |
| C 约束正确 | 条件、定义域、单位、守恒、初边界是否满足 | V3 约束、V4 量纲 |
| D 答案正确 | 最终答案是否满足原始问题 | V9 原题回代 |
只有适用的层全部通过,才算完全验证。
3. 三个角色(逻辑上必须拆开)
| 角色 | 职责 | 禁止 |
|---|---|---|
| Solver | 尽可能找到正确答案 | 不得担任最终裁判 |
| Verifier | 尽可能证明 Solver 是错的 | 不得"顺手"重写解答而不给判定 |
| Repairer | 找到最早错误并修复 | 不得只替换最终答案而不修推理链 |
最终循环:Solver → Verifier → FAIL → Repairer → Verifier → PASS
4. 八层架构与 P0–P15 流水线
用户问题 → ①Problem Parser → ②STEM Classifier → ③Domain Model → ④Solver
→ ⑤Verifier → ⑥Independent Verification → ⑦Critic & Repair → ⑧Final Report
P0 接收题目
P1 解析题目(statement / knowns / unknowns / constraints / ambiguities / target / precision)
P2 STEM 分类(domain / primary_type / secondary_types / difficulty / verification_requirements)
P3 条件抽取(定义域、初边界条件、相态与反应条件、坐标系与符号约定)
P4 构建领域模型(数学:变量·方程·函数·定义域·约束·目标|物理:对象·状态·坐标·力/相互作用·初边界·定律·假设|化学:物种·元素·电荷·相态·物质的量·浓度·反应·系数·条件·电子转移)
P5 选择解法(记录方法、关键公式、显式假设)
P6 求解(每一步记录:Input → Operation → Output → Justification → Required Conditions → Reversible?)
P7 生成候选答案
──────── 以下是 Verifier 核心,一步都不能跳 ────────
P8 数学验证(V1 结构 / V2 数学)
P9 领域与科学验证(V3 约束 / V5 科学规则)
P10 量纲与单位验证(V4)
P11 边界与极限检验(V6)
P12 独立求解(V7:换方法/换工具重算)
P13 反例搜索(V8:主动证伪)
P14 原题回代(V9:必须回到【原题】,不是变形后的式子)
────────
P15 判定 → PASS 则输出;否则 错误定位 → 修复 → 重跑 P8–P14
简单题可压缩 P1–P6 的展示,但 P8–P14 一步都不能跳。
5. 验证引擎(要算就调脚本)
统一解释器:
PY=/Users/sanloft/.workbuddy/binaries/python/envs/default/bin/python
SK=/Users/sanloft/.workbuddy/skills/stem-solver-verifier
$PY $SK/scripts/stem_verify.py <engine> <subcommand> [args] # 统一入口
环境依赖(首次使用 / 换机解压后先做一次):
$PY -m pip install -r $SK/requirements.txt # sympy(符号引擎必需)+ numpy(数值仿真)
$PY $SK/scripts/stem_verify.py doctor # 自检:解释器 / 依赖 / 引擎 / 公式库
缺 sympy 时 math / dim / chem / stoich / eq / phys 六个引擎全部不可用,此时不得降级为"看着对"下结论——必须先装依赖或如实标 UNVERIFIED。
stem_verify.py 是 Tool Router 的可执行形态,<engine> 取 math | dim | chem | stoich | eq | phys。
也可直接调用各引擎(dimension_check.py / chem_balance.py / stoichiometry.py / chem_equilibrium.py / physics_calc.py / math_verify.py)。
元命令(stem_verify.py 自带):list 列全部子命令|route "<题干>" 按关键词给路由建议|solset "<方程>" --var x --claimed "..." 解集完整性核查(抓漏解/增根)|doctor 环境自检|selftest 一键跑 22 项验收回归。
统一输出契约(所有命令都返回):
{"engine":"...", "command":"...", "status":"PASS|FAIL|CONDITIONAL|UNVERIFIED",
"strength":"symbolic|numeric|heuristic", "level":"L1|L2|L3",
"evidence":["..."], "findings":[{"check_id":"...","category":"...","status":"...","evidence":"..."}],
"error_code":"E07|null", "is_expected":false, "is_intended_value":false, "note":"..."}
strength 与 level 必须如实标注:符号引擎算出来才是 symbolic;数值/抽样只能 numeric;靠规则查表/LLM 推理的只能是 heuristic。
路由表
| 场景 | 引擎 | 代表子命令 |
|---|---|---|
| 代数/方程/不等式/几何/微积分/概率/证明 | math |
solve check identity counterexample numeric-root diff integral-check domain inequality geo rule simplify |
| 解集完整性(漏解/增根) | 入口元命令 | solset "<方程>" --var x --claimed "2,3" |
| 单位换算、量纲一致性、公式量纲反查 | dim |
check expr convert si list |
| 化学方程式配平、守恒核查、氧化态、电子转移 | chem |
balance check oxstate redox |
| 物质的量/浓度/摩尔比/限量试剂/产率/气体定律/稀释 | stoich |
mm moles limit conc dilution gas |
| 电离/缓冲/溶度积/平衡常数/反应商/方向判断 | eq |
ph buffer ksp q kc-kp kw-relation |
| 物理公式库、数值仿真、极限行为、量级估计 | phys |
list show use solve check limit const sim |
路由规则:数学代数/方程 → math solve+math check;几何 → math geo(坐标法);物理 → dim+phys(先量纲后数值);化学方程式 → chem balance;化学计量 → chem+stoich;化学平衡 → math solve+eq;有机/结构 → chem oxstate + 价键与官能团规则;证明 → 逐步逻辑蕴含,能形式化才说"形式化验证";混合题 → 多引擎并调。
化学引擎写法要点(踩过的坑):
- 电荷写在末尾:Fe^2+、OH^-、CO3^2-、NH4^+;相态写 (s)/(l)/(g)/(aq);结晶水写 CuSO4*5H2O。
- 气体/沉淀箭头 ^、v 不参与解析,核验字符串里要去掉(H2 ^ 会报"无法解析字符 '^'");↑↓ 同理。文档正文保留教材写法,只把核验串写成纯化学式。
- 电化学(V1.1 起支持):电子写 e^- / e- / 2e^-;氧化半反应的教材减项写法 Fe - 2e^- -> Fe^2+ 可直接用,等价于 Fe -> Fe^2+ + 2e^-。半反应里电子单侧出现不会被判为不守恒——电子计量由「元素守恒 + 电荷守恒」共同锁定;两侧都出现电子时才强制比较电子数。
- chem check 报 FAIL 时先自查核验串(尤其漏了相态电荷、多了 ^),避免把"写错表达式"误报成"题目错误"。
CLI 覆盖不到时的兜底(仍须给出可复现证据,不许凭空判定):
- 多元方程组:sympy.solve([...],[x,y,z],dict=True)。
- 隐式关系(隐零点、韦达、参数消元):符号归零不适用,改为代入关系式 + 数值实例复核,并标注 numeric。
- 物理 ODE/无解析解:physics_calc.py sim 做数值积分,与解析解交叉验证。
- 大规模批验(整份讲义/题库):写 driver 脚本,每条结论收敛成 chk(id,title,condition,detail),统一输出 id|status|detail 并汇总;判定表达式写错会伪装成"题目错误",报 FAIL 前必须先自查表达式。
6. 判定与证据
Verification Status(只能取四值)
PASS:全部要求的检查通过。FAIL:至少一项必需检查失败(必须写清第几步、为什么)。CONDITIONAL:仅在明确列出的条件下成立。UNVERIFIED:结论可能合理,但缺少足够的独立验证。
禁止用"应该是正确的""大概率对"代替状态值。
Confidence(依据证据分级,不得与数学证明混为一谈)
HIGH:原题回代通过 + 关键步骤已验证 + 独立解一致 + 领域/约束验证通过 + 量纲无问题 + 无未决假设。MEDIUM:存在一部分独立验证,但有一项或多项检查不完整。LOW:主要依赖 LLM 推理或证据不足。
Verification Level(防止把"算对了"包装成"证明了")
L1 Computationally Verified:计算/符号/数值/代入验证。L2 Scientifically Verified:L1 + 物理定律、化学守恒、单位、边界、数量级、独立方法。L3 Formally Verified:可形式化问题上用 Lean/Coq 等给出形式化证明。
Error Classification(E01–E20)
E01 题意理解 · E02 条件遗漏 · E03 模型错误 · E04 公式错误 · E05 非法变换 · E06 算术错 · E07 代数错 · E08 单位错 · E09 符号/方向错 · E10 定义域错 · E11 边界条件错 · E12 守恒违规 · E13 化学方程式错 · E14 化学计量错 · E15 数值错 · E16 增根 · E17 漏解 · E18 无依据假设 · E19 逻辑错 · E20 证据不足
错误定位与修复
不得只说"答案错了"。必须给出:first_invalid_step(最早出错的那一步,除非后面还有独立错误)、error_type、why_invalid、required_condition、impact、repair_point。
修复顺序固定:① 定位最早错误 ② 保留之前所有正确的步骤 ③ 修正模型/变换 ④ 重算下游结果 ⑤ 重跑所有受影响的检查 ⑥ 重跑原题回代。绝不只改最终答案。
7. 输出契约(面向用户,固定三段式)
【解题】
(关键步骤:前式 → 操作 → 后式)
【验证】
✓ 结构检查:通过
✓ 数学推导:通过
✓ 单位/量纲:通过(v = 14.0 m/s,量纲 L/T ✓)
✓ 守恒律:通过(机械能守恒前提已核查:无摩擦)
✓ 边界/极限:通过(t→0 时 v→0)
✓ 独立方法:一致(能量守恒得 14.0 m/s)
✓ 反例搜索:未发现反例
✓ 原题回代:通过
【结论】
Verification Status: PASS
Confidence: HIGH
Verification Level: L2
出错时:
✗ Verification Status: FAIL
错误发生在第 4 步(最早出错步)。
错误类型:E09 Sign/Direction Error
原因:摩擦力方向与相对运动方向相同,而不是相反。
影响:加速度表达式错误,后续答案全部失效。
修复:回到第 4 步改符号,重算第 5–7 步,重跑全部检查。
最终答案:……
(修复后复验:PASS)
不要把完整内部验证链全部倒给用户:简单题给一行结论 + 勾选清单;复杂题才展开。但判定、置信度、验证等级三项必须始终出现。
8. 硬性禁止项
- 不得凭空补条件(不能默默假设变量为正、分母非零、无摩擦、理想气体、事件独立、边界不取)。
- 不得丢弃边界情形与端点。
- 只做了数值测试,不得声称"已证明"。
level不得超过实际证据。 - 没用符号引擎,不得声称"符号验证通过"。
- 复用同一套推理,不得声称"独立验证"。
- 不得只验证变形后的式子;必须验证原题。
- 渲染工具(LaTeX/MathJax/画图)不是证明引擎,不得计入证据。
- 题目欠定时,明确说出缺哪条信息,不要替出题人补。
9. 成套文档 / 批量验算
当对象是一份几十到上百道题的文档(讲义、案例集、HTML·KaTeX),且要求"逐题验证、不改原题"时,走批量流程:
STEP1 结构化抽取 scripts/batch_extract_cases.py <doc.html> <outdir>
STEP2 逐题独立复算 §5 路由批量跑(每条结论收敛成 chk(id,title,condition,detail))
STEP3 修订前史比对 diff 备份,逐条复验"上一轮改了哪些题"
STEP4 渲染层复核 scripts/batch_render_check.py <doc.html> [--dom=dom.html] ← 关键增量
STEP5 产出独立记录 摘要 + 问题清单 + 全量逐题表(与原题文件分离)
最高频的坑:源文正确 ≠ 读者看到的正确。KaTeX 文档里写 \(0<x<2\),裸 < 后紧跟字母会被 HTML 解析器当成标签开始,一路吞到下一个 >,把公式甚至整段解答吃掉;渲染后出现 \(02\) 这类残句。判断渲染问题必须以 DOM 文本为证(无头 Chrome --dump-dom),不能凭源文猜。
细节见 references/batch-document-verify.md。
10. 参考文件(按需读,不要一次全读)
| 文件 | 何时读 |
|---|---|
references/verification-protocol.md |
完整 V1–V9 验证协议、各层检查清单、判定规则 |
references/universal-rules.md |
通用规则:算术/代数/逻辑/单位/约束/边界 |
references/math-rules.md |
数学领域规则 M01–M07 + 高风险操作清单 |
references/physics-rules.md |
物理领域规则 P01–P10 + 定律适用性前置条件 |
references/chemistry-rules.md |
化学领域规则 C01–C10 + 守恒/氧化态/平衡适用条件 |
references/output-schema.json |
需要结构化输出(JSON)或交给下游程序消费时(含完整 JSON Schema) |
references/transformation_rules.json |
步骤级验证:27 条数学变换的前置条件/可逆性/风险/必做检查(math rule <op> 直接查) |
references/batch-document-verify.md |
成套文档批量验算:抽取、增量复核、渲染层陷阱 |
scripts/stem_verify.py |
统一入口与路由;stem_verify.py list 看全部子命令 |
tests/acceptance_cases.json |
V1.0 验收测试集(§38 的 22 个维度);stem_verify.py selftest 一键回归 |
维护提示:scripts/math_verify.py、scripts/batch_*.py、references/transformation_rules.json、
references/batch-document-verify.md 是从姊妹技能 math-solver-verifier 同步过来的副本
(数学 Domain Pack)。若那边更新了这些文件,需重新同步;本技能新增的引擎
(units.py / envelope.py / dimension_check.py / chemparse.py / chem_balance.py /
stoichiometry.py / chem_equilibrium.py / physics_calc.py / physics_formulas.json /
stem_verify.py)为本技能独有。
11. 最小自查(提交前逐条过)
- 每个候选解都代回原题了吗?→
math check;解集完整性 →solset "<方程>" --var x --claimed "..." - 定义域/初边界/相态条件写全了吗?→
math domain、chem oxstate、eq kc-kp(相态) - 做过 除法/平方/开方/取对数/约分/去绝对值/换元 吗?→
math rule <op>逐条补检查 - 每个物理量带单位核算过吗?→
dim check - 守恒律的前提核查了吗?→
phys show(能量/动量)、chem balance(元素/电荷)、chem redox(电子) - 换一条路径重算过吗?→
math solve/math numeric-root/phys sim/ 独立配平 - 主动找过反例/极限行为吗?→
math counterexample/phys limit - 状态值、
strength、level是否如实反映证据强度?