本文整理一次面向软件测试工程场景的大模型微调实践。目标不是从零训练基础模型,而是在已有开源大模型基础上,通过指令数据构造、LoRA/QLoRA 轻量化适配、结构化输出评测和私有化部署,将模型能力稳定接入智能测试平台。


1. 背景:为什么在测试工程场景中做大模型微调

在汽车电子底软测试场景中,测试人员经常需要从 AUTOSAR 标准、项目需求、接口文档、历史测试用例和公共测试库中提取信息,并进一步完成测试点设计、测试用例编写、测试脚本开发和报告分析。

传统方式通常存在几个问题:

  1. 需求解析依赖人工经验
    同一条需求可能涉及前置条件、输入类别、核心动作、预期结果、异常场景和覆盖关系。人工拆解容易出现遗漏或粒度不一致。

  2. 测试用例结构化程度不足
    测试用例经常散落在 Excel、Markdown、脚本注释或测试报告中,字段命名、步骤描述、预期结果表达不统一,难以直接进入自动化执行链路。

  3. 脚本开发重复劳动较多
    底软测试脚本通常需要查找公共库 API、参考历史脚本风格、适配测试环境,再补充断言与日志。大量时间消耗在重复查库和仿写上。

  4. 生成式模型直接调用不够稳定
    仅依赖 Prompt 或通用模型,容易出现 JSON 不合法、字段缺失、测试点覆盖不足、测试步骤不可执行、编造不存在 API 等问题。

因此,在智能测试平台中,大模型能力不能只停留在“问答”或“生成文本”层面,而应形成一套可评测、可修正、可部署的工程闭环:

需求文档 / 历史用例 / 公共库 API
        ↓
数据清洗与指令数据构造
        ↓
Base 模型推理基线
        ↓
Prompt / RAG / LoRA 微调方案对比
        ↓
结构化输出评测
        ↓
服务化部署与平台集成
        ↓
用例生成 / 脚本生成 / 执行辅助

2. 项目定位:不是训练基础模型,而是做垂直场景适配

这类项目的关键边界是:不做大规模预训练,而是围绕测试工程任务做监督微调和工程化落地

基础模型已经具备通用语言理解能力,微调要解决的是垂直领域中的稳定性和格式一致性问题,例如:

  • 能否稳定识别需求类型;
  • 能否把自然语言需求拆成测试点;
  • 能否输出符合 Schema 的 JSON;
  • 能否保留必要字段;
  • 能否避免生成不可执行的测试步骤;
  • 能否结合公共库 API 生成更接近项目风格的 pytest 脚本;
  • 能否降低后处理、人工修正和二次返工成本。

在本实践中,模型侧主要围绕 Qwen2.5-1.5B-Instruct 进行私有化部署和 LoRA 原型验证;平台侧结合已有智能测试平台、test_agent 工作流和 Test_Framework 自动化执行底座,形成从测试资产生成到执行闭环的链路。


3. 总体技术架构

整体架构可以分为五层:

数据层
需求文档、公开需求语料、历史测试用例、公共库 API、历史测试脚本
        ↓
标注与构造层
清洗、去重、脱敏、teacher 标注、JSONL / messages 数据构造
        ↓
模型适配层
Base 推理、Prompt 优化、RAG 增强、LoRA / QLoRA 微调
        ↓
评测层
JSON 合法率、Schema 通过率、字段完整率、覆盖率、响应耗时
        ↓
平台集成层
test_agent 生成测试用例 / 脚本,Test_Framework 执行并产出日志、pcap、HTML 报告

其中,test_agentTest_Framework 的职责边界可以概括为:

模块主要职责输出
test_agent需求解析、测试点设计、测试用例生成、测试脚本生成、规则校验JSON、Excel、pytest 脚本、生成校验报告
Test_FrameworkUI 编排、配置驱动、pytest 执行、公共库调用、日志抓包、报告产出执行结果、日志、pcap、HTML 报告
微调模型提升垂直任务中的结构化输出、字段完整性和测试场景理解能力更稳定的需求解析和用例生成结果

