mirror of
https://github.com/hiyouga/LLaMA-Factory.git
synced 2026-09-27 01:45:42 +08:00
[v1] update docs (#10684)
This commit is contained in:
47
docs/zh/developer-guide/core/base_sampler.md
Normal file
47
docs/zh/developer-guide/core/base_sampler.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# BaseSampler
|
||||
|
||||
`BaseSampler` 位于 `core/base_sampler.py`,为推理调用方提供生成接口,并持有具体的推理 engine。模型和 Renderer 由 [ModelEngine](model_engine.md) 创建后传入;Sampler 负责选择后端和转发调用。
|
||||
|
||||
## 组件与状态
|
||||
|
||||
| 组件 | 职责 | 源码 |
|
||||
|------|------|------|
|
||||
| BaseSampler | 根据 `sample_backend` 选择 engine,转发生成请求 | `core/base_sampler.py` |
|
||||
| BaseEngine / HuggingFaceEngine | 定义后端接口,使用模型和 Renderer 执行生成 | `core/utils/inference_engine.py` |
|
||||
| SyncSampler | 将异步生成接口适配为 CLI 使用的同步迭代器 | `samplers/cli_sampler.py` |
|
||||
| `run_chat` | 创建组件,读取用户输入,保存对话历史并输出回复 | `samplers/cli_sampler.py` |
|
||||
|
||||
当前 BaseSampler 直接构造 HuggingFaceEngine,后端选择不经过 BasePlugin 注册表。HuggingFaceEngine 保存模型、Renderer 和推理参数;对话历史由 `run_chat` 中的消息列表持有,每次请求传入完整历史。
|
||||
|
||||
## 单次生成路径
|
||||
|
||||
```text
|
||||
run_chat:追加 user 消息
|
||||
→ SyncSampler.generate(messages)
|
||||
→ BaseSampler.generate(messages, tools)
|
||||
→ HuggingFaceEngine.generate(messages, tools)
|
||||
→ Renderer.render_messages(..., is_generate=True)
|
||||
→ input_ids / attention_mask 转为设备上的张量
|
||||
→ 后台线程调用 model.generate
|
||||
→ AsyncTextIteratorStreamer 异步返回文本片段
|
||||
→ CLI 逐段输出,拼成 assistant 消息并加入历史
|
||||
```
|
||||
|
||||
HuggingFaceEngine 用信号量限制同时进入生成过程的请求数。它将 `max_new_tokens` 和 streamer 传给 `model.generate`,streamer 跳过 prompt 和特殊 token;返回值是解码后的文本片段,不是 token ID,也不保证每个片段恰好对应一个 token。
|
||||
|
||||
SyncSampler 另行维护后台事件循环,逐次等待异步生成器的下一段文本,再交给同步调用方。这个适配层改变调用方式,不改变消息渲染或模型生成逻辑。
|
||||
|
||||
## 接口与当前支持范围
|
||||
|
||||
| 接口 | 输入与输出 | 当前行为 |
|
||||
|------|------------|----------|
|
||||
| `generate(messages, tools=None)` | 标准 Message 列表、可选 tools 字符串;异步产出 `str` | Hugging Face 流式生成 |
|
||||
| `batch_infer(dataset)` | Dataset;约定返回 Sample 列表 | HuggingFaceEngine 抛出 `NotImplementedError` |
|
||||
|
||||
BaseSampler 的非 HF 后端分支会抛出 `ValueError`。CLI 中设置 `train_dataset` 会进入批量推理分支,但当前 engine 尚未实现该接口。因此,已实现的用户路径是 HF 交互式对话,启动方式见[推理](../../feature-guide/inference.md),配置字段见[推理参数](../../configuration/inference.md)。
|
||||
|
||||
## 扩展边界
|
||||
|
||||
新增推理后端时,实现 `BaseEngine` 的接口,并接入 BaseSampler 的后端选择;仅添加文件或写入新的 `sample_backend` 名称不会完成接入。后端需要保持异步文本流接口,并明确批量推理是否可用,SyncSampler 才能沿用现有适配方式。
|
||||
|
||||
改变模板和消息到模型输入的转换时,修改 [Renderer](renderer.md);改变生成参数的传递、模型调用或输出流时,修改 engine;改变命令行输入和对话历史管理时,修改 `run_chat`。当前 HF 生成调用只传递 Renderer 结果中的 `input_ids` 和 `attention_mask`,扩展其他模型输入时还需要补齐 engine 向模型传参的路径。
|
||||
50
docs/zh/developer-guide/core/base_trainer.md
Normal file
50
docs/zh/developer-guide/core/base_trainer.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# BaseTrainer
|
||||
|
||||
`BaseTrainer` 提供 SFT、DPO 和 RM 共用的训练生命周期。子类主要实现 `compute_loss`,必要时覆盖模型分片或输入处理。
|
||||
|
||||
实现位于 `core/base_trainer.py`。任务入口负责加载模型与数据,再把它们传入 Trainer;BaseTrainer 从这些对象开始组织批次生成、优化器更新和训练状态。这样,各训练目标可以共用同一套运行循环。
|
||||
|
||||
## 初始化训练组件
|
||||
|
||||
先保存参数、模型、Renderer 与数据集,创建 BatchGenerator,再确定训练总步数和 checkpoint 间隔。后续组件的创建顺序取决于后端:
|
||||
|
||||
- FSDP2 / FSDPTurbo 先分片模型,再基于处理后的参数创建 optimizer 和 scheduler;没有显式分布式后端时,使用普通模型或 DDP。
|
||||
- DeepSpeed 先构造后端 engine,再创建 optimizer 和 scheduler,最后由 engine 的 `prepare` 统一准备训练对象。
|
||||
|
||||
模型和优化器就绪后,`TrainingCheckpointCoordinator` 才能恢复它们的状态以及批次进度。之后创建 CallbackHandler 和 TrainerState,并把已恢复的 step、epoch 同步给回调状态。CP 模型处理在初始化的最后阶段接入。
|
||||
|
||||
## 训练循环
|
||||
|
||||
```text
|
||||
epoch / global step
|
||||
→ BatchGenerator
|
||||
→ forward + compute_loss
|
||||
→ gradient accumulation
|
||||
→ gradient clipping
|
||||
→ optimizer.step
|
||||
→ scheduler.step
|
||||
→ callback / logging
|
||||
→ 可选 checkpoint
|
||||
```
|
||||
|
||||
`global_batch_size / (dp_size × micro_batch_size)` 决定梯度累积所需的 micro-batch 数。
|
||||
|
||||
BatchGenerator 每次迭代返回一组 micro-batch,对应一次更新步。普通路径对每个 micro-batch 调用 `compute_loss` 并反向传播,累积完成后执行梯度裁剪、参数更新和清零。`compute_loss` 返回标量损失,BaseTrainer 还会根据有效监督 token 数和 DP 规模缩放损失,因此子类不应自行重复执行参数更新。
|
||||
|
||||
DeepSpeed 路径把反向传播和同步边界交给后端 engine;SFT 开启 CP 时,循环改为调用 SequenceParallelLossPlugin。扩展损失时需要同时考虑目标任务是否支持这两条路径。
|
||||
|
||||
## 训练器实现
|
||||
|
||||
- `SFTTrainer`:带 `loss_weights` 的语言模型损失
|
||||
- `DPOTrainer`:policy/reference 偏好损失
|
||||
- `RMTrainer`:chosen/rejected reward 排序损失
|
||||
|
||||
## 保存模型与 Checkpoint
|
||||
|
||||
训练循环在保存 step 调用 `core/utils/checkpoint.py` 中的 TrainingCheckpointCoordinator。它协调模型、优化器、scheduler、批次进度与训练计数等状态;其中依赖分片格式的模型和优化器读写交给 DistributedPlugin。这样,训练器决定何时保存,后端决定如何保存其分布式状态。
|
||||
|
||||
`fit()` 结束后,任务入口另外调用 `save_model()` 保存最终模型。最终模型与用于续训的 checkpoint 用途不同,用户配置见[模型保存与恢复](../../feature-guide/model_saving.md)。
|
||||
|
||||
## 扩展边界
|
||||
|
||||
新增训练目标时,在 Trainer 子类中实现损失和必要的任务准备。替换优化器、批处理或分布式实现时使用[训练器插件](../plugins/trainer_plugins.md),避免在每个任务的训练循环中复制后端分支。只观察生命周期事件时使用 [Callback](callback.md)。
|
||||
45
docs/zh/developer-guide/core/batch_generator.md
Normal file
45
docs/zh/developer-guide/core/batch_generator.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# BatchGenerator
|
||||
|
||||
`core/utils/batching.py` 负责 sampler、DataLoader、collate、梯度累积批次和状态恢复;`trainer_plugins/batching.py` 提供非 normal 策略。
|
||||
|
||||
## 输入、输出与状态
|
||||
|
||||
BatchGenerator 接收 DataEngine、Renderer 和批处理参数。内部的 StatefulDataLoader 按 DP 维度分配样本,并用 `Renderer.process_samples` 把读出的消息转换为 ModelInput 列表。此时还没有完成训练 batch 的组装。
|
||||
|
||||
这些 ModelInput 进入 StatefulBuffer,再由选定策略取出、截断并组织为 BatchInput。`__next__()` 返回的是一个更新步所需的 micro-batch 列表,BaseTrainer 逐个计算损失和累积梯度。
|
||||
|
||||
```text
|
||||
DataEngine + StatefulDistributedSampler
|
||||
→ StatefulDataLoader(Renderer.process_samples)
|
||||
→ StatefulBuffer
|
||||
→ normal collate 或 BatchingPlugin.generate_batch
|
||||
→ list[BatchInput]
|
||||
```
|
||||
|
||||
BatchGenerator 持有 DataLoader、迭代器和缓冲区;策略插件接收缓冲区和 `batch_info`,决定如何填充与取样。读取进度因此不保存在插件注册表中。
|
||||
|
||||
## Normal Batching
|
||||
|
||||
固定取 `micro_batch_size` 个样本,Renderer 处理后按当前 batch 最长序列 padding。
|
||||
|
||||
## Padding-Free Batching
|
||||
|
||||
`BatchingPlugin("padding_free")` 将多个样本拼成无 padding 的序列,并维护能够隔离文档的 attention/position 信息。
|
||||
|
||||
## Dynamic Batching
|
||||
|
||||
动态策略根据样本 token 数决定每个 batch 包含多少样本。纯 `dynamic_batching` 仍执行 padding;`dynamic_padding_free` 同时拼接序列。
|
||||
|
||||
## 保存批次状态
|
||||
|
||||
`state_dict()` 同时保存 DataLoader 的读取状态与 buffer 中已读取、尚未消费的样本。只恢复前者会丢掉预读样本,只恢复后者则无法确定接下来应该读哪里。
|
||||
|
||||
`load_state_dict()` 恢复两部分状态并设置 `_is_resuming`。普通 `__iter__()` 会清空 buffer;恢复后的首次迭代保留 buffer,随后清除恢复标记。新增策略必须保持这个状态约定,不能将剩余样本藏在无法随 checkpoint 保存的全局变量中。
|
||||
|
||||
## 校验动态批处理参数
|
||||
|
||||
纯 `dynamic_batching` 需要正数 `max_steps` 且不能使用 `save_epochs`,这些条件在 `TrainingArguments.__post_init__` 中校验。多模态输入是否能由当前策略处理,则在 BatchGenerator 生成 batch 时检查。配置条件与使用选择见[批处理策略](../../feature-guide/batching.md)。
|
||||
|
||||
## 扩展边界
|
||||
|
||||
改变 token 预算或样本拼接方式时实现 BatchingPlugin 的方法组,接口见[训练器插件](../plugins/trainer_plugins.md#batchingplugin)。改变消息如何变成 token 时修改 Renderer,改变反向传播和更新边界时检查 BaseTrainer。
|
||||
39
docs/zh/developer-guide/core/callback.md
Normal file
39
docs/zh/developer-guide/core/callback.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Callback
|
||||
|
||||
Callback 系统位于 `utils/callbacks/`,用于把日志和生命周期通知从训练循环中分离。
|
||||
|
||||
## Callback 组件
|
||||
|
||||
- `TrainerCallback`:事件接口
|
||||
- `CallbackHandler`:按注册顺序广播事件
|
||||
- `LoggingCallback`:输出 loss、learning rate、grad norm 等指标
|
||||
|
||||
## 事件如何传递
|
||||
|
||||
BaseTrainer 创建 CallbackHandler,并先加入默认 LoggingCallback,再加入构造参数 `callbacks` 中的实例。训练循环在固定位置调用 handler;handler 按列表顺序同步调用每个实例的同名方法,不经过 BasePlugin 注册表。
|
||||
|
||||
```text
|
||||
on_train_begin
|
||||
→ on_epoch_begin
|
||||
→ on_step_begin
|
||||
→ 前向、反向与更新
|
||||
→ on_step_end
|
||||
→ on_log(到达 logging_steps 时)
|
||||
→ on_save(checkpoint 写入后)
|
||||
→ on_epoch_end
|
||||
on_train_end
|
||||
```
|
||||
|
||||
事件位置由 Trainer 和 checkpoint 协调器决定。Callback 无需自行判断什么时候保存模型或推进优化器,只响应已经发生的生命周期事件。
|
||||
|
||||
## Callback 能读取什么
|
||||
|
||||
每个事件接收训练参数 `args`、进度对象 `state` 和额外关键字参数。TrainerState 保存 step、epoch、最近一次损失、梯度范数和学习率等;Handler 还通过关键字参数传入当前 model、optimizer、lr_scheduler 和批次生成器。
|
||||
|
||||
在 `on_step_begin` 时,本步计算尚未发生,损失等指标仍来自此前的更新;本步指标在 `on_step_end` 前写入 state。`on_log` 额外接收本次日志字典。
|
||||
|
||||
## 扩展边界
|
||||
|
||||
自定义 Callback 继承 TrainerCallback,仅覆盖关心的事件,并将实例传给 Trainer 的 `callbacks` 参数。它适合记录指标、连接外部观察工具等附加行为。需要改变损失、更新规则或 checkpoint 格式时,使用 Trainer 或对应插件。
|
||||
|
||||
接口约定将 state 作为供观察的进度信息,不通过修改它来控制训练流程;代码没有把这个 dataclass 冻结。事件也不会统一限制到 rank 0,涉及单次输出的 Callback 需要自行判断 rank,默认 LoggingCallback 就在自身内部处理这个条件。
|
||||
39
docs/zh/developer-guide/core/data_engine.md
Normal file
39
docs/zh/developer-guide/core/data_engine.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# DataEngine
|
||||
|
||||
`DataEngine(dataset_path: str)` 位于 `core/data_engine.py`,把一个或多个原始数据集暴露为可按整数索引访问的统一 Dataset。它处理数据来源、字段转换和样本索引,返回的仍是消息结构;分词和监督标签由后续 [Renderer](renderer.md)生成。
|
||||
|
||||
## 加载数据集
|
||||
|
||||
```text
|
||||
dataset_path
|
||||
→ 识别 YAML、目录、数据文件或 Hub ID
|
||||
→ 生成 dataset name → DatasetInfo 映射
|
||||
→ hf_hub 直接加载,其他 source 调用 DataLoaderPlugin.load
|
||||
→ 逐条转换样本,确定 SFT 的受监督轮次
|
||||
→ 建立 (dataset_name, sample_index, cut) 全局索引
|
||||
→ 根据 size / weight 调整索引
|
||||
```
|
||||
|
||||
初始化时,`datasets` 保存各来源加载出的 Dataset,`dataset_infos` 保存来源配置,`data_index` 保存训练样本到原始行的映射。索引项中的 `cut` 表示取消息列表的哪个前缀;它不是 token 截断长度。
|
||||
|
||||
多轮 SFT 的每个受监督 assistant turn 对应一个索引项,多个索引项可以指向同一条原始对话。DPO 等非 SFT 样本保持完整,`cut` 为 `None`。这一设计让 sampler 能按训练样本分配索引,同时保留原始数据集。
|
||||
|
||||
## 读取一个样本
|
||||
|
||||
`__getitem__` 从全局索引取出数据集名称、原始行号和 `cut`,再由 `_get` 读取原始行、调用 converter,并按 `cut` 截取消息前缀。返回样本带有 `_dataset_name`,供后续处理识别来源。
|
||||
|
||||
Converter 既会在初始化建立索引时调用,也会在实际取样时调用;DataEngine 不把索引阶段的转换结果缓存为新的数据集。因此转换函数应对相同输入产生一致的消息结构,避免依赖调用次数或在转换中改变原始行,否则索引记录的轮次可能与训练读取的内容不一致。
|
||||
|
||||
## 解析 DatasetInfo
|
||||
|
||||
字段结构定义在 `utils/types.py`。`_get_dataset_info` 将路径、Hub ID 或 YAML 统一成名称到 DatasetInfo 的映射,后续加载逻辑只处理这个映射。字段与默认值见[数据参数](../../configuration/data.md#datasetinfo)。
|
||||
|
||||
## 处理 Streaming Dataset
|
||||
|
||||
所有数据集必须同时为 map-style 或同时为 streaming。混合模式无法共享同一种索引和 sampler 语义,因此 DataEngine 初始化阶段会拒绝。当前 BatchGenerator 只支持 map-style dataset;streaming dataset 进入批处理初始化时会抛出 `NotImplementedError`。
|
||||
|
||||
## 扩展数据源与格式
|
||||
|
||||
加载新来源时,扩展 `DataLoaderPlugin`,保持返回 Dataset 的约定;只改变原始字段的含义时,扩展 `DataConverterPlugin`,保持返回标准 Sample 的约定。两种接口及其调用参数见[数据插件](../plugins/data_plugins.md)。
|
||||
|
||||
多轮展开和全局索引属于 DataEngine,共用索引行为应在此处理。模型模板、tokenization 和 padding 分别属于 Renderer 与 BatchGenerator,不放入 loader 或 converter。用户用法见[数据准备](../../feature-guide/data_preparation.md)。
|
||||
26
docs/zh/developer-guide/core/index.md
Normal file
26
docs/zh/developer-guide/core/index.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Core(核心模块)
|
||||
|
||||
Core 负责连接配置、数据、模型和训练流程。各组件由 Trainer 或 Sampler 组合,不通过插件注册表选择。
|
||||
|
||||
| 组件 | 职责 | 源码 |
|
||||
|------|------|------|
|
||||
| [DataEngine](data_engine.md) | 加载、转换和索引数据集 | `core/data_engine.py` |
|
||||
| [ModelEngine](model_engine.md) | 加载 Processor、Renderer 和模型 | `core/model_engine.py` |
|
||||
| [Renderer](renderer.md) | 将 Messages 转换为模型输入 | `core/rendering/` |
|
||||
| [BaseTrainer](base_trainer.md) | 管理通用训练生命周期 | `core/base_trainer.py` |
|
||||
| [BaseSampler](base_sampler.md) | 选择推理后端并连接生成接口 | `core/base_sampler.py` |
|
||||
| [BatchGenerator](batch_generator.md) | 生成批次并恢复批次状态 | `core/utils/batching.py` |
|
||||
| [Callback](callback.md) | 分发训练生命周期事件 | `utils/callbacks/` |
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
data_engine
|
||||
model_engine
|
||||
renderer
|
||||
base_trainer
|
||||
base_sampler
|
||||
batch_generator
|
||||
callback
|
||||
```
|
||||
46
docs/zh/developer-guide/core/model_engine.md
Normal file
46
docs/zh/developer-guide/core/model_engine.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# ModelEngine
|
||||
|
||||
`ModelEngine(model_args, is_train=False)` 拥有 processor、model config、Renderer 和最终 Hugging Face model。
|
||||
|
||||
实现位于 `core/model_engine.py`。它把同一份模型配置转为相互匹配的模型与输入处理组件;任务入口随后把 `model` 和 `renderer` 交给 Trainer 或 Sampler。训练循环、优化器创建和常规分布式分片在后续组件中完成。
|
||||
|
||||
## 模型加载流程
|
||||
|
||||
```text
|
||||
AutoProcessor.from_pretrained
|
||||
→ 同步或覆盖 chat_template
|
||||
→ AutoConfig.from_pretrained
|
||||
→ Renderer(processor)
|
||||
→ 选择初始化设备
|
||||
→ 应用量化加载参数
|
||||
→ 选择 AutoModel 类
|
||||
→ from_pretrained / from_config
|
||||
→ PEFT
|
||||
→ Kernel
|
||||
```
|
||||
|
||||
这个顺序由 ModelEngine 固定:初始化插件先决定在哪里创建模型,量化插件再补充权重加载参数;模型对象创建后,PEFT 决定可训练部分或加载 adapter,Kernel 最后处理实际得到的模型。插件之间不互相调度,后一阶段接收前一阶段的结果。
|
||||
|
||||
`is_train` 会传给量化和 PEFT 路径,并影响未启用 PEFT 时的模型精度处理。它表达本次加载的用途,训练循环仍会在 `fit()` 中设置模型的训练模式。
|
||||
|
||||
## 同步 Chat Template
|
||||
|
||||
多模态 processor 没有模板时,会从其 tokenizer 同步。`custom_chat_template` 则覆盖 processor/tokenizer 模板。Renderer 最终调用 `apply_chat_template`,不再导入模型专属 Python 模板。
|
||||
|
||||
## 选择 Hugging Face 模型类
|
||||
|
||||
- `llm`:根据模型 config 选择 image-to-text、多模态语言模型或因果语言模型类;多模态语言模型类仅在当前 Transformers 提供时参与选择
|
||||
- `cls`:单标签 token classification 模型,RM 使用
|
||||
- `other`:`AutoModel`
|
||||
|
||||
## Meta 与 ZeRO-3 初始化
|
||||
|
||||
普通路径通过 `from_pretrained` 加载权重。选择 meta device 后,ModelEngine 使用 `init_empty_weights()` 和 `from_config` 构造模型结构,此时参数没有真实数据,需要后续分布式加载路径填充。`init_on_rank0` 则让 rank 0 在 CPU 加载,其余 rank 构造 meta 模型。
|
||||
|
||||
Meta 初始化不能与量化同时使用;当前 LoRA 路径也会拒绝 `init_on_meta`。这些检查发生在模型加载阶段,不能通过调整 YAML 中字段的书写顺序绕过。
|
||||
|
||||
DeepSpeed ZeRO-3 需要在 `from_pretrained` 创建参数时介入,因此 ModelEngine 在加载前建立 ZeRO-3 上下文,并在加载后清理;后续 BaseTrainer 再准备训练 engine。它与 FSDP2 在 Trainer 中对已构造模型进行分片的时机不同。
|
||||
|
||||
## 扩展边界
|
||||
|
||||
改变加载顺序或 AutoModel 类选择时,修改 ModelEngine;增加一种初始化、PEFT 或量化实现时,扩展相应[模型插件](../plugins/model_plugins.md)。只需改变消息格式时,使用 chat template 或修改 Renderer 的转换逻辑,无需增加一种模型加载插件。
|
||||
51
docs/zh/developer-guide/core/renderer.md
Normal file
51
docs/zh/developer-guide/core/renderer.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Renderer
|
||||
|
||||
当前 Renderer 位于 `core/rendering/`,把 v1 `Sample` 转成 tokenized `ModelInput`。它不再依赖 `RenderingPlugin` 或模型名称模板表。
|
||||
|
||||
## 在数据路径中的位置
|
||||
|
||||
DataEngine 负责返回标准消息结构,ModelEngine 提供与模型匹配的 processor 并创建 Renderer。BatchGenerator 的 DataLoader 调用 `Renderer.process_samples(samples)`,得到已分词的样本列表,再执行批次组装。
|
||||
|
||||
Renderer 的结果包含 `input_ids`、`attention_mask`、`labels`、`loss_weights` 和位置信息;多模态样本还携带 processor 产生的媒体特征。它负责表达模型输入和监督范围,batch 内的 padding、拼接以及长度截断由后续批处理承担。
|
||||
|
||||
## Chat Template 的来源
|
||||
|
||||
1. 使用 processor/tokenizer 自带 `chat_template`。
|
||||
2. `custom_chat_template` 可以在 ModelEngine 中覆盖它。
|
||||
3. 模型完全没有模板时使用内置 ChatML fallback。
|
||||
|
||||
## 生成训练标签
|
||||
|
||||
多轮对话由 DataEngine 按每个受监督 assistant turn 切分为训练样本(见[DataEngine](data_engine.md))。Renderer 对样本最后一个 assistant turn 分别渲染 prompt 和完整序列,通过两者前缀差恢复监督 token 区间,不维护模型专属 role marker 表。
|
||||
|
||||
```text
|
||||
messages before assistant + generation prompt → prompt ids
|
||||
messages including assistant response → full ids
|
||||
full ids 中超出 prompt 的尾部 → supervised span
|
||||
```
|
||||
|
||||
这种方式兼容模型在历史消息中处理 reasoning 内容的差异。
|
||||
|
||||
该方法要求 prompt 的 token 序列与完整序列的前缀完全一致。Renderer 会实际比较两次编码的结果;如果模板在追加最后一轮后改写了前面的内容,会抛出错误,避免把上下文 token 当作回复标签。
|
||||
|
||||
前缀部分的 `labels` 为 `IGNORE_INDEX`、`loss_weights` 为零;最后回复按该轮的监督权重设置 `loss_weights`,有监督的位置使用实际 token ID 作为 label。生成模式则添加 generation prompt,并把所有位置设为不参与监督。
|
||||
|
||||
## 处理多模态内容
|
||||
|
||||
Renderer 先把标准内容块转换为 Hugging Face 消息结构,再通过 chat template 生成文本。存在媒体内容时,processor 接收文本与图片、视频或解码后的音频,并返回 token 与媒体特征。Renderer 把这些特征和媒体位置标记一并传给批处理,保持文本与媒体对应。
|
||||
|
||||
## 拼接 Chosen/Rejected 序列
|
||||
|
||||
chosen 与 rejected 分别渲染后拼接,并使用 `token_type_ids` 标记两个文档。DPO/RM 根据标记构造 block-diagonal attention 和各自 position ids,避免 rejected 序列读取 chosen 序列。
|
||||
|
||||
Renderer 为两段序列分别从起点生成 position IDs,并用 `token_type_ids` 的 `1`、`2` 保留段边界。物理拼接只改变存储布局;两段仍是独立回答,任务 Trainer 需要保留这个隔离语义。
|
||||
|
||||
## 转义特殊 Token
|
||||
|
||||
`core/rendering/escape.py` 在渲染用户控制的文本和 tools 前处理中和 tokenizer 的特殊 token 字符串,避免输入直接注入特殊 token。
|
||||
|
||||
## 自定义 Chat Template
|
||||
|
||||
新模型通常应在模型仓库的 tokenizer 配置中提供标准 HF chat template。仅在运行时覆盖时使用 `custom_chat_template`,无需注册 Python 插件。
|
||||
|
||||
若原始数据字段需要变化,扩展 converter;若标准消息如何映射到模型输入发生变化,再检查 `rendering/format.py` 和 `rendering/rendering.py`。转换原始字段与生成监督标签分属不同阶段,避免在 converter 中依赖模型的 token ID。
|
||||
Reference in New Issue
Block a user