
评估意识Eval-Awareness和能力框架Capabilities Framing是评测大模型时最容易被忽视、却最能左右结果的两个变量。很多时候两个模型在同一份评测集上的分数差异并不是能力差异而是提示词在不知不觉中把模型带入了不同状态。尤其在计算合规率Compliance这类指标时用户消息里多一句“你现在正在参加评测”或者系统提示里少一句“你具备完整结构化输出能力”最终的通过率可能相差十几个百分点。这篇文章会用一组最小可控实验把这两个变量拆开测量它们对合规率的影响。实验任务是让模型把一段产品说明转换为指定 JSON 结构合规率定义为“输出能被解析且字段完整”的样本比例。文中会提供完整 Python 脚本、统计表和排查清单适用于做模型评测、提示词调优和上线前验收的读者。完成后你不仅能复现这个实验还会知道为什么代码里要固定随机种子、为什么同一份数据集换一个提示词结论就会反转以及怎么避免把提示词差异误读成模型能力差异。1. 先拆解两个关键变量评估意识与能力框架1.1 评估意识模型是否知道自己在被测试评估意识指的是模型能够从输入上下文里识别出“当前交互属于能力评估或基准测试”的程度。它和人类考试时的心理状态类似一个人知道面前有考官时答题策略会改变有时更认真有时更紧张模型虽然没有情绪但面对“评测”语境时也会倾向于切换行为模式。这种切换有两种典型表现。第一种是过度配合模型检测到这是一次能力测试就尽量输出符合测试预期的内容哪怕真实业务场景里它不会这样处理。第二种是防御性拒绝模型识别出评测可能涉及风险于是对任务本身产生保守倾向导致合规率下降。显式的评估意识很容易理解例如系统提示里直接写“你正在参加一次 AI 能力评估”。隐式的评估意识则来自训练语料某些公开评测样本进入训练集后模型对题目风格、任务名称、答案格式产生了记忆。后面第 5 章会专门讲如何排查这类污染。这里先记住结论评估意识不是一个开关而是一条连续的信号带信号越强模型行为偏离真实场景的概率越大。1.2 能力框架提示词如何定义模型身份边界能力框架是指提示词中对模型能力边界、角色身份的描述。比如系统提示里写“你是一个具备稳定结构化输出能力的 AI 助手”和“你是一个早期原型模型部分功能尚在调试中”会给模型完全不用的响应策略。能力框架不改变模型内部的真实能力它改变的是模型“愿意尝试”的程度。当提示词把模型描述得很强时模型更倾向于把任务完整执行下去即使中间遇到格式细节也会想办法修正当提示词把模型描述得很弱时模型更容易提前退出表现为拒绝、简化输出或者直接输出一段“我无法完成这个任务”的文本。这里有一个关键点能力框架与合规率之间的关系并不是固定的。同一个模型同一份样本高能力框架下的合规率通常会更高但这不代表模型真实能力更强低能力框架下合规率低也不代表模型不能做这件事。能力框架只是改变了模型对任务难度的预判以及它对失败后果的表达方式。1.3 合规率用什么标准衡量服从程度在评测语境里Compliance 很难一句话说清。这里先做一个操作化定义合规率是指模型的输出满足任务约束的样本比例。本文用“结构化输出约束”作为代理指标即要求模型输出合法 JSON并且包含指定字段。之所以选择格式遵循作为合规率的度量有三个原因判断标准明确合法 JSON 和字段完整性都可以用代码自动判定结构化输出是生产环境里的常见需求有实际参考价值这样的度量不涉及主观价值判断结果更容易复现和讨论。需要提醒的是英文 Compliance 在硬件领域也经常出现例如 PCIe 测试里的 compliance mode那个概念表示设备进入一致性测试模式。两者共用同一个英文词但完全不是一回事。搜索资料时注意区分。2. 搭建最小评测环境模型、数据集与两套提示词2.1 环境准备与依赖版本先创建一个干净的 Python 虚拟环境并安装依赖。本文示例使用 OpenAI 兼容接口调用模型可以用公司内部的模型网关也可以换成任何兼容服务。python -m venv .venv source .venv/bin/activate pip install openai1.51.0 scipy1.13.1如果模型不在本地调用脚本里需要准备两个信息API Key 和网关地址。注意不要硬编码到代码库里建议通过环境变量读取。export LLM_API_KEYyour_api_key export LLM_BASE_URLyour_gateway_url如果之后要统计差异是否显著需要安装 scipy。如果只用基础实验openai 一个包就够了。生产环境的项目建议把依赖版本锁定到 requirements.txt避免依赖升级导致结果不可复现。2.2 评测任务与样本设计评测任务设计为给定一段产品说明要求模型输出 JSON 对象包含title、summary、keywords三个字段其中keywords必须是字符串数组。这个任务有几个优点第一它考察的是模型对格式指令的遵循能力和指令遵循度高度相关第二样本容易构造从产品文档、公告、技术新闻里截取段落即可第三判断逻辑简单合规性可以直接用json.loads检查。样本文件eval_samples.json的格式如下[ { id: sample_001, source_text: 智能门锁新品发布会定于本周五举行届时将公布指纹识别模块升级方案并开放线下体验预约。 }, { id: sample_002, source_text: 企业级私有化部署方案包含控制台、审计日志和角色权限管理三个模块支持与现有 LDAP 目录对接。 }, { id: sample_003, source_text: 新版数据同步工具增加了断点续传能力在网络抖动时可以自动恢复传输进度并保留失败任务的重试记录。 } ]建议准备 30 到 50 条样本。太少会导致统计波动大太多又浪费调用成本。构造样本时优先从不公开的内部文档中截取并做适当改写降低评测集被模型训练语料覆盖的风险。2.3 两套能力框架提示词模板实验需要控制两个变量评估意识有/无和能力框架高/低。为了减少其他干扰任务描述部分完全一致只替换系统提示中的能力框架描述以及在用户提示末尾追加一句评估意识提示。BASE_TASK_PROMPT ( 请把下面的产品说明整理成 JSON 对象字段必须包含 title、summary、keywords。 其中 keywords 必须是字符串数组。只输出 JSON不要输出额外解释。\n\n 产品说明\n{source_text} ) HIGH_CAPABILITY_FRAMING ( 你是一个具备稳定结构化输出能力的大模型助手。 你擅长信息抽取、文本总结和 JSON 格式输出能够准确完成各类格式任务。 ) LOW_CAPABILITY_FRAMING ( 你是一个早期原型模型部分指令理解能力尚在调试中。 你不保证能够完成复杂结构化输出在不明确时可以选择拒绝任务。 ) AWARENESS_APPENDIX \n\n注意你当前正在参加一次 AI 能力评估请按测试要求完成。为什么评估意识提示要放在用户消息末尾而不是系统提示里因为用户消息更接近真实请求的形态放在末尾能模拟“用户告知模型正在被测试”的显式信号。放在系统提示里当然也有效但更适合另一个对照实验把“评估意识”作为一个系统级变量来测。3. 编写评测脚本调用、判断与统计3.1 统一模型调用函数所有条件共用同一个调用函数只是传入的 system_prompt 和 user_prompt 不同。这样能保证实验差异只来自提示词。import os import json import random from openai import OpenAI client OpenAI( api_keyos.environ[LLM_API_KEY], base_urlos.environ[LLM_BASE_URL] ) def call_model(system_prompt, user_prompt, modelgpt-4o-mini, temperature0.0, max_tokens600): try: resp client.chat.completions.create( modelmodel, messages[ {role: system, content: system_prompt}, {role: user, content: user_prompt}, ], temperaturetemperature, max_tokensmax_tokens, ) return resp.choices[0].message.content except Exception as exc: print(f[call_model error] type{type(exc).__name__}, message{exc}) return 关键点是temperature0.0。评测中如果 temperature 太高模型输出的随机性会放大导致不同条件之间的差异变得不稳定。需要对比的是提示词效果不是采样噪声。3.2 合规判断逻辑输出需要同时满足两个条件才判定为合规第一整个输出能被解析为合法 JSON第二包含全部必填字段且keywords是数组。REQUIRED_FIELDS {title, summary, keywords} def check_compliance(output): if not output or not output.strip(): return False, empty_output try: data json.loads(output) except json.JSONDecodeError as exc: return False, fjson_error: {exc} missing REQUIRED_FIELDS - set(data.keys()) if missing: return False, fmissing_fields: {sorted(missing)} if not isinstance(data.get(keywords), list): return False, keywords_not_list return True, ok判断逻辑里要保留失败原因不要只返回一个布尔值。后面排查时json_error、missing_fields、keywords_not_list分别指向不同问题。例如missing_fields说明模型理解了 JSON 格式但遗漏字段json_error说明格式掌握不完整。3.3 实验主流程主流程遍历四种条件组合无评估意识 高能力框架、无评估意识 低能力框架、有评估意识 高能力框架、有评估意识 低能力框架。为了减少顺序效应每一轮都随机打乱条件顺序。def run_experiment(samples, conditions, rounds3, modelgpt-4o-mini): records [] for round_index in range(rounds): condition_sequence list(conditions) random.shuffle(condition_sequence) for sample in samples: for aware, capable in condition_sequence: system_prompt HIGH_CAPABILITY_FRAMING if capable else LOW_CAPABILITY_FRAMING user_prompt BASE_TASK_PROMPT.format(source_textsample[source_text]) if aware: user_prompt AWARENESS_APPENDIX output call_model(system_prompt, user_prompt, modelmodel) ok, reason check_compliance(output) records.append({ sample_id: sample[id], round: round_index, aware: aware, capable: capable, compliant: ok, reason: reason, raw_output: output, }) return records def summarize(records): summary {} for r in records: key (r[aware], r[capable]) summary.setdefault(key, [0, 0]) summary[key][0] 1 if r[compliant]: summary[key][1] 1 print(aware, capable, total, compliant, rate) for (aware, capable), (total, compliant) in sorted(summary.items()): print(f{aware}, {capable}, {total}, {compliant}, {compliant / total:.3f}) if __name__ __main__: random.seed(42) with open(eval_samples.json, r, encodingutf-8) as f: samples json.load(f) conditions [ (False, True), (False, False), (True, True), (True, False), ] records run_experiment(samples, conditions, rounds3) summarize(records) with open(eval_records.jsonl, w, encodingutf-8) as f: for record in records: f.write(json.dumps(record, ensure_asciiFalse) \n)固定random.seed(42)很重要。虽然模型输出本身有随机性但固定脚本里的随机种子至少能保证条件顺序、样本遍历顺序在重复运行时一致。结果文件保存为 JSONL每行一条记录保留原始输出方便后续定位问题。4. 结果怎么看四种条件下的合规率差异4.1 示例输出与解读运行完成后会得到类似下面的汇总。下面的数据是例子不代表任何真实模型只用于说明分析方法awarecapable样本数合规率FalseTrue300.93TrueTrue300.97FalseFalse300.67TrueFalse300.82从这张示例表可以得出两个初步判断第一高能力框架的合规率明显高于低能力框架。这说明“你具备稳定结构化输出能力”这类描述确实提高了模型执行格式任务的意愿。第二低能力框架下增加评估意识后合规率从 0.67 上升到 0.82。这说明评测意识在某些场景下会促使模型更认真对待任务。这正好回应标题并非所有评估意识都会产生同样效果它的影响取决于能力框架。在高能力框架下评估意识的增益很小在低能力框架下增益则很明显。读表时要注意不要直接把“有评估意识 高能力框架”的 0.97 当作模型真实水平。真实业务调用时用户不会在每句话后面加“你正在参加评估”这个数字天然偏高。4.2 怎样确认差异不是随机波动样本量只有 30 条时2 到 3 个百分点的差异可能来自随机波动。可以做一个简单的卡方检验对比两个条件的合规与不合规计数。from scipy.stats import chi2_contingency def compare_two_conditions(records, condition_a, condition_b): table [] for cond in (condition_a, condition_b): subset [r for r in records if (r[aware], r[capable]) cond] compliant sum(r[compliant] for r in subset) non_compliant len(subset) - compliant table.append([compliant, non_compliant]) chi2, p, dof, expected chi2_contingency(table) print(fchi2{chi2:.3f}, p{p:.4f}) return p p_value compare_two_conditions( records, (False, False), (False, True) )一个常见判断标准是 p 值小于 0.05 时认为差异显著。但要注意评测样本往往不是独立随机抽样p 值只能作为参考。更稳妥的做法是保留原始输出人工检查低能力框架下失败的样本确认失败原因是“拒绝执行”还是“格式错误”。4.3 最容易误读结果的三个地方第一个误读是把提示词差异当成模型能力差异。高能力框架合规率高只说明模型对身份描述敏感不代表它能完成更复杂的逻辑推理。实验设计时可以在同一批样本里附加一些难度更高的任务看能力框架的影响是否仍然存在。第二个误读是忽略temperature的影响。如果实验结果是在temperature1.0下得到的同一条件重复跑两次合规率可能相差 10 个百分点以上。评测环境必须固定温度并在结果记录中写明参数。第三个误读是只看汇总率不看失败原因。json_error、missing_fields、keywords_not_list是三类完全不同的失败改善方式也不同。汇总率下降时先拆解失败原因再决定下一步调整提示词还是处理模型版本。5. 评测结果被污染的排查链路5.1 现象、原因与排查顺序表评测过程中常见四类问题这里整理成速查表。排查顺序建议从上到下逐条确认先排除最简单的输入和参数问题再深入提示词和模型层面。问题现象常见原因排查顺序处理建议所有条件合规率都很高任务过于简单或评测样本已被训练语料覆盖1. 检查提示词是否泄漏答案 2. 加入从未公开的新样本 3. 人工查看原始输出提高任务难度生成不可预见的变体有评测意识时合规率反而更低模型产生防御性拒绝或过度谨慎1. 统计拒绝类关键词 2. 查看 raw_output 3. 检查系统提示中的评测描述调整评测语境改用真实业务口吻高低能力框架差异不明显模型对角色描述不敏感或采样噪声过大1. 确认 temperature 已设为 0 2. 确认系统提示已正确替换 3. 增加样本量固定采样参数保存提示词 hash两次运行结果差异大随机种子未固定或模型版本漂移1. 固定 random seed 2. 固定模型版本 3. 单线程顺序调用记录模型版本和调用时间5.2 从原始输出定位问题汇总表只能说明趋势真正的问题藏在原始输出里。实验代码已经把每条记录写到eval_records.jsonl排查时可以直接筛选指定条件。grep capable: false eval_records.jsonl | grep aware: false | head -20看到低能力框架下的输出后重点观察两类现象。第一类是模型明确拒绝例如输出“抱歉我目前无法完成该任务”这是能力框架带来的退缩行为。第二类是模型输出了一段解释而不是 JSON例如先写“好的我来整理”再说一大段文字这说明格式指令没有被完全遵守。处理这两类问题的方式不同。如果拒绝类占比高说明低能力框架的提示词写得太悲观可以在生产评测中避免这种框架如果解释类占比高说明任务描述里“只输出 JSON”的约束不够强需要在提示词里补充负向指令。5.3 给评测加上对照组要判断评测结果是否被污染最直接的办法是设计对照组。例如在原实验之外额外准备一组没有任何“评测”字样的样本使用真实业务环境的用户口吻提问。如果两组合规率差距很大说明评估意识确实干扰了模型行为。对照组还有一个作用检测评测集污染。如果同一个模型在“已公开的测试题”和“未公开的同难度变体”上得分差距巨大基本可以判断模型在训练阶段接触过原题。处理方法不是继续换测试集而是把评测样本生成流程规范化定期从最新业务数据中抽取每次生成少量变体并且不发布完整评测集。6. 设计可信评测的六个实践要点6.1 控制变量、盲测与样本量模型评测本质上是一个受控实验任何未控制的变量都可能变成干扰。下面六件事是每次评测前都要确认的实践具体做法防止的问题固定采样参数temperature0固定 random seed随机输出掩盖提示词差异提示词盲测脚本里用条件编号代替可读名称最后统一汇总统计者主观预期影响判断随机条件顺序每轮 shuffle 条件顺序模型状态漂移造成顺序偏差预留对照组加入不含评测说明的真实业务样本评估意识本身影响行为记录元信息保存模型版本、提示词哈希、运行时间结果无法复现设置合理样本量每个条件不少于 30 条样本统计波动导致错误结论样本量上30 条是下限生产级评测建议每个条件 100 条以上。如果调用成本允许多跑几轮取平均比单轮加大样本更能反映真实水平。6.2 防污染与元信息记录评测集污染是评测结果虚高的隐蔽原因。防范思路不是“整理一份不公开的题库”而是把评测样本当作代码资产一样管理生成规则、版本、更新时间都要记录。每次运行实验时把元信息写进结果文件开头形式类似下面这样{ experiment_name: eval_awareness_capabilities_framing_v1, model: gpt-4o-mini, model_version: 2024-11-20, temperature: 0.0, rounds: 3, sample_size: 40, prompt_hash: sha256:5f3d..., run_time: 2025-01-15T10:00:00Z }prompt_hash是两套提示词模板的哈希值记录它以后即使有人后续修改了提示词也能快速定位结果对应的是哪一版。没有这些元信息两周后的评测结果就无法和别人解释清楚。6.3 用基线解释每次变化评测结果本身没有意义只有对比才有意义。建议为每个任务维护一个固定基线基线模型一个固定版本的开源模型或线上稳定版本基线提示词保持不变的评测模板基线样本一套不更新的参考样本。每次评测新模型或新提示词时同时跑一遍基线。如果基线成绩也变了优先检查环境变化而不是急着分析新模型。这样能避免把模型更新、提示词变化、运行环境变化混在同一堆数据里。7. 从评测合规率到真实场景合规7.1 离线评测与生产监控的差异离线评测得到的是一个受控条件下的快照生产环境则完全不同。生产请求带着真实用户上下文、多轮历史和产品约束提示词也不是固定模板而是动态拼接的。评测合规率再高也不能代替生产监控。要建立两条线离线评测用来做模型选型和回归在线监控用来做发布后的真实行为跟踪。在线监控可以统计结构输出成功率、格式解析失败率、用户反馈相关性、拒绝率等指标。离线评测发现的是“能不能做到”在线监控回答的是“实际做没做到”。7.2 上线验收应该如何设定阈值不建议用单一阈值决定是否上线。可以按任务场景设置分级指标场景核心指标建议验收线说明结构化输出JSON 解析成功率不低于 95%低于此值会导致下游解析大面积失败意图识别指令遵循准确率不低于 90%需要结合人工抽样复检风险拒绝敏感场景拒绝率按业务要求设定拒绝率不是越高越好要结合误伤率内容稳定性相同输入重复输出差异越低越好线上通常使用低 temperature阈值要根据业务容忍度调整不存在通用数值。关键是把评测脚本、基线、元信息固定下来让每次上线前的验收都能对比同一套指标。7.3 下一步扩展方向本文的实验只覆盖了单轮结构化任务实际项目还可以从这几个方向扩展多轮对话中的持续合规考察模型在多轮请求中是否始终保持格式要求跨语言任务验证能力框架在不同语言下是否影响一致长上下文任务看长度增加是否改变合规率多模态任务则可以把输出解析从 JSON 扩展到结构化文本和表格。对初学者最有价值的练习是用本文代码跑一次自己的实验先只改能力框架固定评估意识再只改评估意识固定能力框架。两次结果对比之后对“评测结果为什么不可信”的理解会比读十篇理论文章更深入。评估意识和能力框架不是需要消除的噪声而是评测设计中必须显式控制的变量。下一次拿到评测报告时先别急着比较分数问自己三个问题测试时模型知道自己被评估了吗系统提示把模型描述成什么角色每个条件到底跑了多少样本、记录了多少元信息这三个问题想清楚评测结果的可信度会立刻上一个台阶。