一个更准确的关系是:

微调模型提供垂直能力,test_agent 负责把模型能力编排成测试工程工作流,Test_Framework 负责执行生成后的自动化测试资产。


4. 模型选型与部署:先建立可调用的本地基线

微调前需要先建立一个可重复评测的 Base 模型基线。这里采用 Qwen2.5-1.5B-Instruct 作为轻量模型进行验证,主要考虑:

  • 参数量较小,适合单卡或云 GPU 快速验证;
  • Instruct 模型具备基础指令跟随能力;
  • 可通过 Hugging Face / Transformers / vLLM 快速部署;
  • 便于后续 LoRA 或 QLoRA 适配。

4.1 使用 vLLM 启动 OpenAI-compatible 服务

示例命令:

python -m vllm.entrypoints.openai.api_server \
  --model /data/models/Qwen2.5-1.5B-Instruct \
  --served-model-name qwen2.5-1.5b-instruct \
  --host 0.0.0.0 \
  --port 8000 \
  --max-model-len 4096

启动后,可以用 OpenAI-compatible API 调用:

from openai import OpenAI

client = OpenAI(
    api_key="EMPTY",
    base_url="http://127.0.0.1:8000/v1",
)

resp = client.chat.completions.create(
    model="qwen2.5-1.5b-instruct",
    messages=[
        {"role": "system", "content": "你是一个软件测试需求解析助手,只输出合法 JSON。"},
        {"role": "user", "content": "系统应在通信超时时记录错误码并进入降级状态。"}
    ],
    temperature=0.0,
)

print(resp.choices[0].message.content)

4.2 为什么先做部署而不是直接微调

直接进入微调容易忽略两个问题:

  1. 没有 baseline 就无法判断微调是否有效
    必须先知道 Base 模型在目标任务上的 JSON 合法率、字段完整率、覆盖率和响应耗时。

  2. 很多问题不一定需要微调解决
    Prompt、RAG、Schema 约束、后处理和规则校验可以解决一部分格式问题。微调更适合解决输出风格、领域术语、任务模式和稳定性问题。

因此推荐顺序是:

Base 模型部署
  ↓
构建评测集
  ↓
Base 指标评测
  ↓
Prompt / RAG 优化
  ↓
判断是否需要 LoRA 微调
  ↓
微调后与 Base / Prompt 版本对比

5. 数据集构造:从需求文本到指令微调样本

微调效果很大程度取决于数据质量。对于测试用例生成场景,数据构造的目标不是简单收集问答,而是构建“输入需求 → 结构化测试资产”的映射。

5.1 数据来源

可用数据主要包括:

数据来源用途
公开软件需求数据集,如 PURE / PurePlainDataset构建通用需求解析样本
AUTOSAR SWS / 项目需求文档构建底软领域需求理解样本
历史测试用例 Excel / JSON提供标准字段、步骤粒度和预期结果风格
历史 pytest 测试脚本提供脚本结构、fixture 使用、断言方式和日志风格
Test_Framework 公共库 API约束脚本生成只能调用真实存在的接口
评审规则 / 测试规范构建规则校验与反例数据

5.2 数据清洗原则

清洗时重点关注以下问题:

  1. 去除无效文本
    删除页眉页脚、目录、版权声明、无业务含义的表格残片。

  2. 按需求粒度切分
    对规范性需求,尽量做到“一条需求一个样本”,避免一个样本里混入多个独立需求。

  3. 保留上下文但控制长度
    可保留上级章节、术语定义和相关需求,但不应把整章内容无差别塞入 input。

  4. 脱敏处理
    去除项目名称、客户名称、内部地址、Token、账号、日志路径等敏感信息。

  5. 训练集、验证集、测试集隔离
    测试集不能参与训练,也不应参与 Prompt 调参,否则评测结果会失真。

