CritICL:用小模型找错,增强大模型上下文学习推理

发布时间:2026/9/2 3:21:13
CritICL:用小模型找错,增强大模型上下文学习推理 大模型推理能力再强也经常被几个 few-shot 示例“带偏”。示例选得好数学题能多对几道示例选得差模型会照着错误范式一路错下去。这个问题在上下文学习In-Context LearningICL里尤其明显而 CritICL 提供了一条不太一样的解决思路不用更大更强的模型来做校正反而用一个小模型去提前暴露错误再把这些错误转成对大模型有用的提示信息。这个方向的直观价值在于成本。大模型推理本身就很贵如果每一步都靠大模型自我反思、自我修正延迟和 token 消耗都会翻倍。CritICL 的思路是把“找错”这件事交给小模型把“改错”这件事留在大模型形成一个低成本流水线小模型先跑跑出错误案例或高风险样例大模型再基于这些信息做二次推理。换句话说小模型不是替代大模型而是给大模型当“侦察兵”。这篇文章会拆解 CritICL 的核心原理、小模型与标注错误的搭配方式、适合哪些推理任务以及在本地部署和接口调用场景下如何落地验证。如果你关心大模型推理优化、提示词构造、上下文学习或者正在做本地大模型部署和批量推理任务可以直接往下看。1. CritICL 核心能力速览在展开技术细节之前先给一个总览。CritICL 本质上是一套提示词构建和推理增强方法不单独依赖某一个模型而是强调“小模型 大模型”的配合。能力项说明方向定位上下文学习下的推理增强方法核心目标用小模型发现并暴露大模型在推理任务中的易错点增强上下文提示小模型角色预推理、错误检测、错误信号提取大模型角色基于增强上下文做最终推理和输出适用任务数学推理、逻辑推理、常识问答、多步推理关键收益降低人工标注错误示例的成本提高推理准确率与自洽性成本特征将部分纠错工作转移到小模型上降低大模型 token 开销部署门槛小模型可 CPU 推理大模型可用 API 或本地 GPU 服务扩展能力可接入批量评测、在线推理服务、多轮反馈机制从成本结构看CritICL 的思路很符合当前大模型推理优化的大趋势不是所有步骤都堆在大模型上而是把“找错”这种相对独立、可并行的任务拆出来用小模型完成。这样不仅能降低整体推理开销还能让大模型更专注在最终答案的生成上。2. CritICL 要解决什么问题先说 ICL 的痛点。大模型在没有微调的情况下靠 prompt 中给出的少量示例完成推理这个过程中有两个明显问题。第一示例选择非常敏感。同样一道数学题换一个示例顺序推理结果可能完全不同。如果示例中恰好包含一个错误的中间步骤模型很容易把错误模式复制到新问题上而且这种错误往往是系统性的不是随机抖动。第二要人工构造高质量的错误示例非常费劲。一个理想提示词里不仅要有正确答案还要有“容易踩坑的地方”以及“为什么这里会错”的解释。这些内容需要领域专家逐条编写成本很高。即使有标注人员也很难保证覆盖所有错误类型。CritICL 解决的是第二个问题的自动化同时间接缓解第一个问题。它用小模型对候选示例做一次预推理把那些结果明显偏差、置信度偏低、或者逻辑不一致的样例筛选出来。这些样例本身就是天然的错误信号来源。把这个信号拼接进大模型的上下文大模型就能看到“这类问题容易出什么错”而不是盲目模仿示例表面的解题步骤。这和大模型自反馈、自修正的方式有明显区别。自修正通常依赖同一个大模型先生成答案再对答案进行检查和修改。问题是模型自身的偏差会同时影响“生成”和“检查”两个环节容易出现错误放大的情况。CritICL 把检查环节外置到小模型上等于给推理过程引入了一个独立的错误视角减少同一个模型“既当运动员又当裁判”带来的盲区。3. CritICL 技术原理拆解CritICL 的完整流程可以拆成四个阶段。理解这四个阶段基本就理解了整个方法。3.1 小模型预推理先拿一批任务样例用小模型独立跑一遍。这里的“小模型”可以是参数量明显小于主模型的轻量模型比如百亿以下参数的稠密模型甚至量化后的端侧模型。小模型不要求答案全对关键是产生输出分布暴露出哪里容易出错。这一步的输入是任务和候选示例输出是小模型的预测结果和相应置信度。如果小模型支持 token 级别 logits还可以记录它在哪一步开始犹豫、哪一步结果跳变这些都是非常有价值的错误信号。3.2 错误检测与信号提取拿到小模型的输出后要判断什么是真正的“错误信号”。常见做法有三种一是规则判断。如果任务有明确答案格式比如数学题有最终数值可以直接比对小模型输出和标准答案是否一致。不一致的就标记为错误样例。二是置信度判断。模型对答案越不确定说明这个 task 越容易出错。可以设定置信度阈值低于阈值的样例进入错误池。三是逻辑一致性判断。让同一个小模型对同一道题多次采样看输出是否稳定。多次结果不一致说明这个样例对上下文变化很敏感大模型也容易受影响。这段逻辑是整个 CritICL 的关键。小模型生成的错误不是无意义噪声而是用来标注“什么情况下模型会犯错”的事件样本。3.3 构建增强上下文错误信号提取完之后需要把它们组织成 prompt 的一部分。一个典型做法是保留原始任务描述。加入若干正确的示范样例。加入小模型跑出来的错误结果并附上错误原因解释。最后是目标任务。增强上下文的提示词大致如下任务解决给定的数学应用题。 要求写出推理过程并给出最终答案。 示例1... 正确答案... 这是一个容易出错的题目小模型倾向把“倍数关系”直接叠加需注意总量约束。 现在请解决以下题目 ...这样大模型在正式推理之前已经提前知道这类题目的“雷区”。它不需要自己探索到底哪里容易错而是可以直接绕开。3.4 大模型推理与修正最后一个阶段是把增强后的上下文交给大模型让它完成推理并输出。大模型可以是 API 服务也可以是本地部署的模型。因为有错误提示在前大模型的输出通常会更谨慎也会在推理步骤里主动强调容易出错的条件。如果对输出要求更高还可以加入第二轮检查大模型给出结果后再让小模型快速验证结果是否在合理区间。这类似于给流水线加一个质检环节。4. CritICL 适用场景与使用边界CritICL 不是所有场景都适合。它更适合有一定推理链路、同时错误模式相对固定的任务。4.1 适合什么场景数学应用题。错误类型比较集中比如计算顺序错误、比例关系理解偏差、单位换算出错。小模型很容易在这些点上暴露问题。常识推理。大模型有时会用“想当然”的方式推理小模型先跑一遍可以把这些想当然的具体形态带出来。多步逻辑推理。每一步都可能出错错误信号可以按步骤定位帮助大模型准确定位易错环节。批量评测和训练数据筛选。可以用 CritICL 从大量未标注数据中筛选高质量难点样本供人工标注或后续微调使用。4.2 不适合什么场景对延迟极度敏感的场景。CritICL 需要先跑小模型再跑大模型推理链路变长。如果单次请求要求毫秒级响应这种额外延迟通常不可接受。小模型能力太弱的场景。如果小模型错误率过高错误信号会变成噪声甚至误导大模型。无明确校验基准的场景。如果任务没有客观标准答案那么判断“什么是错误”本身就很难CritICL 的收益会大幅下降。4.3 使用边界与合规处理真实业务数据时需要注意两点一是数据来源是否合法涉及用户隐私或版权内容时必须确保有授权二是小模型先跑出来的数据如果涉及个人信息不能直接进入日志或数据集。建议在小模型推理环节增加脱敏处理发布评测数据前也做人工抽检。5. 本地部署环境准备CritICL 涉及两个模型环境准备也要分两层。下面给出一套通用检查清单具体路径和版本以实际项目为准。5.1 大模型服务大模型可以选择本地部署也可以直接接云厂商 API。本地部署时可以参考 vLLM、Ollama 或 Transformers 这类常见框架。安装后的通用启动思路# 以 vLLM 思路为例实际命令需要替换模型名称和配置 python -m vllm.entrypoints.openai.api_server \ --model 你的大模型路径 \ --served-model-name critic-llm \ --host 127.0.0.1 \ --port 8000如果使用 Ollama思路更简单先下载模型再启动服务ollama pull 模型名称 ollama serve5.2 小模型服务小模型的作用是快速暴露错误不需要太大。可以单独用一个 Python 进程加载也可以直接复用同一个推理框架开第二个端口。如果机器资源有限小模型甚至可以跑 CPU推理速度也基本够用。5.3 依赖与目录结构建议把依赖拆成两个环境一个用于大模型推理一个用于小模型错误检测和脚本调度。用 Python 虚拟环境隔离避免版本冲突。目录结构可以这样规划criticl-workflow/ ├── config/ │ ├── large_model.yaml │ └── small_model.yaml ├── data/ │ ├── raw_tasks.json │ ├── small_model_outputs.json │ └── error_signals.json ├── scripts/ │ ├── run_small_model.py │ ├── extract_errors.py │ └── run_large_model.py ├── outputs/ │ └── final_results.json └── logs/ └── pipeline.log这样的结构方便批量任务和后续排查。6. CritICL 流程实现示例下面给出一个思路示意代码不是某个开源项目的真实 API。实际使用时需要把小模型推理部分、错误检测规则、大模型调用地址替换成你自己的实现。import json import requests # 第一步小模型预推理 def small_model_infer(task_text: str) - dict: # 这里替换成你的小模型请求 response requests.post( http://127.0.0.1:8001/infer, json{text: task_text} ) return response.json() # 第二步错误检测 def detect_error(task_text: str, small_output: dict) - dict: answer small_output.get(answer, ) confidence small_output.get(confidence, 0.0) is_error False reason # 规则1答案为空或置信度过低 if not answer or confidence 0.4: is_error True reason 小模型置信度较低本题存在混淆风险 # 规则2与标准答案不一致前提是有标注答案 ground_truth get_ground_truth(task_text) # 按实际数据源实现 if ground_truth is not None and answer ! ground_truth: is_error True reason 小模型输出与标准答案不一致 return { task_text: task_text, error: is_error, reason: reason, small_answer: answer } # 第三步构建增强提示 def build_critic_prompt(task_text: str, common_errors: list) - str: prompt 解决下列任务注意规避已知易错点。\n\n prompt 已知易错点\n for err in common_errors: if err[error]: prompt f- {err[reason]}\n prompt f\n任务{task_text}\n return prompt # 第四步调用大模型 def large_model_infer(prompt: str) - str: payload { model: critic-llm, messages: [ {role: user, content: prompt} ], temperature: 0.2 } response requests.post( http://127.0.0.1:8000/v1/chat/completions, jsonpayload, timeout120 ) return response.json()[choices][0][message][content] def run_criticl(task_text: str): # 小模型预推理 small_output small_model_infer(task_text) # 错误检测 error_signal detect_error(task_text, small_output) # 构造增强上下文 prompt build_critic_prompt(task_text, [error_signal]) # 大模型最终推理 final_answer large_model_infer(prompt) return final_answer if __name__ __main__: sample_task 某商品原价120元先降价20%再涨价20%现价是多少 result run_criticl(sample_task) print(result)这段代码里最核心的部分是detect_error。它决定了哪些小模型输出会被当作“错误信号”传给大模型。实际项目中可以根据任务补充更多规则例如数值结果是否在合理范围。是否包含关键运算符号。是否回答为“不确定”。错误信号越准确CritICL 对大模型推理的提升越明显。6.1 接入 OpenAI 兼容接口现在很多本地推理框架都提供 OpenAI 兼容接口调用方式可以统一成一套curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: critic-llm, messages: [ {role: user, content: 解决下列任务注意规避已知易错点...} ], temperature: 0.2 }如果大模型服务本身就是 OpenAI 兼容协议小模型和大模型可以共用同一个调用封装只是地址和端口不同。6.2 批量任务配置批量评测时建议把任务列表放在一个 JSON 文件里逐条处理并保存中间结果{ task_file: ./data/raw_tasks.json, small_model_url: http://127.0.0.1:8001/infer, large_model_url: http://127.0.0.1:8000/v1/chat/completions, error_threshold: 0.4, save_dir: ./outputs, log_file: ./logs/pipeline.log }批量脚本要特别注意两点一是小模型和大模型都可能偶发超时需要重试二是中间结果要及时落盘避免一个任务失败导致整个批次重跑。7. 评测维度与效果验证CritICL 的收益不能只看“准确率提升”这一个指标建议从多个维度观察。7.1 核心评测指标指标说明观察方式准确率最终推理结果正确比例对比标准 few-shot 和 CritICL 两组自洽性同一任务多次推理结果是否一致多次采样观察方差错误修正率小模型标记的错误中大模型能改正多少统计修正数量和未修正数量噪声注入率小模型误报为错误、但实际上正确的比例检查小模型错误信号质量平均响应延迟单条任务完成完整流程的时间含小模型与大模型耗时Token 消耗大模型输入输出 token 总量对比上下文长度差异7.2 对照组设计很关键的一步。第一组标准的 few-shot 提示不加入小模型错误信号。 第二组CritICL 完整流程。 第三组加入随机错误信号作为对照组用于验证“错误信号是否真的有价值”。如果第三组和第一组效果差不多而第二组效果明显更好说明 CritICL 的增益来自高质量错误信号而不是多出来那几行 prompt。7.3 验证流程推荐在公开数据集上先跑通比如数学推理类任务可以看 GSM8K 或类似题型常识推理可以看 StrategyQA 这类多跳问答数据集。先用小的子集验证流程比如 100 到 200 条确认小模型的错误检出率和大模型对错误提示的响应情况再扩展到全量数据。判断一次 CritICL 实验是否成功的标准准确率没有明显下降。在小模型检出错误的子集上大模型修正率显著高于对照组。额外延迟和 token 成本在可接受范围。失败也很常见。比如小模型提示的错误大模型本来就能避开那就说明“找错”方向错了需要调整小模型或错误检测规则。8. 批量任务与接口集成CritICL 适合做成离线批量评测管道也可以嵌入在线推理服务。8.1 离线批量评测离线场景下小模型先跑完全量数据错误信号统一提取再批量调用大模型。这样做的好处是小模型推理可以并行错误信号也可以先人工抽检一遍。抽检合格后再用增强提示批量跑大模型。# 批量处理建议流程 python scripts/run_small_model.py --config config/small_model.yaml python scripts/extract_errors.py --config config/small_model.yaml python scripts/run_large_model.py --config config/large_model.yaml8.2 在线推理服务在线服务要控制延迟。可以给 CritICL 加一个前置开关只有小模型置信度低于阈值才触发大模型的二次推理置信度高的任务直接走常规大模型流程。这相当于把 CritICL 变成一个条件分支而不是所有请求都走完整链路。从接口设计角度看增加参数use_criticl可以让调用方按需开启。增加参数critic_threshold控制错误信号是否进入上下文。返回结果里增加critic_info字段回传小模型的置信度和错误判断方便监控。8.3 失败重试与缓存批量任务中小模型和大模型都有可能超时。建议对每次请求做超时控制和重试重试次数建议 2 到 3 次。同时已经跑过的小模型结果应该缓存下来避免因为大模型端故障导致所有任务重跑。缓存键可以用任务文本的 hash 值缓存内容包括小模型输出、置信度、错误信号和 final prompt。9. 资源占用与性能观察CritICL 的资源占用主要分开两部分看。9.1 小模型资源占用小模型可以是参数量较小的模型CPU 也能跑。在批处理场景下小模型的推理吞吐非常关键。可以观察单条任务小模型推理耗时。小模型进程占用的内存或显存。是否可以通过量化进一步降低资源占用。小模型优势是快、便宜但也不能完全忽视延迟。如果小模型太慢CritICL 整体延迟会很难看。9.2 大模型资源占用大模型才是资源消耗大头。如果本地部署显存占用主要由模型大小、量化精度、批次大小和上下文长度决定。CritICL 会往 prompt 里增加一段错误信号这会增加少量输入 token 和显存占用但通常不会造成数量级变化。观察方法是使用nvidia-smi实时查看显存占用。在服务日志里记录每次请求的输入 token 数和输出 token 数。对比开启 CritICL 前后的平均延迟和首 token 延迟。9.3 如何降低资源占用小模型用 CPU 推理大模型用 GPU避免两个模型抢显存。小模型结果做缓存重复任务不重复推理。大模型和流程脚本拆成不同容器或进程方便单独调整资源配额。错误信号只保留最核心的文本不要把所有小模型输出都塞进 prompt。10. CritICL 常见问题与排查问题现象可能原因排查方式解决方案小模型输出全为空请求格式不匹配查看小模型服务日志检查接口字段名确认传入文本编码正确错误信号基本没用小模型误报率过高统计误差信号与标准答案比对准确率提高置信度阈值增加规则判断大模型延迟明显上升prompt 变长或错误信号重复插入查看 token 数量与首 token 延迟精简错误文案使用缓存复用 prompt相同任务两次结果不一致采样温度过高检查大模型请求参数降低 temperature增大确定性批量任务卡住无重试机制或单任务崩溃查看进程日志和任务进度增加超时重试及时落盘中间结果显存不足两个模型同时占用 GPU查看 GPU 显存占用小模型改 CPU 推理或分批处理大模型开始模仿小模型错误错误信号里包含误导信息抽检错误信号质量关闭低置信度信号加强规则过滤其中最常见的坑是“小模型错误信号写得太满”。一个 prompt 里如果塞了大量错误描述大模型有时候会把这些描述当成正确答案来模仿。更稳妥的做法是只保留错误风险和规避建议不让大模型直接看到小模型的错误答案原文。11. 最佳实践与合规建议CritICL 的工程化落地有几点经验值得直接照做。第一先跑通一个 50 条左右的小样本人工检查小模型的错误信号是不是命中真实问题。如果是再扩大规模如果不是先调模型或规则不要急着全量跑。第二维护“错误信号库”。把每次任务中挖出的典型错误沉淀成一个独立的 JSON 文件后续不需要每次重新跑小模型可以直接复用。错误信号库本身也可以作为微调数据的一部分。第三设置预算控制。小模型推理虽然便宜但全量铺开仍然会消耗不少算力。按置信度阈值和任务优先级来控制使用范围。第四合规方面重点做三件事数据采集和使用的授权确认、用户隐私信息脱敏、输出内容不直接对外发布。如果 CritICL 用于客服、金融、医疗等场景最终结果需要人工抽检复核不能完全依赖自动流程。第五不要忽视小模型本身的迭代。小模型发现错误的能力直接决定 CritICL 的上限。定期用新标注数据微调小模型错误检出率会逐步提升CritICL 的整体效果也会水涨船高。12. 总结与下一步CritICL 的核心价值不是让小模型教大模型怎么做题而是用小模型先把错误暴露出来再把这些错误变成大模型推理时的规避信号。这种“小模型找错、大模型改错”的配合方式在数学推理、逻辑推理、批量评测等任务上有比较清晰的适用空间。建议先从一个简单任务和一个小型数据集开始重点验证两件事小模型错误信号的质量以及大模型是否真的会因为错误提示而提高推理准确率。最容易踩的坑是错误信号太杂太满把大模型带偏。一个简单的改进方向是错误提示只保留错误类型和规避建议不要直接把小模型的错误答案原文贴进去。再往后可以探索的方向包括多轮批评反馈让大模型输出后再由小模型做一次复核把错误信号与向量检索结合从错误信号库中自动选择最相关的提示以及在 Agent 框架里引入 CritICL 作为专门的“评审节点”。这些方向都围绕同一个核心问题如何让大模型在推理时更聪明地使用错误信息而不是盲目自信。