diff --git a/.claude/skills/llamafactory-v1-docs/SKILL.md b/.claude/skills/llamafactory-v1-docs/SKILL.md new file mode 100644 index 000000000..64d802a86 --- /dev/null +++ b/.claude/skills/llamafactory-v1-docs/SKILL.md @@ -0,0 +1,52 @@ +--- +name: llamafactory-v1-docs +description: Write, review, update, build, or preview LlamaFactory v1 documentation. Use for docs work grounded in src/llamafactory/v1; not for running model training. +--- + +# LlamaFactory v1 Documentation + +## Scope + +- Work in the repository containing both `docs/` and `src/llamafactory/v1/`. Check the branch and existing changes first. +- Treat this branch's v1 implementation as the source of truth; do not infer behavior from v0 or upstream code. +- Maintain Chinese and English counterparts for pages touched by the task unless the user limits the language. Align relative page paths, structure, technical meaning, examples, and navigation; translate prose naturally while preserving code identifiers and commands. Report any remaining language gaps. +- Preserve unrelated edits and explicitly deferred issues. Review-only requests stay read-only; build-only requests do not rewrite content. + +## Writing + +- Explain features directly: behavior, configuration, execution, and constraints. Avoid assumed user goals, selection advice, rhetorical questions, and “use case” columns unless requested. +- Keep content ownership clear: feature guides explain usage; configuration pages define fields and semantics; developer guides explain internals. Link between them instead of repeating full sections. +- Use tables for factual comparisons. Keep examples short and distinguish complete configurations from partial snippets without repetitive setup reminders. +- Explain defaults, omitted versus explicit values, precedence, units, and conditional behavior—not just parameter names. +- In developer guides, show responsibilities, inputs, outputs, state ownership, and call order. Use a small example or tensor shapes when abstractions need clarification. +- Use one H1 per page, meaningful headings, language-tagged code blocks, relative links, and the appropriate `toctree` entry for new pages. + +## Source and Examples + +- Trace relevant configuration parsing, plugin registration, and call sites. A declared field or interface alone does not establish support. +- Distinguish related concepts, such as quantization plugins, backends, bit widths, and formats. Verify current support rather than hardcoding assumptions into this skill. +- Keep model IDs, adapter paths, model directories, and filenames consistent across training, inference, and export examples. Match each downstream input to the preceding output. +- Parse changed YAML examples and check their placement and composition. Examples described as runnable need the required imports, interfaces, and registration. +- Document confirmed behavior and limitations. Report unresolved implementation questions separately; do not insert speculation or conversation history into public documentation. + +## Build and Preview + +Use an existing Python environment with `docs/requirements.txt` installed. Build both languages from the repository root, or just the language explicitly requested: + +```bash +for doc_language in zh en; do + env LC_ALL=C LANG=C python3 -m sphinx -b html -n -W --keep-going "docs/$doc_language" "docs/_build/html/$doc_language" || exit 1 +done +``` + +Review the diff and build diagnostics; check changed pages, links, anchors, and table/code rendering. Fix issues introduced by authorized edits and rebuild. For review-only or build-only requests, report existing failures without expanding the scope. Do not disable strict checks or run model training merely to validate documentation. + +When a preview is requested, reuse a server serving this output or start one on an available local port: + +```bash +python3 -m http.server 8765 --bind 127.0.0.1 --directory docs/_build/html +``` + +Open the relevant pages under `/zh/` and `/en/` on the preview server and verify the served content and language-switch links. Do not stop unrelated servers or publish the site automatically. + +Report the changed files and completed checks briefly; include a preview link if available. Distinguish a successful documentation build from validated model execution. diff --git a/docs/_static/css/tables.css b/docs/_static/css/tables.css new file mode 100644 index 000000000..e23417ed3 --- /dev/null +++ b/docs/_static/css/tables.css @@ -0,0 +1,5 @@ +.rst-content table.docutils td code { + white-space: nowrap; + overflow-wrap: normal; + word-break: normal; +} diff --git a/docs/conf.py b/docs/conf.py index 46496019a..050461257 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,6 +26,7 @@ html_js_files = [ html_css_files = [ "css/lang-switcher.css", + "css/tables.css", ] myst_enable_extensions = [ diff --git a/docs/en/advanced/distributed/fsdpturbo-ep-efsdp.md b/docs/en/advanced/distributed/fsdpturbo-ep-efsdp.md index 73bf2d9c7..c0c2f6f92 100644 --- a/docs/en/advanced/distributed/fsdpturbo-ep-efsdp.md +++ b/docs/en/advanced/distributed/fsdpturbo-ep-efsdp.md @@ -1,6 +1,6 @@ # FSDPTurbo EP/EFSDP and LlamaFactory FSDP2/CP Design -Chinese version: [FSDPTurbo EP/EFSDP 与 LlamaFactory FSDP2/CP 设计说明](../../../zh/advanced/distributed/fsdpturbo-ep-efsdp.md) +Chinese v1 guide: [Distributed training with FSDPTurbo](https://llamafactory.readthedocs.io/zh-cn/latest/feature-guide/distributed_training.html#fsdpturbo) This document describes the current implementation of the `fsdpturbo` distributed plugin. Its core principle is a clear separation of responsibilities: diff --git a/docs/zh/advanced/custom-kernels/custom-kernels.md b/docs/zh/advanced/custom-kernels/custom-kernels.md deleted file mode 100644 index a4aca5e6b..000000000 --- a/docs/zh/advanced/custom-kernels/custom-kernels.md +++ /dev/null @@ -1,93 +0,0 @@ -# LLaMA-Factory Kernels 系统 - -## 概述 - -LLaMA-Factory Kernels 系统用于管理不同硬件设备提供的高性能计算内核(kernel)实现,该系统通过替换模型中的关键模块(如 RMSNorm、SwiGLU、RoPE、MoE 等)为硬件优化的版本,从而显著提升模型训练和推理的性能。 - -Kernels 系统采用基于注册表的自动发现机制,能够根据当前运行环境自动检测可用的硬件设备(NPU、CUDA 等),并使能相应的高性能 kernels。这种设计使得用户无需关心底层实现细节,只需简单调用接口即可获得性能提升。 - -## 核心特性 - -- **自动注册机制**:基于 `@register_kernel` 装饰器实现自动注册系统。系统启动时会自动扫描 `ops` 目录下的 kernel 实现,并将其注册到全局注册表中。 - -- **设备适配感知**:自动检测当前硬件设备(NPU、CUDA 等)并应用相应的优化。系统会跳过不支持的设备,确保在不同环境下都能正常工作。 - -- **模块化设计**:每个 kernel 独立实现,互不干扰。可以单独应用某个 kernel,也可以批量应用所有默认的 kernels。 - -- **后向兼容**:kernel 替换不修改模型权重,保持数值一致性。优化后的实现与原始实现保持精度一致(在浮点误差范围内)。 - -- **灵活扩展**:通过继承 `BaseKernel` 基类并使用装饰器,可以轻松添加新的 kernel 实现,支持新的硬件设备或优化算法。 - -## 使用方式 - -### 1. 通过训练 YAML 配置文件使用 - -要在训练过程中使能 kernels,只需在配置文件中增加如下配置,即可自动使能所有默认可用的 kernels: - -```yaml -... -kernel_config: - name: auto - include_kernels: auto # choice: null/true/false/auto/kernel_id1,kernel_id2,kernel_id3, default is null - -... -``` - -### 2. 调用 API 使能 - -#### 2.1 apply_default_kernels 使能所有默认 kernels - -`apply_default_kernels` API 能够自动应用当前设备上所有默认注册的 kernels: - -```python -from transformers import AutoModelForCausalLM -from llamafactory.v1.plugins.model_plugins.kernels import apply_default_kernels - -# 加载模型 -model = AutoModelForCausalLM.from_pretrained("qwen/qwen2.5-0.5B") - -# 自动应用所有默认 kernels -model = apply_default_kernels(model, include_kernels="auto") -``` - -#### 2.2 apply_kernel 使能特定 kernel - -如果需要更精细的控制,例如在某些场合单独应用某个 kernel,可以手动调用 `apply_kernel` 函数并传入 kernel ID: - -```python -from transformers import AutoModelForCausalLM -from llamafactory.v1.plugins.model_plugins.kernels import apply_kernel - -# 加载模型 -model = AutoModelForCausalLM.from_pretrained("qwen/qwen2.5-0.5B") - -# 手动应用各个 kernels -# 注意:kernel ID 必须与定义时的 _kernel_id 一致 -model = apply_kernel("npu_fused_rope", model=model) -model = apply_kernel("npu_fused_rmsnorm", model=model) -model = apply_kernel("npu_fused_swiglu", model=model) -model = apply_kernel("npu_fused_moe", model=model) - -### 3. 查询已注册的可用 kernels - -可以通过 `get_default_kernels` 获取当前环境中所有已注册且可用的默认 kernel ID: - -```python -from llamafactory.v1.plugins.model_plugins.kernels import get_default_kernels - -# 获取默认 kernel 列表 -available_kernels = get_default_kernels() -print(f"Available kernels: {available_kernels}") -# 输出示例: ['npu_fused_rmsnorm', 'npu_fused_swiglu', 'npu_fused_rope', 'npu_fused_moe'] -``` - -### 当前已实现的 kernels - -| Kernel ID | 功能 | 支持的设备 | 备注 | -|-----------|------|-----------|------| -| [npu_fused_rmsnorm](./fused-operators.md/#npufusedrmsnorm) | RMSNorm 融合算子 | NPU | NPU 设备的高性能 RMSNorm 实现 | -| [npu_fused_swiglu](./fused-operators.md/#npufusedswiglu) | SwiGLU 融合算子 | NPU | NPU 设备的高性能 SwiGLU 实现 | -| [npu_fused_rope](./fused-operators.md/#npufusedrope) | RoPE 融合算子 | NPU | NPU 设备的高性能 RoPE 实现 | -| [npu_fused_moe](./fused-operators.md/#npufusedmoe) | MoE 融合算子 | NPU | MoE 融合算子,适配 Qwen3-MoE 等模型 | - -我们会持续适配更多的 kernels,如果您需要自己开发新的 kernels,请参考我们的 [Kernel 开发文档](../../dev-guide/plugins/model-plugins/kernels.md),欢迎您向 LLaMA-Factory 贡献代码。 diff --git a/docs/zh/advanced/custom-kernels/fused-operators.md b/docs/zh/advanced/custom-kernels/fused-operators.md deleted file mode 100644 index 7848d3635..000000000 --- a/docs/zh/advanced/custom-kernels/fused-operators.md +++ /dev/null @@ -1,104 +0,0 @@ -# Fused Operators - -LLaMA-Factory 提供了一系列针对特定硬件优化的融合算子。这些算子位于 `src/llamafactory/v1/plugins/model_plugins/kernels/ops` 目录下。 - -系统启动时,`scan_all_kernels` 函数会自动扫描该目录,注册所有可用的算子。您可以通过 `apply_default_kernels(model, include_kernels="auto")` 一键启用它们,或者使用 `apply_kernel` 单独启用。 - -以下是当前支持的融合算子详情: - -## NpuFusedRMSNorm -RMSNorm(Root Mean Square Layer Normalization)是一种常用于大模型的归一化方法。在推理或训练中,RMSNorm 融合算子 将bias、residual等操作进行融合,可以减少显存访问次数,加速计算。 - -Ascend npu 通过 `torch_npu.npu_rms_norm` 接口提供 RMSNorm 融合算子调用接口,支持 float16, bfloat16, float 等数据格式。RMSNorm 算子常见于Qwen等LLM模型中,由于torch侧没有提供 RMSNorm 算子的接口,因此在模型中通常是以自定义类的形式出现,通过替换 RMSNorm 类的 `forward` 方法即可使能。 - -```python -def _npu_rms_forward(self, hidden_states): - """NPU forward implementation for RMSNorm. - - Args: - self: RMSNorm module instance with `weight` and `variance_epsilon`. - hidden_states: Input hidden states tensor, same shape as the baseline. - - Returns: - Normalized tensor consistent with the baseline RMSNorm behavior. - """ - - return torch_npu.npu_rms_norm(hidden_states, self.weight, epsilon=self.variance_epsilon)[0] -``` - - 在 LlamaFactory 中,通过 `NpuRMSNormKernel` 提供使能该融合算子的入口,只需要调用 `apply_kernel("npu_fused_rmsnorm", model=model)` 即可针对已适配的模型使能 npu RMSNorm 融合算子。 - -## NpuFusedSwiGlu -SwiGLU(Swish-Gated Linear Unit)是一种结合了Swish激活函数和门控线性单元(GLU)的混合激活函数,其主要功能是对输入张量进行门控线性变换,近年来被广泛应用于 LLM 模型中的 MLP 层。SwiGLU 融合算子将分割、激活、矩阵乘等多个操作融合为单一硬件指令,避免多次内核启动开销。 - -Ascend npu 通过 `torch_npu.npu_swiglu` 接口提供 SwiGLU 融合算子调用接口,支持 float16,bfloat16,float SwiGLU 算子常见于Qwen等LLM模型中,由于torch侧没有提供 SwiGLU 算子的接口,因此在模型中通常是以自定义类的形式出现,通过替换 SwiGLU 类的 `forward` 方法即可使能。替换过程可参考如下示例: - -```python -# 原始 MLP forward 方法: -def forward(self, x): - down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x)) - return down_proj - -# 替换后的 forward 方法: -def _npu_swiglu_forward(self, hidden_state): - return self.down_proj( - torch_npu.npu_swiglu(torch.cat((self.gate_proj(hidden_state), self.up_proj(hidden_state)), dim=-1), dim=-1) - ) -``` - - 在 LLaMA-Factory 中,通过 `NpuSwiGluKernel` 提供使能该融合算子的入口,只需要调用 `apply_kernel("npu_fused_swiglu", model=model)` 即可针对已适配的模型使能 npu SwiGLU 融合算子。对于未适配的模型,如有需要,您可根据示例以及[开发者文档](../../dev-guide/plugins/model-plugins/kernels.md)自行适配。 - - -## NpuFusedRoPE -RoPE(Rotary Positional Embedding,旋转式位置嵌入) 是一种位置编码技术,广泛应用于 Qwen 等 LLM 模型中,用于有效编码文本序列的位置信息。它结合了绝对位置编码的稳定性与相对位置编码的灵活性,同时具备优秀的长度泛化能力。传统 RoPE 算子通常在 LLM 等模型结构中通过自定义函数的形式实现。RoPE 融合算子将原计算流程合并为单个硬件优化算子,从而提升性能。 - -Ascend npu 通过 `torch_npu.npu_rotary_mul` 提供 RoPE 融合算子调用接口,支持 float16,bfloat16,float32 等数据格式。以 Qwen3 系列模型为例,通过替换其 `apply_rotary_pos_emb` 函数即可实现 RoPE融合算子使能: - -```python -# 原始 apply_rotary_pos_emb: -def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1): - cos = cos.unsqueeze(unsqueeze_dim) - sin = sin.unsqueeze(unsqueeze_dim) - q_embed = (q * cos) + (rotate_half(q) * sin) - k_embed = (k * cos) + (rotate_half(k) * sin) - return q_embed, k_embed - -# 替换 RoPE 融合算子后: -def _apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1): - cos = cos.unsqueeze(unsqueeze_dim) - sin = sin.unsqueeze(unsqueeze_dim) - q_embed = torch_npu.npu_rotary_mul(q, cos, sin) - k_embed = torch_npu.npu_rotary_mul(k, cos, sin) - return q_embed, k_embed -``` - - 在 LLaMA-Factory 中,通过 `NpuRoPEKernel` 提供使能该融合算子的入口,只需要调用 `apply_kernel("npu_fused_rope", model=model)` 即可针对已适配的模型使能 npu RoPE 融合算子。对于未适配的模型,如有需要,您可根据示例以及[开发者文档](../../dev-guide/plugins/model-plugins/kernels.md)自行适配。 - - -## NpuFusedMoE -MoE(Mixture of Experts)模型通过稀疏激活扩展容量。在原生 Transformers 实现中,使用串行循环遍历专家,导致内核启动开销大、硬件利用率低。 - -**MoE 融合算子** 利用 **GMM(Grouped Matrix Multiplication,分组矩阵乘)** 技术,支持在单个硬件指令内并行处理多组不同形状(行数不一)的矩阵乘法,消减循环开销,同时无需额外的显存复制,显著提升训练性能。 - -Ascend npu 通过 `torch_npu.npu_grouped_matmul` 等接口提供底层支持,通过替换模型中的 MoE Block forward 方法,即可利用 NPU 的分组矩阵乘能力。 - -核心逻辑替换如下(简化示意): - -```python -def _npu_moe_forward(self, hidden_states, routing_weights, router_indices): - # 1. 排序:将乱序的 Token 按指派的专家归类,并生成索引映射 - permuted_states, row_map = torch_npu.npu_moe_token_permute(hidden_states, router_indices) - - # 2. 统计:计算每个专家需要处理的 Token 数量 - tokens_per_expert = torch.histc(router_indices, bins=self.num_experts, min=0, max=self.num_experts) - - # 3. 计算 (GMM):一次性并行计算所有专家的权重,自动适配不同专家的输入长度 - inter_states = torch_npu.npu_grouped_matmul(permuted_states, self.gate_up_proj_weights, split_sizes=tokens_per_expert, ...) - inter_states = torch_npu.npu_swiglu(inter_states) - output = torch_npu.npu_grouped_matmul(inter_states, self.down_proj_weights, split_sizes=tokens_per_expert, ...) - - # 4. 还原:将结果恢复成原始 Token 顺序并应用路由权重 - return torch_npu.npu_moe_token_unpermute(output, row_map, routing_weights) -``` - -在 LLaMA-Factory 中,通过 `NpuFusedMoEKernel` 提供使能该融合算子的入口。只需要调用 `apply_kernel("npu_fused_moe", model=model)` 即可针对已适配的模型使能 NPU MoE 融合算子。对于未适配的模型,您也可以参考上述示例代码以及[开发者文档](../../dev-guide/plugins/model-plugins/kernels.md)自行适配。 diff --git a/docs/zh/advanced/custom-kernels/triton.md b/docs/zh/advanced/custom-kernels/triton.md deleted file mode 100644 index 2e3863793..000000000 --- a/docs/zh/advanced/custom-kernels/triton.md +++ /dev/null @@ -1 +0,0 @@ -# Triton diff --git a/docs/zh/advanced/distributed/deepspeed.md b/docs/zh/advanced/distributed/deepspeed.md deleted file mode 100644 index 34f17b957..000000000 --- a/docs/zh/advanced/distributed/deepspeed.md +++ /dev/null @@ -1 +0,0 @@ -# DeepSpeed diff --git a/docs/zh/advanced/distributed/fsdp.md b/docs/zh/advanced/distributed/fsdp.md deleted file mode 100644 index 6326e429f..000000000 --- a/docs/zh/advanced/distributed/fsdp.md +++ /dev/null @@ -1 +0,0 @@ -# FSDP diff --git a/docs/zh/advanced/distributed/fsdpturbo-ep-efsdp.md b/docs/zh/advanced/distributed/fsdpturbo-ep-efsdp.md deleted file mode 100644 index 538e2a540..000000000 --- a/docs/zh/advanced/distributed/fsdpturbo-ep-efsdp.md +++ /dev/null @@ -1,215 +0,0 @@ -# FSDPTurbo EP/EFSDP 与 LlamaFactory FSDP2/CP 设计说明 - -English version: [FSDPTurbo EP/EFSDP and LlamaFactory FSDP2/CP Design](../../../en/advanced/distributed/fsdpturbo-ep-efsdp.md) - -本文描述 `fsdpturbo` distributed plugin 的当前实现。核心原则是保持两侧职责清晰: - -- FSDPTurbo 负责专家并行(EP)、专家参数分片(EFSDP)和设备算子注册。 -- LlamaFactory 负责进程初始化、基础 DeviceMesh、外层 FSDP2、CP、模型初始化与权重加载。 -- LlamaFactory 的集成层负责把两套参数布局组合起来,并处理跨 Mesh 的梯度范数。 - -## 1. 配置边界 - -公共并行拓扑放在 `TrainingArguments` 顶层,FSDPTurbo 私有参数保留在 `dist_config`: - -```yaml -cp_size: 1 - -dist_config: - name: fsdpturbo - ep_size: 16 - ep_dispatcher: eager -``` - -最小示例中的字段职责如下: - -- `ep_size`:专家并行组大小。 -- `ep_dispatcher`:FSDPTurbo EP dispatcher,默认为 `eager`。 - -`dp_size`、`cp_size`、`cp_mode`、`mp_replicate_size`、`mp_shard_size` 和 `dist_timeout` -属于公共拓扑字段,继续放在顶层。`dist_config` 会被严格解析为 `FSDPTurboParams`;如果把公共拓扑 -字段误放进去,会直接报错,而不是静默忽略。 - -顶层训练参数 `bf16` 同时控制 FSDPTurbo 的参数存储和计算 dtype。backend 会在 FSDP materialization -前完成模型 dtype 转换,因此 `ModelEngine` 不需要读取 distributed backend 配置。 - -以下高级字段为可选项,因此没有写入上面的最小 YAML 示例: - -- `fsdp_ignored_modules`:额外排除在 LlamaFactory 外层 FSDP2 之外的模块。模型规格选中的专家参数 - 会被集成层自动加入忽略集合,普通配置无需重复填写。 -- `hook_modules`:FSDPTurbo EFSDP hook 的可选模块模式,默认为空列表。 -- `fsdp_implementation`:FSDPTurbo EFSDP 实现,可选 `native` 或 `custom`,默认为 `native`。 - -EFSDP 的目标由模型规格决定。Attention、Embedding、LM Head 等非专家参数不进入 FSDPTurbo -EFSDP plan,而是继续由 LlamaFactory 外层 FSDP2 管理。 - -模型相关的模块路径和准备逻辑统一由 `FSDPTurboEPModelSpec` 注册表管理。当前内置 `qwen3_moe` -和 `qwen3_5_moe`;未注册的模型会明确报错。`ep_modules` 和 `ep_fsdp_modules` 不属于 YAML -接口,严格参数解析会拒绝这两个字段,避免用户配置与模型实际结构失配。 - -## 2. Mesh 初始化 - -LlamaFactory 的 `DistributedInterface` 只初始化自身原有的 model/data mesh。它不感知 EP、EFSDP, -也不为 distributed plugin 提供额外 mesh 注册接口。FSDPTurbo 的专家拓扑由插件文件内的 -`FSDPTurboParallelState` 独立创建和持有: - -```text -run_sft / run_dpo / run_rm - -> DistributedInterface(training_args) - -> 初始化 LlamaFactory model/data mesh - -> DistributedPlugin("fsdpturbo").shard_model(...) - -> FSDPTurboFSDP2Engine.__init__() - -> FSDPTurboParallelState.initialize() - -> 初始化并保存 expert parent mesh 及其子 mesh -``` - -`FSDPTurboParallelState` 创建专家侧四维父 Mesh: - -```text -(edp, efsdp, ep, expert_cp) -``` - -当前尺寸计算为: - -```text -dp_size = world_size / cp_size -ep_fsdp_size = dp_size / ep_size -edp_size = dp_size / (ep_size * ep_fsdp_size) -mesh_shape = (edp_size, ep_fsdp_size, ep_size, cp_size) -``` - -状态对象保存 `edp_mesh`、`efsdp_mesh`、`ep_mesh` 和 `expert_cp_mesh`。插件内部模型切分和梯度范数 -都从这个状态对象读取专家通信域;LlamaFactory 其他 backend 不需要实现或感知这些接口。状态初始化 -会校验 `ep_size` 为正数且能够整除 `dp_size`,重复初始化时也会拒绝拓扑发生变化。 - -## 3. 模型切分顺序 - -模型包装顺序必须保持为“专家侧优先,外层 FSDP2 随后”: - -```text -DistributedPlugin("fsdpturbo") - -> FSDPTurboFSDP2Engine.shard_model(model) - -> prepare_model_ep(model) - -> expert_parallelize_modules(model, ep_mesh, ep_plan) - -> expert_fully_shard_modules(model, efsdp_mesh, ep_plan, fsdp_plan) - -> 收集专家参数作为 ignored_params - -> FSDP2Engine.prepare_model(model, ignored_params=...) - -> 对剩余 Transformer Layer 和根模块执行 outer fully_shard -``` - -这样可以避免同一专家参数同时被 EFSDP 和外层 FSDP2 管理。外层 FSDP2 仍复用 LlamaFactory -原有的初始化、checkpoint 和保存流程。 - -LlamaFactory 集成层接受 `eager`、`fused`、`mc2` 和 `domino`,并将选项原样传给 -FSDPTurbo。这四种模式的实现边界和当前验证状态不同: - -| Dispatcher | 主要路径 | 额外要求 | 本 PR 验证状态 | -| --- | --- | --- | --- | -| `eager` | 使用 PyTorch 实现 permute、unpermute 和 grouped matmul,张量仍在当前加速设备上,通过标准 AllToAll 完成 token dispatch/combine | 依赖最少,用作参考实现 | 已在 A3 上完成精度和性能验证 | -| `fused` | 保持相同的 AllToAll 拓扑,将 permute、unpermute 和 grouped matmul 切换为设备融合算子 | 需要对应的设备算子、dtype 和 layout 支持;存在空专家时可回退到 eager 局部算子 | 已在 A3 上完成精度和性能验证 | -| `mc2` | 使用专用算子融合 AllToAllV 和 grouped matmul,减少通信与计算之间的中间开销 | 依赖 MC2 NPU 算子、HCCL communicator 以及对应的 shape/dtype 约束 | FSDPTurbo 提供实现,本 PR 未做端到端验证 | -| `domino` | 将专家模块输入的第一维分成两片,使用独立通信流和 event 重叠 AllToAll 与专家计算 | 需要异步 stream/event 支持,且两个分片都要有足够的 token 工作量才能覆盖调度开销 | FSDPTurbo 提供实现,本 PR 未做端到端验证 | - -当前只验证 `eager` 和 `fused`,是因为它们分别覆盖参考实现和 A3 常用设备融合路径,可用于隔离并验证 -LlamaFactory 与 FSDPTurbo 之间的 EP/EFSDP 集成正确性。本次实验矩阵没有继续扩展到 `mc2` 和 -`domino`:它们还引入了额外的算子、通信调度和输入形状约束,需要独立比较数值、长步稳定性和 profiler 结果。 -因此,它们在配置接口上可选,但不应从本 PR 的实验结果推断为已达到相同的稳定性、精度或性能水平。 - -## 4. FSDPTurbo 依赖入口 - -LlamaFactory 从各功能的定义模块直接导入所需对象: - -```python -from fsdp_turbo.distributed.expert_parallel.expert_fully_shard_parallel import ( - expert_fully_shard_modules, -) -from fsdp_turbo.distributed.expert_parallel.expert_parallel import expert_parallelize_modules -from fsdp_turbo.fsdp_turbo_config import EPPlanConfig, FSDPPlanConfig -from fsdp_turbo.utils.str_match import module_name_match -``` - -导入发生在 `prepare_model_ep()` 内,因此没有安装 FSDPTurbo 时,其他 distributed backend 仍可正常导入。 -这里不通过 `fsdp_turbo.distributed.__init__` 聚合导出,避免 package 初始化期间的额外依赖和潜在循环导入。 - -## 5. 梯度范数 - -外层参数和专家参数可能属于不同 DTensor Mesh,不能直接放入一次标准 `clip_grad_norm_()`。 -`fsdpturbo` plugin 按参数所属 Mesh 分组计算局部 p 次方和: - -- 非专家参数沿 DP 和 CP group 汇总。 -- 专家参数沿 `FSDPTurboParallelState` 保存的 EFSDP、EP 和 expert-CP group 汇总。 -- 汇总得到全局范数后,对所有本地梯度应用同一个 clipping coefficient。 - -启动阶段会执行一次零梯度 warmup,使相关 collective 在正式训练前完成初始化。 -当前这是 `fsdpturbo` backend 的专用实现;其他 backend 继续保留原有梯度范数路径,等待上游 -distributed plugin 解耦后再统一公共接口。 - -## 6. 权重加载 - -LlamaFactory 保留 `init_on_meta` 和 safetensors 加载流程。父类 `FSDP2Engine` 的加载器通过 -`self._copy_weights(...)` 动态调用 FSDPTurbo engine 的覆写实现,因此该方法不是未使用代码。 -它支持包含多个 `Shard` placement 的 DTensor,按各 Mesh 维度依次计算当前 rank 对应的本地切片。 -模型保存和 checkpoint 接口继续复用 LlamaFactory FSDP2 实现。 - -## 7. Kernel plugin - -FLA 算子不属于 distributed config。算子选择通过独立的 `kernel_config` 完成: - -```yaml -kernel_config: - name: auto, flash-linear-attention - include_kernels: chunk_gated_delta_rule, fused_recurrent_gated_delta_rule - chunk_size: 32 -``` - -调用链如下: - -```text -ModelEngine - -> apply_kernels("auto, flash-linear-attention") - -> LlamaFactory 当前加速器对应的 auto kernels - -> KernelPlugin("flash-linear-attention").apply(...) - -> fsdp_turbo.ops.get_op() - -> FSDPTurbo device operator registry - -> fsdp_turbo.utils.patch.patch_model_members() - -> FLA backend implementation -``` - -`chunk_size` 当前支持 `16`、`32` 和 `64`,默认值为 `64`。Kernel plugin 与 distributed plugin -彼此独立。`name: flash-linear-attention` 只安装所选 FLA 算子;逗号分隔的 -`name: auto, flash-linear-attention` 会在分布式切分前组合 LlamaFactory 当前加速器的 auto kernels -与 FLA plugin。LlamaFactory 负责算子名到模型属性的映射和 `chunk_size` 参数绑定;FSDPTurbo 负责设备 -算子注册、选择和通用 callable patch。FLA 依赖可选的外部三方件,因此保持显式选择,不属于内置 -`auto` 集合。FSDPTurbo -随后会替换目标专家模块的 `forward`,所以专家计算的最终路径由 `ep_dispatcher` 决定;auto 阶段 -应用的 MoE kernel 不会作为独立的第二条专家执行路径保留下来。 - -## 8. CP 运行约束与验证范围 - -`init_on_meta` 构造模型时必须与 `from_pretrained` 路径一样传递 `attn_implementation`,否则模型会退回 -非 FlashAttention 实现,Ulysses CP 无法启动。Ulysses 在调用 Hugging Face FlashAttention 前重建全局 -attention mask;只有二维 position IDs 才参与 packed-sequence 检测。Qwen3.5 mRoPE 等多轴 position IDs -已经在 rotary embedding 中消费,不应传入 FlashAttention 的 packed-sequence 检测逻辑。 - -当前实现已在 Atlas 900 A3 SuperPoD 和 Atlas 950 SuperPoD 上用 Qwen3.5-35B-A3B 完成以下 -BF16、AdamW full SFT 验证。本次重验证使用 FSDPTurbo `0e96fbc`;A3 环境为 CANN 9.0.0、 -PyTorch 2.7.1 和 torch-npu 2.7.1.post4,A5 环境为 CANN 9.1.0-beta.3、PyTorch 2.10.0 和 -torch-npu 2.10.0.post2。表中性能按第 1 步至第 100 步的日志时间戳计算,不包含首步前的初始化、 -编译和训练后的模型保存时间: - -| 机器型号 | CP | EP | EFSDP | Checkpoint | Kernel / Dispatcher | 步数 | Loss(首步 -> 末步) | 性能 | 结果 | -| --- | ---: | ---: | ---: | --- | --- | ---: | --- | ---: | --- | -| Atlas 900 A3 SuperPoD | 1 | 16 | 1 | 关闭 | FLA(chunk size 16)/ eager | 100 | 1.3361 -> 0.0793 | 2.51 s/it | 通过并完成保存 | -| Atlas 900 A3 SuperPoD | 1 | 16 | 1 | 关闭 | FLA(chunk size 16)/ fused | 100 | 1.3354 -> 0.1179 | 2.17 s/it | 通过并完成保存 | -| Atlas 900 A3 SuperPoD | 2 | 4 | 2 | 关闭 | auto + FLA(chunk size 64)/ fused | 100 | 1.8114 -> 0.5260 | 7.65 s/it | 通过并完成保存 | -| Atlas 900 A3 SuperPoD | 2 | 4 | 2 | 关闭 | auto + FLA(chunk size 64)/ eager | 100 | 1.8095 -> 0.5596 | 5.88 s/it | 通过并完成保存 | -| Atlas 950 SuperPoD | 1 | 8 | 1 | 关闭 | 未配置 kernel plugin / eager | 100 | 1.3575 -> 0.4439 | 2.68 s/it | 通过并完成保存 | - -五组训练的 loss 和 grad norm 均保持有限,并完成 100 步及模型保存。同一切分下,EP16 eager/fused -的逐步 loss 相关系数为 0.997,CP2/EP4/EFSDP2 eager/fused 为 0.977,说明两种 dispatcher 的 -优化轨迹一致。性能收益与切分有关:EP16 下 fused 比 eager 快约 13%,而加入 CP 和 EFSDP 后 fused -比 eager 慢约 30%,因此不能把 fused 视为所有 mesh 的默认最优选择。 - -EP16 两组使用 global batch 16 和 cutoff length 256;CP2 两组使用 global batch 8 和 cutoff length -128;A5 组使用 global batch 8 和 cutoff length 256。因此,首末 loss 用于验证各组自身的收敛趋势, -不同切分组之间的绝对 loss 不应直接作为精度等价结论。 diff --git a/docs/zh/advanced/distributed/parallel-dp-tp-ep-sp-cp.md b/docs/zh/advanced/distributed/parallel-dp-tp-ep-sp-cp.md deleted file mode 100644 index 4ae4aede2..000000000 --- a/docs/zh/advanced/distributed/parallel-dp-tp-ep-sp-cp.md +++ /dev/null @@ -1 +0,0 @@ -# Parallel(DP, TP, EP, SP, CP) diff --git a/docs/zh/advanced/ktransformers.md b/docs/zh/advanced/ktransformers.md deleted file mode 100644 index 58b666ff3..000000000 --- a/docs/zh/advanced/ktransformers.md +++ /dev/null @@ -1,119 +0,0 @@ -# KTransformers LoRA SFT - -KTransformers(KT)将 MoE routed experts 放在 CPU 执行,LLaMA-Factory 继续负责数据、LoRA 参数和训练入口。 -当前生产范围是 routed-BF16 LoRA 与 routed-INT8 LoRA;Accelerate 配置只负责 FSDP2,不再保存 KT 参数。 - -## 安装检查 - -必须同时安装带 KT 公共接口的 `ktransformers`、`transformers-kt` 和 `accelerate-kt`。启动前可检查: - -```bash -python - <<'PY' -from accelerate import Accelerator -from kt_kernel.sft import resolve_kt_pretrained_artifacts -from transformers import TrainingArguments - -assert hasattr(TrainingArguments, "update_kt_config") -assert "adapter_only" in __import__("inspect").signature(Accelerator.get_state_dict).parameters -print(resolve_kt_pretrained_artifacts) -PY -``` - -## 配置 - -KT 只有一个用户配置源:训练 YAML。LoRA rank、alpha、dropout 和 runtime capacity 由 LLaMA-Factory -标准字段派生;不要在 `kt_config` 中重复填写。 - -BF16 示例: - -```yaml -finetuning_type: lora -lora_rank: 8 -lora_alpha: 16 -lora_target: all - -use_kt: true -disable_gradient_checkpointing: false -kt_cpu_activation: retain -kt_config: - kt_expert_weight_format: bf16 - kt_backend: AMXBF16 - kt_num_threads: 96 - kt_tp_enabled: true - kt_threadpool_count: 2 - kt_max_cache_depth: 2 -``` - -INT8 还需要相互匹配的 routed expert 与 BF16 non-expert cache: - -```yaml -kt_weight_path: /abs/path/to/routed-int8-experts -kt_non_expert_weight_path: /abs/path/to/bf16-non-expert-cache -kt_config: - kt_expert_weight_format: int8 - kt_backend: auto - kt_weight_lifecycle: persistent -``` - -完整配置见: - -- `examples/ktransformers/train_lora/qwen3_5moe_lora_sft_kt.yaml` -- `examples/ktransformers/train_lora/deepseek_v3_int8_lora_sft_kt.yaml` - -Activation 策略: - -| `disable_gradient_checkpointing` | `kt_cpu_activation` | CPU / GPU | -| --- | --- | --- | -| `false` | `recompute` 或省略 | recompute / recompute | -| `false` | `retain` | retain / recompute | -| `true` | `retain` 或省略 | retain / retain | -| `true` | `recompute` | 不支持,启动前报错 | - -## 启动与复用 - -```bash -CUDA_VISIBLE_DEVICES=0,1 accelerate launch \ - --config_file examples/ktransformers/accelerate/fsdp2_kt_bf16.yaml \ - src/train.py examples/ktransformers/train_lora/qwen3_5moe_lora_sft_kt.yaml -``` - -输出 adapter 同时包含 standard PEFT 与 fused expert LoRA。 - -## 新进程加载 - -对话或评测必须使用本地的完整 KT adapter 目录,并重复训练时的 LoRA 形状配置:`finetuning_type`、 -`lora_rank`、`lora_alpha`、`lora_dropout`,以及相同的 KT base weight 配置。routed INT8 尤其要沿用训练时 -的 `kt_weight_path` 和 `kt_non_expert_weight_path`。 - -```yaml -model_name_or_path: /abs/path/to/base-model -adapter_name_or_path: /abs/path/to/output/checkpoint-300 -finetuning_type: lora -lora_rank: 8 -lora_alpha: 16 -lora_dropout: 0.0 - -use_kt: true -kt_cpu_activation: retain -kt_config: - kt_expert_weight_format: bf16 - kt_backend: AMXBF16 - kt_num_threads: 96 -``` - -```bash -llamafactory-cli chat path/to/kt_adapter_infer.yaml -llamafactory-cli eval path/to/kt_adapter_eval.yaml -``` - -目录必须包含 standard PEFT adapter 文件;使用 fused routed-expert LoRA 时,还必须包含 -`fused_expert_lora.safetensors` 和 `kt_adapter_manifest.json`。LLaMA-Factory 先加载 standard PEFT,随后由 -KT 校验并恢复 fused artifact。`adapter_folder` 可以选择本地子目录;越出 adapter 根目录的路径和 Hub -adapter ID 会在加载模型前报错,Hub bundle 需要先完整下载到本地。 - -续训应保留原训练 YAML,并使用 `resume_from_checkpoint`。分布式 optimizer checkpoint 暂要求相同 world -size。artifact 缺失、hash 不匹配或来源模型不一致时会直接失败,不会退回源 checkpoint。 - -不要同时启用 Transformers/FSDP activation checkpointing、Unsloth GC,也不要把 `kt_config` 放入 -Accelerate YAML。每次训练都应确认 loss/grad finite、base model 未修改,并验证 standard/router/fused LoRA -均包含非零更新。 diff --git a/docs/zh/advanced/lora-and-quantization/lora.md b/docs/zh/advanced/lora-and-quantization/lora.md deleted file mode 100644 index cfe5383ea..000000000 --- a/docs/zh/advanced/lora-and-quantization/lora.md +++ /dev/null @@ -1,3 +0,0 @@ -# Lora - -参数管理(二级参数形式) diff --git a/docs/zh/advanced/lora-and-quantization/quantization.md b/docs/zh/advanced/lora-and-quantization/quantization.md deleted file mode 100644 index 54af7cb44..000000000 --- a/docs/zh/advanced/lora-and-quantization/quantization.md +++ /dev/null @@ -1 +0,0 @@ -# Quantization diff --git a/docs/zh/configuration/data.md b/docs/zh/configuration/data.md new file mode 100644 index 000000000..76dc5bab1 --- /dev/null +++ b/docs/zh/configuration/data.md @@ -0,0 +1,37 @@ +# 数据参数 + +## DataArguments + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `train_dataset` | `str \| None` | `None` | 训练数据集路径、YAML 或 Hub ID | +| `eval_dataset` | `str \| None` | `None` | 字段已定义;评估流程尚未实现 | + +## DatasetInfo + +数据集 YAML 的每个顶层条目使用以下字段: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `path` | `str` | 必填 | 本地路径或 Hub ID | +| `source` | `local \| hf_hub` | `hf_hub` | 数据来源 | +| `split` | `str` | `train` | 数据集 split | +| `converter` | `str \| None` | `None` | `alpaca`、`sharegpt`、`pair` 或已注册名称 | +| `size` | `int \| None` | 全部 | 重采样后的目标索引数量 | +| `weight` | `float` | 不设置 | 索引数量的缩放倍率 | +| `streaming` | `bool` | `false` | 字段已定义;当前训练路径不支持 streaming 数据集 | + +### 采样规模的计算 + +`size` 和 `weight` 作用于数据集展开后的训练索引。多轮 SFT 中,每个受监督的 assistant turn 对应一个索引条目,因此索引数量可能大于原始数据的行数;偏好对数据则以一组 chosen/rejected 为一个条目。 + +使用正数 `size`、`weight` 时,按以下顺序计算: + +1. 设置 `size` 后,先从展开后的索引中有放回抽取 `size` 个条目;省略时保留完整索引。 +2. 设置 `weight` 后,再从上一步结果中有放回抽取 `int(当前条目数 × weight)` 个条目,小数部分向下取整;省略时保留上一步结果。 + +例如,`size: 1000` 与 `weight: 0.5` 同时设置时,先抽取 1000 个条目,再抽取其中的 500 个条目。最终规模为 500,但可能包含重复条目,也可能没有覆盖某些原始记录。 + +`weight` 控制每个数据集贡献的索引数量,不是各数据集之间归一化后的抽样概率,也不改变样本的损失权重。`weight > 1` 可以增加索引数量。显式设置 `weight: 1.0` 仍会执行有放回重采样;省略 `size` 和 `weight` 才会直接保留全部展开后的索引。 + +数据格式和多数据集组合方式见[数据准备](../feature-guide/data_preparation.md)。 diff --git a/docs/zh/configuration/index.md b/docs/zh/configuration/index.md new file mode 100644 index 000000000..d6edeac30 --- /dev/null +++ b/docs/zh/configuration/index.md @@ -0,0 +1,30 @@ +# 参数说明 + +v1 使用一份 YAML 同时描述数据、模型、训练和推理配置。顶层字段来自四个参数类。`peft_config`、`quant_config`、`kernel_config`、`dist_config` 等插件配置通过 `name` 选择具体实现,其余字段由对应实现解析;可用名称和字段统一列在所属的参数页面中。 + +```yaml +model: Qwen/Qwen3-0.6B +train_dataset: data/v1_sft_demo.yaml + +output_dir: outputs/qwen3_sft +micro_batch_size: 1 +learning_rate: 1.0e-4 +max_steps: 10 + +dist_config: + name: fsdp2 + +kernel_config: + name: liger_kernel +``` + +## 参数分类 + +| 页面 | 参数 | +|------|------| +| [数据参数](data.md) | `DataArguments`、`DatasetInfo` | +| [模型参数](model.md) | `ModelArguments`、PEFT、量化、初始化和 Kernel | +| [训练参数](training.md) | `TrainingArguments`、分布式和优化器 | +| [推理参数](inference.md) | `SampleArguments` | + +功能指南中的示例只列出完成对应任务所需的字段。字段类型、默认值和可用选项以本目录为准。 diff --git a/docs/zh/configuration/inference.md b/docs/zh/configuration/inference.md new file mode 100644 index 000000000..5fe1c4ee9 --- /dev/null +++ b/docs/zh/configuration/inference.md @@ -0,0 +1,10 @@ +# 推理参数 + +## SampleArguments + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `sample_backend` | `str` | `hf` | 采样后端;可用值为 `hf` | +| `max_new_tokens` | `int` | `128` | 单次最多生成 token 数 | + +使用方法见[推理](../feature-guide/inference.md)。 diff --git a/docs/zh/configuration/model.md b/docs/zh/configuration/model.md new file mode 100644 index 000000000..4474cf39b --- /dev/null +++ b/docs/zh/configuration/model.md @@ -0,0 +1,119 @@ +# 模型参数 + +## ModelArguments + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `model` | `str` | `Qwen/Qwen3-4B-Instruct-2507` | 本地模型路径或 Hub ID | +| `custom_chat_template` | `str \| None` | `None` | 覆盖 tokenizer/processor 的 Jinja2 chat template | +| `trust_remote_code` | `bool` | `false` | 是否加载 Hub 远端代码 | +| `flash_attn` | `str` | `sdpa` | `eager`、`sdpa` 或 `flash_attention_2` | +| `model_class` | `str` | `llm` | `llm`、`cls` 或 `other` | +| `init_config` | `dict \| None` | `None` | 模型初始化配置 | +| `peft_config` | `dict \| None` | `None` | LoRA 或 Freeze 配置 | +| `kernel_config` | `dict \| None` | `None` | 融合算子加速配置 | +| `quant_config` | `dict \| None` | `None` | 量化配置 | + +`llm` 加载因果语言模型或 image-to-text 模型,`cls` 加载单标签 token +classification 模型,`other` 使用 `AutoModel`。 + +## peft_config + +### LoRA + +设置 `name: lora`: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `r` | `int` | `8` | LoRA rank | +| `lora_alpha` | `int` | `16` | LoRA alpha | +| `lora_dropout` | `float` | `0.05` | LoRA dropout | +| `target_modules` | `list[str] \| str` | `all` | 目标模块 | +| `use_rslora` | `bool` | `false` | 是否启用 RS-LoRA | +| `use_dora` | `bool` | `false` | 是否启用 DoRA | +| `modules_to_save` | `list[str] \| None` | `None` | 额外保存模块 | +| `adapter_name_or_path` | `list[str] \| str \| None` | `None` | adapter 路径 | +| `export_dir` | `str \| None` | `None` | 合并导出目录 | +| `export_size` | `int` | `5` | 导出分片大小,GB | +| `export_hub_model_id` | `str \| None` | `None` | Hub 仓库 ID | +| `infer_dtype` | `str` | `auto` | `auto`、`float16`、`float32` 或 `bfloat16` | +| `export_legacy_format` | `bool` | `false` | 是否使用旧式权重格式 | + +### Freeze + +设置 `name: freeze`: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `freeze_trainable_layers` | `int` | `2` | 正数选择最后 N 层,负数选择最前 N 层 | +| `freeze_trainable_modules` | `list[str] \| str` | `all` | 层内可训练模块 | +| `freeze_extra_modules` | `list[str] \| str \| None` | `[]` | 额外可训练模块 | +| `cast_trainable_params_to_fp32` | `bool` | `true` | 是否将可训练参数转换为 fp32 | + +## quant_config + +当前 v1 注册了 `bnb` 和 `auto` 两个量化插件入口。`bnb` 使用 bitsandbytes;`auto` 在指定有效位宽后也转交 `bnb`,当前没有按模型或环境切换到其他量化后端的逻辑。 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `name` | `str` | 必填 | `bnb` 或 `auto` | +| `quantization_bit` | `int \| None` | `None` | 量化加载位宽,4 或 8 | +| `compute_dtype` | `str \| torch.dtype` | `float16` | 4-bit 计算和存储 dtype | +| `double_quantization` | `bool` | `true` | 是否启用 4-bit double quant | +| `quantization_type` | `str` | `nf4` | 4-bit 量化格式,`nf4` 或 `fp4` | + +4-bit 分支将 `compute_dtype`、`double_quantization` 和 `quantization_type` 传给 [Hugging Face BitsAndBytesConfig](https://huggingface.co/docs/transformers/main_classes/quantization#transformers.BitsAndBytesConfig),其中 NF4 和 FP4 是 bitsandbytes 的两种 4-bit 格式。8-bit 分支设置 `load_in_8bit=True`,不使用这三个 4-bit 专属字段。 + +`quantization_bit` 的字段默认值为 `None`,实际行为取决于 `name`: + +- 不设置 `quant_config` 或将其设为 `null` 时,不通过此插件添加量化加载配置。 +- `name: auto` 且省略 `quantization_bit`(或设为 `null`)时,保持模型加载参数不变。 +- `name: bnb` 且省略 `quantization_bit`(或设为 `null`)时,使用 4-bit 量化。 +- `name: auto` 且指定 `quantization_bit` 为 `4` 或 `8` 时,转交 `bnb` 实现处理,仍需满足该实现的依赖和运行条件。 + +以上描述插件构造量化加载配置的行为。[SFT 的 QLoRA 示例](../feature-guide/sft.md#qlora)展示 `bnb`、4-bit、NF4 与 LoRA 的组合。 + +## init_config + +`init_config` 当前只使用 `name` 选择模型初始化设备: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `name` | `str` | 必填 | 初始化插件名称 | + +| `name` 取值 | 初始化设备 | +|-------------|------------| +| `init_on_default` | 当前分布式设备 | +| `init_on_meta` | meta device | +| `init_on_rank0` | rank 0 使用 CPU,其余 rank 使用 meta | + +meta 初始化不能与量化同时使用。 + +## kernel_config + +`kernel_config` 可以配置单个融合算子,也可以启用 Liger Kernel 这类包含多项优化的外部加速库。 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `name` | `str` | 必填 | `auto`、单个实现名称或逗号分隔的多个名称 | + +可用名称: + +- `liger_kernel` +- `cuda_fused_moe` +- `flash-linear-attention` +- `npu_fused_moe` +- `npu_fused_rmsnorm` +- `npu_fused_rope` +- `npu_fused_swiglu` + +### Flash Linear Attention + +当 `name` 包含 `flash-linear-attention` 时,可以使用以下专属字段: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `include_kernels` | `str` | `auto` | `auto` 或逗号分隔的 FLA 算子名称 | +| `chunk_size` | `int` | `64` | chunk size;可选 `16`、`32`、`64` | + +用法见[融合算子加速](../feature-guide/kernel_acceleration.md)。 diff --git a/docs/zh/configuration/training.md b/docs/zh/configuration/training.md new file mode 100644 index 000000000..214290be1 --- /dev/null +++ b/docs/zh/configuration/training.md @@ -0,0 +1,125 @@ +# 训练参数 + +## TrainingArguments + +### 训练过程与精度 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `output_dir` | `str` | `outputs/` | 输出目录 | +| `micro_batch_size` | `int` | `1` | 基础 micro-batch 大小 | +| `global_batch_size` | `int \| None` | `None` | 默认 `dp_size × micro_batch_size` | +| `cutoff_len` | `int` | `2048` | 最大序列长度 | +| `learning_rate` | `float` | `1e-4` | 训练及优化器插件使用的学习率 | +| `num_train_epochs` | `int` | `3` | 训练轮数 | +| `max_steps` | `int \| None` | `None` | 设置后使用 step 作为终止条件 | +| `max_grad_norm` | `float` | `1.0` | 梯度裁剪阈值 | +| `bf16` | `bool` | `true` | 是否使用 bf16 | +| `seed` | `int` | `42` | 随机种子 | +| `full_determinism` | `bool` | `false` | 是否启用完整确定性模式 | + +`global_batch_size` 与 `micro_batch_size` 共同决定每次参数更新需要累积多少个 micro-batch。省略 `global_batch_size` 时,每个 DP 进程每次更新处理一个 micro-batch;显式设置时,它必须能被 `dp_size × micro_batch_size` 整除,每个进程的累积次数为 `global_batch_size / (dp_size × micro_batch_size)`。 + +例如,`dp_size: 4`、`micro_batch_size: 2`、`global_batch_size: 32` 对应每个 DP 进程累积 4 个 micro-batch。固定样本数策略下,一次更新共使用 32 条样本;动态策略中的实际样本数随长度变化,`global_batch_size` 仍决定累积次数,token 预算见[批处理策略](../feature-guide/batching.md)。 + +### 批处理配置 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `batching_strategy` | `str` | `normal` | `normal`、`padding_free`、`dynamic_batching` 或 `dynamic_padding_free` | +| `batching_workers` | `int` | `16` | 数据加载 worker 数 | +| `enable_activation_checkpointing` | `bool` | `true` | 是否启用激活值重算 | + +各策略的 token 预算和使用约束见[批处理策略](../feature-guide/batching.md)。 + +### 分布式与优化器 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `dist_config` | `dict \| None` | `None` | FSDP2、FSDPTurbo 或 DeepSpeed 配置 | +| `dp_size` | `int \| None` | `None` | 默认由 world size 和 `cp_size` 推导 | +| `cp_size` | `int` | `1` | Context Parallel 大小 | +| `cp_mode` | `str` | `ulysses` | Context Parallel 实现 | +| `mp_replicate_size` | `int` | `1` | FSDP 二维 Mesh 的参数复制维度大小 | +| `mp_shard_size` | `int \| None` | `None` | FSDP 二维 Mesh 的参数分片维度大小;默认由 world size 推导 | +| `dist_timeout` | `int` | `18000` | 进程组初始化超时,秒 | +| `optim_config` | `dict \| None` | `None` | 优化器插件 | +| `lr_scheduler_config` | `dict \| None` | `None` | 学习率调度插件;当前没有内置实现 | + +### Checkpoint 与日志配置 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `resume_from_checkpoint` | `str \| None` | `None` | checkpoint 路径或 `auto` | +| `save_steps` | `int \| None` | `None` | 每 N 个全局 step 保存 | +| `save_epochs` | `float \| None` | `None` | 每 N 个 epoch 保存 | +| `save_ckpt_as_hf` | `bool` | `false` | 是否在中间 checkpoint 中额外保存 HF 格式模型 | +| `save_total_limit` | `int \| None` | `None` | 最多保留数量 | +| `logging_steps` | `int` | `1` | 日志间隔 | + +### 偏好优化参数 + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `pref_loss` | `str` | `sigmoid` | `sigmoid`、`orpo` 或 `simpo` | +| `pref_beta` | `float` | `0.1` | DPO beta | +| `pref_ftx` | `float` | `0.0` | SFT 损失系数 | +| `simpo_gamma` | `float` | `0.5` | SimPO reward margin | +| `dpo_label_smoothing` | `float` | `0.0` | cDPO label smoothing | +| `ld_alpha` | `float \| None` | `None` | LD-DPO 长度差异权重 | + +## dist_config + +### FSDP2 + +设置 `name: fsdp2`: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `reshard_after_forward` | `bool` | `true` | forward 后是否重新分片 | +| `offload_params` | `bool` | `false` | 是否 offload 参数 | +| `pin_memory` | `bool` | `true` | 是否使用 pinned memory | +| `dcp_path` | `str \| None` | `None` | 初始化 DCP 权重路径 | + +### DeepSpeed + +设置 `name: deepspeed`: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `config_file` | `str` | 必填 | DeepSpeed JSON 配置 | + +### FSDPTurbo + +设置 `name: fsdpturbo`: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `reshard_after_forward` | `bool` | `true` | forward 后是否重新分片 | +| `offload_params` | `bool` | `false` | 是否 offload 参数 | +| `pin_memory` | `bool` | `true` | 是否使用 pinned memory | +| `dcp_path` | `str \| None` | `None` | 初始化 DCP 权重路径 | +| `ep_size` | `int` | `1` | 专家并行组大小 | +| `ep_dispatcher` | `str` | `eager` | 专家 token dispatcher | +| `fsdp_ignored_modules` | `list[str]` | `[]` | 外层 FSDP2 忽略的额外模块 | +| `hook_modules` | `list[str]` | `[]` | EFSDP hook 的模块模式 | +| `fsdp_implementation` | `str` | `native` | `native` 或 `custom` | + +`dp_size`、`cp_size`、`mp_replicate_size` 和 `mp_shard_size` 是 `TrainingArguments` 字段,不放在 `dist_config` 中。 + +## optim_config + +设置 `name: muon`: + +| 字段 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `wd` | `float` | `0.1` | weight decay | +| `momentum` | `float` | `0.95` | Muon momentum | +| `nesterov` | `bool` | `true` | 是否启用 Nesterov | +| `ns_steps` | `int` | `5` | Newton-Schulz 步数 | +| `adamw_betas` | `list[float]` | `[0.9, 0.95]` | 内部 AdamW betas | +| `adamw_eps` | `float` | `1e-8` | 内部 AdamW epsilon | + +学习率统一使用顶层 `learning_rate`。 + +Muon 的完整配置示例见[优化器](../feature-guide/optimizer.md)。 diff --git a/docs/zh/data-preparation/data-processing.md b/docs/zh/data-preparation/data-processing.md deleted file mode 100644 index 5d568bbe1..000000000 --- a/docs/zh/data-preparation/data-processing.md +++ /dev/null @@ -1,479 +0,0 @@ -# LLaMA-Factory v1 数据预处理 - -## 总览 - -LLaMA-Factory `v1` 采用了全新的数据处理架构,主要包含以下核心组件: - -- **DataEngine**:数据引擎,负责数据集的加载、索引和转换等各种插件的接入和调用,并提供数据访问接口 -- **DataConverterPlugin**:数据转换器,将非标准格式转换为统一的标准格式 -- **DataLoaderPlugin**:数据加载插件,支持多种文件格式的加载 -- **DataIndexPlugin**:数据索引插件,支持数据集的采样和权重调整 -- **DataSelectorPlugin**:数据选择插件,支持灵活的数据访问方式 - -与 LLaMA-Factory `v0` 版本相比,`v1` 版本采用了统一的数据格式(Messages Format),所有数据都会被转换为标准的对话消息列表;此外,`v1` 版本通过 DataEngine 与 Plugin 机制,提供了自定义数据处理流的接口,具有更好的可扩展性和一致性。 - ---- - -## 目录 - -- [基本用法](#基本用法) -- [标准数据格式](#标准数据格式) -- [数据集配置文件](#数据集配置文件) -- [完整示例](#完整示例) - ---- - -## 基本用法 - -### 在训练配置文件,可以通过如下方式配置数据集: - -
-方式 1:使用 HF Hub Repo ID - -直接指定 HF Hub 上的数据集 Repo ID,DataEngine 会自动从 HF Hub 下载并加载数据集。 - -注:使用 Repo ID 直接加载的数据集需要为标准格式 - -**训练配置文件示例:** - -```yaml -# example_sft.yaml - -... - -dataset: llamafactory/v1-sft-demo # HF Hub Repo ID - -... -``` - -
- -
-方式 2:使用 HF Hub 上的 YAML 配置文件 - -`dataset`字段指定 HF Hub 上的 `dataset_info.yaml` 的 URI,DataEngine 会自动下载该配置文件并根据其中的配置加载数据集。 - -**训练配置文件示例:** - -```yaml -# example_sft.yaml - -... - -dataset: llamafactory/v1-sft-demo/dataset_info.yaml # 远程 dataset_info.yaml 路径 - -... - -``` - -
- -
-方式 3:使用本地 HF 数据集文件路径 - -`dataset`字段指定本地的数据集文件路径(`.json`、`.jsonl` 等) - -注:直接指定数据集文件路径,要求该数据文件的格式已为标准格式 - -**训练配置文件示例:** - -```yaml -# example_sft.yaml - -... - -dataset: ~/data/v1_sft_demo.jsonl # 本地数据集文件绝对路径 - -... -``` - -
- -
-方式 4:使用本地 YAML 配置文件路径 - -`dataset`字段指定本地的 `dataset_info.yaml` 配置文件路径,DataEngine 会根据该配置加载其中的数据集。 - -**训练配置文件示例:** - -```yaml -# example_sft.yaml - -... - -dataset: ~/data/dataset_info.yaml # 本地 dataset_info.yaml 文件路径 - -... -``` - -
- - ---- - - - -## 标准数据格式 - -v1 使用统一的 **Messages 格式**作为标准数据格式。每个样本都是一个包含 `messages` 字段的 JSON 对象。 - -针对alpaca、sharegpt、以及dpo等格式的数据,可以通过内置的`DataConverterPlugin`插件,自动将其转化为标准格式,对于其他自定义格式的数据,用户也可通过自定义`DataConverterPlugin`来实现数据格式标准化,这部分内容参见[`DataConverterPlugin`](../dev-guide/plugins/data-plugins.md/#data-converter-plugin) - -### 1. SFT(监督微调)样本格式 - - -```json -{ - "messages": [ - { - "role": "system", - "content": [{"type": "text", "value": "You are a helpful assistant."}], - "loss_weight": 0.0 - }, - { - "role": "user", - "content": [{"type": "text", "value": "Hello, who are you?"}], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [{"type": "text", "value": "I am an AI assistant."}], - "loss_weight": 1.0 - } - ] -} -``` - -#### 字段说明: - -- **messages**: 消息列表,包含一轮或多轮对话 - - **role**: 消息角色,可选值: - - `"system"`: 系统提示 - - `"user"`: 用户输入 - - `"assistant"`: 模型回复 - - **content**: 内容列表,每个元素包含: - - **type**: 内容类型,可选值: - - `"text"`: 文本内容 - - `"image_url"`: 图像 URL(多模态) - - `"audio_url"`: 音频 URL(多模态) - - `"video_url"`: 视频 URL(多模态) - - `"tools"`: 工具描述 - - `"tool_calls"`: 工具调用 - - `"reasoning"`: 推理过程 - - **value**: 具体内容(字符串) - - **loss_weight**: 损失权重(浮点数) - - `0.0`: 不计算损失(用于提示词部分) - - `1.0`: 完全计算损失(用于回复部分) - - 可设置为其他值以调整不同部分的学习权重 - -- **_dataset_name** (可选): 数据集名称,由 DataEngine 自动添加 -- **extra_info** (可选): 额外信息字段 - -### 2. DPO(偏好对齐)样本格式 - -```json -{ - "chosen_messages": [ - { - "role": "user", - "content": [{"type": "text", "value": "用户提问"}], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [{"type": "text", "value": "更优的回答"}], - "loss_weight": 1.0 - } - ], - "rejected_messages": [ - { - "role": "user", - "content": [{"type": "text", "value": "用户提问"}], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [{"type": "text", "value": "较差的回答"}], - "loss_weight": 1.0 - } - ] -} -``` - -### 3. 多模态支持 - -对于多模态数据,可以在 `content` 列表中添加非文本类型的内容: - -```json -{ - "messages": [ - { - "role": "user", - "content": [ - {"type": "text", "value": "这张图片里有什么?"}, - {"type": "image_url", "value": "path/to/image.jpg"} - ], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [{"type": "text", "value": "图片中有一只猫。"}], - "loss_weight": 1.0 - } - ] -} -``` - -**说明**:`image_url`、`audio_url`、`video_url` 的路径可以是相对路径或绝对路径,具体加载方式由 `DataLoaderPlugin` 决定。 - ---- - -## 数据集配置文件 - -### 1. dataset_info.yaml 配置文件格式 - -`dataset_info.yaml` 支持同时配置多个数据集,支持分别从 HF Hub 和本地获取数据集,数据集默认会混合并打乱顺序。 - -**示例配置文件:`data/dataset_info.yaml`** - -```yaml -# 数据集 1:使用本地文件 + Alpaca 转换器 -identity: - file_name: ~/data/identity.json #本地数据集文件绝对路径 - converter: alpaca # 使用 alpaca 转换器 - -# 数据集 2:指定自定义数据集目录 -alpaca_en_demo: - file_name: ~/data/alpaca_en_demo.json # 数据集文件名 - converter: alpaca # 转换器插件 - size: 500 # 只使用 500 个样本 - weight: 0.5 # 数据集权重,用于控制该数据集的采样频率 - split: train # 数据集划分,默认为 train - streaming: false # 是否流式加载,默认为 false - -# 数据集 3:从 Hugging Face Hub 加载 -hf_dataset: - hf_hub_url: llamafactory/v1-sft-demo # HF repo ID - streaming: false - -# 数据集 4:已经是标准格式,无需转换器 -standard: - file_name: ~/data/v1_sft_demo.jsonl # 本地标准数据集文件路径 - -# 数据集 5:自定义数据集和 converter 插件 -custom_dataset: - file_name: custom_data.json - converter: custom_converter - weight: 1.0 -``` - -### 2. 配置字段说明 - -#### 数据源配置(二者必选其一): - -- **hf_hub_url** (str): Hugging Face Hub 数据集仓库 ID - - 示例:`"llamafactory/v1-sft-demo"` - - 如果指定,则从 HF Hub 加载数据集 - -- **file_name** (str): 本地文件路径 - - 支持格式:`.json`、`.jsonl`、`.csv`、`.parquet`、`.arrow`、`.txt` - -#### 可选配置: - -- **split** (str): 数据集划分,默认为 `"train"` -- **converter** (str): 数据转换器名称 - - 可选值:`"alpaca"`(更多转换器持续添加中,也可在 data_plugin 中添加自定义 converter) - - 如果不指定,则假定数据已是标准格式 -- **size** (int): 使用的样本数量,默认使用全部 -- **weight** (float): 数据集权重,用于混合数据集时的采样频率,默认为 1.0 -- **streaming** (bool): 是否流式加载,默认为 `False` - ---- - - -## 完整示例 - -### 1. 基础使用示例 - -```python -from llamafactory.v1.config.data_args import DataArguments -from llamafactory.v1.core.data_engine import DataEngine - -# 使用本地 YAML 配置 -data_args = DataArguments( - dataset="~/data/v1_sft_demo.jsonl", - cutoff_len=2048 -) - -# 初始化 DataEngine -engine = DataEngine(data_args=data_args) - -# 查看数据集信息 -print(f"数据集总样本数: {len(engine)}") -print(f"数据集列表: {list(engine.datasets.keys())}") - -# 访问数据样本 -sample = engine[0] -print(f"样本格式: {sample.keys()}") -print(f"消息列表: {sample['messages']}") - -# 批量访问 -batch = engine[0:10] -print(f"批量样本数: {len(batch)}") -``` - -### 2. 输出示例 - -**查看数据集信息输出:** - -``` -数据集总样本数: 500 -数据集列表: ['default'] -样本格式: dict_keys(['_dataset_name', 'messages']) -消息列表: [{'role': 'user', 'content': [{'type': 'text', 'value': 'hi'}], 'loss_weight': 0.0}, {'role': 'assistant', 'content': [{'type': 'text', 'value': 'Hello! I am {{name}}, an AI assistant developed by {{author}}. How can I assist you today?'}], 'loss_weight': 1.0}] -批量样本数: 10 -``` - -**访问单个样本输出:** - -```python -{ - '_dataset_name': 'alpaca_en_demo', - 'messages': [ - { - 'role': 'user', - 'content': [{'type': 'text', 'value': 'What is the capital of France?'}], - 'loss_weight': 0.0 - }, - { - 'role': 'assistant', - 'content': [{'type': 'text', 'value': 'The capital of France is Paris.'}], - 'loss_weight': 1.0 - } - ] -} -``` - -### 3. 混合多数据集配置文件示例 - -**配置文件:`data/mixed_datasets.yaml`** - -```yaml -dataset_1: - file_name: alpaca_en_demo.json - converter: alpaca - weight: 1.0 - -dataset_2: - file_name: identity.json - converter: alpaca - weight: 2.0 - -dataset_3: - hf_hub_url: llamafactory/v1-sft-demo - weight: 1.5 -``` - - -### 4. 多模态数据示例 - -**数据文件:`data/multimodal_demo.jsonl`** - -标准化后数据示例: - -```json -[ - { - "messages": [ - { - "role": "user", - "content": [ - {"type": "text", "value": "Who are they?"}, - {"type": "image_url", "value": "mllm_demo_data/1.jpg"} - ], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [ - {"type": "text", "value": "They're Kane and Gretzka from Bayern Munich."} - ], - "loss_weight": 1.0 - }, - { - "role": "user", - "content": [ - {"type": "text", "value": "What are they doing?"}, - {"type": "image_url", "value": "mllm_demo_data/1.jpg"} - ], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [ - {"type": "text", "value": "They are celebrating on the soccer field."} - ], - "loss_weight": 1.0 - } - ] - }, - { - "messages": [ - { - "role": "user", - "content": [ - {"type": "text", "value": "Who is he?"}, - {"type": "image_url", "value": "mllm_demo_data/2.jpg"} - ], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [ - {"type": "text", "value": "He's Thomas Muller from Bayern Munich."} - ], - "loss_weight": 1.0 - }, - { - "role": "user", - "content": [ - {"type": "text", "value": "Why is he on the ground?"} - ], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [ - {"type": "text", "value": "Because he's sliding on his knees to celebrate."} - ], - "loss_weight": 1.0 - } - ] - } -] -``` - -```python -from llamafactory.v1.config.data_args import DataArguments -from llamafactory.v1.core.data_engine import DataEngine - -data_args = DataArguments(dataset="data/multimodal_demo.jsonl") -engine = DataEngine(data_args=data_args) - -# 访问多模态样本 -sample = engine[0] -print("用户消息内容:") -for content_item in sample['messages'][0]['content']: - print(f" 类型: {content_item['type']}, 值: {content_item['value']}") -``` - ---- - -**注意事项**: - -1. 所有数据最终都会转换为标准的 Messages 格式 -2. 通过 `converter` 插件可以支持多种数据格式 -3. 通过 `weight` 和 `size` 参数可以灵活控制数据分布 -4. 支持同时使用本地数据集和 HuggingFace Hub 数据集 -5. 多模态数据通过在 `content` 中添加不同类型的元素来支持 -6. 更多细节信息请参考我们的 [API REFERENCE](../dev-guide/core/data-engine.md/#data-engine) diff --git a/docs/zh/dev-guide/core/data-engine.md b/docs/zh/dev-guide/core/data-engine.md deleted file mode 100644 index a78064f16..000000000 --- a/docs/zh/dev-guide/core/data-engine.md +++ /dev/null @@ -1,253 +0,0 @@ -# DataEngine - -## 1. DataEngine 简介 - - -`DataEngine` 是 LLaMA-Factory v1 数据处理的核心类,继承自 PyTorch 的 `Dataset`,负责各种插件的接入,其他功能(如数据格式转换、数据加载等)均通过插件的形式实现并接入 `DataEngine`。 - -`DataEngine`接受一个唯一入参:`DataArguments` 实例,所有的元数据集信息均通过该参数配置传入。 - -## 2. DataEngine 与 DataArguments 接口定义 - -```python -@dataclass -class DataArguments: - """ `DataEngine`初始化入参 - - args: - dataset (str): 数据集路径,远程数据集 repo id / dataset_info.yaml 路径,或本地数据集路径/dataset_info.yaml路径 - cutoff_len (int): 数据集截止长度,即数据集最大样本采样数量 - """ - ... - - -class DataEngine(Dataset): - """数据引擎(DataEngine) - - `DataEngine` 负责数据集的加载与统一管理,支持: - - 从本地路径或 Hugging Face Hub 加载数据 - - 通过插件机制加载自定义数据 - - 构建统一的数据索引 - - 支持流式(streaming)与非流式数据访问 - - attr: - args (DataArguments): 数据参数配置 - datasets (dict[str, HFDataset]): 数据集名称到数据对象的映射 - dataset_infos (dict[str, DatasetInfo]): 数据集名称到元信息的映射 - data_index (list[tuple[str, int]]): 数据索引列表,每项为 (dataset_name, sample_index) - streaming (bool): 是否为流式数据集 - """ - - def __init__(self, data_args: DataArguments) -> None: - """初始化 `DataEngine` - - 初始化时自动执行以下步骤: - 1. 调用 `get_dataset_info`, 从 `data_args` 读取并解析数据集元信息 - 2. 调用 `load_dataset`,根据配置加载数据集 - 3. 调用 `build_data_index`,构建统一的索引列表 - - args: - data_args (DataArguments): 数据参数配置对象 - """ - ... - - def get_dataset_info(self) -> None: - """从配置文件或远程仓库加载数据集元信息 - - 根据 `self.args.dataset` 确定数据源,数据源支持如下选项: - - 本地 YAML 配置文件路径 - - Hugging Face Hub 上的 YAML 配置文件路径 - - 本地数据集文件路径 - - Hugging Face Hub 数据集 repo id - - """ - ... - - def load_dataset(self) -> None: - """根据数据集元信息加载所有数据集 - - 每个数据集条目可以包含以下字段: - - `hf_hub_url`: 使用 `datasets.load_dataset` 加载 - - 本地数据文件:通过 `DataLoaderPlugin` 插件加载 - - `streaming`: 是否启用流式模式 - - 更新: - self.datasets (dict): 数据集名称到已加载数据对象的映射 - self.streaming (bool): 如果任一数据集为流式模式,则设置为 True - """ - ... - - def build_data_index(self) -> None: - """构建统一的数据索引 - - 为所有数据集创建全局索引列表 `(dataset_name, sample_index)` - - 当启用流式模式时,生成固定长度(例如 1000)的占位索引; - 否则,为每条样本建立索引。 - - 插件 `DataIndexPlugin` 可根据数据集大小或权重调整索引分布 - """ - ... - - def _convert_data_sample(self, raw_sample: dict[str, Any], dataset_name: str) -> Sample: - """将原始样本转换为统一格式 - - 根据 `dataset_info` 中的 `converter` 字段,调用对应的转换插件, - 将原始样本标准化为统一的数据结构。 - - args: - raw_sample (dict[str, Any]): 原始数据样本 - dataset_name (str): 样本所属的数据集名称 - - return: - Sample: 转换后的标准化格式样本 - """ - ... - - def __len__(self) -> int: - """返回数据集的总样本数 - - return: - int: 数据集长度 - 如果为流式数据集,返回 `-1` - """ - ... - - def __getitem__(self, index: Union[int, Any]) -> Union[Sample, list[Sample]]: - """根据索引或选择器获取样本 - - args: - index (Union[int, Any]): 数据索引,int 或 list[int] - - return: - Union[Sample, list[Sample]]: 单个样本或样本列表 - """ - ... - - def __iter__(self) -> Iterable: - """返回数据集迭代器 - - 用于非流式数据集的顺序或随机访问 - 流式模式下需要实现异步加载逻辑 - - return: - Iterable: 数据集迭代器。 - """ - ... - - async def __aiter__(self) -> AsyncIterable: - """返回异步数据集迭代器 - - 用于流式数据集或异步数据加载场景 - 允许在异步环境中以流的方式读取样本 - - return: - AsyncIterable: 异步迭代器,按顺序产出样本 - """ - ... - - -``` - -`DataArguments` 参数说明: - -`dataset`: 数据集路径,支持本地或远程,当传入本地数据集文件路径时,需要满足该数据集为标准格式;否则需要传入 `dataset_info.yaml` 来配置数据集的 `converter` 等元信息,以告知 `DataEngine` 应当如何处理该数据。 - -`cutoff_len`: 数据集的截止长度,即该数据集的最大样本数量。 - ---- - -## 3. DataEngine 核心方法 - -### 3.1 `get_dataset_info`:加载数据元信息 - -根据 `dataset` 参数加载数据集配置,获取数据位置、数据格式、插件配置等所有数据元信息,在实例化 `DataEngine` 时会自动调用此方法。 - -### 3.2 加载数据集:`load_dataset` - -遍历所有数据源,根据不同的数据源加载数据,在实例化 `DataEngine` 时会自动调用此方法。 - -```python -for key, value in self.dataset_infos.items(): - split = value.get("split", "train") - streaming = value.get("streaming", False) - - if "hf_hub_url" in value: - # 从 HF Hub 加载 - dataset = load_dataset(value["hf_hub_url"], split=split, streaming=streaming) - else: - # 使用 DataLoaderPlugin 加载本地文件 - dataset = DataLoaderPlugin(args=self.args).auto_load_data(value) - - self.datasets[key] = dataset -``` - -### 3.3 `build_data_index`:构建数据索引 - -为每个数据集创建索引列表 `[(dataset_name, sample_index), ...]`, `DataIndexPlugin`插件在此处被调用,可控制各数据集的采样频率、采样方式等,在实例化`DataEngine`时会自动调用此方法。 - -```python -for dataset_name, dataset in self.datasets.items(): - # 创建基础索引 - data_index = [(dataset_name, idx) for idx in range(len(dataset))] - - # 根据 size 和 weight 调整索引 - size = self.dataset_infos[dataset_name].get("size") - weight = self.dataset_infos[dataset_name].get("weight") - if size or weight: - data_index = DataIndexPlugin().adjust_data_index(data_index, size, weight) - - self.data_index.extend(data_index) -``` - -### 3.4 `_convert_data_sample`:数据格式标准化 - -将原始数据转换为标准格式,`DataConverterPlugin`插件在此处被调用,具体调用的插件由 `get_dataset_info` 方法获取的 `converter` 信息指定,若 `converter` 为空则假定数据集为标准格式,此方法由`DataEngine`的 `__getitem__` 方法调用。 - -```python -def _convert_data_sample(self, raw_sample: dict, dataset_name: str) -> Sample: - converter = self.dataset_infos[dataset_name].get("converter") - if converter is not None: - # 使用指定的转换器 - from ..plugins.data_plugins.converter import get_converter - return {"_dataset_name": dataset_name, **get_converter(converter)(raw_sample)} - else: - # 已经是标准格式 - return {"_dataset_name": dataset_name, **raw_sample} -``` - ---- - -## 4. 初始化 - -`DataEngine` 初始化过程只需传入一个构建好的 `DataArguments` 即可,后续可通过该 `DataEngine` 访问数据集中的数据。 - -```python -from llamafactory.v1.config.data_args import DataArguments -from llamafactory.v1.core.data_engine import DataEngine - -# 1. 创建数据参数 -data_args = DataArguments( - dataset="~/data/v1_sft_demo.jsonl", - cutoff_len=2048 -) - -# 2. 初始化 Data Engine -data_engine = DataEngine(data_args=data_args) - -# 3. 访问数据 -sample = data_engine[0] # 获取第一个样本 -``` - -## 5. 数据访问方式 - -实例化后的`DataEngine`支持整数索引、列表索引、以及切片等访问方式,其数据读取用法可等价于 Python 列表。 - -```python -sample = data_engine[0] # 获取第一个样本 - -sample = data_engine[0:10] # 获取前 10 个样本 - -sample = data_engine[[0, 5, 10]] # 获取指定索引的样本 - -``` diff --git a/docs/zh/dev-guide/core/model-engine.md b/docs/zh/dev-guide/core/model-engine.md deleted file mode 100644 index bec23e077..000000000 --- a/docs/zh/dev-guide/core/model-engine.md +++ /dev/null @@ -1 +0,0 @@ -# ModelEngine diff --git a/docs/zh/dev-guide/core/trainer.md b/docs/zh/dev-guide/core/trainer.md deleted file mode 100644 index 6be20bca4..000000000 --- a/docs/zh/dev-guide/core/trainer.md +++ /dev/null @@ -1 +0,0 @@ -# Trainer diff --git a/docs/zh/dev-guide/plugins/data-plugins.md b/docs/zh/dev-guide/plugins/data-plugins.md deleted file mode 100644 index acee27b52..000000000 --- a/docs/zh/dev-guide/plugins/data-plugins.md +++ /dev/null @@ -1,467 +0,0 @@ -# Data Plugins - -## 1. Data Plugins 简介 - -## DataConverterPlugin - -### 1. DataConverterPlugin 简介 - -DataConverter 负责将非标准格式的数据集转换为 v1 的标准 Messages 格式。这使得用户可以继续使用现有的数据集(如 Alpaca 格式),而无需手动转换。针对自定义格式的数据集,用户也可以通过构建对应的自定义 DataConverter 插件,来负责其数据格式标准化。 - -当前,LLaMA-Factory 已内置了 `Alpaca Converter` 和 `Pair Converter`,这两类数据集可以直接使用对应的 converter 进行标准化,无需自定义转换器。 - - -### 2. Alpaca Converter 详解 - -#### 2.1 Alpaca 格式 - -Alpaca 格式是一种常见的指令微调数据格式: - -```json -{ - "system": "You are a helpful assistant.", - "instruction": "Describe a process of making crepes.", - "input": "", - "output": "Making crepes is an easy and delicious process..." -} -``` - -#### 2.2 Alpaca Converter 接口定义 - -```python -class AlpacaSample(TypedDict, total=False): - """Alpaca 格式数据样本结构 - - attr: - system (str, 可选): 系统提示信息(system prompt),用于设定对话背景或模型行为。 - instruction (str, 可选): 用户指令(user instruction),通常为任务描述。 - input (str, 可选): 额外的输入内容(input text),可与 instruction 拼接。 - output (str, 可选): 模型生成的目标输出(expected response)。 - """ - ... - - -def alpaca_converter(raw_sample: AlpacaSample) -> SFTSample: - """将 Alpaca 样本转换为 SFT(Supervised Fine-Tuning)标准样本格式 - - `alpaca_converter` 将 Alpaca 数据集中一条样本转换为通用的 `SFTSample` 格式 - 该格式用于监督微调(SFT)或多轮对话建模 - - 转换逻辑: - - 若存在 `system` 字段,则生成一条系统消息,loss_weight = 0.0 - - 若存在 `instruction` 或 `input` 字段,则合并为一条用户消息,loss_weight = 0.0 - - 若存在 `output` 字段,则生成一条助手机器人回复消息,loss_weight = 1.0 - - args: - raw_sample (AlpacaSample): 原始 Alpaca 数据样本 - - return: - SFTSample: 转换后的标准化样本,格式如下: - - { - "messages": [ - {"role": "system", "content": [{"type": "text", "value": "..."}], "loss_weight": 0.0}, - {"role": "user", "content": [{"type": "text", "value": "..."}], "loss_weight": 0.0}, - {"role": "assistant", "content": [{"type": "text", "value": "..."}], "loss_weight": 1.0}, - ] - } - - example: - >>> raw = {"instruction": "请将以下句子翻译成英文:", "input": "你好", "output": "Hello"} - >>> alpaca_converter(raw) - { - "messages": [ - {"role": "user", "content": [{"type": "text", "value": "请将以下句子翻译成英文:你好"}], "loss_weight": 0.0}, - {"role": "assistant", "content": [{"type": "text", "value": "Hello"}], "loss_weight": 1.0} - ] - } - """ - -``` - -#### 2.3 转换过程 - -`alpaca_converter` 函数将 Alpaca 格式转换为标准格式,转换逻辑如下: - -```python -def alpaca_converter(raw_sample: AlpacaSample) -> SFTSample: - messages = [] - - # 1. 添加系统提示词(如果存在) - if "system" in raw_sample: - messages.append({ - "role": "system", - "content": [{"type": "text", "value": raw_sample["system"]}], - "loss_weight": 0.0 - }) - - # 2. 添加用户输入(instruction + input) - if "instruction" in raw_sample or "input" in raw_sample: - user_content = raw_sample.get("instruction", "") + raw_sample.get("input", "") - messages.append({ - "role": "user", - "content": [{"type": "text", "value": user_content}], - "loss_weight": 0.0 - }) - - # 3. 添加模型回复 - if "output" in raw_sample: - messages.append({ - "role": "assistant", - "content": [{"type": "text", "value": raw_sample["output"]}], - "loss_weight": 1.0 - }) - - return {"messages": messages} -``` - -#### 2.4 转换示例 - -**输入(Alpaca 格式):** - -```json -{ - "instruction": "What is the capital of France?", - "input": "", - "output": "The capital of France is Paris." -} -``` - -**输出(标准格式):** - -```json -{ - "messages": [ - { - "role": "user", - "content": [{"type": "text", "value": "What is the capital of France?"}], - "loss_weight": 0.0 - }, - { - "role": "assistant", - "content": [{"type": "text", "value": "The capital of France is Paris."}], - "loss_weight": 1.0 - } - ] -} -``` - -### 3. 自定义转换器 - -#### 3.1 创建自定义转换器 - -如果用户有自己的数据格式,可以轻松添加自定义转换器将其标准化,实现过程可参考如下示例: - -```python -# src/llamafactory/v1/plugins/data_plugins/converter.py - -from typing import TypedDict, NotRequired -from ...extras.types import SFTSample - -# 1. 定义输入格式的类型 -class MyCustomSample(TypedDict, total=False): - question: str - answer: str - context: NotRequired[str] - -# 2. 实现转换逻辑 -def custom_converter(raw_sample: MyCustomSample) -> SFTSample: - messages = [] - - # 构建用户消息 - user_text = raw_sample["question"] - if "context" in raw_sample: - user_text = f"Context: {raw_sample['context']}\n\nQuestion: {user_text}" - - messages.append({ - "role": "user", - "content": [{"type": "text", "value": user_text}], - "loss_weight": 0.0 - }) - - # 构建助手消息 - messages.append({ - "role": "assistant", - "content": [{"type": "text", "value": raw_sample["answer"]}], - "loss_weight": 1.0 - }) - - return {"messages": messages} - -# 3. 注册 custom_converter -#src/llamafactory/v1/plugins/data_plugins/converter.py: CONVERTERS -CONVERTERS = { - "alpaca": alpaca_converter, - "custom": custom_converter, # 添加自定义转换器 -} -``` - -#### 3.2 使用自定义转换器 - -在 YAML 配置中指定转换器名称: - -```yaml -my_dataset: - file_name: custom_data.json - converter: custom -``` - ---- - -## DataLoaderPlugin - -### 1. DataLoaderPlugin 简介 - -`DataLoaderPlugin` 负责从本地文件加载数据集,当前支持如下文件格式: - -- **JSON**: `.json` -- **JSONL**: `.jsonl` -- **CSV**: `.csv` -- **Parquet**: `.parquet` -- **Arrow**: `.arrow` -- **Text**: `.txt` - -### 2. DataLoaderPlugin 接口定义 - -```python -@dataclass -class DataLoaderPlugin: - """数据加载插件(DataLoaderPlugin) - - 负责根据数据集信息(`DatasetInfo`)自动加载本地或远程数据集。 - 支持多种文件格式(如 CSV、JSON、Parquet、Text、Arrow),并可选择是否以流式方式加载。 - - 通常由 `DataEngine` 调用,用于统一封装数据加载逻辑。 - """ - - args: DataArguments - """数据参数对象,包含数据目录、缓存路径、分片等配置信息。""" - - - def _get_builder_name(self, path: str) -> Literal["arrow", "csv", "json", "parquet", "text"]: - """获取数据集文件格式 - - 根据输入文件路径自动判断应使用的 HuggingFace `load_dataset` 构建器类型。 - 通过文件扩展名推断数据类型,例如 `.csv`、`.jsonl`、`.parquet`、`.txt` 等。 - - args: - path (str): 数据集文件路径,用于识别文件类型。 - - return: - Literal["arrow", "csv", "json", "parquet", "text"]: - 数据构建器名称,用于 `datasets.load_dataset()`。 - - example: - >>> _get_builder_name("data/train.jsonl") - "json" - """ - ... - - - def auto_load_data(self, dataset_info: DatasetInfo) -> HFDataset: - """根据传入的 `dataset_info` 自动选择合适的加载方式 - - args: - dataset_info (DatasetInfo): 数据集元信息,通常包含: - - `file_name`: 数据文件路径 - - `split`: 数据划分(如 "train"、"test"); - - `streaming`: 是否启用流式加载 - - return: - HFDataset: 加载完成的 Hugging Face 数据集对象。 - - example: - >>> plugin = DataLoaderPlugin(args) - >>> ds = plugin.auto_load_data({"file_name": "~/data.json", "split": "train"}) - """ - ... - - - def load_data_from_file(self, filepath: str, split: str, streaming: bool) -> HFDataset: - """从文件或目录加载数据集 - - 根据输入路径自动识别文件类型(CSV、JSON、Parquet、Text 等), - 并通过 `datasets.load_dataset()` 加载数据集。 - 若 `streaming=True`,则将结果转换为迭代式数据集。 - - args: - filepath (str): 文件路径或目录路径。 - split (str): 数据划分名称(如 "train"、"validation")。 - streaming (bool): 是否启用流式加载模式。 - - return: - HFDataset: 加载后的数据集对象。 - - example: - >>> plugin.load_data_from_file("data/train.json", "train", False) - """ - ... - -``` - ---- - -## DataIndexPlugin - -### 1. DataIndexPlugin 简介 - -`DataIndexPlugin` 负责调整数据索引,支持通过配置 `size`, `weight` 等参数控制数据集样本数量和采样频率。 - -- 使用 `size` 参数 限制使用的样本数量: - -```yaml -my_dataset: - file_name: large_dataset.json - size: 1000 # 只使用前 1000 个样本 -``` - -- 使用 `weight` 参数调整数据集在混合数据中的采样频率: - -```yaml -dataset_a: - file_name: data_a.json - weight: 1.0 - -dataset_b: - file_name: data_b.json - weight: 2.0 # dataset_b 的样本出现频率是 dataset_a 的 2 倍 -``` - -**说明**:`weight` 参数适用于在多个数据集混合训练时,调整不同数据集的的采样频率 - -- 当 `weight=1.0` 时,数据集按原始比例采样 -- 当 `weight=2.0` 时,该数据集的索引会复制 2 倍,使其样本出现频率翻倍 - -### 2. DataIndexPlugin 接口定义 - -```python -@dataclass -class DataIndexPlugin: - """数据索引插件(DataIndexPlugin) - - 根据 `size` 和 `weight` 调整数据索引列表,控制数据集的样本数量和采样频率 - 通常在多数据集混合训练时使用,以控制不同数据集在总体样本中的占比。 - - 在 `DataEngine.build_data_index` 中被自动调用,用于实现样本重采样或加权分布。 - """ - - def adjust_data_index( - self, data_index: list[tuple[str, int]], size: Optional[int], weight: Optional[float] - ) -> list[tuple[str, int]]: - """调整数据索引列表 - - 根据 `size` 或 `weight` 参数对输入的数据索引进行采样、扩展或缩减。 - 若两个参数同时存在,将依次执行基于大小和基于权重的调整。 - - args: - data_index (list[tuple[str, int]]): - 数据索引列表,每个元素为 `(dataset_name, sample_index)`。 - size (Optional[int]): - 目标样本数量,若指定则根据该数量裁剪或重复样本。 - weight (Optional[float]): - 数据集权重,用于控制数据集在混合训练中的采样比例。 - - return: - list[tuple[str, int]]: - 调整后的数据索引列表。 - - example: - >>> plugin = DataIndexPlugin() - >>> adjusted = plugin.adjust_data_index([("ds1", i) for i in range(100)], size=50, weight=None) - >>> len(adjusted) - 50 - """ - ... - - - def adjust_by_size(self, data_index: list[tuple[str, int]], size: int) -> list[tuple[str, int]]: - """根据目标大小调整数据索引 - - 通过裁剪或重复样本,使索引总数等于 `size`。 - 常用于统一不同数据集的样本数量。 - - args: - data_index (list[tuple[str, int]]): - 原始数据索引列表。 - size (int): - 目标样本数量。 - - return: - list[tuple[str, int]]: - 调整后长度等于 `size` 的数据索引列表。 - - example: - >>> plugin.adjust_by_size([("ds1", i) for i in range(10)], 20) - """ - ... - - - def adjust_by_weight(self, data_index: list[tuple[str, int]], weight: float) -> list[tuple[str, int]]: - """根据权重调整数据索引 - - 通过加权采样或重复样本,使数据集样本出现频率符合指定权重。 - 常用于多数据源训练中按比例平衡样本。 - - args: - data_index (list[tuple[str, int]]): - 原始数据索引列表。 - weight (float): - 数据集权重(相对比例,可与其他数据集共同归一化)。 - - return: - list[tuple[str, int]]: - 调整后的加权数据索引列表。 - - example: - >>> plugin.adjust_by_weight([("ds1", i) for i in range(10)], 0.5) - """ - ... - -``` ---- - -## DataSelectorPlugin - -### 1. DataSelectorPlugin 简介 - -`DataSelectorPlugin` 为 `DataEngine`提供基于索引访问数据的功能,由 `DataEngine` 的 `__getitem__` 方法自动调用。 - - -### 2. DataSelectorPlugin 接口定义 - -```python -@dataclass -class DataSelectorPlugin: - """根据索引选择数据集样本。 - - 配合 `DataEngine` 使用,通过统一的 `data_index` 结构(包含数据集名与样本索引)来实现灵活的数据选择 - - """ - - data_index: list[tuple[str, int]] - """数据索引列表,每个元素为 (dataset_name, sample_index)。""" - - - def select(self, index: Union[slice, list[int], Any]) -> Union[tuple[str, int], list[tuple[str, int]]]: - """选择数据集样本 - - 根据输入类型从 `data_index` 中选择对应的样本索引 - 支持三种索引方式: - - 切片(slice):返回对应范围内的样本 - - 索引列表(list[int]):返回指定索引处的多个样本 - - 其他类型输入将触发异常。 - - args: - index (Union[slice, list[int], Any]): 数据样本索引 - 可以是切片(`slice`)或索引列表 - - return: - Union[tuple[str, int], list[tuple[str, int]]]: - - 若为单个索引:返回一个 `(dataset_name, sample_index)` - - 若为多个索引或切片:返回多个样本的列表 - - except: - Raises: - ValueError: 当输入索引类型不受支持时抛出。 - ... -``` diff --git a/docs/zh/dev-guide/plugins/model-plugins/initialization.md b/docs/zh/dev-guide/plugins/model-plugins/initialization.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/zh/dev-guide/plugins/model-plugins/kernels.md b/docs/zh/dev-guide/plugins/model-plugins/kernels.md deleted file mode 100644 index eda8d0c63..000000000 --- a/docs/zh/dev-guide/plugins/model-plugins/kernels.md +++ /dev/null @@ -1,197 +0,0 @@ -# Kernels plugins - -## 概览 -LLaMA-Factory 通过 Kernels plugins 系统,依据不同硬件设备提供高性能计算内核(kernel)实现。该系统通过注册表机制管理所有 kernel,通过 `@register_kernel` 装饰器实现 kernel 定义后自动注册,由 `apply_kernel` 方法来使能指定的 kernel,`apply_default_kernels` 可使能注册表中当前环境所有可用的默认 kernels。 - -## 架构设计 - -### 核心组件 - -#### 1. Registry(注册表) - -`Registry` 是一个用于管理所有 kernel 实现的静态类。它维护一个字典结构:`{kernel_id: KernelClass}`。 - -```python -# 注册表结构示例 -{ - "npu_fused_rmsnorm": NpuRMSNormKernel, - "npu_fused_swiglu": NpuSwiGluKernel, - ... -} -``` - -#### 2. register_kernel (装饰器) - -`@register_kernel` 是 `Registry.register` 的别名。所有 kernel 类均应使用该装饰器进行注册。 - -**注册机制**: -- 装饰器检查类是否继承自 `BaseKernel`。 -- 检查类是否定义了 `_kernel_id` 和 `_device` 属性。 -- 检查 `_device` 是否与当前运行环境的加速器类型匹配。如果不匹配,则跳过注册。 -- 如果一切符合要求,将 kernel 类注册到全局注册表中。 - -#### 3. BaseKernel(基类) - -所有 kernel 的实现都必须继承自 `BaseKernel` 抽象基类。`BaseKernel` 定义了 kernel 的基本属性和接口。 - -#### 4. 标识系统 - -**Kernel ID** (`_kernel_id`): -每个 kernel 必须拥有一个唯一的字符串标识符,例如 `"npu_fused_rmsnorm"`。 - -**Device Type** (`_device`): -kernel 必须声明其支持的设备类型,例如 `DeviceType.NPU` 或 `DeviceType.CUDA`。 - -## Kernel 系统 API 设计 - -### **Registry**:全局 kernel 注册表 - -`Registry` 类提供了注册和获取 kernel 的接口: - -```python -class Registry: - @classmethod - def register(cls, kernel_cls: type[BaseKernel]) -> type[BaseKernel] | None: - """注册一个 kernel 类""" - ... - - @classmethod - def get(cls, kernel_id: str) -> type[BaseKernel] | None: - """根据 ID 获取 kernel 类""" - ... -``` - -### **BaseKernel** - -`BaseKernel` 定义了所有 kernel 必须实现的协议: - -- `_kernel_id`: 类属性,kernel 的唯一标识符。 -- `_device`: 类属性,kernel 支持的设备类型。 -- `check_deps()`: 类方法,检查 kernel 的依赖项是否满足(如 `torch_npu` 是否安装)。 -- `apply(**kwargs)`: 抽象类方法,实现 kernel 的具体应用逻辑。 - -```python -class BaseKernel(ABC): - _kernel_id: Any = "" - _device: DeviceType = DeviceType.CPU - - @classmethod - def check_deps(cls) -> bool: - """检查依赖项""" - ... - - @classmethod - @abstractmethod - def apply(cls, **kwargs) -> HFModel: - """应用 kernel 到模型""" - ... -``` - -### **scan_all_kernels** - -`scan_all_kernels` 函数会自动扫描 `ops` 目录下的所有 `.py` 文件并导入它们,从而触发 `@register_kernel` 装饰器完成自动注册。 - -### **apply_kernel** - -对模型使能指定的 kernel。 - -```python -def apply_kernel(kernel_id: str, **kwargs) -> HFModel: - """应用指定的 kernel 到模型 - - Args: - kernel_id: 目标 kernel 的 ID - **kwargs: 传递给 kernel.apply 的参数,通常包含 model - """ -``` - -**用法示例**: -```python -from llamafactory.v1.plugins.model_plugins.kernels import apply_kernel - -model = apply_kernel("npu_fused_rmsnorm", model=model) -``` - -### **apply_default_kernels** - -对模型使能所有默认注册的 kernel。这是一个高级 API,通常在模型加载流程中自动调用。 - -```python -def apply_default_kernels(model: HFModel, include_kernels: str = None) -> HFModel: - """应用所有默认 kernel - - Args: - model: HFModel 实例 - include_kernels: 包含的 kernel ID 列表(逗号分隔字符串),或者 "auto"/True 表示全部 - """ -``` - -## 扩展 Kernels - -如果用户有针对特定模型或者设备的 kernel,可以按照下述步骤去实现并接入 LLaMA-Factory。 - -### 创建新 Kernel 的步骤 - -#### 1. 创建 Kernel 实现文件 - -在 `src/llamafactory/v1/plugins/model_plugins/kernels/ops` 下的相应子目录中创建新的 kernel 实现文件,例如 `mlp/cuda_swiglu.py`: - -```python -import torch -from ......accelerator.helper import DeviceType -from ......utils.types import HFModel -from ...base import BaseKernel -from ...registry import register_kernel - -# 实现具体的 kernel 函数 -def _cuda_swiglu_forward(self, hidden_state): - # ... CUDA 优化实现 ... - pass - -@register_kernel -class CudaSwiGluKernel(BaseKernel): - _kernel_id = "cuda_fused_swiglu" - _device = DeviceType.CUDA - - @classmethod - def apply(cls, **kwargs) -> HFModel: - model = kwargs.get("model") - if model is None: - raise ValueError("model is required") - - if not cls.check_deps(): - raise RuntimeError("Dependencies not met") - - # 遍历模型并替换 forward 方法 - for name, module in model.named_modules(): - # ... 匹配和替换逻辑 ... - pass - - return model -``` - -#### 2. 自动发现 - -由于 `scan_all_kernels` 会自动扫描 `ops` 目录,只要文件位于该目录下且没有语法错误,系统启动时会自动导入并注册,无需手动修改注册表代码。 - -#### 3. 测试 Kernel - -创建测试用例验证 kernel 的正确性: - -```python -from llamafactory.v1.plugins.model_plugins.kernels import apply_kernel - -# ... 加载模型 ... -model = apply_kernel("cuda_fused_swiglu", model=model) -# ... 验证 forward 是否被替换 ... -``` - -## 异常处理 - -### 依赖不可用 - -`BaseKernel.check_deps()` 默认会检查当前设备类型是否匹配。子类可以重写此方法以添加额外的依赖检查(如检查特定的库是否安装)。如果 `check_deps()` 返回 `False`,`apply()` 方法应当抛出异常或进行相应处理。 - -### Kernel ID 未找到 - -如果调用 `apply_kernel` 时传入了不存在的 `kernel_id`,会抛出 `ValueError`。 diff --git a/docs/zh/dev-guide/plugins/model-plugins/rendering.md b/docs/zh/dev-guide/plugins/model-plugins/rendering.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/zh/developer-guide/architecture_overview.md b/docs/zh/developer-guide/architecture_overview.md new file mode 100644 index 000000000..3e73bef4f --- /dev/null +++ b/docs/zh/developer-guide/architecture_overview.md @@ -0,0 +1,64 @@ +# 整体架构 + +v1 将命令入口、运行流程和可替换实现分开组织。Core 负责连接配置、数据、模型和训练状态,Plugin 为 Core 提供数据加载、模型处理、批处理和分布式训练等具体实现。 + +这样划分后,更换数据格式不需要改训练循环,更换分布式后端也不需要重新实现 SFT 损失。任务入口负责把组件组装成一次运行,Core 决定何时执行操作,Plugin 提供被选择的具体操作。 + +下文源码路径均相对于 `src/llamafactory/v1/`。 + +## 模块分层 + +| 模块 | 目录 | 职责 | +|------|------|------| +| 命令入口 | `launcher.py` | 路由 `sft`、`dpo`、`rm`、`chat` 和 `merge`,并在多设备训练时通过 `torchrun` 重启 | +| 参数配置 | `config/` | 解析数据、模型、训练和推理参数 | +| 任务入口 | `trainers/`、`samplers/` | 组装 SFT、DPO、RM 或推理流程 | +| Core | `core/` | 管理数据索引、模型加载、样本渲染、批处理、训练循环和推理引擎 | +| Plugin | `plugins/` | 提供数据、模型和训练器相关的可替换实现 | +| 设备抽象 | `accelerator/` | 管理设备、进程组和 DeviceMesh | + +## 调用关系 + +```text +llamafactory-cli config.yaml + → launcher + → get_args + → 任务入口(run_sft / run_dpo / run_rm / run_chat 等) + ├── DataEngine + │ ├── DataLoaderPlugin + │ └── DataConverterPlugin + ├── ModelEngine + │ ├── InitPlugin + │ ├── QuantizationPlugin + │ ├── PeftPlugin + │ └── KernelPlugin + ├── BaseTrainer + │ ├── BatchGenerator → BatchingPlugin + │ ├── DistributedPlugin + │ └── OptimizerPlugin + └── BaseSampler +``` + +上图表示组件依赖,实际初始化次序由对应任务入口决定。以 `trainers/sft_trainer.py` 中的 `run_sft` 为例:先解析参数并初始化 `DistributedInterface`,再构造 DataEngine 和 ModelEngine,将数据集、模型与 Renderer 传给 SFTTrainer,最后调用 `fit()`、`save_model()` 并销毁分布式环境。SFTTrainer 继承 BaseTrainer 的运行循环,并提供 SFT 的损失计算。 + +## 数据如何到达训练循环 + +```text +DataEngine[index] → 标准 Sample(仍是消息结构) +Renderer.process_samples(samples) → ModelInput 列表(已分词,尚未组 batch) +BatchGenerator → 一个更新步所需的 micro-batch 列表 +Trainer.compute_loss(batch) → 标量 loss +BaseTrainer.fit() → 反向传播、参数更新与生命周期事件 +``` + +ModelEngine 同时提供模型和与模型匹配的 Renderer,BatchGenerator 持有这个 Renderer。这样,数据源的读取与字段转换可以独立于模型的 tokenizer、chat template 和多模态 processor。 + +## 状态与实现分别由谁管理 + +DataEngine 保存数据集和索引,ModelEngine 保存加载结果,BatchGenerator 保存读取进度与缓冲区,BaseTrainer 保存模型、优化器和训练进度。它们都是一次运行中的对象。 + +插件注册表保存函数或类对象。调用方每次把模型、配置或缓冲区传给插件,并接收处理结果;插件路由对象本身只记录实现名称。例如,分布式插件可以返回有状态的后端 engine,由 BaseTrainer 持有,但注册表本身不保存某次训练的 engine。 + +判断改动位置时,先区分是在改变任务目标、组件流程,还是替换某个操作:新损失属于 Trainer,统一的数据索引逻辑属于 DataEngine,新的原始字段转换属于 DataConverterPlugin。具体扩展边界分别在下方页面说明。 + +Core 各组件见[Core(核心模块)](core/index.md),插件的注册方式见[插件注册机制](baseplugin_mechanism.md),内置实现见[插件实现](plugins/index.md)。 diff --git a/docs/zh/developer-guide/baseplugin_mechanism.md b/docs/zh/developer-guide/baseplugin_mechanism.md new file mode 100644 index 000000000..94dbb1157 --- /dev/null +++ b/docs/zh/developer-guide/baseplugin_mechanism.md @@ -0,0 +1,132 @@ +# 插件注册机制 + +`BasePlugin` 位于 `utils/plugin.py`,负责按名称注册和查找实现。每个 `BasePlugin` 子类表示一个独立的插件类型,并拥有自己的 `_registry`,例如 `OptimizerPlugin` 和 `DistributedPlugin` 的注册项互不共享。 + +## 插件类型、路由对象与实现 + +以 `DistributedPlugin("fsdp2").shard_model(...)` 为例,这里有三个不同对象: + +| 对象 | 职责 | +|------|------| +| `DistributedPlugin` | 插件类型,持有这个类型的名称注册表 | +| `DistributedPlugin("fsdp2")` | 路由对象,仅保存要查找的名称 | +| 注册在 `fsdp2` 下的实现类 | 提供 `shard_model` 等实际操作 | + +创建路由对象只保存名称,不会立即加载或创建后端 engine。第一次调用函数或访问实现方法时,`_resolve` 才从该类型的注册表中查找对象。模型、优化器、buffer 等运行状态由调用方持有并作为参数传入。 + +## 注册与调用流程 + +```text +定义插件类型 + → PluginType(BasePlugin) + → PluginType("name").register() + → 将函数或类对象写入 PluginType._registry + → PluginType("name") 按名称查找实现 + → 通过 __call__ 或 __getattr__ 调用 +``` + +装饰器在模块导入时完成注册。注册名称必须存在;查找未注册的名称时会抛出 `ValueError`。同一插件类型重复注册相同名称时会记录警告,并使用后注册的实现。 + +注册表不会自动扫描文件或按 YAML 名称导入 Python 模块。内置实现通过其入口模块的正常导入完成注册,例如 Kernel 入口显式导入各实现。新增实现也必须在被调用前执行所在模块的导入,仅添加文件或写入配置名称不会触发注册。 + +## 函数实现 + +一个插件名称只对应一个操作时,直接注册函数。调用 `PluginType("name")(...)` 时,`BasePlugin.__call__` 查找并调用该函数。 + +```python +class OptimizerPlugin(BasePlugin): + pass + + +@OptimizerPlugin("example").register() +def create_optimizer(model, config): + return ExampleOptimizer(model.parameters(), lr=config["learning_rate"]) + + +optimizer = OptimizerPlugin("example")(model, config) +``` + +数据加载、数据转换、模型初始化、PEFT 和优化器等插件使用这种形式。插件类型也可以提供语义化方法,在方法内部调用 `super().__call__`,例如 `DataLoaderPlugin.load(...)`。 + +## 类实现(静态方法组) + +同一插件名称需要提供多个相关操作时,注册一个类对象。`BasePlugin.__getattr__` 先查找该类,再把方法访问转发给它。 + +```python +@DistributedPlugin("example").register() +class ExampleDistributed(BaseDistributed): + @staticmethod + def shard_model(model, dist_config, **kwargs): + ... + + @staticmethod + def save_checkpoint(model, optimizer, checkpoint_dir, **kwargs): + ... + + +model = DistributedPlugin("example").shard_model(model, dist_config) +DistributedPlugin("example").save_checkpoint(model, optimizer, checkpoint_dir) +``` + +通过 `.method(...)` 访问时,路由会取出注册类上的方法,不创建该类的实例。因此,这类实现使用 `staticmethod` 或 `classmethod`,不在 `self` 中保存运行状态: + +| 方法形式 | 调用时接收 | 用途 | +|----------|------------|------| +| `staticmethod` | 只接收显式参数 | 实现不依赖类本身的独立操作,例如保存 checkpoint | +| `classmethod` | 首个参数为 `cls` | 需要调用子类方法的公共流程,例如 `BaseKernel.apply` | +| 普通实例方法 | 首个参数为 `self` | 需要先创建实例,不适用于当前类对象路由 | + +Python 没有单独的“静态类”类型;这里使用的是包含静态方法或类方法的普通类。分布式后端、批处理策略和 Kernel 使用这种方法组形式。对应抽象基类声明的也是静态方法或类方法,`ensure_methods_implemented` 在具体子类定义时检查这些方法是否完整。 + +## 两种实现形式的选择 + +| 实现形式 | 注册对象 | 调用入口 | 适用情况 | +|----------|----------|----------|----------| +| 函数 | 函数对象 | `PluginType("name")(...)` | 一个名称对应一个操作 | +| 类方法组 | 类对象 | `PluginType("name").method(...)` | 一个名称需要提供多个相关操作 | + +两种形式使用相同的名称注册表。区别只在于注册对象和调用方式,不影响配置文件通过 `name` 选择实现。 + +## 参数解析 + +注册过程只完成名称到实现的映射,不会自动解析参数。参数配置经过两个不同阶段: + +1. `config/arg_utils.py` 的 `get_plugin_config` 将顶层参数中的插件配置包装成 PluginConfig,并检查是否有 `name`。这时并未根据名称验证插件专属字段。 +2. 调用进入具体实现后,由实现解析自己的字段。PEFT 和分布式入口使用参数 dataclass 与 `parse_params`;Muon 等实现直接读取配置。插件类型本身没有为所有实现统一选择参数类。 + +使用参数 dataclass 的入口可以显式调用 `parse_params(config, ParamsClass)`: + +```python +from dataclasses import dataclass +from typing import Literal + + +class ExamplePlugin(BasePlugin): + pass + + +@dataclass +class ExampleParams: + name: Literal["example"] = "example" + enabled: bool = True + + +@ExamplePlugin("example").register() +def apply_example(model, config): + params = ExamplePlugin.parse_params(config, ExampleParams) + if params.enabled: + ... +``` + +`parse_params` 的处理规则如下: + +- `config` 为目标 dataclass 实例时直接返回; +- `config` 为字典时检查字段名,再创建参数实例; +- `config` 为 `None` 时使用 dataclass 默认值创建实例; +- 未声明的字段会抛出 `ValueError`; +- 参数类不是 dataclass,或配置不是字典、`None`、目标 dataclass 实例时,会抛出 `TypeError`; +- 取值范围和字段组合可以在参数 dataclass 的 `__post_init__` 中继续校验。 + +这里的严格检查主要针对未知字段和配置对象的形式;Python dataclass 不会自动强制执行每个类型注解或 `Literal` 的可选值,额外约束需要实现显式校验。 + +参数 dataclass 由具体插件入口选择,因此不同实现可以使用不同字段。用户可配置字段记录在对应的[参数说明](../configuration/index.md)中。 diff --git a/docs/zh/developer-guide/core/base_sampler.md b/docs/zh/developer-guide/core/base_sampler.md new file mode 100644 index 000000000..63440561b --- /dev/null +++ b/docs/zh/developer-guide/core/base_sampler.md @@ -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 向模型传参的路径。 diff --git a/docs/zh/developer-guide/core/base_trainer.md b/docs/zh/developer-guide/core/base_trainer.md new file mode 100644 index 000000000..f101983c2 --- /dev/null +++ b/docs/zh/developer-guide/core/base_trainer.md @@ -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)。 diff --git a/docs/zh/developer-guide/core/batch_generator.md b/docs/zh/developer-guide/core/batch_generator.md new file mode 100644 index 000000000..f138b5db3 --- /dev/null +++ b/docs/zh/developer-guide/core/batch_generator.md @@ -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。 diff --git a/docs/zh/developer-guide/core/callback.md b/docs/zh/developer-guide/core/callback.md new file mode 100644 index 000000000..c54fc5ef3 --- /dev/null +++ b/docs/zh/developer-guide/core/callback.md @@ -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 就在自身内部处理这个条件。 diff --git a/docs/zh/developer-guide/core/data_engine.md b/docs/zh/developer-guide/core/data_engine.md new file mode 100644 index 000000000..135b97365 --- /dev/null +++ b/docs/zh/developer-guide/core/data_engine.md @@ -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)。 diff --git a/docs/zh/developer-guide/core/index.md b/docs/zh/developer-guide/core/index.md new file mode 100644 index 000000000..89869aed3 --- /dev/null +++ b/docs/zh/developer-guide/core/index.md @@ -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 +``` diff --git a/docs/zh/developer-guide/core/model_engine.md b/docs/zh/developer-guide/core/model_engine.md new file mode 100644 index 000000000..9880bd546 --- /dev/null +++ b/docs/zh/developer-guide/core/model_engine.md @@ -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 的转换逻辑,无需增加一种模型加载插件。 diff --git a/docs/zh/developer-guide/core/renderer.md b/docs/zh/developer-guide/core/renderer.md new file mode 100644 index 000000000..7ce63db7e --- /dev/null +++ b/docs/zh/developer-guide/core/renderer.md @@ -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。 diff --git a/docs/zh/developer-guide/index.md b/docs/zh/developer-guide/index.md new file mode 100644 index 000000000..fedc86e5f --- /dev/null +++ b/docs/zh/developer-guide/index.md @@ -0,0 +1,20 @@ +# 开发者指南 + +开发者指南说明 v1 的运行路径和扩展点。v1 由 Core(核心模块)组织主要运行流程,并通过 Plugin(插件系统)提供可替换实现。 + +## 架构 + +| 页面 | 内容 | +|------|------| +| [整体架构](architecture_overview.md) | 模块分层以及 Core 与 Plugin 的调用关系 | + +## Core(核心模块) + +[Core(核心模块)](core/index.md)说明数据加载、模型加载、样本渲染、批处理和训练循环。 + +## Plugin(插件系统) + +| 页面 | 内容 | +|------|------| +| [插件注册机制](baseplugin_mechanism.md) | `BasePlugin` 的注册、路由和参数解析 | +| [插件实现](plugins/index.md) | 数据、模型和训练器插件,以及融合算子加速 | diff --git a/docs/zh/developer-guide/plugins/data_plugins.md b/docs/zh/developer-guide/plugins/data_plugins.md new file mode 100644 index 000000000..cf1c88cb5 --- /dev/null +++ b/docs/zh/developer-guide/plugins/data_plugins.md @@ -0,0 +1,57 @@ +# 数据插件 + +数据插件把数据来源和原始字段格式从 DataEngine 的索引逻辑中分离。Loader 负责获得可读取的数据集,Converter 负责解释其中的一条记录;两者由不同配置字段选择,可以组合使用。 + +## 与 DataEngine 的交接 + +```text +DatasetInfo.source + → hf_hub:DataEngine 直接调用 datasets.load_dataset + → 其他来源:DataLoaderPlugin(source).load(dataset_info) + → Dataset +Dataset 中的一条原始记录 + DatasetInfo.converter + → DataConverterPlugin(converter)(raw_sample) + → 标准 SFTSample / DPOSample +``` + +相同的本地 loader 可以配合 `alpaca` 或 `sharegpt` converter;数据已经是标准消息结构时省略 converter。分词与标签生成发生在后续 Renderer 中。 + +## DataLoaderPlugin + +接口定义在 `plugins/data_plugins/loader.py`。DataEngine 调用 `DataLoaderPlugin(source).load(dataset_info)`,而 `load` 会从 DatasetInfo 中提取 `path`、`split` 和 `streaming`,再将这三个位置参数传给注册函数。 + +因此,注册函数接收的是以下参数,不是整个 DatasetInfo: + +```python +@DataLoaderPlugin("example").register() +def load_example(path, split, streaming): + ... +``` + +当前注册的 `local` 根据文件扩展名选择 Hugging Face dataset builder,再加载文件或目录。Hub 数据由 DataEngine 直接分派,当前没有通过一个名为 `hf_hub` 的 loader 注册项加载。 + +返回的数据集由 DataEngine 持有并用于建立索引。新增 loader 必须保持调用参数与返回数据集的约定;当前训练链路要求可按索引读取的数据集,具体 streaming 边界见 [DataEngine](../core/data_engine.md#处理-streaming-dataset)。 + +## DataConverterPlugin + +接口定义在 `plugins/data_plugins/converter.py`。Converter 接收单条原始样本字典,返回一个 v1 `SFTSample` 或 `DPOSample`,不是输入或返回整个 batch。当前注册: + +- `alpaca` +- `sharegpt` +- `pair` + +```python +@DataConverterPlugin("example").register() +def convert_example(raw_sample): + return {"messages": ...} +``` + +返回字段必须符合 `utils/types.py` 中的 Messages 类型。SFT 返回 `messages`,偏好数据返回 `chosen_messages` 和 `rejected_messages`;图片等媒体也在这一阶段转为标准内容块,实际媒体特征由 Renderer 的 processor 生成。 + +DataEngine 在建立多轮索引和实际取样时都会调用 converter。它应稳定地转换一条记录,避免在函数中随机选择对话轮次或维护读取进度。轮次展开、采样规模和读取顺序分别由 DataEngine 与 sampler 管理。 + +## 调整数据索引 + +`adjust_data_index` 根据 `size`、`weight` 调整某个数据集的索引,`select_data_sample` 处理索引选择。两者是 `loader.py` 中的普通函数,不通过插件名称注册或路由。改变来源、格式时扩展 loader/converter;改变共用索引语义时,应检查这些函数及 DataEngine 的调用位置。 + +注册在模块导入时生效,机制见[插件注册机制](../baseplugin_mechanism.md)。使用配置见[数据准备](../../feature-guide/data_preparation.md)。 diff --git a/docs/zh/developer-guide/plugins/index.md b/docs/zh/developer-guide/plugins/index.md new file mode 100644 index 000000000..7e4b4bf6d --- /dev/null +++ b/docs/zh/developer-guide/plugins/index.md @@ -0,0 +1,22 @@ +# 插件实现 + +v1 按数据、模型和训练流程组织内置插件。配置文件通过实现名称选择插件,新增实现时使用对应的插件类注册。 + +| 分类 | 内容 | +|------|------| +| [数据插件](data_plugins.md) | DataLoader 与 DataConverter | +| [模型插件](model_plugins.md) | 初始化、PEFT、量化、Kernel 和 Sequence Parallel | +| [训练器插件](trainer_plugins.md) | 分布式后端、批处理和优化器 | +| [融合算子加速](kernel-acceleration/overview.md) | Kernel 选择与调用流程 | + +插件注册和参数解析的通用机制见[插件注册机制](../baseplugin_mechanism.md)。 + +```{toctree} +:maxdepth: 2 +:hidden: + +data_plugins +model_plugins +trainer_plugins +kernel-acceleration/overview +``` diff --git a/docs/zh/developer-guide/plugins/kernel-acceleration/overview.md b/docs/zh/developer-guide/plugins/kernel-acceleration/overview.md new file mode 100644 index 000000000..150c5cb76 --- /dev/null +++ b/docs/zh/developer-guide/plugins/kernel-acceleration/overview.md @@ -0,0 +1,48 @@ +# 融合算子加速 + +Kernel 系统在模型加载后应用融合算子加速。一个实现既可以替换单个算子,也可以组合多个融合操作或接入外部加速库。 + +入口位于 `plugins/model_plugins/kernels/interface.py`。它负责名称选择与调用顺序,`base.py` 中的 BaseKernel 负责执行公共检查,各实现的 `_apply` 负责识别模型并进行具体替换。注册机制、检查流程和模型适配由这三层分别承担。 + +## Kernel 应用流程 + +```text +ModelEngine + → apply_kernels(model, kernel_config) + → 解析 kernel_config.name + → auto 设备选择或 KernelPlugin(name) + → BaseKernel.apply() + → check_device() + → check_deps() + → _apply() +``` + +接口模块显式导入内置实现,使装饰器在调用前完成注册。`apply_kernels` 将名称按逗号拆分,逐个调用,并将返回模型传给下一个实现;每个实现收到同一份配置与 `require_logits` 等上下文。 + +`auto` 是入口处的特殊分派:根据设备查询 `_AUTO_KERNELS`,再调用其中的已注册实现。它不是自动搜索最快实现的算法;当前映射只包含 NPU,其他设备不会因 `auto` 而执行替换。 + +## BaseKernel 与具体实现如何协作 + +注册表保存的是实现类。`KernelPlugin(name).apply(...)` 将方法调用转发到该类,继承的 `BaseKernel.apply` 再使用 `cls` 调用该实现的检查和替换方法。 + +`check_device` 检查设备,`check_deps` 检查可选依赖,随后公共入口确认存在模型对象,最后调用 `_apply`。模型是否受支持、需要替换哪个模块,由具体 `_apply` 决定。BaseKernel 不统一检测所有模型结构。 + +例如,CUDA Fused MoE 按模型架构和模块类名寻找目标并替换 forward;Liger 根据 model type 调用对应外部适配函数;FLA 通过算子注册表匹配模型属性。成功找到注册名称,只说明能进入实现,不能保证模型中存在可替换目标。 + +## 组合与扩展边界 + +组合时,后一个实现看到的是已经修改过的模型。入口不提供冲突检测、模型快照或失败回滚,也不会把各实现的专属配置拆成独立配置块。新增实现需要清楚界定自己修改哪些模块,并返回后续调用所需的模型对象。 + +实现类继承 BaseKernel,提供 `check_device` 和 `_apply`,需要额外依赖时覆盖 `check_deps`;子类定义时会检查必需方法是否实现。名称注册后,还需要确保实现模块在使用前被导入。通用路由与注册规则见[插件注册机制](../../baseplugin_mechanism.md)。 + +## 已注册实现 + +- `liger_kernel` +- `cuda_fused_moe` +- `flash-linear-attention` +- `npu_fused_moe` +- `npu_fused_rmsnorm` +- `npu_fused_rope` +- `npu_fused_swiglu` + +用户配置见[融合算子加速](../../../feature-guide/kernel_acceleration.md)。 diff --git a/docs/zh/developer-guide/plugins/model_plugins.md b/docs/zh/developer-guide/plugins/model_plugins.md new file mode 100644 index 000000000..ca9cdb035 --- /dev/null +++ b/docs/zh/developer-guide/plugins/model_plugins.md @@ -0,0 +1,47 @@ +# 模型插件 + +模型插件提供模型加载和处理过程中的可替换操作。初始化、量化、PEFT 和 Kernel 由 ModelEngine 依次调用;Sequence Parallel 需要训练拓扑,因此由 BaseTrainer 在训练初始化阶段调用。 + +## 每个插件接收和改变什么 + +| 插件 | 接收 | 返回或修改 | +|------|------|------------| +| InitPlugin | 当前进程的设备与 rank 信息 | 返回用于创建模型的 `torch.device` | +| QuantizationPlugin | 模型加载参数、量化配置与训练标记 | 返回补充量化选项后的加载参数 | +| PeftPlugin | 已构造模型、PEFT 配置与训练标记 | 设置可训练参数、加载或合并 adapter,返回处理后的模型 | +| KernelPlugin | PEFT 处理后的模型与 Kernel 配置 | 替换适配的计算路径,返回处理后的模型 | + +它们的接口不同,不能仅通过替换 `name` 在不同插件族之间互换。具体调用次序及原因见 [ModelEngine](../core/model_engine.md)。 + +## InitPlugin + +注册 `init_on_default`、`init_on_meta`、`init_on_rank0`,返回模型创建使用的 `torch.device`。 + +实现位于 `plugins/model_plugins/initialization.py`。这些函数不加载模型权重;ModelEngine 根据返回设备决定调用 `from_pretrained` 还是在 meta 上使用 `from_config`。Rank 0 加载与其他 rank 的权重同步需要后续分布式路径协作。 + +## PeftPlugin + +注册 `lora` 与 `freeze`。两者分别通过 `LoraParams` 和 `FreezeParams` 严格解析配置。LoRA 还负责 adapter 加载、合并与导出。 + +实现位于 `plugins/model_plugins/peft.py`。训练时,LoRA 创建或加载 adapter,Freeze 按层和模块选择可训练权重;后续优化器只收集 `requires_grad` 的参数。推理与合并导出也复用 LoRA 插件,因此同一配置入口的行为还取决于调用时的 `is_train`。 + +## QuantizationPlugin + +注册 `auto` 与 `bnb`。插件修改 `from_pretrained` 的 init kwargs,不直接替换已经加载的权重。 + +实现位于 `plugins/model_plugins/quantization.py`。调用发生在模型创建之前,使量化选项能参与权重加载;这也解释了它与加载完成后执行的 PEFT、Kernel 所处阶段不同。当前可配置字段见[模型参数](../../configuration/model.md#quant_config)。 + +## KernelPlugin + +Kernel 在模型加载和 PEFT 处理后应用。调用流程见[融合算子加速](kernel-acceleration/overview.md)。 + +## Sequence Parallel Plugins + +设置 `TrainingArguments.cp_size > 1` 后,BaseTrainer 使用 `cp_mode` 的值选择 `SequenceParallelModelPlugin`。因此,`cp_mode: ulysses` 会调用 `SequenceParallelModelPlugin("ulysses")` 修改模型 forward 所需的通信;训练循环再调用 `SequenceParallelLossPlugin("sequence_parallel_loss")` 处理 loss 聚合。用户配置见[分布式训练](../../feature-guide/distributed_training.md#ulysses-context-parallel)。 + +这两个插件共同完成序列并行:模型侧处理 attention 的通信与切分,损失侧处理分布后的输入与监督计算。只替换 forward 而沿用不匹配的损失路径,会破坏这组协作关系。实现位于 `plugins/model_plugins/parallelization/`。 + +## Chat Template 迁移 + +旧 `RenderingPlugin` 和 `plugins/model_plugins/templates/` 已删除。Chat +template 统一由 `core/rendering/` 调用 Hugging Face 模板。 diff --git a/docs/zh/developer-guide/plugins/trainer_plugins.md b/docs/zh/developer-guide/plugins/trainer_plugins.md new file mode 100644 index 000000000..556c26ff6 --- /dev/null +++ b/docs/zh/developer-guide/plugins/trainer_plugins.md @@ -0,0 +1,51 @@ +# 训练器插件 + +训练器插件替换训练过程中的具体操作。BaseTrainer 持有模型、优化器和训练计数,BatchGenerator 持有读取进度与缓冲区;插件通过调用参数访问这些对象。替换实现时需要维持调用方依赖的输入、输出和状态约定。 + +## DistributedPlugin + +当前注册 `fsdp2`、`fsdpturbo` 和 `deepspeed`。每个实现类提供统一的模型切分、保存和 checkpoint 方法组: + +- `shard_model` +- `save_model` +- `save_checkpoint` +- `load_checkpoint` + +参数分别由 `FSDP2Params`、`FSDPTurboParams` 和 `DeepSpeedParams` 解析。FSDPTurbo 额外实现跨专家并行 Mesh 的梯度裁剪。公共 DeviceMesh 拓扑由 `TrainingArguments` 和 `DistributedInterface` 管理。 + +注册和入口位于 `plugins/trainer_plugins/distributed/interface.py`,具体引擎位于同目录下的 `fsdp2.py`、`fsdpturbo.py` 和 `deepspeed.py`。路由层把配置转换为对应 Params,再委托后端执行;参数配置本身不负责创建进程组。 + +FSDP2 / FSDPTurbo 的 `shard_model` 返回处理后的模型,BaseTrainer 再创建优化器。DeepSpeed 的该入口返回后端 engine,BaseTrainer 随后调用它的 `prepare`,共同准备模型、优化器和 scheduler。因此,公共入口背后的返回对象与初始化协议仍需结合 BaseTrainer 的后端分支理解。 + +保存时,Trainer 和 checkpoint 协调器决定时机与通用训练状态,分布式插件负责其模型和优化器状态格式。扩展新后端需要同时提供分片、最终模型保存、checkpoint 保存与恢复;仅实现分片无法覆盖完整训练生命周期。 + +## BatchingPlugin + +`normal` 是 BatchGenerator 默认路径。插件注册: + +- `padding_free` +- `dynamic_batching` +- `dynamic_padding_free` + +接口与实现位于 `plugins/trainer_plugins/batching.py`。实现类继承 BaseBatcher,提供四个操作: + +| 方法 | BatchGenerator 用它决定什么 | +|------|-----------------------------| +| `get_data_provider_batch_size` | 底层 DataLoader 每次读多少条样本 | +| `compute_length` | 批次生成器报告的长度 | +| `fill_buffer` | 何时继续读取样本、怎样填充缓冲区 | +| `generate_batch` | 如何取出样本并组织一个更新步的 micro-batch 列表 | + +方法接收 `batch_info`、buffer 或读取函数,状态由调用方管理。`generate_batch` 返回 `None` 时,BatchGenerator 结束本次迭代。新策略需要同时考虑数据耗尽、剩余 buffer 和 checkpoint 恢复,不能只实现拼接张量。 + +## OptimizerPlugin + +当前注册 `muon`。未指定插件时 BaseTrainer 使用默认优化器。Muon 将适合正交化更新的二维权重和其余 AdamW 权重分组。用户配置见[优化器](../../feature-guide/optimizer.md)。 + +入口位于 `plugins/trainer_plugins/optimizers/optimizer.py`,接收处理后的模型与 `optim_config`,返回 optimizer 实例。当前 Muon 直接读取配置字段;顶层 `learning_rate` 在 TrainingArguments 初始化时写入配置的 `lr`。插件负责参数分组与优化器构造,反向传播和更新时机仍由 Trainer 或 DeepSpeed engine 控制。 + +## LRSchedulerPlugin + +插件族存在,但当前没有注册可选的 scheduler 名称。 + +接口位于 `plugins/trainer_plugins/lr_scheduler.py`。BaseTrainer 未收到配置时使用固定倍率的 LambdaLR;收到配置时按名称调用插件,传入 optimizer、训练总步数与配置,并保存返回的 scheduler。扩展实现应返回兼容训练循环和 checkpoint 状态保存的 scheduler 对象。 diff --git a/docs/zh/feature-guide/batching.md b/docs/zh/feature-guide/batching.md new file mode 100644 index 000000000..26785abab --- /dev/null +++ b/docs/zh/feature-guide/batching.md @@ -0,0 +1,42 @@ +# 批处理策略 + +`batching_strategy` 决定每个 micro-batch 包含多少条样本,以及这些样本是通过 padding 组成矩形张量还是拼接为一条连续序列。 + +| 策略 | 样本数 | 序列组织方式 | +|------|--------|--------------| +| `normal` | 固定 | 按 batch 内最长序列 padding | +| `padding_free` | 固定 | 将多条样本拼接为一条连续序列 | +| `dynamic_batching` | 动态 | 按最长序列 padding | +| `dynamic_padding_free` | 动态 | 按 token 预算选择样本并拼接 | + +例如设置 `cutoff_len: 2048`、`micro_batch_size: 4` 时,动态策略的 token 预算为 `2048 × 4 = 8192`。假设依次读到的样本长度为 2048、512、512、512: + +- `normal` 固定选择 4 条样本,并将每条样本 padding 到 2048,最终处理 8192 个 token 位置。 +- `padding_free` 仍选择 4 条样本,但将它们拼接为长度 3584 的序列,从而移除 padding。 +- `dynamic_batching` 在 `最长样本长度 × 样本数` 不超过 8192 的范围内决定样本数,然后按最长样本进行 padding。 +- `dynamic_padding_free` 在样本总长度不超过 8192 的范围内决定样本数,并将所选样本拼接起来。 + +因此,动态策略中的 `micro_batch_size` 用于计算 token 预算,并不表示最终 batch 一定包含相同数量的样本。 + +## 配置示例 + +`batching_strategy` 是训练 YAML 的顶层字段。以下片段配置 `dynamic_padding_free`,每个 micro-batch 的 token 预算为 `2048 × 4 = 8192`: + +```yaml +batching_strategy: dynamic_padding_free +micro_batch_size: 4 +cutoff_len: 2048 +max_steps: 100 +flash_attn: flash_attention_2 +``` + +仓库在 `examples/v1/train_batching_strategy/` 下为四种策略提供了完整示例。 + +## 使用约束 + +- `dynamic_batching` 必须设置正数 `max_steps`。 +- `dynamic_batching` 不支持 `save_epochs`,应使用 `save_steps`。 +- `padding_free` 和 `dynamic_padding_free` 需要设置 `flash_attn: flash_attention_2`。 +- `normal` 以外的策略仅支持纯文本数据;使用其他策略处理多模态数据时,BatchGenerator 会在生成 batch 时抛出 `NotImplementedError`。 + +内部 collate 和状态恢复流程见[BatchGenerator](../developer-guide/core/batch_generator.md)。 diff --git a/docs/zh/feature-guide/data_preparation.md b/docs/zh/feature-guide/data_preparation.md new file mode 100644 index 000000000..8861b0272 --- /dev/null +++ b/docs/zh/feature-guide/data_preparation.md @@ -0,0 +1,89 @@ +# 数据准备 + +v1 将训练样本统一为 Messages 结构。`DataEngine` 根据 `train_dataset` 指向的路径加载数据,并在存在 `converter` 时转换原始字段。 + +## 配置训练数据集 + +训练 YAML 的 `train_dataset` 指定数据来源。数据文件路径或 Hub ID 对应单个 Messages 格式数据集;数据集 YAML 则通过条目描述数据路径、split、converter 和采样配置,并支持组合多个数据集。 + +训练 YAML 包含 `model`、`train_dataset` 等训练字段;数据集 YAML 以数据集名称为键,包含 `path`、`source`、`converter` 等字段。下文“组合多个数据集”展示数据集 YAML 的结构。 + +`train_dataset` 接受以下形式: + +- 本地数据集 YAML,例如 `data/v1_sft_demo.yaml` +- 本地数据文件或目录 +- Hugging Face Hub 数据集 ID +- Hub 数据集仓库中的 YAML + +`eval_dataset` 字段已定义,评估流程尚未实现。完整字段见[数据参数](../configuration/data.md#dataarguments)。 + +## SFT 数据格式 + +```json +{ + "messages": [ + { + "role": "user", + "content": [{"type": "text", "value": "介绍一下你自己。"}], + "loss_weight": 0.0 + }, + { + "role": "assistant", + "content": [{"type": "text", "value": "我是一个 AI 助手。"}], + "loss_weight": 1.0 + } + ] +} +``` + +`content` 是内容块列表;文本使用 `text`,多模态内容可以使用 `image_url`、`audio_url` 或 `video_url`。`loss_weight` 是该 assistant turn 的监督权重,并应用到该回复的每个监督 token。`0.0` 不参与损失计算,`1.0` 使用完整权重,也可以设置 `0.5` 等中间值调整不同回复的相对权重。 + +多轮对话会按每个受监督的 assistant turn 展开为多条训练样本,每条样本只监督最后一个 assistant turn。 + +多模态 SFT 示例位于 `data/v1_multimodal_demo.yaml`,对应训练配置为 `examples/v1/train_full/train_multimodal.yaml`。 + +## DPO/RM 数据格式 + +DPO 和 RM 使用 `chosen_messages` 与 `rejected_messages`: + +```json +{ + "chosen_messages": [ + {"role": "user", "content": [{"type": "text", "value": "问题"}], "loss_weight": 0.0}, + {"role": "assistant", "content": [{"type": "text", "value": "更优回答"}], "loss_weight": 1.0} + ], + "rejected_messages": [ + {"role": "user", "content": [{"type": "text", "value": "问题"}], "loss_weight": 0.0}, + {"role": "assistant", "content": [{"type": "text", "value": "较差回答"}], "loss_weight": 1.0} + ] +} +``` + +## 组合多个数据集 + +```yaml +identity: + path: data/identity.json + source: local + converter: alpaca + +demo: + path: organization/dataset + source: hf_hub + split: train + size: 1000 + weight: 0.5 + streaming: false +``` + +同一个 YAML 中的 streaming 配置必须一致;当前训练路径不支持 streaming 数据集。多个条目会组成一个全局数据索引;`size` 与 `weight` 用于控制每个数据集的采样规模,计算顺序与有放回抽样的含义见[采样规模的计算](../configuration/data.md#采样规模的计算)。 + +## 转换现有数据格式 + +| 名称 | 原始数据 | +|------|----------| +| `alpaca` | `instruction`、`input`、`output` | +| `sharegpt` | `conversations` | +| `pair` | chosen/rejected 偏好对 | + +扩展 converter 的接口见[数据插件](../developer-guide/plugins/data_plugins.md)。 diff --git a/docs/zh/feature-guide/distributed_training.md b/docs/zh/feature-guide/distributed_training.md new file mode 100644 index 000000000..ae41fc269 --- /dev/null +++ b/docs/zh/feature-guide/distributed_training.md @@ -0,0 +1,103 @@ +# 分布式训练 + +训练命令检测到多设备后会自动通过 `torchrun` 启动。拓扑字段属于 `TrainingArguments`,后端专属字段放在 `dist_config`。 + +本页列出后端和拓扑配置,完整任务配置见 [SFT](sft.md)、[DPO](dpo.md)和 [RM](rm.md)。设备安装与支持范围见 [NPU 说明](../multi-backend/npu/index.md)。 + +## 数据并行 + +未设置 `dist_config` 时,多个 DP 进程使用 DDP,每个进程持有完整模型;单设备直接训练。 + +## FSDP2 + +FSDP2 通过分片降低每个设备上的模型状态内存开销,配置入口为 `dist_config.name: fsdp2`。 + +```yaml +dist_config: + name: fsdp2 + reshard_after_forward: true + offload_params: false + pin_memory: true + dcp_path: null +``` + +## FSDPTurbo + +FSDPTurbo 在 FSDP2 基础上提供 MoE 专家并行和专家参数分片。先安装 FSDPTurbo 依赖: + +```bash +python -m pip install -r requirements/fsdpturbo.txt +``` + +FSDPTurbo 的配置入口为 `dist_config.name: fsdpturbo`: + +```yaml +dist_config: + name: fsdpturbo + ep_size: 16 + ep_dispatcher: eager +``` + +`ep_size` 必须能够整除 data parallel size。完整示例见 `examples/v1/train_full/train_full_qwen3_moe_fsdpturbo_ep_fsdp.yaml`。 + +## DeepSpeed + +DeepSpeed 后端从 `config_file` 读取 ZeRO 等配置,该字段必填。 + +```yaml +dist_config: + name: deepspeed + config_file: examples/deepspeed/ds_z3_config.json +``` + +## Ulysses Context Parallel + +Ulysses CP 跨设备切分序列计算,由顶层 `cp_mode` 和 `cp_size` 启用: + +```yaml +flash_attn: flash_attention_2 +cp_mode: ulysses +cp_size: 2 + +dist_config: + name: fsdp2 +``` + +设置 `cp_size > 1` 后,训练使用 Ulysses 通信和 Sequence Parallel loss 完成跨 CP 进程的损失聚合。Ulysses 需要 `flash_attention_2` 和 FSDP2,不要求特定的 `batching_strategy`,支持 `normal` 和符合[批处理约束](batching.md)的 padding-free 策略。 + +`cp_size` 需要能够整除 world size。模型的 attention head 数必须能被 `cp_size` 整除,即 `num_attention_heads % cp_size == 0`;例如 32 个 attention head 可以使用 `cp_size: 2`。KV head 数与 `cp_size` 则要求其中一个能被另一个整除,即 `num_key_value_heads % cp_size == 0` 或 `cp_size % num_key_value_heads == 0`。当前只有 SFT 支持 `cp_size > 1`;DPO 和 RM 要求 `cp_size: 1`。 + +当前训练器不支持 `model_type: qwen3_5` 的 CP 路径。 + +## 配置并行拓扑 + +```yaml +dp_size: 4 +cp_size: 2 +cp_mode: ulysses +mp_replicate_size: 2 +mp_shard_size: 4 +dist_timeout: 18000 +``` + +上例使用 8 个进程,并同时构造两套 DeviceMesh: + +- Data Mesh 的形状为 `dp_size × cp_size = 4 × 2`,分别用于 Data Parallel 和 Context Parallel。 +- Model Mesh 的形状为 `mp_replicate_size × mp_shard_size = 2 × 4`。FSDP 在 4 个进程间分片参数,并在 2 个分片组间复制参数。 + +`mp_replicate_size` 和 `mp_shard_size` 描述 FSDP 的二维参数 Mesh,不是额外的 Tensor Parallel 配置。未显式指定时,`dp_size` 默认为 `world_size / cp_size`,`mp_shard_size` 默认为 `world_size / mp_replicate_size`。后端完整配置见[训练参数](../configuration/training.md#dist_config)。 + +## 配置多机启动 + +CLI 读取 `NNODES`、`NODE_RANK`、`NPROC_PER_NODE`、`MASTER_ADDR` 和 `MASTER_PORT`。例如使用 4 台机器、每台机器 8 个设备时,在每台机器上执行: + +```bash +NNODES=4 \ +NODE_RANK=<0到3,各节点不同> \ +NPROC_PER_NODE=8 \ +MASTER_ADDR= \ +MASTER_PORT=29500 \ +llamafactory-cli sft config.yaml +``` + +4 个节点需要使用相同的 `NNODES`、`NPROC_PER_NODE`、`MASTER_ADDR` 和 `MASTER_PORT`,并分别设置 `NODE_RANK=0`、`1`、`2`、`3`。 diff --git a/docs/zh/feature-guide/dpo.md b/docs/zh/feature-guide/dpo.md new file mode 100644 index 000000000..2729b517e --- /dev/null +++ b/docs/zh/feature-guide/dpo.md @@ -0,0 +1,53 @@ +# 偏好优化(DPO) + +v1 通过统一的 `dpo` 入口运行偏好优化,`pref_loss` 支持 `sigmoid`、`orpo` 和 `simpo`。数据必须是 chosen/rejected 偏好对。 + +## 运行 DPO + +```bash +llamafactory-cli dpo examples/v1/train_lora/train_lora_dpo.yaml +``` + +## 训练配置 + +`peft_config.name: lora` 启用 LoRA,未配置 `peft_config` 时进行全参训练。以下是完整的 LoRA DPO 配置,保存为 `config.yaml` 后运行 `llamafactory-cli dpo config.yaml`: + +```yaml +model: Qwen/Qwen3-4B +model_class: llm +train_dataset: data/v1_dpo_demo.yaml + +peft_config: + name: lora + r: 16 + lora_alpha: 32 + target_modules: all + +pref_loss: sigmoid +pref_beta: 0.1 +pref_ftx: 0.0 +dpo_label_smoothing: 0.0 + +dist_config: + name: fsdp2 + +output_dir: outputs/qwen3_dpo +micro_batch_size: 1 +cutoff_len: 2048 +learning_rate: 1.0e-5 +max_steps: 10 +``` + +## 偏好损失 + +`pref_loss` 指定偏好损失: + +- `sigmoid`:标准 DPO,相对参考策略进行偏好优化,`pref_beta` 控制偏好项缩放。 +- `orpo`:无参考策略的 odds-ratio 偏好目标,基于回答的平均 log-prob 计算。 +- `simpo`:无参考策略的平均 log-prob 差值目标,通过 `simpo_gamma` 设置 margin。 + +`pref_ftx` 加入 SFT 损失,`dpo_label_smoothing` 用于 cDPO。设置 `ld_alpha` 后,LD-DPO 会将 chosen 和 rejected 中超出较短响应长度的尾部 token log-prob 乘以该系数。参数定义见[训练参数](../configuration/training.md#trainingarguments)。 + +## 参考模型 + +标准 DPO 需要 reference log-prob:全参训练会建立独立的 reference model;LoRA 训练复用 policy model 的基座权重,并在计算 reference log-prob 时禁用 adapter。ORPO 和 SimPO 的目标计算不使用 reference log-prob。 diff --git a/docs/zh/feature-guide/index.md b/docs/zh/feature-guide/index.md new file mode 100644 index 000000000..3c6270f85 --- /dev/null +++ b/docs/zh/feature-guide/index.md @@ -0,0 +1,29 @@ +# 功能指南 + +功能指南面向使用 v1 完成训练与推理任务的用户。配置结构、默认值和可用选项统一放在[参数配置](../configuration/index.md)。 + +## 训练任务 + +| 页面 | 内容 | +|------|------| +| [数据准备](data_preparation.md) | Messages 格式、数据集 YAML 和 converter | +| [SFT](sft.md) | 全参、LoRA、Freeze、QLoRA | +| [DPO](dpo.md) | DPO、ORPO、SimPO 与偏好数据 | +| [RM](rm.md) | 奖励模型训练 | + +## 训练效率与扩展 + +| 页面 | 内容 | +|------|------| +| [批处理](batching.md) | 四种 batching strategy | +| [分布式训练](distributed_training.md) | FSDP2、FSDPTurbo、DeepSpeed、Ulysses | +| [优化器](optimizer.md) | AdamW 与 Muon 配置 | +| [融合算子加速](kernel_acceleration.md) | Liger、融合算子和组合配置 | + +## 模型保存与使用 + +| 页面 | 内容 | +|------|------| +| [模型保存与恢复](model_saving.md) | 最终模型、checkpoint、断点续训 | +| [模型导出](model_export.md) | LoRA 合并和 HF 格式导出 | +| [推理](inference.md) | CLI 对话与 adapter 加载 | diff --git a/docs/zh/feature-guide/inference.md b/docs/zh/feature-guide/inference.md new file mode 100644 index 000000000..4eace2e29 --- /dev/null +++ b/docs/zh/feature-guide/inference.md @@ -0,0 +1,53 @@ +# 推理 + +v1 已实现基于 Hugging Face 后端的 `chat` 入口,可以在命令行中进行流式对话。模型对话格式来自 tokenizer 自带的 Hugging Face chat template;没有模板时回退到内置 ChatML。 + +当前 `chat` 入口支持 `sample_backend: hf` 的交互式单条推理。批量推理和 `vllm` 采样后端尚未接入该入口;交互式配置中不设置 `train_dataset`。 + +## 启动 CLI 对话 + +`model` 指定模型 Hub ID 或包含完整权重的 HF 模型目录。LoRA adapter 的加载方式见下文。 + +以下对话配置保存为 `chat.yaml`,使用与 [SFT 示例](sft.md)相同的基座: + +```yaml +model: Qwen/Qwen3-0.6B +sample_backend: hf +max_new_tokens: 512 +``` + +```bash +llamafactory-cli chat chat.yaml +``` + +## 覆盖模型 Chat Template + +`custom_chat_template` 接收一段 Jinja2 模板字符串,并覆盖 tokenizer 自带模板: + +```yaml +model: path/to/model +custom_chat_template: >- + {% for message in messages %} + {{ message['role'] + ': ' + message['content'] }} + {% endfor %} +``` + +v1 使用模板字符串,不接受 `template: ` 字段。 + +## 使用 LoRA Adapter + +LoRA 推理通过 `model` 指定训练时的基座,通过 `peft_config.adapter_name_or_path` 指定 adapter。以下片段加入 `chat.yaml`,加载 [SFT 的 LoRA 示例](sft.md#lora)产生的 `outputs/qwen3_lora`;对应基座为 `Qwen/Qwen3-0.6B`: + +```yaml +peft_config: + name: lora + adapter_name_or_path: outputs/qwen3_lora +``` + +推理模式会依次合并 `adapter_name_or_path` 中的 adapter。[模型导出](model_export.md)说明合并结果的持久化保存。 + +## 使用训练或合并后的模型 + +完成 [SFT 全参示例](sft.md#全参训练)后,将 `chat.yaml` 中的 `model` 改为 `outputs/qwen3_full`;完成[模型导出示例](model_export.md#导出配置)后,改为 `outputs/qwen3_merged`。这两种目录都包含完整模型权重,加载时移除此前的 `peft_config`,保留采样参数并运行 `llamafactory-cli chat chat.yaml`。 + +完整字段见[推理参数](../configuration/inference.md)。 diff --git a/docs/zh/feature-guide/kernel_acceleration.md b/docs/zh/feature-guide/kernel_acceleration.md new file mode 100644 index 000000000..15471f698 --- /dev/null +++ b/docs/zh/feature-guide/kernel_acceleration.md @@ -0,0 +1,53 @@ +# 融合算子加速 + +`kernel_config` 统一配置模型侧的融合算子加速。它可以替换单个算子,也可以像 Liger Kernel 一样同时应用多个融合实现和训练优化。 + +`kernel_config.name` 接受一个加速实现名称,也接受逗号分隔的多个名称。未设置 `kernel_config` 或设为 `null` 时,此入口不替换算子。以下为算子配置片段,完整训练配置见 [SFT](sft.md)。 + +## 自动配置 + +`name: auto` 根据当前设备应用默认组合。当前仅 [NPU](../multi-backend/npu/index.md) 配置了默认组合,CUDA 上不会自动启用 Liger 或 CUDA Fused MoE。 + +## Liger Kernel + +Liger Kernel 依赖 `liger-kernel`,并要求模型具有对应适配。 + +```yaml +kernel_config: + name: liger_kernel +``` + +Liger Kernel 根据模型类型调用 `liger_kernel.transformers` 中对应的应用函数,可融合 RMSNorm、RoPE、SwiGLU、Cross Entropy 等训练路径。具体启用项由模型支持范围和 Liger Kernel 版本决定。 + +## CUDA Fused MoE + +```yaml +kernel_config: + name: cuda_fused_moe +``` + +该方案依赖 CUDA 和 Triton,并要求模型结构匹配,使用融合实现替换 MoE 计算路径。模型架构不匹配时保留原模型。 + +## Flash Linear Attention + +`flash-linear-attention` 通过 FSDPTurbo 的算子注册表替换模型中已有的 FLA 实现,支持 CUDA 和 NPU。它依赖 FLA 和 FSDPTurbo,不会将普通 attention 模型转换成线性注意力模型。 + +```yaml +kernel_config: + name: flash-linear-attention + include_kernels: chunk_gated_delta_rule,fused_recurrent_gated_delta_rule + chunk_size: 64 +``` + +`include_kernels` 可以设置为 `auto` 或逗号分隔的算子名称;`chunk_size` 支持 `16`、`32` 和 `64`。使用前需要安装 `requirements/fsdpturbo.txt`。 + +## 组合多个加速实现 + +多个名称以逗号分隔。以下为语法示意,`first_kernel` 和 `second_kernel` 是占位符,运行时替换为实际注册的实现名称: + +```yaml +kernel_config: + name: first_kernel,second_kernel +``` + +多个实现按书写顺序应用,后一个接收前一个处理后的模型;所有实现共享同一份 `kernel_config`。设备与依赖检查在应用前执行,模型匹配由各实现负责。组合入口不自动处理重复替换或顺序冲突。内部调用关系见[开发者指南](../developer-guide/plugins/kernel-acceleration/overview.md),字段定义见[模型参数](../configuration/model.md#kernel_config)。 diff --git a/docs/zh/feature-guide/model_export.md b/docs/zh/feature-guide/model_export.md new file mode 100644 index 000000000..557102e62 --- /dev/null +++ b/docs/zh/feature-guide/model_export.md @@ -0,0 +1,44 @@ +# 模型导出 + +`merge` 命令将一个或多个 LoRA adapter 依次合并到基座模型,并保存为 Hugging Face 格式目录。 + +导出目录包含合并后的模型权重。基座与 adapter 的直接加载见[推理](inference.md),训练状态的保存和续训见[模型保存与恢复](model_saving.md)。 + +## 导出配置 + +以下配置保存为 `merge.yaml`,接续 [SFT 的 LoRA 示例](sft.md#lora):基座为 `Qwen/Qwen3-0.6B`,adapter 位于 `outputs/qwen3_lora`,合并结果保存到 `outputs/qwen3_merged`。`model` 必须与 adapter 训练时的基座一致。 + +```yaml +model: Qwen/Qwen3-0.6B +peft_config: + name: lora + adapter_name_or_path: outputs/qwen3_lora + export_dir: outputs/qwen3_merged + export_size: 5 + infer_dtype: auto + export_legacy_format: false +``` + +```bash +llamafactory-cli merge merge.yaml +``` + +导出完成后,可以将推理配置的 `model` 设置为 `outputs/qwen3_merged`,按[推理指南](inference.md#使用训练或合并后的模型)加载。 + +`export_size` 的单位为 GB。`infer_dtype` 支持 `auto`、`float16`、`float32` 和 `bfloat16`。完整字段见[模型参数](../configuration/model.md#peft_config)。 + +## 合并多个 Adapter + +`adapter_name_or_path` 可以使用列表。系统按照列表顺序将每个 LoRA adapter 合并到前一步得到的模型中: + +```yaml +model: Qwen/Qwen3-0.6B +peft_config: + name: lora + adapter_name_or_path: + - outputs/domain_adapter + - outputs/task_adapter + export_dir: outputs/qwen3_merged +``` + +上例先合并 `domain_adapter`,再合并 `task_adapter`。这两个目录是独立训练的 adapter 示例,均须与 `Qwen/Qwen3-0.6B` 基座匹配;使用时替换为实际目录。 diff --git a/docs/zh/feature-guide/model_saving.md b/docs/zh/feature-guide/model_saving.md new file mode 100644 index 000000000..66536d32d --- /dev/null +++ b/docs/zh/feature-guide/model_saving.md @@ -0,0 +1,61 @@ +# 模型保存与恢复 + +训练结束时 `save_model()` 保存最终模型;训练过程中可以按 step 或 epoch 保存 checkpoint。 + +## 保存训练 Checkpoint + +`save_steps` 按更新步数触发保存,`save_epochs` 按数据遍历进度触发保存。同时设置时,训练器根据 `save_epochs` 重新计算并覆盖 `save_steps`。纯 `dynamic_batching` 只支持按 step 保存。 + +以下字段位于训练 YAML 的顶层: + +```yaml +save_steps: 500 +save_epochs: null +save_total_limit: 3 +save_ckpt_as_hf: false +``` + +`save_steps` 与 `save_epochs` 控制触发时机。`save_total_limit` 删除最旧的完整 checkpoint。 + +## 从 Checkpoint 恢复训练 + +`resume_from_checkpoint` 恢复训练状态。以下配置从当前 `output_dir` 中自动查找 checkpoint: + +```yaml +resume_from_checkpoint: auto +``` + +`auto` 在 `output_dir` 下寻找最新的完整 checkpoint,也可以直接填写 checkpoint 路径。未设置 `resume_from_checkpoint` 时,即使 `output_dir` 中存在 checkpoint,也不会触发续训。 + +## 不同后端的保存格式 + +| 训练后端 | 默认 checkpoint | `save_ckpt_as_hf: true` | +|----------|-------------------|--------------------------| +| FSDP2 / FSDPTurbo | 保存用于续训的分布式 checkpoint | 额外在 checkpoint 中生成 `hf_model` 目录 | +| DeepSpeed | 保存 DeepSpeed 训练状态 | 额外在 checkpoint 中生成 `hf_model` 目录 | +| 单设备 / DDP | 模型权重使用 HF 格式保存 | 不生成额外的 `hf_model` 目录 | + +FSDP2、FSDPTurbo 和 DeepSpeed 启用 `save_ckpt_as_hf` 后,仍会保留用于恢复训练的原始 checkpoint,同时额外保存 HF 格式模型。聚合完整模型权重会提高保存时的内存占用。 + +`save_ckpt_as_hf: false` 是默认值,保存中间 checkpoint 时不额外聚合 HF 格式权重。 + +## 初始化权重与恢复训练 + +| 配置 | 用途 | 加载时机 | 恢复内容 | +|------|------|----------|----------| +| `dist_config.dcp_path` | 使用 DCP 权重初始化模型 | FSDP2/FSDPTurbo 模型分片阶段 | 仅模型权重 | +| `resume_from_checkpoint` | 从训练 checkpoint 继续训练 | Trainer 初始化阶段 | 模型、优化器、学习率调度器、批次进度、训练步数及可用的随机数状态 | + +以下配置使用已有 DCP 模型权重初始化新训练: + +```yaml +dist_config: + name: fsdp2 + dcp_path: path/to/dcp_model +``` + +以下配置从 `output_dir` 中最新的完整 checkpoint 恢复训练状态: + +```yaml +resume_from_checkpoint: auto +``` diff --git a/docs/zh/feature-guide/optimizer.md b/docs/zh/feature-guide/optimizer.md new file mode 100644 index 000000000..4d8c7f9a0 --- /dev/null +++ b/docs/zh/feature-guide/optimizer.md @@ -0,0 +1,39 @@ +# 优化器 + +`optim_config` 未设置或为 `null` 时,v1 使用 AdamW,并从顶层 `learning_rate` 读取学习率。 + +## Muon + +设置 `optim_config.name: muon` 启用 Muon。Muon 对适合正交化更新的二维权重使用 Muon,并将偏置、归一化参数、embedding、输出层和 LoRA 参数交给内部 AdamW。 + +以下为完整的 SFT 配置(`config.yaml`): + +```yaml +model: Qwen/Qwen3-0.6B +model_class: llm +train_dataset: data/v1_sft_demo.yaml + +dist_config: + name: fsdp2 + +optim_config: + name: muon + wd: 0.1 + momentum: 0.95 + nesterov: true + ns_steps: 5 + adamw_betas: [0.9, 0.95] + adamw_eps: 1.0e-8 + +output_dir: outputs/qwen3_muon +micro_batch_size: 1 +cutoff_len: 2048 +learning_rate: 1.0e-5 +max_steps: 10 +``` + +```bash +llamafactory-cli sft config.yaml +``` + +学习率统一由顶层 `learning_rate` 控制。仓库示例见 `examples/v1/train_full/train_full_muon.yaml`,完整字段见[训练参数](../configuration/training.md#optim_config)。 diff --git a/docs/zh/feature-guide/rm.md b/docs/zh/feature-guide/rm.md new file mode 100644 index 000000000..b35bd5277 --- /dev/null +++ b/docs/zh/feature-guide/rm.md @@ -0,0 +1,38 @@ +# 奖励模型训练(RM) + +`rm` 入口训练回答评分模型,使 chosen 回答的评分高于 rejected 回答。 + +RM 与 [DPO](dpo.md) 使用相同的偏好对数据结构,输出模型用于回答评分,不作为普通聊天模型使用。 + +## 训练配置 + +`peft_config.name: lora` 启用 LoRA,未配置 `peft_config` 时进行全参训练。分布式后端由 `dist_config` 配置,支持条件见[分布式训练](distributed_training.md)。以下为完整的 LoRA RM 配置(`config.yaml`): + +```yaml +model: Qwen/Qwen3-0.6B +train_dataset: data/v1_dpo_demo.yaml + +peft_config: + name: lora + r: 16 + target_modules: all + +dist_config: + name: fsdp2 + +output_dir: outputs/qwen3_rm +micro_batch_size: 1 +cutoff_len: 2048 +learning_rate: 1.0e-5 +max_steps: 10 +``` + +```bash +llamafactory-cli rm config.yaml +``` + +入口会将 `model_class` 设置为 `cls`,初始化 score head,并在训练开始前检查首个样本是否包含 `chosen_messages` 和 `rejected_messages`。 + +## 训练约束 + +RM 当前要求 `cp_size` 为 `1`。`cutoff_len` 需要保留 chosen 和 rejected 的有效 token;否则当前 micro-batch 无法组成偏好对。 diff --git a/docs/zh/feature-guide/sft.md b/docs/zh/feature-guide/sft.md new file mode 100644 index 000000000..c5fa09542 --- /dev/null +++ b/docs/zh/feature-guide/sft.md @@ -0,0 +1,91 @@ +# 监督微调(SFT) + +`llamafactory-cli sft` 启动监督微调。下文依次说明全参训练、LoRA、Freeze 和量化 LoRA 的配置。 + +## 全参训练 + +全参训练更新全部模型参数,配置中不设置 `peft_config`。以下完整配置保存为 `config.yaml`,使用 `Qwen/Qwen3-0.6B` 和 FSDP2: + +```yaml +model: Qwen/Qwen3-0.6B +model_class: llm +train_dataset: data/v1_sft_demo.yaml + +output_dir: outputs/qwen3_full +micro_batch_size: 1 +cutoff_len: 2048 +learning_rate: 1.0e-4 +max_steps: 10 + +dist_config: + name: fsdp2 +``` + +```bash +llamafactory-cli sft config.yaml +``` + +## LoRA + +LoRA 冻结基座权重并训练 adapter,通过 `peft_config.name: lora` 配置。在上述训练配置中加入以下块,并将 `output_dir` 改为 `outputs/qwen3_lora`;基座仍为 `Qwen/Qwen3-0.6B`: + +```yaml +peft_config: + name: lora + r: 16 + lora_alpha: 32 + lora_dropout: 0.05 + target_modules: all +``` + +训练结束后,adapter 保存到 `outputs/qwen3_lora`。[推理](inference.md#使用-lora-adapter)和[模型导出](model_export.md#导出配置)示例沿用这一基座与目录。 + +继续训练已有 adapter 时设置 `adapter_name_or_path`。训练只允许一个 adapter;LoRA 参数从 adapter 自身恢复。 + +## Freeze + +Freeze 直接更新指定层或模块的权重,其余参数保持冻结。以下 `peft_config` 替换 LoRA 配置,模型、数据与训练字段沿用全参示例: + +```yaml +peft_config: + name: freeze + freeze_trainable_layers: 2 + freeze_trainable_modules: all + freeze_extra_modules: null + cast_trainable_params_to_fp32: true +``` + +正数表示最后 N 层,负数表示最前 N 层。 + +## QLoRA + +量化 LoRA 在量化后的基座上训练 adapter,分别由 `quant_config` 和 `peft_config` 控制。当前 v1 的量化插件入口为 `bnb` 和 `auto`:`bnb` 提供 bitsandbytes 的 4-bit、8-bit 加载分支;`auto` 在指定有效位宽时转交 `bnb` 处理。 + +下面是使用 bitsandbytes 4-bit 的 QLoRA 示例,运行环境需安装 bitsandbytes。将以下字段加入全参示例,模型、数据与 FSDP2 配置保持一致: + +```yaml +output_dir: outputs/qwen3_qlora + +peft_config: + name: lora + r: 16 + target_modules: all + +quant_config: + name: bnb + quantization_bit: 4 + quantization_type: nf4 + double_quantization: true +``` + +`quantization_bit` 表示加载位宽,`quantization_type` 表示 4-bit 量化格式,`double_quantization` 控制 4-bit double quant。位宽分支与字段默认行为见[量化参数](../configuration/model.md#quant_config),后端限制见 [NPU 说明](../multi-backend/npu/index.md)。 + +## 激活值重算 + +`enable_activation_checkpointing` 默认为 `true`。启用后,训练在反向传播时重新计算部分前向结果,以减少激活值占用的显存或设备内存,并增加计算量。设置为 `false` 关闭重计算: + +```yaml +enable_activation_checkpointing: false +``` + +分布式后端、批处理与算子配置分别见[分布式训练](distributed_training.md)、[批处理](batching.md)和[融合算子加速](kernel_acceleration.md)。 diff --git a/docs/zh/getting-started.md b/docs/zh/getting-started.md deleted file mode 100644 index b62ee1e5b..000000000 --- a/docs/zh/getting-started.md +++ /dev/null @@ -1,161 +0,0 @@ -# 快速开始 - -LLaMA Factory 是一个高效、灵活的大模型微调框架,支持 100+ 种主流大语言模型的微调训练。本文档将帮助您快速上手使用 LLaMA Factory。 - -## 支持的训练方法 - -| 方法 | 全参数训练 | 部分参数训练 | LoRA | QLoRA | -|:---------------------:| ------------------ | ------------------ | ------------------ | ------------------ | -| 指令监督微调 (SFT) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| DPO 训练 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | - -> **提示**: v1 版本目前支持 SFT 和 DPO 两种训练方法,均支持多种加速特性,包括 DeepSpeed、FSDP、FlashAttention-2 等。 - -## 软件依赖 - -| 必需项 | 至少 | 推荐 | -|:---------------------:|--------|--------| -| python | 3.11 | 3.12 | -| torch | 2.7.1 | 2.7.1 | -| torch-npu(Ascend NPU) | 2.7.1 | 2.7.1 | -| torchvision | 0.22.1 | 0.22.1 | -| transformers | 5.0.0 | 5.0.0 | -| datasets | 3.2.0 | 4.0.0 | -| peft | 0.18.1 | 0.18.1 | - - -| 可选项 | 至少 | 推荐 | -|:----------------:|--------|--------| -| CUDA(NVIDIA GPU) | 11.6 | 12.2 | -| deepspeed | 0.18.4 | 0.18.4 | -| flash-attn(NVIDIA GPU) | 2.5.6 | 2.7.2 | - - -## 安装 LLaMA Factory - -> [!IMPORTANT] -> 此步骤为必需。请确保您的环境满足上述软件依赖要求。 - -### 从源码安装(推荐) - -```bash -git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git -cd LLaMA-Factory -pip install -e . -``` - -### 使用 pip 安装 - -```bash -pip install llamafactory -``` - -### 可选依赖 - -如果您需要使用特定的加速特性,可以安装相应的依赖: - -```bash -# 安装 FlashAttention-2 支持 -pip install flash-attn --no-build-isolation - -# 安装 DeepSpeed 支持 -pip install deepspeed - -# 安装 Unsloth 支持(用于加速 LoRA 训练) -pip install unsloth -``` - -## 数据准备 - -LLaMA Factory 支持多种数据格式,包括 JSON、JSONL、CSV 等。关于数据集文件的详细格式说明,请参考 [数据准备指南](../../data/README_zh.md)。 - -### 使用内置数据集 - -LLaMA Factory 提供了多个内置数据集用于快速测试,您可以在 `data/dataset_info.json` 中查看所有可用的数据集。 - -### 使用自定义数据集 - -您可以使用 HuggingFace / ModelScope 上的数据集或加载本地数据集。 - -> [!NOTE] -> 使用自定义数据集或自定义数据集格式时,请参照 [数据准备指南](../../data/README_zh.md) 进行配置。如有必要,请重新实现自定义数据集的数据处理逻辑,包括对应的 `converter`。 - -### 数据构建工具 - -您也可以使用以下工具构建用于微调的合成数据: -- **[Easy Dataset](https://github.com/ConardLi/easy-dataset)** - 易于使用的数据集构建工具 -- **[DataFlow](https://github.com/OpenDCAI/DataFlow)** - 高质量数据准备管道 -- **[GraphGen](https://github.com/open-sciencelab/GraphGen)** - 基于图的数据生成工具 - -## 快速开始 - -### 命令行训练 - -下面的命令展示了对 Qwen3-0.6B 模型使用 FSDP2 进行全参数微调: - -```bash -export USE_V1=1 -llamafactory-cli sft examples/v1/train_full/train_full_fsdp2.yaml -``` - -> **提示**: `llamafactory-cli sft` 和 `llamafactory-cli train` 命令等价。 - -### Web UI 训练 - -LLaMA Factory 提供了直观的 Web 界面(LLaMA Board),您可以通过图形界面进行训练: - -```bash -llamafactory-cli webui -``` - -在浏览器中打开 http://localhost:7860 即可开始使用。 - -### 推理部署 - -训练完成后,您可以使用以下命令部署模型: - -```bash -# 使用 vLLM 后端进行高性能推理 -llamafactory-cli chat --model_name_or_path path/to/your/model --template qwen --infer_backend vllm - -# 使用 HuggingFace 后端进行推理 -llamafactory-cli chat --model_name_or_path path/to/your/model --template qwen -``` - -## 进阶用法 - -高级用法请参考 [进阶指南](./advanced/README.md),包括: -- 多卡多机分布式训练 -- LoRA/QLoRA 微调 -- 模型量化(AWQ/GPTQ/LLM.int8 等) -- 各种加速特性(DeepSpeed、FSDP、FlashAttention 等) -- 多模态模型微调 - -## 常见问题 - -### 1. 内存不足怎么办? - -- 使用 LoRA 或 QLoRA 代替全参数训练 -- 减小 `batch_size` 和 `cutoff_len` -- 启用 `gradient_checkpointing` -- 使用 DeepSpeed ZeRO-2 或 ZeRO-3 - -### 2. 如何选择合适的训练方法? - -- **SFT(指令微调)**: 最常用的方法,适用于大多数场景,通过监督数据训练模型 -- **DPO(直接偏好优化)**: 用于对齐人类偏好,提升模型输出质量,无需训练奖励模型 - -### 3. 训练完成后如何评估模型? - -```bash -llamafactory-cli eval --model_name_or_path path/to/your/model --template qwen --dataset mmlu -``` - -更多评估方法请参考 [评估指南](./advanced/evaluation.md)。 - -## 获取帮助 - -如果您在使用过程中遇到问题: -- 查看 [GitHub Issues](https://github.com/hiyouga/LLaMA-Factory/issues) -- 加入 [Discord 社区](https://discord.gg/rKfvV9r9FK) -- 加入微信群(扫描二维码) diff --git a/docs/zh/hyperparameters/data-argument.md b/docs/zh/hyperparameters/data-argument.md deleted file mode 100644 index b4cbe514f..000000000 --- a/docs/zh/hyperparameters/data-argument.md +++ /dev/null @@ -1 +0,0 @@ -# Data Argument diff --git a/docs/zh/hyperparameters/model-argument.md b/docs/zh/hyperparameters/model-argument.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/zh/hyperparameters/sample-argument.md b/docs/zh/hyperparameters/sample-argument.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/zh/hyperparameters/training-argument.md b/docs/zh/hyperparameters/training-argument.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/zh/index.rst b/docs/zh/index.rst index 46463b02e..8e677bc40 100644 --- a/docs/zh/index.rst +++ b/docs/zh/index.rst @@ -1,64 +1,51 @@ -LlamaFactory 文档 -================= +LlamaFactory v1 文档 +===================== .. toctree:: :maxdepth: 1 :caption: Getting Started - getting-started - installation - llamaboard-web-ui + quick_start .. toctree:: - :maxdepth: 1 - :caption: Data Preparation + :maxdepth: 2 + :caption: Feature Guide - data-preparation/data-processing + feature-guide/index + feature-guide/data_preparation + feature-guide/sft + feature-guide/dpo + feature-guide/rm + feature-guide/batching + feature-guide/distributed_training + feature-guide/optimizer + feature-guide/model_saving + feature-guide/model_export + feature-guide/inference + feature-guide/kernel_acceleration .. toctree:: - :maxdepth: 1 - :caption: Training + :maxdepth: 2 + :caption: Configuration - training/sft - training/dpo + configuration/index + configuration/data + configuration/model + configuration/training + configuration/inference .. toctree:: - :maxdepth: 1 - :caption: Inference + :maxdepth: 2 + :caption: Developer Guide - inference/deploy + developer-guide/index + developer-guide/architecture_overview + developer-guide/core/index + developer-guide/baseplugin_mechanism + developer-guide/plugins/index .. toctree:: - :maxdepth: 1 - :caption: Advanced + :maxdepth: 2 + :caption: Multi-Backend - advanced/lora-and-quantization/lora - advanced/lora-and-quantization/quantization - advanced/ktransformers - advanced/distributed/fsdp - advanced/distributed/deepspeed - advanced/distributed/parallel-dp-tp-ep-sp-cp - advanced/distributed/fsdpturbo-ep-efsdp - advanced/custom-kernels/triton - advanced/custom-kernels/fused-operators - -.. toctree:: - :maxdepth: 1 - :caption: Hyperparameters - - hyperparameters/data-argument - hyperparameters/model-argument - hyperparameters/sample-argument - hyperparameters/training-argument - -.. toctree:: - :maxdepth: 1 - :caption: Dev Guide - - dev-guide/core/data-engine - dev-guide/core/model-engine - dev-guide/core/trainer - dev-guide/plugins/data-plugins - dev-guide/plugins/model-plugins/initialization - dev-guide/plugins/model-plugins/kernels - dev-guide/plugins/model-plugins/rendering + multi-backend/npu/index diff --git a/docs/zh/inference/deploy.md b/docs/zh/inference/deploy.md deleted file mode 100644 index 168a97008..000000000 --- a/docs/zh/inference/deploy.md +++ /dev/null @@ -1 +0,0 @@ -# Deploy diff --git a/docs/zh/installation.md b/docs/zh/installation.md deleted file mode 100644 index 25267fe2b..000000000 --- a/docs/zh/installation.md +++ /dev/null @@ -1 +0,0 @@ -# Installation diff --git a/docs/zh/llamaboard-web-ui.md b/docs/zh/llamaboard-web-ui.md deleted file mode 100644 index 8ed9de7b4..000000000 --- a/docs/zh/llamaboard-web-ui.md +++ /dev/null @@ -1 +0,0 @@ -# LlamaBoard Web UI diff --git a/docs/zh/multi-backend/npu/index.md b/docs/zh/multi-backend/npu/index.md new file mode 100644 index 000000000..47b95d173 --- /dev/null +++ b/docs/zh/multi-backend/npu/index.md @@ -0,0 +1,130 @@ +# Ascend NPU + +本页介绍 Ascend NPU 的手动安装、功能范围和融合算子加速能力。 + +## 手动安装 + +手动安装需要依次准备 HDK 驱动与固件、CANN 和 `torch-npu`。安装包需要与 NPU 型号、CPU 架构和操作系统匹配。本分支使用以下软件组合: + +| 组件 | 版本 | +|------|------| +| CANN | `9.1.0` | +| PyTorch | `2.10.0` | +| torch-npu | `2.10.0.post2` | +| torchvision | `0.25.0` | +| torchaudio | `2.10.0` | +| Triton Ascend | `3.2.1` | + +安装前使用[Ascend 兼容性查询助手](https://www.hiascend.com/hardware/compatibility)确认硬件与操作系统组合,并从[CANN 9.1.0 社区版资源中心](https://www.hiascend.com/developer/download/community/result?cann=9.1.0&module=cann)选择对应 CPU 架构的软件包。 + +### 安装驱动与固件 + +从 Ascend 下载与设备匹配的 HDK 驱动和固件安装包。以下命令中的文件名需要替换为实际下载的包名: + +```bash +chmod +x Ascend-hdk--npu-driver__linux-.run +chmod +x Ascend-hdk--npu-firmware_.run + +sudo ./Ascend-hdk--npu-driver__linux-.run \ + --full --install-for-all +sudo ./Ascend-hdk--npu-firmware_.run --full +``` + +根据安装程序提示重启系统,然后验证驱动: + +```bash +npu-smi info +``` + +### 安装 CANN + +先安装 Toolkit,再安装与设备匹配的 ops 算子包: + +```bash +chmod +x Ascend-cann-toolkit__linux-.run +sudo ./Ascend-cann-toolkit__linux-.run --install + +chmod +x Ascend-cann--ops__linux-.run +sudo ./Ascend-cann--ops__linux-.run --install +``` + +默认以 root 安装时,加载以下环境变量: + +```bash +source /usr/local/Ascend/ascend-toolkit/set_env.sh +``` + +普通用户安装时,环境脚本位于用户选择的 CANN 安装目录。需要在每个运行 LlamaFactory 的 shell 中加载该脚本,也可以将命令加入 shell 配置文件。 + +### 安装 LlamaFactory + +在项目根目录创建 Python 环境,并安装 NPU 依赖和 LlamaFactory: + +```bash +python -m venv .venv +source .venv/bin/activate +python -m pip install --upgrade pip +python -m pip install -e . +python -m pip install -r requirements/npu.txt +python -m pip install -r requirements/triton_ascend.txt +``` + +`requirements/npu.txt` 固定了相互匹配的 PyTorch、torchvision、torchaudio 和 `torch-npu` 版本;`requirements/triton_ascend.txt` 安装 NPU 对应的 Triton 实现。如果使用已有 Python 环境,应确认安装完成后的 PyTorch 与 `torch-npu` 版本仍与上述版本一致。 + +### 验证 PyTorch NPU + +```bash +python -c "import torch, torch_npu; print(torch.npu.is_available())" +``` + +输出 `True` 表示 PyTorch 已识别 NPU。启用 v1 后即可运行 SFT: + +```bash +export USE_V1=1 +llamafactory-cli sft examples/v1/train_full/train_full_fsdp2.yaml +``` + +## 功能范围 + +| 功能 | 状态 | 说明 | +|------|:----:|------| +| [SFT 全参训练](../../feature-guide/sft.md) | 支持 | 支持 FSDP2 | +| [LoRA / Freeze](../../feature-guide/sft.md) | 支持 | 使用通用 PEFT 路径 | +| [QLoRA](../../feature-guide/sft.md#qlora) | 不支持 | 当前量化路径依赖 bitsandbytes | +| [DPO](../../feature-guide/dpo.md) | 支持 | 使用偏好对数据 | +| [RM](../../feature-guide/rm.md) | 支持 | `cp_size` 需要为 `1` | +| [FSDP2](../../feature-guide/distributed_training.md) | 支持 | 使用 NPU 设备和通信后端 | +| [FSDPTurbo](../../feature-guide/distributed_training.md) | 支持 | 提供 MoE 专家并行和专家参数分片 | +| [Ulysses CP](../../feature-guide/distributed_training.md#ulysses-context-parallel) | 支持 | 依赖适配的 attention 实现 | +| [DeepSpeed](../../feature-guide/distributed_training.md#deepspeed) | 依赖环境 | 由 NPU DeepSpeed 发行版和配置决定 | +| [HF CLI 推理](../../feature-guide/inference.md) | 支持 | `sample_backend: hf` | + +## 量化支持 + +当前 v1 QLoRA 依赖 bitsandbytes,因此不适用于 NPU。 + +## 融合算子加速 + +`kernel_config.name: auto` 在 NPU 上依次尝试: + +- `npu_fused_moe` +- `npu_fused_rmsnorm` +- `npu_fused_rope` +- `npu_fused_swiglu` + +也可以显式选择一个或多个名称: + +```yaml +kernel_config: + name: npu_fused_rmsnorm,npu_fused_rope +``` + +每个实现会检查当前设备及 `torch_npu` 依赖。模型结构不匹配时,具体 Kernel 可能跳过替换或抛出明确错误。 + +## Liger Kernel + +`liger_kernel` 接受 CUDA 或 NPU,但仍要求模型类型在当前 Liger 映射中,并且已安装兼容版本的 `liger_kernel`。 + +## 分布式训练 + +FSDP2、FSDPTurbo 与 Ulysses 使用 accelerator 抽象选择 NPU 通信设备。DeepSpeed 的可用性由 NPU DeepSpeed 发行版、依赖版本和配置共同决定。 diff --git a/docs/zh/quick_start.md b/docs/zh/quick_start.md new file mode 100644 index 000000000..27ae9ce86 --- /dev/null +++ b/docs/zh/quick_start.md @@ -0,0 +1,48 @@ +# 快速开始 + +v1 是 LlamaFactory 的实验性架构,通过 `USE_V1=1` 启用。稳定版(v0)的功能与完整文档见[LlamaFactory 文档](https://llamafactory.readthedocs.io/)。 + +本页是 v1 的快速指南,介绍安装、启用 v1 和运行 SFT。更完整的环境说明见仓库 README。 + +## 安装 + +```bash +git clone --depth 1 https://github.com/hiyouga/LlamaFactory.git +cd LlamaFactory +pip install -e . +``` + +## 启用 v1 + +```bash +export USE_V1=1 +``` + +## 运行 SFT + +仓库提供数据配置 `data/v1_sft_demo.yaml` 和可运行示例。以下训练配置已经通过 `train_dataset` 引用该数据配置,可以直接运行: + +```bash +llamafactory-cli sft examples/v1/train_full/train_full_fsdp2.yaml +``` + +检测到多个设备时,CLI 会自动通过 `torchrun` 重启;单设备需要强制走该入口时可以设置 `FORCE_TORCHRUN=1`。 + +## 选择运行命令 + +v1 当前支持以下命令: + +| 命令 | 用途 | +|------|------| +| `sft` | 监督微调 | +| `dpo` | 偏好优化 | +| `rm` | 奖励模型训练 | +| `chat` | 交互式推理 | +| `merge` | 合并 LoRA adapter 并导出模型 | + +## 文档导航 + +- [功能指南](feature-guide/index.md):训练、推理、分布式训练、模型保存与融合算子加速 +- [参数说明](configuration/index.md):数据、模型、训练和推理参数 +- [开发者指南](developer-guide/index.md):v1 架构、Core 与 Plugin +- [多后端](multi-backend/npu/index.md):昇腾 NPU 的环境安装与功能说明 diff --git a/docs/zh/training/dpo.md b/docs/zh/training/dpo.md deleted file mode 100644 index 767a9849d..000000000 --- a/docs/zh/training/dpo.md +++ /dev/null @@ -1 +0,0 @@ -# DPO diff --git a/docs/zh/training/sft.md b/docs/zh/training/sft.md deleted file mode 100644 index 93a21753e..000000000 --- a/docs/zh/training/sft.md +++ /dev/null @@ -1 +0,0 @@ -# SFT