5.3 指令数据格式

对于 SFT,建议使用 messages 格式:

{
  "messages": [
    {
      "role": "system",
      "content": "你是软件测试需求解析助手。请根据需求生成结构化测试点,只输出合法 JSON。"
    },
    {
      "role": "user",
      "content": "需求:系统应在 CAN 通信超时时记录错误码,并在 100ms 内进入降级状态。"
    },
    {
      "role": "assistant",
      "content": "{\"requirement_type\":\"functional\",\"test_points\":[{\"id\":\"TP-001\",\"condition\":\"CAN通信超时\",\"action\":\"触发通信超时场景\",\"expected\":\"记录错误码并在100ms内进入降级状态\"}]}"
    }
  ]
}

如果任务是测试脚本生成,样本可以进一步加入公共库 API 摘要和相似示例:

{
  "messages": [
    {
      "role": "system",
      "content": "你是 pytest 自动化测试脚本生成助手。必须优先使用给定 API,不得编造不存在的接口。"
    },
    {
      "role": "user",
      "content": "测试用例:...\n可用API:tester.SDO_Upload_ExpeditedOrSegmented, tester.SDO_Download...\n相似脚本:..."
    },
    {
      "role": "assistant",
      "content": "import pytest\n\nclass Test_CANopen:\n    def test_xxx(self, start):\n        ..."
    }
  ]
}

6. Teacher 标注:用高能力模型生成初始 gold 数据

在早期缺少足够人工标注数据时,可以用高能力模型做 teacher 标注,再通过规则和人工抽检提高质量。

推荐流程:

原始需求文本
  ↓
规则清洗与切分
  ↓
teacher 模型生成结构化输出
  ↓
JSON 合法性检查
  ↓
Schema 校验
  ↓
规则检查与人工抽检
  ↓
train / valid / test 数据集

teacher 标注不是直接拿来训练,而是要经过质量门禁。常见门禁包括:

检查项说明
JSON 合法性是否能被 json.loads() 解析
Schema 通过率是否满足字段、类型、枚举值要求
字段完整性是否包含需求编号、测试点、前置条件、动作、预期结果
需求一致性是否遗漏或篡改原始需求含义
覆盖关系测试点是否覆盖核心条件、动作和结果
可执行性是否生成可以落入测试环境的步骤

对于关键样本,建议保留 teacher 输出、规则检查结果和人工修正记录,后续可以用于错误分析和数据迭代。


7. Prompt、RAG 与微调的边界

在智能测试平台里,Prompt、RAG 和微调解决的问题不同。

方案适合解决不适合解决
Prompt输出格式约束、任务说明、少量示例引导长期稳定性、领域风格沉淀
RAG补充项目知识、API 文档、配置参数、历史用例改变模型内在输出习惯
LoRA / QLoRA固化领域任务模式、提升结构化输出稳定性、降低反复提示成本替代知识库、记忆频繁变化的项目配置
规则校验发现格式错误、字段缺失、覆盖不足直接生成高质量内容

在测试用例生成场景中,一个实用组合是:

RAG 提供上下文
  +
Prompt 约束任务和格式
  +
LoRA 固化领域输出模式
  +
规则校验兜底

例如,AUTOSAR 规范、公共库 API、项目配置和历史脚本经常变化,更适合放入 RAG 或上下文检索;而“如何把需求拆成测试点”“如何输出统一 JSON”“如何描述前置条件和预期结果”这类稳定模式,更适合通过 SFT/LoRA 固化。


8. LoRA / QLoRA 微调方案

8.1 LoRA 的基本思路

LoRA 的核心思想是冻结基础模型大部分参数,只在注意力层或部分线性层中加入低秩矩阵进行训练。这样可以显著降低显存和训练成本,同时让模型适配特定任务。

简化理解:

原始权重 W 不更新
        +
可训练低秩增量 ΔW = A × B
        ↓
