2、模型加载与单条验证
2.1 在 Chat 页面加载模型
先打开第 31 章的 LLaMA-Factory WebUI,进入 Chat 页。若已经加载过模型,先点“卸载模型”,再填写:
| 页面字段 | 本章填写值 | 作用 |
|---|---|---|
| 模型名称 / 路径 | Qwen3-0.6B-Thinking / Qwen/Qwen3-0.6B | 选择基础模型 |
| 模型下载源 | modelscope | 沿用训练时的模型文件 |
| 微调方法 / 量化等级 | lora / none | 本次加载普通 LoRA,不额外量化 |
| 检查点路径 | keywords-clean | 指向第 31 章训练得到的 Adapter |
| 对话模板 | qwen3_nothink | 按选定规则组织对话 |
| 推理引擎 / 推理数据类型 | huggingface / float16 | 本次聊天使用的引擎与精度设置 |
模型名称中的 Thinking 是页面上的名称,不等于每次都必须开启思考。按第 29 章的约定选好模板,并在聊天区域取消勾选“启用思考模式”。
在 **Chat 页的“额外参数”**中填写:
{ "do_sample": false, "max_new_tokens": 256, "repetition_penalty": 1.0 }do_sample: false 表示关闭随机采样;max_new_tokens 限制最多生成多少个 token;repetition_penalty: 1.0 表示不额外施加重复惩罚。页面下方的最大生成长度也填 256,随机种子填 42,系统提示词留空。
前面第 11 章介绍过温度与生成长度。本次关闭采样后,所用聊天引擎不会用温度和 Top-p 进行随机选词,因此不要只看截图中的温度滑块,就以为本次启用了随机生成。
点“加载模型”,等待“模型已加载,可以开始聊天了”。下面按模型位置、加载状态和生成设置放大显示关键区域,逐项核对:
先核对模型名称、模型路径、检查点与模板。本图已选中 keywords-clean:

再看推理引擎、FP16 精度与加载成功提示:

最后核对“额外参数”,并在下方聊天区域设置最大生成长度 256、随机种子 42,取消勾选“启用思考模式”。系统提示词保持空白:


