23级山东大学软件学院创新实训-个人纪录(二)口语对话模型微调设计方案:基于 Qwen3-8B 的口语对话训练规划
在 LingualSpark 项目中,我负责设计英语口语对话能力的模型微调方案。目标是让模型不仅“答得对”,还要“说得像真人”——能够识别用户情绪,给出温和、自然、有共情的回应。目前项目处于设计阶段,尚未实际训练,但已完成数据接入分析、清洗规则制定、样本构造设计、两阶段训练流程规划以及超参预设。以下是我的完整设计方案。
一、模型选型与资源评估
我们计划选用 Qwen3-8B 作为基座模型。受限于单张 RTX 4090(24GB)的算力,我决定采用 QLoRA 4bit 量化作为技术主线。经过显存估算:
- 4bit 量化后基座模型约占用 5-6GB
- LoRA adapter 参数量极小(约 0.5GB)
- 激活值与梯度(序列长度 4096,batch size 2)约占用 10-12GB
- 加上优化器状态(使用 paged_adamw_8bit),总显存预计在 18-20GB 之间,理论上可以稳定运行。
如果实际训练中出现显存不足,我会进一步降低 batch size 或启用梯度检查点(已在计划中)。这个选型在能力与资源之间取得了平衡。
二、数据接入与初步分析
2.1 主数据集:EmpatheticDialogues
我已下载 EmpatheticDialogues 的三个分片:train.csv(76,673 行)、valid.csv(12,030 行)、test.csv(10,943 行),总计约 2.3 万个会话、近 10 万条话语。初步分析显示:
- 每个会话平均 4.3 轮,说话人数量稳定在 2 人,适合多轮口语对话学习。
- 文本长度适中:utterance 词数均值 17.25,prompt 词数均值 18.74,符合“短句多轮”的口语交互特征。
- 情绪标签覆盖 32 种情绪(如 excited, anxious, lonely, proud 等),有利于训练模型的共情能力。
2.2 辅助数据集:Human-Like-DPO-Dataset
为了进一步提升回复的自然度和偏好对齐,我计划引入 Human-Like-DPO-Dataset。该数据集包含多个 JSON 子集:
data.json:约 10,884 条,是主偏好数据。dpo_dataset_16_09_2024_more_info_convs_2k.json:约 1,979 条,偏向信息充分、结构完整的对话。dpo_dataset_4_09_2024_more_casual_convs_1k.json及...much_2k.json:偏向口语化、随意风格的对话。dpo_dataset_part1_part2_merged.json:约 3,986 条,历史合并产物。
每个样本均包含 prompt、chosen、rejected 三个字段,天然适配 DPO 训练格式。我会在正式训练前对这些子集进行质量抽样,剔除模糊样本。
三、数据清洗规则设计
原始 EmpatheticDialogues 中存在结构异常和自评格式错误,我设计了五步顺序清洗流程,确保不同脚本版本下样本分布一致。这套规则将在训练前执行。
-
结构层清洗:按标准字段
conv_id, utterance_idx, context, prompt, speaker_idx, utterance, selfeval, tags解析 CSV。任何出现额外列的行(通常由尾部异常拼接导致)直接标记为异常,不进入训练集。预期剔除率约 0.7%。 -
文本归一化:将
_comma_统一替换为英文逗号,去除多余空白,控制重复标点(如将“!!!”规范为“!”),保留原句语义但消除模板噪声。 -
长度过滤:清除空
utterance或空prompt。将utterance的 token 长度限制在 3 到 120 之间(使用 Qwen 的 tokenizer 计算)。超过上限的样本移入长尾池,留作后续可选增强,不直接进入主训练。 -
会话级过滤:仅保留 3 到 8 轮的会话,并要求同一
conv_id内context情绪标签一致、至少出现两个说话人交替。这保证了多轮对话的连贯性和交互性。 -
质量增强:解析
selfeval字段。格式合法的样本(形如5|5|5_2|2|5)赋予更高采样权重;格式异常样本降权或剔除。预计约 8% 的样本存在selfeval格式错误,我计划剔除而不是修补,避免引入噪声标签。
清洗后,训练集预计从 76,673 行压缩到约 62,000 行,但信噪比会显著提升。
四、训练流程设计:SFT → DPO 两阶段
我规划采用 SFT 先监督微调,DPO 后偏好对齐 的两阶段策略,两者数据源完全分离,避免混淆。
4.1 SFT 阶段设计(监督微调)
- 数据:清洗后的 EmpatheticDialogues。
- 目标:让模型学会基本的情绪感知和共情回复格式。
样本构造模板(ChatML):
我会将 EmpatheticDialogues 中的 context(用户当前情绪)映射到 system 消息中,把历史对话拼接到 user 输入,目标回复作为 assistant 输出。模板设计如下:
{
"messages": [
{
"role": "system",
"content": "你是 LinguaSpark,一位温和、自然、不过度说教的英语对话伙伴。用户当前情绪是【apprehensive】。"
},
{
"role": "user",
"content": "Context: I feel nervous about my interview tomorrow.\nHistory:\nUser: I might fail...\nAssistant: You've prepared a lot.\nUser: But what if they ask something I don't know?"
},
{
"role": "assistant",
"content": "You're not alone in feeling this. Try a short plan tonight: 20 minutes review, then rest. You've got this."
}
]
}
注意:context 情绪词从数据集中动态提取,共 32 种。
超参预设(单卡可跑):
- 量化:NF4(4bit),双重量化开启
- LoRA 秩:
r=64,lora_alpha=128,lora_dropout=0.05 - target_modules:覆盖
q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj(即 Attention 和 MLP 全部线性层) - 批大小:
per_device_train_batch_size=2,gradient_accumulation_steps=4→ 有效批大小 = 8 - 学习率:
2e-4(采用 cosine 衰减,warmup ratio 0.03) - 最大序列长度:
4096 - 训练轮数:3 epoch
- 优化器:paged_adamw_8bit(节省显存)
- 梯度检查点:启用
预期显存占用约 18-20GB,若实际超出,我会将 batch size 降为 1 并增加梯度累积步数。
4.2 DPO 阶段设计(直接偏好优化)
- 数据:Human-Like-DPO-Dataset,先以
data.json为主,再按目标风格叠加more_info和more_casual子集。 - 目标:将模型从“冷硬、说教”的回复风格推向“有温度、自然共情”的风格。
数据格式:直接使用数据集原始字段,无需额外构造。prompt 通常包含对话历史和当前用户输入;chosen 是人类偏好的共情回复;rejected 是生硬或缺乏共情的回复。
超参预设:
- 基座模型:SFT 阶段训练完成的 adapter 合并后的完整模型(作为初始策略模型
π_θ),同时冻结一份副本作为参考模型π_ref - 学习率:
5e-6(显著低于 SFT,避免破坏已学能力) - beta(KL 惩罚系数):
0.1 - 批大小:
per_device_train_batch_size=1,gradient_accumulation_steps=8(有效批大小 8) - 最大长度:
prompt截断至 2048,chosen/rejected截断至 512 - 训练轮数:1 epoch(先过 data.json),然后增量训练 more_info 和 more_casual 各 0.5 epoch
- LoRA 配置与 SFT 保持一致(继续训练已有 adapter,不重新初始化)
训练策略:我会采用渐进式混合——先在主数据集上训练 1 epoch,观察 loss 下降和偏好差值;然后依次加入 more_info 和 more_casual 子集,每个子集训练 0.5 epoch,并在验证集上检查回复的自然度是否回退。如果发现模型变得过度随意或信息过载,会降低学习率或提前停止。
显存优化:DPO 需要同时加载策略模型和参考模型,显存压力更大。我计划使用 peft 的 disable_adapter() 技巧——参考模型使用合并 adapter 后的全量权重(冻结),策略模型使用 LoRA adapter,这样实际显存占用约 22GB,刚好能跑。如果仍然不足,我会将参考模型也量化到 4bit 并部分卸载到 CPU。
五、损失函数设计
5.1 SFT 损失:带掩码的交叉熵
标准自回归交叉熵损失,但会应用掩码策略:在 ChatML 格式中,只有 assistant 回复部分的 token 参与 loss 计算,system 和 user 部分的 label 设为 -100(忽略索引)。数学表达为:
[
L_{SFT} = -\frac{1}{T}\sum_{t=1}^{T} w_t \log P_{\theta}(y_t \mid x, y_{<t})
]
其中 (w_t = 1) 当且仅当 token 属于 assistant 回复,否则 (w_t = 0)。
5.2 DPO 损失:直接偏好优化
DPO 损失函数避免了训练单独的奖励模型,直接在偏好数据上优化:
[
L_{DPO} = -\mathbb{E}{(x,y_w,y_l)} \left[ \log \sigma \left( \beta \log \frac{\pi{\theta}(y_w|x)}{\pi_{ref}(y_w|x)} - \beta \log \frac{\pi_{\theta}(y_l|x)}{\pi_{ref}(y_l|x)} \right) \right]
]
- (\pi_{\theta}):当前训练的策略模型
- (\pi_{ref}):冻结的 SFT 模型(参考点)
- (\beta=0.1):控制偏离参考模型的惩罚强度
该损失会同时提高 chosen 的生成概率、降低 rejected 的概率,且当偏好差异已明显时梯度自动减小,防止过优化。
六、质量控制计划
在正式训练前,我制定了自动评估线,用于训练过程中的监控和最终验收。
自动评估:
- 监控 SFT/DPO 训练 loss 曲线,确保收敛。
- 计算回复长度稳定性(避免 DPO 后回复无限拉长或过度缩短)。
- 使用 ROUGE-L 和 BERTScore 对比验证集上 SFT 与 DPO 输出的语义保留程度。
七、部署方案设计
训练完成后(目前尚未执行),我计划合并 LoRA adapter 与基座模型,得到完整的 Qwen3-8B-Chat-Empathetic 模型。部署将采用 vLLM 框架,以 OpenAI 兼容 API 的方式启动服务:
python -m vllm.entrypoints.openai.api_server \
--model /path/to/merged_model \
--tensor-parallel-size 1 \
--max-model-len 4096 \
--quantization awq # 或使用 FP16
本地快速验证则使用 Ollama 导入模型,方便口语对话原型测试。部署方案已准备就绪,待训练完成后即可实施。
八、当前方案合理性与后续调整空间
目前的设计方案基于单卡 24GB 显存的硬约束,采用 QLoRA + 两阶段训练是业界成熟且可行的路线。我特别关注了以下几点:
- 数据清洗严格:五步规则剔除了结构异常、长度异常、自评格式错误,确保训练集高信噪比。
- SFT 与 DPO 数据分离:避免数据污染,逻辑清晰。
- 渐进式 DPO:先主数据后风格子集,可观察模型变化,降低不稳定性。
- 显存优化技巧:梯度检查点、paged_adamw_8bit、disable_adapter 等均已纳入计划。
实际训练时,如果遇到显存不足或 loss 异常,我会动态调整 batch size、学习率或 LoRA rank。另外,我注意到 DPO 数据集中可能存在个别 chosen/rejected 质量接近的样本,计划在训练前人工抽检并剔除约 3% 的模糊样本。
九、总结
本文档详细记录了我在灵语星火团队中为口语对话模型微调所做的设计方案。目前项目处于设计阶段,已完成数据接入分析、清洗规则制定、样本构造模板设计、两阶段训练流程规划、超参预设、损失函数设计、质量控制计划和部署方案。所有设计均基于单卡 RTX 4090(24GB)(实际上我们还可能调用 L40显卡)的实际资源约束,并预留了动态调整空间。
以上是我在 LingualSpark 口语对话能力微调任务中的完整设计工作记录。希望这份方案能为算力受限下的共情对话训练提供一份可复用的参考。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)