推理时使用 W + ΔW

在垂直测试任务中,LoRA 适合用于:

  • 提高结构化 JSON 输出稳定性;
  • 固化需求解析字段;
  • 学习测试用例描述风格;
  • 降低每次 Prompt 中重复说明规则的成本;
  • 让小模型在特定任务上接近更大模型的输出风格。

8.2 QLoRA 适用场景

QLoRA 是在量化基础上进行 LoRA 训练,通常用于显存更紧张的场景。它适合:

  • 单卡显存有限;
  • 模型参数量较大;
  • 需要降低训练成本;
  • 对训练吞吐和精度有折中要求。

如果使用 1.5B 级别模型做原型验证,普通 LoRA 已经比较轻量;如果后续扩大到 7B 或更大模型,可以考虑 QLoRA。

8.3 训练参数建议

一个初始配置可以参考:

model_name_or_path: /data/models/Qwen2.5-1.5B-Instruct
stage: sft
finetuning_type: lora
template: qwen
cutoff_len: 4096

lora_rank: 8
lora_alpha: 16
lora_dropout: 0.05
target_modules: all

learning_rate: 2.0e-4
num_train_epochs: 3
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
lr_scheduler_type: cosine
warmup_ratio: 0.03

logging_steps: 10
save_steps: 200
eval_steps: 200

参数不是固定答案,实际要结合数据量、输出长度、显存、验证集表现和过拟合情况调整。

8.4 防止过拟合

微调数据通常规模不大,容易过拟合。建议:

  1. 保留独立测试集;
  2. 监控 train loss 与 eval loss;
  3. 控制 epoch 数;
  4. 对同一需求避免重复增强过多;
  5. 保持输入表达多样性;
  6. 保留 hard case,而不是只保留模型容易答对的样本;
  7. 对输出进行 Schema 和业务规则双重评估。

9. 评测体系:不要只看“生成得像不像”

微调是否有效,必须通过统一评测集量化对比。建议至少比较三组:

Base 模型
Prompt 优化版本
LoRA 微调版本

9.1 结构化输出指标

指标含义
JSON 合法率输出能否被标准 JSON 解析
Schema 通过率字段、类型、枚举值是否符合定义
字段完整率必填字段是否完整
需求类型准确率是否正确识别功能、性能、接口、异常、安全等类型
测试点覆盖率是否覆盖需求中的核心条件、动作和预期结果
冗余率是否生成重复或无关测试点
平均响应耗时单条需求生成耗时
人工修正率最终进入平台前需要人工修改的比例

9.2 一个简单的评测脚本思路

import json
from jsonschema import validate, ValidationError

def is_valid_json(text: str):
    try:
        return True, json.loads(text)
    except Exception:
        return False, None

def check_schema(obj, schema):
    try:
        validate(instance=obj, schema=schema)
        return True
    except ValidationError:
        return False

def evaluate_one(pred_text, gold, schema):
    json_ok, pred_obj = is_valid_json(pred_text)
    if not json_ok:
        return {
            "json_ok": False,
            "schema_ok": False,
            "field_complete": 0.0,
            "coverage_score": 0.0,
        }

    schema_ok = check_schema(pred_obj, schema)
    required_fields = ["requirement_id", "requirement_type", "test_points"]
    field_complete = sum(1 for f in required_fields if f in pred_obj) / len(required_fields)

    # 覆盖率可结合关键词、测试点映射、人工规则或 LLM-as-Judge
    coverage_score = compute_coverage(pred_obj, gold)

    return {
        "json_ok": True,
        "schema_ok": schema_ok,
        "field_complete": field_complete,
        "coverage_score": coverage_score,
    }

9.3 评测结果如何解读

如果 LoRA 后:

  • JSON 合法率明显提升;
  • Schema 通过率明显提升;
  • 字段完整率提升;
  • 测试点覆盖率提升;
  • 平均耗时保持可接受;
  • 人工修正率下降;