查看完整加载区截图 · 查看完整聊天设置截图。实际目录名以自己的训练结果为准。
</details>切换两种模型时,按下面的顺序操作:
| 要检查哪一组 | 操作顺序 |
|---|---|
| 原始模型 | 卸载模型 → 清空检查点路径 → 加载模型 |
| 基础模型 + Adapter | 卸载模型 → 选择自己的检查点 → 加载模型 |
只改下拉框还不够,内存中可能仍是上一次加载的模型。每次提交比较输入前,也要点“清空历史”,避免上一轮对话影响本次回答。
2.2 从验证集读取输入与参考答案
先用下方这条验证输入练习。把文章连同“关键词抽取”一起交给模型,参考答案留到回答后再看。先核对回答是否直接给出关键词、是否保留参考答案中的完整名称,再检查有没有漏掉主题。
在本机课程项目根目录打开终端,执行下面的代码。它只读取验证集,不调用模型:
python3 - <<'PY'
import json
from pathlib import Path
path = Path("案例与源码-4-微调/processed/keywords-clean/keywords_validation.jsonl")
sample_number = 1 # 验证集中的第几条,从 1 开始
with path.open(encoding="utf-8") as f:
samples = [json.loads(line) for line in f]
sample = samples[sample_number - 1]
print("【粘贴到 Chat 的完整输入】")
print(sample["conversations"][0]["content"])
print("\n【回答后再对照的参考答案,不粘贴到 Chat】")
print(sample["conversations"][1]["content"])
PY只把第一部分的输入正文粘贴到 Chat,不带打印的提示标题,也不带参考答案。 第 29 章已经说明:推理时让模型根据用户输入生成回答,不能先把参考答案交给它。
后面要换一篇文章时,把 sample_number 改成 2、3 等,再运行一次。当前验证集共 200 条,编号范围是 1~200;本节先查看第 1 条。
当前验证集第一条讨论矿山巷道降温。完整输入如下,复制时保留“关键词抽取”这句任务要求。文中的“工程的的”是原始数据的重复字,此处保留原样,确保对照使用相同输入:
关键词抽取:
金属矿山独头掘进巷道制冷系数是计算独头掘进巷道降温需冷量非常重要的参数之一,关系到能否达到预期降温效果及影响着降温工程的的经济投入。利用“金属矿山深部开采降温试验系统”分别模拟通风降温、加大风量降温、制冷降温、加大制冷降温4种条件下独头掘进巷道的降温过程,并分析独头掘进巷道降温效果,在通风及加大风量降温后,独头掘进巷道内温度先下降然后趋于稳定,再也无法下降,只有通过制冷措施,对独头掘进工作面进行降温。通过监测数据的焓差值计算出降温制冷系数,同时利用多次试验得出制冷系数范围在1.38~1.68,进而为独头掘进巷道降温设计提供设计依据。参考答案是:
独头掘进巷道;降温试验系统;制冷降温;焓差;制冷系数先检查回答是否直接给出关键词列表,再对照原文和标注规则,检查选词是否有依据、名称是否完整。
2.3 原始模型与 Adapter 的回答对照
前面的 Chat 操作用于人工检查回答。要保存可复查的正式对照,我们改用固定配置的命令行预测,第 3 节会带你运行完整测试。这里先阅读课程已保存的验证集前 3 条预测中的第 1 条,即上面的矿山降温文章。
两组都使用同一份 Qwen3-0.6B、qwen3_nothink 模板和生成设置,实际参数精度均为 torch.float16;其中一组加载了当前 keywords-clean 数据训练出的 Adapter。
加载 Adapter 后,得到:
金属矿山;独头掘进;降温试验系统;制冷系数不加载 Adapter 时,原始模型从 <think> 开始输出分析,在本次 256 token 的生成上限内没有给出完整关键词列表,末尾停在一句未写完的话上。
<think>
好的,我现在需要处理用户提供的关于金属矿山独头掘进巷道制冷系数的文本,提取关键词。首先,我得通读一遍这段文字,理解其主要内容和关键点。
用户提到金属矿山独头掘进巷道的制冷系数是重要的参数,关系到降温效果和经济投入。然后他们用“金属矿山深部开采降温试验系统”模拟了四种降温条件:通风、加大风量、制冷和加大制冷,分析降温效果。温度变化过程是先下降后稳定,只有通过制冷才能降温。通过焓差值计算制冷系数,范围在1.38到1.68,为设计提供依据。
接下来,我需要确定哪些是关键词。通常,关键词包括主要术语、研究方法、结果和应用领域等。可能的关键词有:金属矿山、独头掘进巷道、制冷系数、降温试验系统、通风降温、加大风量降温、制冷降温、焓差值、设计依据、经济投入。
还要注意用户可能希望关键词既准确又简洁,可能需要排除一些次要信息。例如,“金属矿山深部开采”可能是一个背景,但作为关键词可能不需要。同样,“降温试验系统”是方法,但下图展示两组完整回答和共同设置。先看回答形式,再对照参考词:

把两组回答与参考答案放在一起看:
| 检查项 | 原始模型 | 加载 Adapter |
|---|---|---|
| 是否直接输出关键词 | 否,达到长度上限时仍在分析 | 是,给出 4 个分号分隔的词 |
| 是否符合目标格式 | 不符合,有分析段落,没有最终列表 | 符合,没有前缀、序号或解释 |
| 与参考答案一致的词 | 尚未形成可供比较的最终关键词列表 | 降温试验系统、制冷系数 |
| 还需检查什么 | 为什么没有在长度上限内完成任务 | 漏掉“制冷降温”“焓差”,将“独头掘进巷道”缩短为“独头掘进” |
这里有个容易忽略的细节:“金属矿山”出现在原文中,只是没有被参考答案收录。 在后面的精确匹配评分中,它算“多出的词”,但不能仅凭这一点就说模型编造了信息。判断它是否值得保留,仍要回到文章主题与选词规则。
这条示例中,Adapter 的回答更接近目标格式,仍有漏词和名称缩短的问题。接下来用更多输入检查这些现象是否普遍。
<details> <summary>示例的比较条件与配套文件</summary>示例 Adapter 用 1,600 条训练数据完成 3 轮、150 步训练,按验证 Loss 选择 checkpoint-150。两组使用同一份基础模型、完整输入和 qwen3_nothink 模板;关闭采样和思考设置,最大生成长度为 256,重复惩罚为 1.0,种子为 42,不加入系统提示词或历史对话。
本节单条验证每批处理 1 条,两组模型参数均为 torch.float16;第 3 节的完整测试每批处理 4 条。比较时不要混用这两种批次设置。
示例中,原始模型在关闭思考设置后仍返回分析文字。第 2.4 节会从实际输入检查原因;这只能说明当前调用条件没有完成目标输出,不能推出其他 Prompt 或思考控制方法也无效。
三条输入的完整验证记录见验证与合并模型对照:
configuration:共同的模板、精度与生成设置。models:原始模型、加载 Adapter、合并模型三种状态及各自实际精度。samples:完整输入、参考答案和三种状态下的原始回答。merge_check:合并模型独立加载及三条回答一致性检查,配合第 5 节阅读。
2.4 从单条观察到批量测试
Chat 适合快速发现明显问题。但看到原始模型格式不对,还需要回答第 28 章留下的问题:把要求说清楚,是否已经能够改善? 可以先做一组小范围验证,再决定是否值得继续训练。
首次阅读先记住三个判断:任务要求要说清;比较微调影响时条件要相同;格式合格还要检查内容。 下方保留了对应的练习与结果,读懂结论后即可进入第 3 节,不必先完成所有实验。
做自己的项目时,再展开第 2.4.1 节实际比较提示词;遇到分析段、重复或回答不完整,再查第 2.4.3 节。
2.4.1 固定输入,比较提示词与模型
先固定一小组验证文章,观察三种提示词:A 使用原有要求,B 写清格式与选词要求,C 在 B 的基础上补一个示例。选好提示词后,让原始模型和加载 Adapter 的模型使用同一版本,才能继续比较微调的影响。
第一步:固定验证输入,只改变提示词。 先按第 2.1 节加载原始模型,检查点路径留空。初次练习可固定使用验证集前 10 条,按第 2.2 节修改 sample_number 依次读取。每条都比较下面三个版本,不能给某个版本单独换更容易的文章:
| 版本 | 交给模型的内容 | 想观察什么 |
|---|---|---|
| A:原始指令 | 第 2.2 节打印的完整用户输入,原样粘贴 | 当前数据里的任务指令能否让模型完成要求 |
| B:明确要求 | 在 A 前加上下面的格式与选词要求 | 说明分隔符、前缀和选词范围后,错误是否减少 |
| C:加入示例 | 在 B 的要求之后、待处理输入之前,增加一组示范 | 看过期望答案的写法后,是否更容易遵守要求 |
B 版本可以这样组织。把最后一行占位说明换成第 2.2 节打印的完整用户输入,保留文章和原有任务指令:
请从下面的输入中抽取能够概括文章主题的关键词。
只输出一行关键词,关键词之间使用英文分号 ; 分隔。
不要输出“关键词:”、序号、解释或分析过程,不要重复关键词。
关键词应有原文依据,保留影响含义的完整名称,不为凑数量拆开短语。
原文同时给出全称和简称时优先使用全称,只有简称时保留简称。
待处理输入:
【替换为第 2.2 节打印的完整用户输入,不粘贴参考答案】C 版本在相同要求与“待处理输入”之间加入下面这段示范,其余内容保持一致。这是第 29 章的教学例子,答案由我们编写,用来展示格式与选词口径,不是模型实测输出:
示例文章:市图书馆周末开设儿童阅读课,读者可通过公众号预约。
示例答案:市图书馆;儿童阅读课;公众号预约准备自己的示例时,可从训练集中选取已审核的记录;不要把正在比较的验证题或测试题及其答案放进提示词。
第二步:保存原始回答,再选提示词。 每次发送前清空历史,沿用第 2.1 节的模板、精度、生成长度等设置。不要手动删掉解释或修正分隔符,按下面的表格记录,每条验证输入各占三行:
| 验证集编号 | 提示词版本 | 模型原始回答 | 格式是否符合要求 | 选词问题 |
|---|---|---|---|---|
| 1 | A / B / C(分别记录) | 粘贴实际回答 | 检查分号、前缀、解释和重复 | 对照原文记录漏词、过度缩写、无依据内容等 |
另外保存 A、B、C 的完整输入文本和共同的生成设置,便于复查。先看 10 条中各有多少条格式合格,再检查选词质量;不要只挑最好的一次回答。若几种方案都不理想,继续在验证集检查问题原因。这里的小样本练习用于筛选方案,不能据此估计正式使用时的成功率。
第三步:固定选定的提示词,再比较 Adapter。 用验证中选定的同一个版本,分别运行原始模型与“基础模型 + Adapter”,输入与生成设置都保持相同。第 31 章已按验证 Loss 选择检查点,核对方法见最佳检查点核对。加载那份已选 Adapter,再结合实际回答判断;Loss 较低并不保证每条关键词都更好。
2.4.2 怎样理解这组对照结果
下面使用验证集第 1~10 条:原始模型分别采用 A、B、C 提示词,Adapter 使用 B。四组各 10 条,均为 FP16、每批 1 条,其他生成设置相同。
| 比较组 | 格式合格条数 | 逐条阅读后的发现 |
|---|---|---|
| 原始模型 + A | 0/10 | 回答含分析段,没有交付合格列表 |
| 原始模型 + B | 0/10 | 加上明确要求后仍含分析段,部分回答还有英文改写或无依据内容 |
| 原始模型 + C | 0/10 | 加入示例仍未解决格式问题;部分分析把示例的三个词当成数量提示 |
| Adapter + B | 7/10 | 更常直接输出列表,但仍有重复、漏词、拆词和无依据词 |
B 用于固定清楚的任务要求,不表示它效果最好。 三种提示词下的原始模型都没有通过格式检查;B 不额外加入示例,适合用来继续观察模板与 Adapter 的影响。
怎样理解 Adapter 的 7/10?看第 6 条的真实回答就知道了。原文写的是用 F58050 为母本、Bakeking 为父本育成“夏波蒂”,Adapter 返回:
F58050;Bakeking;F68050它符合一行、英文分号、无重复等形式规则,但 F68050 没有原文依据,还漏掉了品种名“夏波蒂”。另外,第 3、7、8 条分别重复输出英文片段,也没有成为合格列表。因此,7/10 不能当作“七条内容完全正确”,更不能当作业务准确率。
参考答案也要审核。 第 4 条原文是“万安县”,参考词却是“安县”。这类问题会影响按参考答案计算的分数,审核方法见第 29 章的标注规则与三个示例。评价模型时区分参考命中与内容正确;修订参考答案后,应按同一套新标准重新评估所有比较组。
完整文章、参考答案及 40 份回答见提示词对照示例。提示词与模板示例的原始文件位置、比较设置和本机复算方法见示例说明。
2.4.3 检查模板与生成停止条件
第 29 章讲过,模板决定模型实际收到的输入。课程的小样本对照中,换一种输入包装减少了分析段,但漏词和重复仍在;这说明思考控制、格式和选词质量需要分别检查。
另一个要点是:达到生成长度上限,只表示不能继续生成,不表示任务已经完成。先保存原始回答和停止原因,再检查输入与设置。下面给出具体实验和排查方法,首次阅读无需记住 token 标记。
<details> <summary>遇到分析段或重复时:查看模板实验与停止条件</summary>为什么取消勾选后,原始模型仍在分析? 第 29 章讲过,模型收到的是模板整理后的输入。在课程固定的 LLaMA-Factory 版本中,qwen3_nothink 不在输入末尾加入空思考区块;qwen3 配合 enable_thinking: false 则会加入。可以把这个区块理解为:在模型开始回答的位置,先写好“思考区已经结束”的标记。设置名称相似,真正送给模型的内容却不同。
下面固定 B 提示词,选取验证集第 1、6、8 条,分别观察普通输出、无依据词和重复输出。每组 3 条,共 12 条回答;基础模型、Adapter、FP16 精度及其他生成设置保持不变,只比较模板的影响:
| 比较组 | 模板 | 含分析段 | 格式合格 |
|---|---|---|---|
| 原始模型 | qwen3_nothink | 3/3 | 0/3 |
| 原始模型 | qwen3 | 0/3 | 2/3 |
| Adapter | qwen3_nothink | 0/3 | 2/3 |
| Adapter | qwen3 | 0/3 | 2/3 |
四组配置都写着 enable_thinking: false。原始模型换用带空思考区块的输入后,这 3 条回答不再出现分析段,但关键词质量仍未过关:第 6 条只返回 F58050;Bakeking,漏掉主题品种“夏波蒂”;第 8 条仍重复输出英文词。Adapter 的第 6 条依然包含无依据词 F68050,第 8 条的重复也没有消失。
这个小样本对照展示了输入包装对分析段的影响,但不能证明“换模板就解决了关键词抽取”或“微调优于充分优化的原始模型”。思考控制、回答格式和选词质量,要分别检查。
<details> <summary>选读:实际输入中多出了什么</summary>在课程固定的源码版本中,qwen3_nothink 使用普通 Template;qwen3 使用 ReasoningTemplate,后者会处理关闭思考时的空区块。仅凭名称或开关状态,不能替代实际输入检查。
查看两种模板的文本和 token 编号时,用户消息相同,qwen3 在助手起始标记后多出 <think>\n\n</think>\n\n,在示例分词器中对应 4 个 token;其中 \n 表示换行。这与官方关闭思考模板的输入一致。推理输入只包含用户消息和回答起点,参考答案另存用于评估。
四组共同设置为 FP16、每批 1 条、关闭采样、生成上限 256、重复惩罚 1.0、种子 42。阅读预测文件时,先确认实际输入符合所选模板,再评价模型回答。
完整回答见模板对照示例。这里改变的是推理模板,使用的是同一个按 qwen3_nothink 训练的 Adapter,因此不能把它理解为两种训练模板的效果比较。
模型停下来了,是否表示答案写完了? 还要检查它为什么停止。max_new_tokens: 256 只是本次最多允许生成的 token 数;模型可能提前生成指定的结束标记,也可能一直写到上限。它不会因为设置了 256,就自动知道应该交付几个关键词。
把第 29 章的消息边界与本章生成设置放在一起看:
| 标记或设置 | 表示什么 | 不能据此认定什么 |
|---|---|---|
</think> | 思考区结束,后面还可以生成最终答案 | 不能当作整个回答结束 |
| EOS / 配置的停止 token | 推理程序识别到指定 token 时,可以终止生成;具体编号须与模型、模板和引擎匹配 | 生成正常结束,也不保证内容正确 |
max_new_tokens | 最多生成多少个新 token,不包含输入 token | 不是期望关键词数量,也不是必须写满的长度 |
接口返回 finish_reason: length | 触及长度限制;第 6.3 节的实测达到了请求的生成上限 | 不能证明是结束标记配置错误,也不能证明答案已经完整 |
例如,市图书馆;儿童阅读课;公众号预约 后结束,可以是一份完整答案;反复写 book;book;book 直到上限,则需要排查。提高上限可能只是让重复持续更久;重复惩罚也可能影响选词,不能直接当作修复内容的开关。
先保存完整回答与停止原因,再按顺序检查:实际输入是否正确 → 模板与引擎的停止 token 是否匹配 → 训练答案及结束位置是否被截断 → 生成设置是否合适。 查看解码文本时,结束标记可能已被工具隐藏,必要时连同原始 token 编号核对,不能仅凭页面看不到标记就认定模型没生成它。模板与 EOS 的关系可参考 TRL 的说明,课程中的具体值仍以固定版本的实际输入和配置为准。
空思考区块解释了输入包装的差异,不能单凭这一点解释重复输出。遇到重复时,仍需按上述顺序检查,不把某个设置当作通用修复方法。
</details> </details>进入批量测试前,确认你在做哪一组实验。 下表用于查找结果,不要求重新跑完三组:
| 对照范围 | 主要检查什么 | 结果用于哪里 |
|---|---|---|
| 10 条验证输入:A/B/C 提示词与 Adapter | 提示词与模型对格式、选词的影响 | 小范围排查与方案选择 |
| 3 条验证输入:模板与模型组合 | 输入包装改变后,分析段和关键词是否变化 | 定位模板影响,不能估计整体成功率 |
| 第 3~4 节的 200 条测试输入 | 原始指令、qwen3_nothink 下两组模型的批量表现 | 复算本轮既定条件的评估结果 |
下面先复算固定条件的课程实验,学习完整评估方法。 提示词或模板变了,就另存为新实验;课程这组结果尚不能证明微调优于充分优化后的原始模型。自己的项目仍按“验证集选方案 → 冻结设置 → 独立测试”执行。