用大模型训练小模型的系统提示词
前言
小模型的系统提示词很难一次写好。本文介绍一种用 GitHub Copilot(或其他大模型 Agent)当执行者,自动迭代小模型提示词的方法。
核心思路:写好测试用例 → Copilot Agent 跑用例 → 看错误 → 改提示词 → 提交 → 跑回归。人在关键节点介入。
为什么需要这套方法
- 小模型对提示词敏感,模糊指令容易自由发挥
- 调一次就要全量回归
- 没有量化指标,全凭感觉
- 大模型直接写提示词”答一次就完”,没形成闭环
核心技巧:Function Call 加 analysis 参数
小模型默认直接输出 tool_call,看不到思考过程。给 function call 强制加一个 analysis 参数,强制它先输出分析:
tools = [{
"type": "function",
"function": {
"name": "search_order",
"description": "查询订单物流",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"analysis": {
"type": "string",
"description": "分析过程:意图识别 + 参数提取依据 + 置信度"
}
},
"required": ["order_id", "analysis"]
}
}
}]
analysis 字段是 Copilot 定位错误的唯一线索。没有它,Agent 只能看到结果错,不知道错在哪。
真实案例:3.9 vs 3.11
让小模型判断版本号:compare("3.9", "3.11"),期望 3.11 > 3.9。
没有 analysis 时:
- 小模型直接输出
"3.9 > 3.11"(按字符串比较确实成立) - Agent 只看到结果错,无法判断是参数传错、概念理解错、还是别的
加了 analysis 后,小模型输出:
analysis: "按字符串比较,'3.9' 第三个字符 '9' > '3.11' 的 '1',
所以 '3.9' > '3.11'"
Agent 立刻定位:
错误归因:模型把版本号当字符串做字典序比较,没识别 SemVer 语义
修改建议:明确"按 . 分割成段、每段整数比较",加 few-shot
黑盒变白盒,Agent 自主改提示词、commit、回归。
项目结构
prompt-trainer/
├── system_prompt.md # Copilot 修改这里
├── test_cases.json # 测试用例
├── tools.json # function call 定义
├── run_cases.py # 执行脚本
├── results/
│ ├── v1.json
│ ├── v2.json
│ └── ...
├── CHANGELOG.md # 迭代记录
└── README.md
Step 1:测试用例
用例是迭代的依据,没有量化用例就没有优化。
{
"cases": [
{
"id": "logistics_001",
"input": "帮我查一下订单 20260504001 现在到哪了",
"expected_tool": "search_order",
"expected_args": {"order_id": "20260504001"}
},
{
"id": "refund_001",
"input": "我想退款,订单号是 20260504002",
"expected_tool": "refund_order",
"expected_args": {
"order_id": "20260504002",
"reason": "用户主动申请退款"
}
}
]
}
设计原则:
- 覆盖所有参数组合(有/无/多值)
- 包含边界情况(空字符串、特殊字符)
- 包含歧义场景
- 起步 30-50 条,迭代到 100+ 做回归
Step 2:初始提示词
从最简版本开始:
# 角色
你是客服助手,处理用户售后请求。
# 工具
- search_order(order_id): 查询订单物流
- refund_order(order_id, reason): 申请退款
- create_ticket(category): 创建工单
# 要求
根据用户输入选择工具并提取参数。
这个版本一定很差,但没关系,是迭代起点。
Step 3:给 Copilot Agent 的初始指令
# 项目目标
训练小模型(Qwen2.5-7B-Instruct)的系统提示词,
在 test_cases.json 上准确率达到 95%。
# 工作流程
1. 读取 system_prompt.md 和 test_cases.json
2. 运行 run_cases.py,生成 results/v{N}.json
3. 统计准确率
4. 未达标:
- 分析错误用例的 analysis 字段
- 定位错误归因
- 修改 system_prompt.md
- git commit -m "v{N+1}: 方向=xxx"
- 更新 CHANGELOG.md
- 回到第 2 步
5. 达标:输出总结报告
# 约束
- 只改 system_prompt.md,不改 test_cases.json
- 连续 3 轮无提升,停下来问人
- 每次 commit 前必须跑完所有用例
- analysis 字段不能为空
- commit 时必须标注"优化方向"
优化方向标签
避免 commit 信息写 “v3: 改了点东西”。明确标注优化方向,方便后期复盘:
| 方向 | 含义 | 典型修改 |
|---|---|---|
tool_dispatch |
工具选择 | 加触发关键词、调整场景描述 |
param_extract |
参数提取 | 补参数规则、加 few-shot |
anti_hallucination |
反幻觉 | 加”宁缺毋滥”、禁止编造 |
reasoning_chain |
推理链 | 要求分步、显式分析 |
format_alignment |
输出格式 | 调 analysis 字段结构 |
edge_case |
边界情况 | 补空值/特殊字符规则 |
CHANGELOG.md 样例:
## v1 → v2 (anti_hallucination)
改动:增加"宁缺毋滥"原则
准确率:60% → 73%
剩余问题:物流查询和退款场景仍有混淆
## v2 → v3 (tool_dispatch)
改动:给 search_order 加触发关键词清单
准确率:73% → 85%
## v3 → v4 (anti_hallucination)
改动:增加"宁可追问也不要猜测退款金额"
准确率:85% → 91%
备注:anti_hallucination 方向两次优化效果递减,
下次换 param_extract 方向的 few-shot 负例
方向标签的作用:
- 避免重复打补丁(看到历史记录就知道哪些方向试过)
- 找到”重灾区”(多次迭代还没解决的方向)
- 量化各方向贡献度(哪个方向提升最大)
Step 4:run_cases.py 骨架
import json
from openai import OpenAI
with open('test_cases.json') as f:
cases = json.load(f)
with open('system_prompt.md') as f:
system_prompt = f.read()
client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
results = []
for case in cases:
resp = client.chat.completions.create(
model="Qwen2.5-7B-Instruct",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": case['input']}
],
tools=tools
)
tool_call = resp.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
results.append({
"case_id": case['id'],
"expected": case['expected_tool'],
"actual": tool_call.function.name,
"args_match": tool_call.function.arguments == case['expected_args'],
"analysis": args.get('analysis', '')
})
accuracy = sum(1 for r in results if r['args_match']) / len(results)
print(f"准确率: {accuracy:.1%}")
Step 5:迭代过程
Copilot Agent 在一个会话里连续推进:
[Copilot] 读取 system_prompt.md v1
[Copilot] 跑 v1 → 准确率 60%(18/30)
[Copilot] 12 个错误用例,8 个是工具选错
[Copilot] 加触发关键词清单 → v2
[Copilot] v2 → 73%
[Copilot] 加"宁缺毋滥"原则 → v3
[Copilot] v3 → 85%
[Copilot] 连续 2 轮提升但增速放缓
人的介入时机:
- 连续 3 轮无提升(止损线)
- Agent 想改 run_cases.py(提醒改错了)
- Agent 想换小模型(明确禁止)
Step 6:达标与收尾
量化目标:
- 准确率 ≥ 95%
- 幻觉率 < 2%
- 工具选错率 < 1%
达标后 Agent 自主做:
- git tag v_final
- 更新 CHANGELOG.md 总结
- 输出最终报告(各方向贡献度统计)
- 复制到生产环境
人只做最后审阅:通读 CHANGELOG,决定是否真的达标。
常见问题
没有 analysis 字段怎么办?
改造原有 tools 定义,给每个工具都加 analysis 必填参数。代价是小模型输出会变长,但调试可控性大幅提升。
小模型完全跑不动测试?
- 降低用例难度
- 减少工具数量(先收敛到 1-2 个)
- 换更大参数的模型(Qwen2.5-7B → Qwen3-8B)
CHANGELOG 应该谁写?
Agent 自动写。每轮 commit 必填。格式强制约束:
# .github/agents/prompt-trainer.md 的硬性要求
- CHANGELOG.md 每条记录必须包含:版本号、优化方向、改动摘要、准确率
- 优化方向必须是预定义标签之一
总结
- Copilot Agent 当执行者,跑 执行→分析→修改→回归 闭环
- 人当 PM,设定目标、约束、止损线
- Function Call 加 analysis 参数,让小模型变白盒
- 测试用例量化,迭代有依据
- CHANGELOG 标签化,方便复盘
- git 每次提交,随时回滚
本质上:指挥 Agent 团队,大模型当执行者,小模型当被优化对象,人当决策者。
参考链接
(完)