则说明微调对该业务任务有实际价值。

如果只是输出更流畅,但结构化指标没有提升,说明微调没有解决核心问题,可能需要回到数据质量、Prompt 约束、Schema 设计或规则校验链路重新调整。


10. 与智能测试平台的集成方式

10.1 与 test_agent 的关系

test_agent 可以作为 AI 测试工程能力层,负责:

需求解析
  ↓
测试点设计
  ↓
测试用例生成
  ↓
覆盖映射
  ↓
规则校验
  ↓
测试脚本生成

微调模型可以接入到其中的 LLM Adapter 中,用于替换或补充外部模型调用。这样,业务工作流不用直接关心模型部署细节,只需要调用统一模型接口。

典型调用关系:

entrypoints
  ↓
Task(domain_type, task_type, input_payload, workflow_name)
  ↓
WorkflowRegistry
  ↓
PlatformOrchestrator
  ↓
具体 Workflow
  ↓
LLM Adapter / RAG / 规则校验 / 文件导出

10.2 与 Test_Framework 的关系

Test_Framework 是自动化执行底座,负责:

UI 用例筛选
  ↓
配置驱动
  ↓
pytest 执行
  ↓
公共库调用
  ↓
日志 / pcap / HTML 报告

AI 微调模型不直接替代自动化执行框架,而是为其生成更稳定的测试资产:

阶段AI 能力Test_Framework 能力
需求理解解析需求、生成测试点不负责
用例设计生成 JSON / Excel 测试用例读取或组织可执行用例
脚本开发生成 pytest 脚本骨架与逻辑执行 pytest 脚本
运行验证可辅助分析失败原因采集日志、pcap、报告
资产沉淀生成样本、回流 bad case沉淀公共库与执行结果

因此,完整闭环是:

大模型生成测试资产
        ↓
test_agent 编排与校验
        ↓
Test_Framework 自动执行
        ↓
证据产出与失败分析
        ↓
bad case 回流数据集

11. 工程经验:从测试平台到模型适配的迁移

在已有测试平台建设中,已经沉淀了几类对微调非常有价值的资产:

  1. 大量测试用例与脚本资产
    自动化测试框架已支撑多类底软测试项目,累计沉淀大量测试脚本、测试用例和执行结果。这些资产可以转化为模型训练样本、相似示例库和评测集。

  2. 公共测试库 API
    SOME/IP、CANopen、DoIP/UDS、SSH、Excel/JSON、日志、抓包等公共能力可以作为脚本生成的 API 约束,避免模型编造不存在的接口。

  3. 结构化输出经验
    智能测试平台中的 JSON 合法性校验、Schema 校验、字段完整性检查、失败重试和规则修复机制,可以直接复用到微调评测和推理服务中。

  4. 自动化执行证据链
    pytest 执行结果、日志、pcap、远端日志和 HTML 报告可以反向用于分析生成脚本是否真正可执行。

  5. Agent 工作流经验
    通过测试点设计、覆盖映射、规则校验、逐条用例复核等节点,可以避免“一次生成到底”的不可控问题,让模型输出进入可追踪、可修复的工程流程。

这种迁移的关键不是“把模型训练得更会聊天”,而是让模型在真实测试工程链路中承担明确职责,并接受规则和执行结果的约束。


12. 常见问题与处理策略

12.1 模型输出不是合法 JSON

处理方式:

  • system prompt 明确“只输出 JSON”;
  • 使用 response_format 或 JSON schema 约束;
  • 本地做 JSON 清洗;
  • 失败时自动重试;
  • 将错误样本加入微调或评测集;
  • 降低 temperature。

12.2 Schema 通过但业务含义错误

Schema 只能保证格式,不能保证覆盖质量。需要加入:

  • 需求关键词覆盖检查;
  • 测试点与需求编号映射;
  • 核心动作与预期结果一致性检查;
  • case_set_validator;
  • 人工抽检高风险样本;
  • LLM-as-Judge 作为辅助评审。

