领域模型微调 指令 & 数据输入格式 要求
1️⃣ 考察意图
这道题看似基础,但面试官真正想看的不是你会背“指令、输入、输出”三个字段,而是你能否讲清楚格式设计的工程取舍和数据质量对微调效果的直接影响。考察类型是“背概念 + 工程取舍”。刁钻点在于:很多人只记得 Alpaca 格式,却不知道为什么需要系统提示、多轮对话分隔符怎么选、长度截断策略如何影响训练。答好了能展示你对 SFT 全流程的掌控力,包括数据清洗、模板设计、多轮对话处理、以及 token 效率优化。
2️⃣ 标准答
指令微调的数据格式,核心是让模型学会“遵循指令”的范式,而不是死记硬背。我从三个层面拆解:字段设计、模板规范、质量要求。
1. 字段设计:最少 2 个,推荐 4 个
- instruction(指令):必须字段,描述任务意图。例如“翻译以下句子为英文”。
- input(输入):可选字段,承载指令的上下文。例如“今天天气真好”。注意:如果指令本身已包含完整上下文(如“写一首关于秋天的诗”),input 可留空。
- output(输出):必须字段,期望的模型回答。
- system(系统提示):推荐字段,设定模型角色或行为边界。例如“你是一个友好的助手”。工程取舍:system 字段会占用 token 预算,但能明显提升角色一致性。实践中,如果数据量小(<1k 条),建议统一 system 内容;数据量大时,可让每条数据携带不同 system,增强泛化性。
- history(历史对话):多轮场景必须,格式为
[{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]。
2. 模板规范:统一且可解析
- 单轮对话:推荐 Alpaca 格式的变体,用特殊标记分隔字段,避免自然语言歧义。
`### Instruction:**{instruction}
Input:
{input}
Response:
{output}
为什么这么做**:用 ###和换行符作为分隔,比用冒号或空格更鲁棒,因为模型输出中可能包含冒号。**实际落地的坑**:如果 input 为空,必须显式写### Input:\n` 或直接省略该行,否则模型会误以为 input 是 instruction 的一部分。我踩过这个坑,导致模型在无输入场景下胡编乱造。
- 多轮对话:使用角色标记,如
<|user|>和<|assistant|>,并在每轮末尾加<|end|>或</s>作为终止符。
<|user|> 今天天气如何?**<|assistant|> 今天晴,25度。 <|user|> 适合跑步吗? <|assistant|> 适合,但建议傍晚。 工程取舍**:角色标记的选择影响 tokenizer 的效率。用 <|user|> 这种多 token 标记,比用 [USER] 更易被 tokenizer 识别为单个 token(如果已加入词表),但需要额外训练 tokenizer。如果复用现有 tokenizer,建议用 [USER] 这种单 token 标记,减少 token 浪费。
3. 质量要求:数据决定上限
- 指令明确性:指令不能模糊。例如“写一段话”是坏指令,“写一段 100 字的产品介绍,突出续航和防水”是好指令。
- 输出正确性:输出必须与指令对齐。例如指令是“翻译”,输出不能是“总结”。实际落地的坑:开源数据集(如 Dolly)中常有指令和输出不匹配的噪声,必须人工抽检或写规则过滤。我遇到过 ShareGPT 数据中用户指令是“解释量子计算”,但助手回答是“我不懂”,这种数据必须剔除。
- 长度控制:确保
instruction + input + output + system + history的总 token 数不超过模型最大长度(如 2048)。策略:优先截断 history 的早期轮次,保留最新对话;如果单轮数据超长,截断 output 的尾部(因为模型训练时 loss 只计算 output 部分,截断 input 不影响学习)。 - 无偏见和有害内容:用关键词过滤或模型分类器清洗。例如过滤包含“暴力”、“歧视”等词的样本。
总结:格式是骨架,质量是血肉。一个统一的模板(如 Alpaca 变体)加上严格的字段校验和长度控制,能避免 80% 的训练异常。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从字段设计、模板规范、质量要求三个层面回答。字段层面,最少需要 instruction 和 output,推荐加上 system 和 history;模板层面,单轮用 Alpaca 格式的
###分隔,多轮用角色标记如<|user|>;质量层面,指令要明确、输出要对齐、长度要截断、有害内容要过滤。总结一句:格式统一是基础,数据质量决定微调效果的上限。”
4️⃣ 高频追问 & 应对
追问 1:如果指令和输入字段合并成一个,会有什么问题?
合并后,模型无法区分“任务描述”和“任务上下文”,导致泛化性下降。例如,指令“翻译以下句子:今天天气真好”和“写一首诗:今天天气真好”会被模型视为同一模式,但实际任务不同。应对:坚持分开字段,除非数据量极大(>100k 条)且任务单一(如纯翻译),此时合并可节省 token。工程上,用
### Instruction:和### Input:分隔,比自然语言分隔更鲁棒。
追问 2:多轮对话中,history 字段的 token 长度如何控制?如果用户历史很长,怎么处理?
策略是“保留最近、丢弃最早”。设定最大历史轮次(如 5 轮),或按 token 数截断(如保留最后 1024 token)。工程取舍:丢弃早期轮次可能丢失上下文,但保留所有轮次会超出长度限制。实践中,如果任务依赖早期信息(如客服对话),用滑动窗口保留关键轮次;否则直接截断。具体方法:在数据预处理时,对每条数据计算 history 的 token 数,如果超限,从最旧轮次开始删除,直到满足要求。
追问 3:你提到用 ### 作为分隔符,但如果模型输出中恰好包含 ### 怎么办?
这是一个经典坑。解法:在数据预处理时,对 output 字段中的
###进行转义(如替换为[HASH]),或在模板中使用更罕见的分隔符,如<|sep|>。工程取舍:转义会增加预处理复杂度,但能避免解析错误;使用罕见分隔符则需确保 tokenizer 能正确处理。实践中,我倾向于用<|sep|>这种多 token 标记,因为模型输出中几乎不会出现。
5️⃣ 避坑 · 常见错误答法
- ❌ 说“格式不重要,模型能学会” → ✅ 正确切入:格式影响数据质量和训练效率,错误格式会导致模型学偏或训练崩溃。
- ❌ 说“直接用 Alpaca 格式就行,不用改” → ✅ 正确切入:Alpaca 格式是基础,但需要根据任务调整(如加入 system、处理多轮),并做长度截断和字段校验。
- ❌ 说“多轮对话用自然语言拼接就行” → ✅ 正确切入:自然语言拼接会导致模型无法区分角色,必须用特殊标记(如
<|user|>)分隔。
6️⃣ 简历呼应
- 如果你有 RAG 项目:从“数据格式对检索增强微调的影响”切入,强调指令中需要包含检索到的上下文,格式上如何拼接 query 和 context。
- 如果你只做过传统 NLP:用“序列标注任务的 BIO 格式”类比,说明指令微调格式也是“输入-输出”的序列化,只是多了角色和分隔符。
- 如果你是校招无项目:聚焦“Alpaca 格式的复现和优化”,展示你写过脚本将 ShareGPT 数据转换为统一格式,并验证了长度截断策略。
- Alpaca: A Strong, Replicable Instruction-Following Model(原始论文)
- ShareGPT 数据格式规范(多轮对话模板)
- LLaMA-Factory 数据预处理文档(字段定义和模板配置)
- 《Instruction Tuning with GPT-4》论文(数据质量评估方法)
- Hugging Face
datasets库的map函数(数据格式转换工具)