Qwen3.5 4B 在 Ollama 上的实际表现与宣传存在偏差;发现 think:true 模式可能因 token 预算耗尽而返回空内容,需同时检查 response 和 thinking 字段。
think: true 会返回空答案
开启 thinking 后,思维链和最终答案共用同一个 token 预算。当 thinking 消耗完预算时,response 返回空内容,而 thinking 中保存着完整回复。代码如果只读取 response 字段,就会看到空字符串,进而判断调用失败。实际上并没有失败。
今天的测量结果,单行问题,num_predict: 128:
think:false response=200 thinking=0
think:true response=0 thinking=483
修复方法:对于提取和结构化任务,同时读取两个字段,或者关闭 thinking。是否触发取决于你的预算——缩小 num_predict 会使触发更可能。
(另外:有证据表明,将长思维链强加给小模型会损害准确率——Luo et al., "Through the Valley: Path to Effective Long CoT Training for Small Language Models," EMNLP 2025。这是训练时的影响,不是这个 API 字段路由的怪癖。两个是不同的 problem;这里提一句是为了避免混淆。)
自我批评让 4B 变差
我让它批评自己的回答。它口头收回了错误的修复方案——"Remove the check proposed above"——然后在同一回复的代码中重新输出了那个错误的修复方案。
这是 Huang et al. 在 "Large Language Models Cannot Self-Correct Reasoning Yet"(arXiv:2310.01798, ICLR 2024)中大规模测量的一个轶事例子:在 GSM8K 上,GPT-4 的自身准确率在内在自我批评下从 95.5% → 91.5% → 89.0% 逐次下降。
自我批评不是免费的可靠性层。你需要一个外部评判者,而不是模型给自己打分。
请求精确度胜过模型深度
相同输入,两种 prompt。要求输出键名与源字段命名完全一致,准确率从 7/10 移动到 10/10。数字规格——"each row has exactly 3 cells and 4 dashes"——修复了一个描述性规格——"a well-formed separator row"——一直产出错误结果的表格。
这是老生常谈的 prompt 工程建议。只因为我有同输入的前后对比数据,才把它放进来。
外部评判者需要自己的负面对照
这是我一直搞错的部分,而且代价昂贵。
"对输出做确定性外部检查"只完成了一半指令。我有这个检查。它放行了一次伪造。
一个合并任务,两列并一列,81 行。模型凭空编造了 5 个值,这些值从未出现在输入中。检查返回 PASS,autoVerified: true,exit code 0。它没有被绕过,也没有崩溃。每个编造的值都来自一个封闭词表——可能出现的每个值都在输入的某处出现过——所以检查运行的每个 token 级断言都满足了。评判者被问了一个无法区分两种情况的问题。
所以我要给开始做这件事的人一条规则:
一个从未被证明会失败的评判者,并没有被证明能通过。
构建检查,然后喂给它必须拒绝的材料。如果它保持绿色,你拥有的不是一个评判者——而是第二个与模型观点一致的东西。当输出是输入的纯函数时,在接受之前机械地与输入比较。exit code 不是证据。
一个未能复现的结果
我之前的一篇笔记报告说这个模型在 Latin↔Arabic 边界处丢失了空格——要求 hello مرحبا,返回 helloمرحبا。我在 2 次运行中都遇到了这个问题,并将其视为真实缺陷。
今天重新运行:53 次生成。零次复现。七种 prompt 形式在固定模型上测试,其中六种形式在其他两个本地 4B 变体上重复测试,加上原始回显 prompt。
我无法告诉你它被修复了,我也不打算假装——磁盘上的模型文件与首次测量时相同。prompt 形式也无法解释它;我尝试了更接近原始上下文的 transform 风格任务,它们返回的结果也是干净的。
我能告诉你的是,一个我会作为已测量缺陷发表的结果,六周后无法复现——而我知道这一点只是因为重新运行它只需要一条命令。两个脚本都在仓库里;边界那个目前是空结果,它留在那里,因为一个可以运行的空结果比一个无法验证的主张更有价值。
这个检查本身只有四行,如果你处理双语文本仍然值得保留——以英语为中心的输出断言从不查看脚本边界,所以测试套件中没有其他东西在监视那个接缝。
小模型在你要求它多想时不会变得更好。它在你减少它必须决定的事情时变得更好,在你给它的输出放上确定性外部评判者时变得更好——然后证明这个评判者可以失败。
这个框架不是我的。DSPy 的 BestOfN 配合自定义 reward_fn 再现了大部分这种形态;CodeT 和 AlphaCode 通过执行测试来过滤样本;Guardrails 的 on_fail=reask 和 Instructor 驱动失败重试。甚至 agent 步骤的渐进式 exit code 也是 Nagios 惯例(0 OK / 1 WARNING / 2 CRITICAL),大约有 25 年历史。
可复现脚本,版本已固定:https://github.com/ahmadyaseen35-coder/local-model-field-notes-repro