背景
大语言模型(LLM)在很多通用任务上已经表现不错,但一到垂直领域,比如软件测试,就容易露怯——术语乱用、用例结构不合理、关键步骤漏掉。我们想基于开源模型定制一个能生成渠道业务测试用例的模型,第一步就是指令微调。
指令微调本身不新鲜,真正头疼的是数据:手工写几百上千条高质量的测试指令,又慢又贵,而且一个人写来写去很容易重复,影响泛化能力。样本少了,模型学不到东西;质量差了,反而学歪。
调研了一圈,最终选了 Self-Instruct:从少量种子指令出发,用大模型自己生成更多的指令数据,再清洗一遍,拿去微调。下面记一下我们怎么落地的,顺便聊聊踩过的坑。
Self-Instruct 思路
Self-Instruct 本质上是一个半自动数据增强流程。流程官方分了六步,我们实际跑的时候简化了不少:
- 手工写一小撮种子任务,覆盖测试的几个核心方向;
- 把种子丢给大模型,让它模仿着生成新的指令;
- 对生成的指令做简单去重过滤;
- 为每条指令再调用大模型生成配套的输入输出例子;
- 人工抽检,剔除明显跑偏的;
- 把处理好的数据集喂给开源模型,用 LLaMA Factory 做微调。
省掉了原始论文里的分类任务识别和复杂相似度计算,因为初期快速验证更重要。

从种子到数据集
种子指令
一开始我们写了 10 条左右的种子指令,全部围绕软件测试的基础概念和方法,比如'什么是回归测试''黑盒与白盒的区别''怎么设计一个登录功能的测试用例'。这些指令不追求面面俱到,但要能代表测试领域的常见问题类型。
| 种子指令示例 |
|---|
| {"id": 1, "question": "什么是软件测试?为什么它对软件开发过程至关重要?"} |
| {"id": 2, "question": "请解释黑盒测试和白盒测试之间的区别。"} |
| {"id": 3, "question": "什么是回归测试?在什么情况下需要进行回归测试?"} |
| {"id": 4, "question": "请描述静态测试和动态测试的不同点。"} |
| {"id": 5, "question": "单元测试、集成测试、系统测试和验收测试有什么区别?"} |
| {"id": 6, "question": "什么是测试用例?请提供一个测试用例的例子。"} |
| {"id": 7, "question": "测试人员在进行性能测试时需要关注哪些关键指标?"} |
| {"id": 8, "question": "请解释什么是缺陷生命周期,以及它通常包括哪些状态。"} |
| {"id": 9, "question": "什么是负载测试和压力测试?它们之间的区别是什么?"} |
| {"id": 10, "question": "请解释什么是边界值分析,并给出一个应用示例。"} |
这些种子构成了指令分布的基础,后面生成的新指令会和它们采样后的样本一起作为上下文,喂给大模型。
指令生成
把种子指令和模型自己之前生成的指令混在一起,从里面随机抽 8 条(6 条人工、2 条机器生成的),拼进提示模板,调用 OpenAI 的 gpt-3.5-turbo 模型,一次性让它续写 10 条新的测试领域指令。
# 读取种子数据
with open("./data/seed/seed_question_%s.jsonl" % domain, "r", encoding=) file:
data = [json.loads(line) line file]
random_questions = random.sample(data, )
os.path.exists(generate_tasks_file) os.path.getsize(generate_tasks_file) != :
(generate_tasks_file, , encoding=) file:
data = [json.loads(line) line file]
random_questions.extend(random.sample(data, ))
num_example = ((random_questions))
question_prompt = question_prompt.replace(, domain).replace(, num_per_generate).replace(, num_example)
example = .join([ % (index + ) + question_dict[] index, question_dict (random_questions)])
prompt = question_prompt.replace(, example)
res = chat(prompt)
generate_questions_base = decode_res(res)