12.3 模型编造不存在的 API

处理方式:

  • Prompt 中只提供检索到的 API;
  • 规则中明确“不得编造 API”;
  • 生成后静态扫描 API 调用;
  • 结合 pytest collect 做基础可执行性检查;
  • 对无法实现的步骤生成 TODO,而不是硬编代码。

12.4 微调后效果没有提升

优先检查:

  • 数据是否太少或质量不稳定;
  • train / valid / test 是否泄漏;
  • 输出格式是否过于复杂;
  • 训练 epoch 是否过多导致过拟合;
  • 评测指标是否与训练目标一致;
  • Prompt、RAG、规则校验是否已经解决了大部分问题。

12.5 小模型能否替代大模型

小模型更适合承担稳定、边界清晰、格式固定的任务,例如:

  • 需求分类;
  • 测试点初稿生成;
  • JSON 字段补全;
  • 脚本骨架生成;
  • 报告摘要。

复杂推理、跨文档推断和高风险设计仍建议结合更强模型、RAG 和人工审核。


13. 后续拓展方向

13.1 从 LoRA 原型到多模型评测

可以扩展为统一评测平台,对比:

  • Qwen 不同参数量模型;
  • Base / Prompt / RAG / LoRA / QLoRA;
  • 不同上下文长度;
  • 不同推理框架;
  • 不同量化方案;
  • 延迟、吞吐、显存和输出质量。

13.2 从测试用例生成扩展到脚本生成

当前可以先从需求到测试用例的结构化任务开始,后续逐步扩展到:

测试用例 JSON
  ↓
检索公共库 API
  ↓
检索相似历史脚本
  ↓
生成 pytest 脚本骨架
  ↓
LLM 补全逻辑
  ↓
语法检查
  ↓
pytest collect
  ↓
Test_Framework 执行

13.3 从生成结果评测扩展到执行结果评测

执行后的日志、pcap 和 HTML 报告可以继续回流到 AI 系统,用于:

  • 自动分析失败原因;
  • 判断失败是环境问题、脚本问题还是被测件问题;
  • 生成测试报告摘要;
  • 形成 bad case 数据集;
  • 反向优化 Prompt、规则和微调数据。

13.4 从单领域适配扩展到多领域 Profile

测试领域差异不应全部硬编码到工作流中。更好的方式是:

公共工作流引擎
  +
领域 Profile
  +
领域 Prompt
  +
领域 Schema
  +
领域规则检查器
  +
领域导出模板

这样 AUTOSAR、RCP、Web、诊断、通信协议等场景可以复用同一套 Agent 与评测基础设施。

13.5 从单次生成扩展到持续学习闭环

最终目标不是一次性微调,而是形成持续迭代机制:

线上生成
  ↓
规则校验
  ↓
人工修正
  ↓
执行结果
  ↓
bad case 归档
  ↓
数据清洗
  ↓
增量评测
  ↓
下一轮微调或 Prompt 更新

14. 小结

面向测试用例生成的大模型微调,本质上是一个工程系统问题,而不是单纯的训练脚本问题。

实践中需要同时关注:

  • 数据是否干净;
  • 输出结构是否稳定;
  • 评测指标是否客观;
  • 模型是否真的降低人工修正成本;
  • 生成内容能否进入自动化执行链路;
  • 失败样本能否回流形成持续优化。

对于汽车电子底软测试这类强流程、强规范、强证据链的场景,比较合理的技术路线是:

Prompt 约束任务
  +
RAG 提供项目知识
  +
LoRA 固化领域输出模式
  +
Agent 编排生成与校验流程
  +
Test_Framework 承接自动化执行
  +
评测与 bad case 回流持续优化

这样的系统既能保留大模型的生成能力,又能通过规则、数据、工作流和执行证据把生成结果纳入工程化管理。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