LLM 指令遵循能力横评
“指令遵循能力”(Instruction Following)和”任务解决能力”是两回事。一个模型可能数学题解得很准,但只要你多加一条约束——“只用一句话回答”、“不要用列表格式”、“不要提到某个词”——它就把约束忘得一干二净。这种”知道怎么做但不听话”的问题,在实际工程里造成的麻烦往往比”不会做”更隐蔽:代码能跑但格式不对导致下游解析失败、内容质量很好但字数超限导致展示区域溢出。本文聚焦指令遵循能力本身的评测和优化,不涉及具体任务(代码、数学)的解题能力对比,这部分可参考站内已有的编程和数学推理基准文章。
数据说明:本文观察综合了 IFEval、FollowBench 等公开指令遵循基准的评测思路、社区实测报告和编者在真实项目中的观察整理。具体数字为近似估算,不同 prompt 措辞、约束类型组合都会显著影响结果,请以自己场景的实测为准。
一、指令遵循能力的评估维度
指令遵循不是一个单一指标,至少要拆成这几个子维度分别看:
| 维度 | 说明 | 典型测试方式 |
|---|---|---|
| 格式约束 | 是否严格按要求的格式输出(JSON、指定字数、指定列表项数) | “用恰好 3 个要点回答,每点不超过 20 字” |
| 否定指令 | 是否遵守”不要做什么”的约束 | ”不要提及价格”、“不要使用感叹号” |
| 多约束叠加 | 同时给出 3-5 条约束时的综合遵守率 | 格式+字数+语气+禁用词同时要求 |
| 优先级冲突处理 | 当指令之间隐含冲突时,模型如何取舍 | ”简洁回答”与”详细列出所有细节”同时出现 |
| 长程指令保持 | 长对话中,早期设定的约束是否在后续轮次持续生效 | 第一轮设定”始终用中文回复”,第 10 轮是否还遵守 |
二、为什么”否定指令”普遍更难遵守
一个几乎所有模型都存在(程度不同)的共性弱点是:“不要做 X” 比 “要做 X” 更容易被忽略。这背后的原因和语言模型的训练机制有关——模型本质上是通过预测”接下来最可能出现什么”来生成内容,而”不出现某个词/某种表达”是一种缺失性约束,不像”输出 JSON”这种正向约束有明确的目标模式可以对齐,天然更容易在生成过程中被”绕过”或”遗忘”,尤其是当否定指令和其他正向指令同时出现、且间隔较远时。
实际观察到的一个规律是:把否定指令改写成正向指令,遵守率会明显提升。比如把”不要使用感叹号”改写成”使用陈述句结尾,避免感叹号等强调性标点”,或者更彻底地改成”保持平实、克制的语气”,往往比单纯强调”不要”更有效。
三、多约束叠加时的表现规律
单条约束模型通常都能遵守得不错,但约束数量一旦超过 3-4 条同时出现,遵守率会明显下降,且下降幅度因模型能力档位而异——旗舰模型(如 Claude 4.x、GPT-4o 及以上)的多约束保持能力明显强于轻量级模型(如 mini/flash 系列),这也是”复杂格式要求的生产任务不建议直接用最便宜的模型”的一个实际依据。
多约束场景下几个提升遵守率的实用技巧:
- 约束分条列出,而不是揉进一段话:把”请用简洁的语言,控制在 100 字以内,用 markdown 列表呈现,且不要包含免责声明”拆成分行的约束列表,比写成一整段更容易被模型逐条对齐。
- 重要约束放在指令末尾:多数模型对紧邻输出前的指令遵守率更高,如果某条约束是硬性要求(比如格式必须是 JSON),可以在指令末尾再重复强调一次。
- 给出反例:光说”不要用列表格式”效果有限,加一句”直接用连贯段落,例如:xxx”(附一个简短的正确示例)通常比纯文字描述更有效。
四、代码示例:约束遵守率的简单自测方法
如果你想在自己的业务场景里快速评估某个模型对特定约束的遵守情况,可以用下面这种批量抽测的思路,而不是依赖公开基准的结论:
import json
from openai import OpenAI
client = OpenAI(base_url="https://your-relay-endpoint/v1", api_key="YOUR_KEY")
TEST_CASES = [
{"prompt": "用一句话总结:人工智能正在改变软件开发方式。不要使用感叹号。", "check": lambda t: "!" not in t and "!" not in t},
{"prompt": "列出 3 个 Python 优点,每条不超过 15 字,用无序列表格式。", "check": lambda t: t.count("-") >= 3 or t.count("•") >= 3},
]
def run_instruction_test(model: str, cases: list[dict]) -> float:
passed = 0
for case in cases:
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": case["prompt"]}],
)
text = resp.choices[0].message.content
if case["check"](text):
passed += 1
return passed / len(cases)
print(run_instruction_test("gpt-4o-mini", TEST_CASES))
这个思路的关键是用你业务里实际会用到的约束类型(字数、格式、禁用词、语气)自己造测试集,而不是照搬公开基准的题目——公开基准测的是通用能力排名,但你关心的是”这个约束在我的具体场景下能不能被稳定遵守”,两者未必一致。
五、长对话中的指令保持问题
多轮对话场景下,一个容易被忽视的问题是:早期轮次设定的约束,会随着对话变长而逐渐被”稀释”。比如在系统提示里设定”全程用中文回复”,前几轮表现良好,但当对话进行到第 10、20 轮,尤其是中间穿插了英文内容(比如用户粘贴了一段英文错误日志)之后,模型可能会不自觉地切换成英文回复。
应对这类问题的实用做法:
- 把关键约束放进 system prompt 而不是只在第一条 user message 里提,system prompt 在整个对话生命周期里的权重通常更稳定。
- 对特别重要的约束做周期性重申,比如每隔几轮在 user message 末尾附加一句简短提醒,尤其是在长任务、Agent 编排链路里,这个成本很小但能显著降低约束丢失的概率。
- 必要时做输出后处理校验,对于格式类的硬性约束(比如必须是合法 JSON),与其完全依赖模型”记住”约束,不如在代码层面做校验,校验失败则触发重试或修正流程,这比纯粹依赖 prompt 层面的约束更可靠。
六、指令遵循能力对下游工程的实际影响
指令遵循能力的强弱,直接决定了你的系统需要在代码层面做多少”兜底”工作:
- 遵循能力强的模型:可以更放心地把格式约束、语气要求直接写进 prompt,减少后处理校验的代码量。
- 遵循能力偏弱的模型(通常是更便宜的轻量级模型):即使 prompt 写得再仔细,也建议在代码层面加一层格式校验和重试机制,把”模型偶尔不听话”当成必然会发生的情况来设计系统,而不是当成例外情况。
这个判断和模型选型的成本权衡是相关的——如果为了省钱选用了指令遵循能力较弱的模型,省下来的调用成本,很可能会被额外增加的校验、重试逻辑的开发和维护成本部分抵消,具体的模型选型成本权衡可参考站内成本优化系列文章。
七、结论
指令遵循能力是一个经常被”任务解决能力”评测掩盖的维度,但在实际工程落地中,它往往决定了系统的稳定性上限。评测这项能力时,建议按”格式约束、否定指令、多约束叠加、长程保持”分别测试,而不是笼统地问”这个模型听话吗”;优化时,把否定指令改写成正向指令、约束分条列出、关键约束放进 system prompt 并周期性重申,是几个低成本高收益的实用技巧。最终建议:不要完全信任 prompt 层面的约束,对硬性格式要求始终保留代码层面的校验兜底。
八、相关阅读
如果你需要横向对比不同模型在自己业务场景下的指令遵循表现,YoTradeApi 提供统一账号下的多模型 API 中转,方便快速切换模型做实测。