小语言模型的代码引导推理:可执行 MCQA 支架的评估 Code-Guided Reasoning for Small Language Models: Evaluating Executable MCQA Scaffolds
提出 CGR 评估协议,量化可执行 Python 支架对小模型 MCQA 的影响与审计。
前置知识
多选题问答 (MCQA)
Multiple-Choice Question Answering,模型从若干离散选项中选出唯一正确答案的任务。MMLU、MedQA、SuperGPQA 等都属于 MCQA 范式,比开放式生成更易精确打分。
本文核心是评估 SLM 在 MCQA 上的表现差异,三通道打分都基于 MCQA 的离散选项匹配。理解 MCQA 才知道为何作者要单独审计'答案抽取失败率'(X 比例)。
小语言模型 (SLM)
Small Language Model,参数量通常在 1B-30B 之间、可以在本地或低成本部署的语言模型。本文的求解器全部为 SLM,包括 Llama 3.2 11B、Mistral Small 24B、Granite 4H Small 等。
SLM 是 CGR 的评估对象。文章反复强调 SLM 在部署中常被外层脚手架包裹,单看直接答题分数无法反映真实系统行为。理解 SLM 才能理解为何要做支架评估。
程序辅助推理 (Program-aided Reasoning)
让模型生成可执行代码(Python 等),把推理中的计算部分交给解释器执行的工作,包括 Program of Thoughts (PoT)、PAL、CodeAct 等。CGR 是该范式在 MCQA 上的具体实例。
CGR 与 PoT/PAL 同源,但独特之处在于'双模型'结构:生成器写代码、求解器被调用多次,三通道分别打分。这是理解 method 章节的关键背景。
LLM 脚手架 (Scaffold)
包裹在模型外的控制系统,包括 prompt 模板、工具调用、循环/分支逻辑、状态管理等。部署中的 LLM 系统几乎都依赖 scaffold 协同多个模型与外部资源。
文章论点是:直接 MCQA 分数不是 scaffold 下的真实表现。理解 scaffold 才能理解为何要单独设计一种'可执行代码形态'的脚手架并审计其影响。
Bootstrap 置信区间
通过对样本做有放回重采样来估计统计量分布的非参数方法。在 MCQA 评估里常用来给 (d, m) 对的差值配 CI,避免被数据集大小主导结果。
本文报告的 $[20.32, 36.43]$ pp 区间就是 dataset-solver pair 上的 percentile bootstrap。没有这个背景就难以理解为何作者要给宏平均配 CI 而非微平均。
研究动机
当前的 MCQA 基准几乎都把小型语言模型 (SLM) 当作'直接答题者'打分,但实际部署中 SLM 极少被裸 prompt 调用,而是被外层 scaffold 包裹:控制器可能拆解问题、调用模型多次、运行小段代码、再合并选项。例如 Llama 3.2 11B 在 MedQA 上直接答题仅 1.20%,而它被代码支架调用后却能拿到 84.57%。这种巨大差距说明直接 MCQA 分数完全没有反映 scaffold 下的真实行为。此外,现有的程序辅助推理 (PoT/PAL/CodeAct) 与工具使用基准 (APPS、InterCode) 也只把推理 trace 视为副产品,没有系统地把'同一求解器在直接 vs. 可执行脚手架下的对比'作为测量目标。
本文的目标是本文提出 CGR (Code-Guided Reasoning) 评估协议,把同一道 MCQA 题分别走两条路径:直接 prompt 让目标求解器输出一个选项字母;以及让一个生成器 LLM 为该题写一段 Python 脚手架,调用同一求解器多次、汇总后返回答案。最终在 9 个本地化数据集、6 个 SLM 求解器上保留 20,498 行结果,并独立审计直接 / 辅助 / 生成器三通道的准确率、调用预算、抽取失败率、生成代码字面答案等。
与已有工作不同的是,切入角度是'测量协议'而不是'新模型'。CGR 明确不做 cost-matched 的因果推断,而是把 scaffold 视为一个可审计的测量条件,强制把三个答案通道拆开记录,禁止把生成器侧的答案喂给求解器 side 的调用。差异化的护城河是 (q, d, m, g) 四元组的三通道 trace 包、非零基线/零基线分区、以及对提取失败、字面答案、调用预算的强审计。这是 PoT/PAL 没有强调、传统 MCQA 基准完全缺失的一层。
核心方法
CGR 的整体思路是'一个题目、两个模型、三个通道、一份审计'。直觉上:先让目标 SLM 求解器直接答一次 (direct),再让另一个生成器 LLM 看到同一道题写一段 Python 脚手架;这段代码可调用求解器多次、提取字母、投票或用 tiebreaker,最后返回 (solver_assisted, generator_side, difficulty) 三元组。技术上,作者给每道题定义了 $(q, d, m, g)$ 的评估单元,$p_{q,g} = G_g(q, d)$ 是生成器写出的程序,$S_m$ 是求解器 API;直接路径观察 $y_b = S_m(q)$,辅助路径执行 $(y_a, y_g, \hat{h}) = p_{q,g}(q, d, S_m)$。三个答案分别与 gold $y_q^\star$ 比较,得到 $z_c(q,m,g) = 1\{y_c = y_q^\star\}$,$c \in \{b, a, g\}$。生成器侧答案 $y_g$ 不被回灌到求解器的 prompt 里,从而隔离'生成器自身知识'与'求解器被多次调用的真实增量'。
核心创新是把'可执行代码 scaffold'从一种推理方法变成一种测量条件,并强制三通道拆分 + 非零基线分区。区别于 PoT/PAL 把代码当作一次性求解器:PoT/PAL 让模型自己写代码自己跑,CGR 的代码由独立的生成器写、由独立的求解器执行;区别于 Chain-of-Thought 把 trace 留在自然语言里:CGR 的 trace 是 Python 对象、可分支可查 state;区别于普通 self-consistency:self-consistency 只重复同一个 prompt,CGR 允许分析 + 验证 + tiebreaker 等异构 prompt。
方法步骤详情
CGR 协议分四步。第一步是数据准备:在本地把 MMLU-Pro、OpenBookQA、SuperGPQA、Time-MQA、MedQA、PhysicsQA、AIME 2025、CorrectBenchQA、FailureSensorIQ 9 个来源统一成 (id, question, options, option_ids, correct_flag) 的 MCQA 项接口。第二步是 direct path:对每对 (q, m) 调用 $S_m(q)$ 一次,记录直接答案 $y_b$,调用计数均值为 1.01。第三步是 assisted path:把 q 喂给生成器 G_g,得到 Python 程序 $p_{q,g}$;执行 $p_{q,g}(q, d, S_m)$ 提取 $(y_a, y_g, \hat{h})$,辅助调用均值为 7.23、p95 为 15、max 为 90。第四步是审计:扫描生成代码是否含字面答案正则 (43/3,569 文件命中,映射 251 条记录)、统计抽取 X 失败率 (辅助 15.67%)、计算 dataset-solver 对的宏平均差值并配 percentile bootstrap CI。分区上,把 (d, m) 对按 $A_b(d, m) > 0$ 与 $A_b(d, m) = 0$ 切两片,$A_b > 30\%$ 作为更强的直接信号门,$\rho = (M(A_a) - M(A_b)) / (M(A_g) - M(A_b))$ 报告生成器 gap 闭合度。
技术新颖性
技术新颖性体现在四点:(1) 把生成器和求解器解耦成双模型 + 固定返回契约 (solverLLM_answer, genLLM_answer, genLLM_difficulty);(2) 强制求解器 prompt 不接收 genLLM_answer,从而可以单独测出'重复调用 + 异构 prompt'的纯增量;(3) 引入非零基线/零基线双分区,把'答不对的题被救回'与'本来就会的题被帮助'清晰隔开;(4) 把'字面答案正则扫描、抽取 X 比例、调用预算分布、bootstrap CI'做成强制审计项。整体不训练新模型、不维护模板库,因此 CGR 是评估协议而非模型架构创新。
实验结果
核心数据来自 20,498 条保留结果,覆盖 9 个数据集配置、6 个求解器。全体微平均上,直接 23.27%、辅助 62.41%、生成器侧 79.19%,差值 +39.14 pp。主结果非零基线宏平均:直接 $38.11\% \pm 28.48$、辅助 $66.21\% \pm 20.14$、生成器 $81.58\pm 14.47$,差值 +28.10 pp $\pm 24.04$,配 bootstrap CI $[20.32, 36.43]$ pp。强基线门 $A_b > 30\%$ 下增益缩到 +14.11 pp。零基线分区宏平均直接 0.00% / 辅助 62.19% / 生成器 82.30%,是诊断性而非部署证据。按数据集看最大增益在 MedQA (Llama 3.2 11B 1.20% → 84.57%)、AIME、SuperGPQA、MMLU-Pro;MMLU-Pro 上 Nemotron-3-Nano-4B 从 64.13% 提到 86.77%,SuperGPQA 上 Granite 8B Code +47.78 pp。负面结果集中在 Time-MQA:Granite 8B Code 从 31.70% 退到 29.24%、Gemma 4 E2B 从 61.65% 退到 56.22%、Nemotron-3-Nano-4B 从 62.25% 退到 61.04%;同数据集低基线求解器反而获益 (Llama 3.2 11B 1.42% → 56.68%)。审计上辅助调用是直接的 7.36 倍 token 预算 (148.12M vs. 20.12M),生成器代码生成 metadata 0/20,498 行被连接,抽取 X 失败 3,212/20,498 行,2,523 行错误日志分布在 15 个文件。
查看结构化数据
| 任务 | 指标 | 本文 | 基线 | 提升 |
|---|---|---|---|---|
| 全部 9 个 MCQA 数据集微平均 | 准确率 | 辅助 62.41% / 生成器侧 79.19% | 直接 23.27% | +39.14 pp(微平均差值) |
| 非零基线 dataset-solver 宏平均(主结果) | 宏平均准确率 | 辅助 66.21% ±20.14 | 直接 38.11% ±28.48 | +28.10 pp ±24.04,CI [20.32, 36.43] |
| 强直接信号门 $A_b > 30\%$ 宏平均 | 宏平均差值 | 辅助 vs 直接 = +14.11 pp | 直接基线 38.11% | 增益缩为 +14.11 pp,证明并非全部由 prompt 失败拯救 |
| MedQA 配 Llama 3.2 11B(单对最大增益之一) | 准确率 | 辅助 84.57% | 直接 1.20% | +83.37 pp |
| Time-MQA 配 Granite 8B Code(最大退化) | 准确率 | 辅助 29.24% | 直接 31.70% | -2.46 pp 回归 |
局限与改进
作者明确指出的局限包括:(1) 不是 cost-matched 因果实验,辅助路径使用 7.36 倍直接 solver token 预算,且辅助均值调用 7.23 次、max 达 90 次,违反 prompt 声明的'最多 10 次';(2) 答案抽取脆弱:辅助 X 失败率 15.67%,这是把 5 选 1 错误判成不可解析的比例,会人为压低直接基线、放大利差;(3) 零基线分区 +62.19 pp 不能简单视为 scaffold 价值,更可能源于抽取修复或生成器自身知识;(4) 生成代码字面答案正则命中 43/3,569 文件并映射到 251 条记录,说明 'no-hard-coding' 是 prompt 指令而非运行时强制;(5) 生成器调用 metadata 0/20,498 行被 join,运行配置 JSONL 未保留,可复现性受限;(6) 没有 matched-budget direct self-consistency、CoT direct、no-code repeated-call、generator-only direct 等关键对照。我自己观察到的额外问题:三通道不是嵌套子集 (1.36% 行辅助对/生成器错,16.72% 行生成器对/辅助错),简单的辅助分掩盖了不同失败模式;Time-MQA 上同一数据集同时有 +55 pp 与 -2 pp 回归,提示该分区在没有 controlling for 时序分解质量时不可解释。
独立分析的弱点
独立分析的具体弱点有三个。第一,协议对生成器侧知识没有隔离:虽然 $y_g$ 不回灌到 $S_m$ 的 prompt,但生成器在写 Python 时已经把答案'塞进' $p_{q,g}$ 的字面字符串,43 个文件 / 251 条记录被字面答案正则命中就是证据,这意味着有些'辅助正确'其实是生成器把答案当常量塞进去的伪装正确。第二,bootstrap CI 在 dataset-cluster / solver-cluster 重采样下加宽到 $[18.41, 38.57]$,提示原 pair-bootstrap 略微低估了不确定性,作者应在主表同时报告两种 CI。第三,prompt 限制 (最多 10 次调用、禁止硬编码) 完全靠指令而没有运行时校验,导致 max 90 次调用、字面答案 251 条都未被发现 — 这对'评估协议'的可信度是硬伤。第四,零基线 +62.19 pp 这个戏剧性数字如果没有 matched-budget 对照,会被读者误读为 scaffold 的普遍收益。改进方向是:(a) 给生成器代码加 AST 校验器,禁止变量赋值中含选项字母;(b) 用调用计数器 + raise 强制 10 次上限;(c) 增加 cost-matched self-consistency 与 CoT-direct 对照;(d) 把字面答案命中行从主结果中剔除并重报差值。
未来方向
作者提出的下一步包括:option-set-aware extraction、runtime call limits、sandboxed execution、generated-code validators、repeated generated-program sampling、matched-budget direct baselines。这些方向都直接对应上面列出的弱点。基于成果可延伸的方向有三个:一是把 CGR 的双模型三通道范式推广到开放式问答与代码生成 (HumanEval 类),看是否在非 MCQA 上也成立;二是把生成器侧 $y_g$ 与 $\hat{h}$ 作为额外的监督信号用于求解器的 RFT / DPO 训练,把审计 trace 反向变成数据资产;三是把 $\rho = (M(A_a) - M(A_b)) / (M(A_g) - M(A_b))$ 这个 gap 闭合率做成 scaffold 健康度指标,在线监控长任务中 scaffold 是否在持续贡献增量、还是在被生成器'搭便车'。
复现评估
复现性偏弱。文章标注了 trace 包 (20,498 retained rows、9 datasets、6 solvers、生成代码 3,569 文件、response metadata) 的存在,但 main-run configuration JSONL 文件未保留,运行参数仅靠 notebook / code 证据与 response metadata 支撑。开源情况未在文中给出明确仓库链接;数据集层面 9 个配置里 AIME 2025 因 MAA 版权不在文中复现题目,Time-MQA、FailureSensorIQ 需自行准备。算力方面:6 个 SLM 求解器各跑 20,490+ 调用,总 token 168.24M,单机本地即可复现但耗时较长。最大复现难度在于 (1) 生成器模型与求解器模型的 prompt 模板、2000 / 8192 token 截断、solverLLM_reattempt_max_ct=3 等参数;(2) 字面答案正则的具体规则未给出;(3) pair-bootstrap / dataset-cluster bootstrap 的 resample 单位定义见 Appendix D。建议按 Appendix B 字段表 + Appendix D 配置表 + trace 包字段对照逐项复现,难度属于'需要中等工程投入'。
论文图表
上半部分:direct baseline 路径 = MCQA item → Direct solver SLM → Answer extractor → Direct answer;executable assistance 路径 = MCQA item → Generator LLM → Python scaffold → Executor with solver calls → Assisted answer,下方有 audit trail 块记录 prompts/代码/调用/响应/元数据。下半部分是 OpenBookQA 'fog around' 例:题目问有雾地点 (marsh/tundra/plains/desert),gold A;scaffold 定义 fog 为近地空气降到露点并比较四选项湿度/冷却/风速/露点差;Granite 4H Small 直接答 E (越界),辅助答 A 且与生成器侧 A 一致,难度 3。
这张图把抽象的三通道协议落到一道具体题上,演示了生成器写代码、求解器被多次调用、抽取与 tiebreaker、genLLM 答案不回流等关键约束,是理解 method 的最佳单图。
三通道在同行的重叠:All evaluated items 20,498 行,A/G 答案一致 15,477 (75.50%),A 对 G 错 249 (1.21%),G 对 A 错 3,688 (17.99%);Observed non-zero baseline 13,256 行,三个比例 76.82% / 1.36% / 16.72%;Zero baseline 7,242 行,三个比例 73.10% / 0.95% / 20.31%。
揭示三通道并非嵌套子集,是评估'辅助分数是否真代表 scaffold 价值'的关键证据。如果 G 对 A 错占 17%,说明 generator-side 答案不能被简单合并进 assisted 准确率。
7 项审计:Response metadata join 20,498/20,498 有 metadata (direct 20,490, assisted 20,492);Generator-call metadata 0/20,498 行 join 成功;Solver-call count direct 1.01/1/1/3 vs assisted 7.23/6/15/90;Token budget 148.12M vs 20.12M,7.36×;Extraction failures assisted X 3,212/20,498、direct X 91/20,498;Error logs 2,523 行跨 15 文件,最大类为 call-limit / key / value errors;Literal-answer regex 43/3,569 文件映射到 251 行;Prompt call limit '≤10 calls' 声明但 runtime 存在超出行。
把'评估协议的可信度'量化成 7 条具体数字。任何一项缺失都会让 +28.10 pp 失去解释力,是 reproducibility 章节的核心证据。
Time-MQA 6 个求解器:低基线获益组 — Llama 3.2 11B (1.42% → 56.68%, gen 61.54%)、Mistral Small 3.1 24B (8.23% → 49.40%, gen 60.64%)、Granite 4H Small (3.58% → 21.89%, gen 59.37%);强基线回归组 — Granite 8B Code (31.70% → 29.24%, gen 59.51%)、Gemma 4 E2B (61.65% → 56.22%, gen 61.45%)、Nemotron-3-Nano-4B (62.25% → 61.04%, gen 62.05%)。
唯一一张把所有负结果集中展示的表,证明 'CGR 普适' 不成立,并提示时序数据的分解质量可能拖累已经能直接答对的求解器,是 limitation 章节的关键证据。