SaddleLLM
当前版本:2.36
SaddleLLM 是一个配置驱动、与行业无关的大模型全生命周期平台。用户准备数据、模型和一份训练配置,系统负责检查输入、安排训练阶段、调用对应训练器,并保存 checkpoint、评测结果、发布产物和运行状态。医疗、护理、教育等是外部领域项目,通过数据、配置或插件接入,不能成为核心包中的硬编码分支。
平台能力边界、成熟度和开发优先级见 通用大模型平台边界;完整命令与参数见 简明命令手册;本轮主链代码审查及后续缺口见 代码完善审查。
本文只讲当前实现,按三个问题展开:
- 这个系统是什么。
- 怎么使用,命令会返回什么。
- 代码和训练过程为什么这样运行。
1. 这个系统是什么
1.1 系统定位
SaddleLLM 不是一个单独的模型,也不是重新实现 PyTorch、Transformers、PEFT 或 TRL。它位于这些训练库的上层,把一次模型实验需要的内容组织起来:
数据 + 基础模型 + 训练参数 + 执行阶段
↓
SaddleLLM
↓
训练计划 + checkpoint + 评测 + 发布文件 + 运行记录
它主要解决五件事:
- 用一份 YAML/JSON 明确本次运行要做哪些阶段。
- 在加载大模型前检查配置、数据和运行环境。
- 按顺序调用预训练、SFT、偏好训练、评测和导出等实现。
- 把前一个阶段产生的模型或数据交给后一个阶段。
- 保存计划、状态和结果,让失败可定位、运行可恢复、产物可追踪。
1.2 输入、处理和输出
| 类型 | 具体内容 |
|---|---|
| 输入 | YAML/JSON 配置、文本或多模态数据、基础模型或 checkpoint |
| 处理 | 数据检查、模型加载、阶段排序、训练、评测、导出 |
| 输出 | 阶段计划、训练 checkpoint、最终模型、指标、发布门禁、运行摘要 |
用于 train、validate-config 和 plan 的训练配置只有一种结构:顶层必须有非空的 stages 列表。
例如:
stages: [sft, preference, eval]
这表示依次执行:
监督微调 → 偏好训练 → 评测
每个阶段的参数放在同名配置块里:
stages: [sft, preference]
sft:
enabled: true
data_path: data/sft.jsonl
preference:
enabled: true
method: dpo
data_path: data/preference.jsonl
1.3 当前支持的能力
| 领域 | 阶段或入口 | 当前实际行为 |
|---|---|---|
| Tokenizer | tokenizer |
训练新 tokenizer;未提供训练参数时加载已有 tokenizer |
| 从零预训练 | pretrain + pretrain_mode: scratch |
创建模型、处理语料、执行 causal LM 训练并保存最终模型 |
| 继续预训练 | pretrain + pretrain_mode: continue |
加载已有权重,用新训练任务继续优化 |
| 监督微调 | sft |
执行全参数、LoRA 或 QLoRA SFT |
| 偏好训练 | preference |
执行 DPO、ORPO 或 KTO |
| RLHF | rlhf |
DPO 可执行;PPO dry-run可规划,实际训练开始前明确阻断 |
| 多教师蒸馏 | mopd |
生成计划,或调用教师收集 on-policy 数据供后续 SFT |
| VLA | vla_sft |
检查并规范化机器人轨迹;vla.train: true 时执行行为克隆训练 |
| 通用图文训练 | mllm_sft、vision_alignment |
当前负责数据规范化和训练计划,还没有执行通用 VLM 参数优化 |
| 图像生成 | media_cache + image_generation |
编码图像与文本条件,训练潜变量生成模型 |
| 音乐生成 | media_cache + music_generation |
编码音频码本与文本条件,训练多码本自回归模型 |
| 视频生成 | media_cache + video_generation |
编码视频潜变量与文本条件,训练时空生成模型 |
| 世界模型 | world_model |
用离线轨迹训练 RSSM 或 categorical RSSM |
| 眼动控制 | eye_control |
在安全软件仿真器中评估 PID 或世界模型规划控制 |
| 评测 | eval |
计算指标,并可按规则生成发布门禁结果 |
| 导出 | export |
打包 HF 或 Saddle 模型;可要求评测门禁先通过 |
| 外部算子 | operator |
调用已配置的 agent/大模型算子并登记产物 |
1.4 两种模型后端
model.backend 决定文本模型由哪套实现负责:
| 后端 | 用途 | 当前边界 |
|---|---|---|
hf |
Hugging Face 模型加载、SFT、LoRA、QLoRA、DPO、ORPO、KTO | 最适合已有开源模型的后训练 |
saddle |
项目原生模块化语言模型、原生 checkpoint、预训练和 DPO | 不支持 LoRA/QLoRA;偏好方法当前只支持 DPO |
非单进程的 DDP、FSDP 和 DeepSpeed 路径,目前只对 model.backend: saddle 的 pretrain 阶段声明为可执行。其他内置阶段使用 distributed.strategy: single。
1.5 代码目录
| 路径 | 作用 |
|---|---|
saddlellm/cli.py |
命令行参数和命令分发 |
saddlellm/training/TrainingOrchestrator.py |
解析配置、校验并执行阶段 |
saddlellm/framework/stages.py |
阶段注册表和阶段能力声明 |
saddlellm/training/ |
预训练、SFT、偏好训练和分布式运行 |
saddlellm/data/ |
数据采集、清洗、规范化和检查 |
saddlellm/models/ |
模型结构、构建、加载和 tokenizer |
saddlellm/multimodal/ |
图像、音频、视频、VLM 和 VLA |
saddlellm/world_models/ |
RSSM 数据、模型、训练和推理 |
saddlellm/spatial/ |
空间感知、路径规划、眼动控制和 WorldAgent |
saddlellm/evaluation/ |
评测、冒烟测试和发布门禁 |
saddlellm/runtime/ |
模型导出、服务和部署 |
configs/ |
可以直接参考的配置文件 |
tests/ |
行为和接口测试 |
2. 怎么使用、命令做什么、返回什么
2.1 安装
建议使用独立虚拟环境:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[posttrain,dev]"
按功能安装可选依赖:
| 需求 | 安装命令 |
|---|---|
| 通用训练 | python -m pip install -e ".[train]" |
| SFT、PEFT、TRL | python -m pip install -e ".[posttrain]" |
| QLoRA | python -m pip install -e ".[posttrain,qlora]" |
| 推理 API | python -m pip install -e ".[serve]";运行时4/8bit量化再加qlora:.[serve,qlora] |
| 空间智能与眼动控制 | python -m pip install -e ".[spatial]" |
| 开发和测试 | python -m pip install -e ".[dev]" |
如果要严格使用仓库验证过的后训练版本:
python -m pip install -r requirements-posttrain.txt
安装完成后确认命令可见:
saddlellm --help
也可以不用 console script:
python -m saddlellm.cli --help
2.2 第一次运行
创建一个 10 步 LoRA SFT 小项目:
saddlellm quickstart ".\my-training"
生成的目录:
my-training/
├─ config.yaml
├─ README.md
└─ data/
└─ sft.jsonl
命令返回 JSON,主要字段如下:
{
"workspace": "绝对路径/my-training",
"config": "绝对路径/my-training/config.yaml",
"stages": ["sft"],
"model": "Qwen/Qwen2.5-0.5B-Instruct",
"data_files": {"sft": "绝对路径/my-training/data/sft.jsonl"},
"created_files": ["..."],
"next_steps": ["..."],
"note": "..."
}
进入目录后依次执行:
Set-Location ".\my-training"
saddlellm doctor
saddlellm inspect-data data/sft.jsonl --task sft
saddlellm validate-config config.yaml
saddlellm train config.yaml --dry-run
saddlellm train config.yaml
正式训练有独立 validation/test 时,一次完成 schema 与跨集合泄漏检查:
saddlellm inspect-data data/train.jsonl --task sft `
--validation-data data/validation.jsonl `
--test-data data/test.jsonl `
--group-field case_id --strict-leakage `
--output outputs/split_audit.json
同一 group、规范化后的同题会阻断;高相似改写默认警告,--strict-leakage 下也会阻断。
报告默认对 group id 做哈希且不复制题目原文;只有在确认数据可安全展示时才使用
--include-content-previews。当配置含独立 validation_data_path 时,validate-config 和正式
训练前置检查也会自动执行训练/验证泄漏审计。
训练启动后,可在另一个终端查看进度、loss 曲线、阶段状态和日志:
saddlellm dashboard outputs/my-sft --open
dashboard 只读取训练目录中的标准产物,不占用第二份模型显存,也不要求安装单独的前端工程。历史训练目录同样可以打开。
创建“SFT 后接 DPO”的项目:
saddlellm quickstart ".\my-training" --stages sft,preference --preference-method dpo
使用自己的数据和模型:
saddlellm quickstart ".\my-training" --model "D:\models\my-model" --data "D:\datasets\sft.jsonl"
quickstart 不会下载模型,也不会开始训练。它只创建配置、示例数据和下一步命令。目标文件已存在时默认拒绝覆盖;--force 只覆盖它负责生成的文件。
2.3 直接训练,或者使用配置文件
最常见的单阶段 SFT 可以直接写命令,不必先创建 YAML:
saddlellm train sft `
--model Qwen/Qwen3-0.6B `
--data train.jsonl `
--epochs 1 `
--output-dir outputs/my-sft
完全等价的显式写法是:
saddlellm train --stage sft `
--model Qwen/Qwen3-0.6B `
--data train.jsonl `
--epochs 1 `
--output-dir outputs/my-sft
直接训练默认使用 LoRA、有效 batch 由 --batch-size 1 和 --gradient-accumulation-steps 4 组成、最大长度 512,并保留 5% 数据作内部验证。常用覆盖参数:
saddlellm train sft --model MODEL --data DATA `
--method lora `
--learning-rate 5e-5 `
--batch-size 1 `
--gradient-accumulation-steps 8 `
--max-seq-length 384 `
--max-steps 150 `
--save-steps 50 `
--eval-steps 50 `
--precision bf16 `
--local-files-only `
--output-dir outputs/my-sft
正式训练建议准备独立验证文件,避免随机划分把同源病例或同一对话的不同轮次分到两边:
saddlellm train sft --model MODEL --data train.jsonl `
--validation-data validation.jsonl `
--method lora --lora-target-modules all-linear `
--save-steps 50 --eval-steps 50 `
--output-dir outputs/my-sft
--validation-data 与 --validation-split 二选一。存在验证集时,SaddleLLM 按 eval_loss
记录并在训练结束恢复最佳 checkpoint;按 step 验证时,--save-steps 必须是
--eval-steps 的整数倍。结果中的 best_model_checkpoint 和 best_metric 是实际选择证据。
--method 支持 lora、qlora 和 full。--lora-target-modules all-linear 使用 PEFT 的
架构无关写法覆盖模型中适合 LoRA 的全部线性层,通常比只训练 Q/K/V/O 投影有更大的适配容量,
也会增加可训练参数、显存和耗时;仍可用逗号明确指定层。用 --dry-run 只显示解析后的完整配置
而不训练;实际训练时 SaddleLLM 会把等价配置保存为输出目录中的 command_config.json,保证
命令行训练仍可复现。
训练中断后,保持原输出目录、模型、数据、更新方法、batch 和并行规模不变,提高总
--max-steps,再加不带路径的 --resume-from-checkpoint,会自动选择最新 checkpoint:
saddlellm train sft --model MODEL --data DATA `
--method lora --batch-size 1 --max-steps 300 `
--output-dir outputs/my-sft --resume-from-checkpoint
也可以在该参数后显式给出 checkpoint-* 路径。直接命令的精确续训一次只允许一个阶段;
多阶段恢复使用 YAML 的 pipeline.resume。SaddleLLM 会拒绝有效训练 batch 发生变化的“伪续训”。
结果同时记录 resumed_from_checkpoint、原始累计 train_metrics、不受续训步数稀释的
latest_train_metrics,并在存在内部验证集时保证写出最终 eval_metrics。
已有模型做领域继续预训练,也可以直接运行:
saddlellm train pretrain `
--model Qwen/Qwen3-0.6B `
--data data/nursing_corpus.jsonl `
--text-column text `
--max-steps 1000 `
--global-batch-size 32 `
--output-dir outputs/nursing-cpt
这是 pretrain_mode: continue:网络结构和 tokenizer 从 --model 继承,数据每行采用
{"text":"连续的护理教材或规范正文……"}。从零创建网络时建议改用 YAML 的
model.config + model.blueprint,因为网络结构属于模型身份,应该完整保存和审计,而不是堆成一长串命令行参数。
不确定后训练数据该用哪种方法时,使用名称明确的 auto-posttrain(不是含义模糊的 auto):
saddlellm train --stage auto-posttrain `
--model Qwen/Qwen3-0.6B `
--data data/posttrain.jsonl `
--dry-run
它先抽样并检查本地数据,再按数据契约选择:instruction/output、messages 或普通
prompt/completion → SFT;prompt/chosen/rejected → DPO;带显式二元 label 的
prompt/completion → KTO。结果会输出 selected_stage、选择理由、质量警告和完整检查报告。
PPO 永远不会被自动选择;混合格式、未知格式、只有单一正负标签的 KTO 数据会直接拒绝,
避免静默丢样本。确认 dry-run 结果后去掉 --dry-run 即可训练。
auto-posttrain 只处理后训练,绝不会选择预训练。两者边界如下:
| 入口 | 数据形态 | 目标 |
|---|---|---|
pretrain / pretrain_mode: continue |
大规模连续文本语料 | 学习语言、通用或护理领域知识 |
auto-posttrain |
带目标回答或偏好标签的样本 | 自动选择 SFT、DPO 或 KTO,塑造回答方式与偏好 |
直接命令也支持有序的多阶段训练。--stage 中的逗号表示严格的先后依赖,不是无序开关;前一阶段成功保存的模型自动成为后一阶段输入:
saddlellm train --stage sft,kto `
--model Qwen/Qwen3-0.6B `
--data data/sft.jsonl `
--kto-data data/kto.jsonl `
--batch-size 2 `
--output-dir outputs/sft-kto
这里 --data 属于第一个阶段,后续阶段分别使用 --dpo-data、--orpo-data、--kto-data 或 --ppo-data。当前直接命令可真实执行 SFT、DPO、ORPO、KTO,一条命令内最多包含一个 DPO/ORPO/KTO 阶段。PPO 名称已经纳入有序解析和 dry-run,但稳定执行器尚未接入;实际命令包含 PPO 时会在任何训练开始前失败,绝不会跳过 PPO 后继续执行后续阶段:
saddlellm train --stage sft,ppo,kto `
--model MODEL `
--data data/sft.jsonl `
--ppo-data data/ppo.jsonl `
--kto-data data/kto.jsonl `
--dry-run
dry-run 会同时展示用户阶段 sft → ppo → kto、内部映射 sft → rlhf → preference,以及每个阶段的 needs 依赖。真正接通 PPO 前必须明确奖励模型、价值模型、rollout 策略和安全验证过的奖励契约,不能用“计划成功”冒充训练成功。
2.4 蒸馏与轻量化命令
轻量化不是一个模糊开关。SaddleLLM 将“得到更小学生模型”“持久化 CPU INT8”“GPU 加载时量化”和“稀疏权重实验”拆成职责清楚的命令:
| 目标 | 命令 | 当前稳定边界 |
|---|---|---|
| 更小的学生模型 | saddlellm distill --mode logits ... |
本地 teacher logits + 正确 causal mask,保存可直接加载的 HF 学生模型,并记录参数缩减与前后 PPL |
| 用教师答案训练已有学生 | saddlellm distill --mode data ... |
在线教师只生成待审核 JSONL;审核后用 --teacher-data 执行 SFT,防止错误医疗答案直接回灌 |
| 持久化 CPU 模型 | saddlellm quantize ... |
动态 INT8;lightweight 是同义入口;产物可由 serve --device cpu 加载 |
| GPU 低显存推理 | saddlellm serve ... --quantization 8bit/4bit |
bitsandbytes 加载时量化,不另建模型目录 |
| 稀疏权重研究 | saddlellm prune ... |
产物可加载,但普通 dense 后端不保证文件更小或推理更快,必须另做效果评估 |
本地 logits 蒸馏会从教师配置创建层数和宽度更小的学生,同时使用真实标签 loss 与 teacher KL loss:
saddlellm distill --mode logits `
--teacher E:\models\Qwen3-4B `
--data data\nursing_corpus.jsonl `
--eval-data data\nursing_validation.jsonl `
--student-layers 12 --student-hidden-size 1024 --student-heads 16 `
--max-steps 1000 --batch-size 1 --max-seq-length 1024 `
--output-dir outputs\nursing-student
先加 --dry-run 可查看最终参数。该模式训练时需同时保留教师和学生,显存不够时应改用
data 模式。学生必须比教师小;不满足时命令会拒绝。输出报告包含
parameter_reduction_ratio、teacher/学生初始/学生训练后 PPL 和蒸馏 loss。PPL 降低仍不等于
护理答案正确。
--eval-data 是独立于蒸馏语料的能力集。提供后,SaddleLLM 会在蒸馏完成后用完全相同的
设置顺序评估教师和学生,并把 baseline.json、candidate.json、comparison.json 和
report.md 写入 输出目录/evaluation/。--eval-task auto 会识别常见
question/answer 选择题或 instruction/output completion 数据;也可以显式指定
multiple-choice 或 completion。选择题报告准确率增减、能力保留率和配对 McNemar p;
completion 报告参考答案 PPL 的前后变化和确定性生成样例。
低显存数据蒸馏可以把教师放在另一个 SaddleLLM 服务中;--concurrency 并发请求教师:
# 1. 生成候选答案;不会自动训练
saddlellm distill --mode data `
--student Qwen/Qwen3-0.6B `
--teacher qwen3-4b-teacher `
--teacher-url http://127.0.0.1:8002 `
--data data\nursing_prompts.jsonl `
--domain nursing --concurrency 4 `
--output-dir outputs\nursing-distill-data
# 2. 护理教师纠正 JSONL 后,才训练学生
saddlellm distill --mode data `
--student Qwen/Qwen3-0.6B `
--teacher-data data\nursing_teacher_reviewed.jsonl `
--eval-data data\nursing_validation.jsonl `
--method lora --epochs 1 `
--output-dir outputs\nursing-distilled-sft
--teacher-url 接受服务根地址、/v1 地址或完整
/v1/chat/completions 地址。密钥只通过 --api-key-env ENV_NAME 传入。在线结果的
metadata.review_status 为 pending;在医疗场景,较大的模型也可能给出危险错误,因此
SaddleLLM 不把回答长度启发式当作临床正确性,也不在同一命令中直接启动 SFT。
此时即使传入 --eval-data 也只会记录为“等待审核后训练”;没有训练后的学生就不存在可比
评估。审核数据进入第二条命令后,才会自动比较原始 student 与蒸馏后的 adapter/完整模型。
创建持久化 CPU INT8 模型:
saddlellm quantize outputs\nursing-release outputs\nursing-int8 --local-files-only
saddlellm serve outputs\nursing-int8 --device cpu --open
saddlellm lightweight ... 与 quantize 完全相同。当前不把 GPTQ/AWQ、静态 QAT 或
“一键剪枝+量化”伪装成稳定命令;这些格式只有在完成可重载、可生成和真实基准验证后才会
进入 CLI。每次量化、剪枝或蒸馏后,仍应单独运行 evaluate 和 compare。
复杂、多阶段或需要续训的任务继续使用 YAML/JSON 配置:
一个可直接运行的 SFT 配置:
project: saddlellm
experiment: my-sft
stages: [sft]
model:
name_or_path: Qwen/Qwen2.5-0.5B-Instruct
tokenizer: Qwen/Qwen2.5-0.5B-Instruct
backend: hf
sft:
enabled: true
data_path: data/sft.jsonl
use_lora: true
use_qlora: false
epochs: 1
learning_rate: 0.0002
per_device_batch_size: 1
gradient_accumulation_steps: 4
max_seq_length: 1024
warmup_steps: 0
save_steps: 50
training:
max_steps: 100
distributed:
strategy: single
num_gpus: 1
bf16: false
fp16: false
logging:
output_dir: outputs/my-sft
backend: local
顶层字段的职责:
| 字段 | 作用 |
|---|---|
project |
项目名,用于记录 |
experiment |
本次实验名 |
stages |
要执行的阶段;必须是非空、无重复的字符串列表 |
model |
模型路径、tokenizer 和后端 |
data |
预训练使用的数据源和清洗参数 |
training |
全局步数、预训练超参数、checkpoint、恢复和 dry-run 设置 |
distributed |
单机或分布式策略、GPU 数和精度 |
logging |
总输出目录和日志后端 |
pipeline |
可选的依赖关系和阶段级恢复设置 |
| 与阶段同名的块 | 该阶段自己的数据、方法和超参数 |
推荐显式写出阶段开关:
stages: [sft, preference, eval]
sft:
enabled: true
preference:
enabled: true
method: dpo
eval:
enabled: true
stages 决定系统是否调度该阶段;对带 enabled 开关的阶段,该开关决定收到调度后是否工作。最不容易出错的写法是:把 sft、preference、eval 等列入 stages 时,其配置块同时写 enabled: true。
文本后训练方法:
| 方式 | 配置 |
|---|---|
| 全参数训练 | use_lora: false,use_qlora: false |
| LoRA | use_lora: true,use_qlora: false |
| QLoRA | use_lora: true,use_qlora: true |
training.max_steps 的含义:
- 大于 0:最多运行指定步数。
- 等于
-1:由阶段自己的epochs决定训练长度。 - 等于 0 或小于
-1:配置无效。
对于 train 使用的训练配置,相对路径按运行命令时的当前目录解释。为了避免路径错误,建议在仓库根目录运行仓库内的示例,或在 quickstart 目录内运行生成的配置。
2.4 推荐的使用顺序
第一步:检查环境
saddle-llm doctor
检查 Python、PyTorch、Transformers、Datasets、Accelerate、PEFT、TRL、CUDA、GPU、内存和磁盘。
主要返回:
{
"ready": true,
"python_version": "...",
"cuda_available": true,
"gpu_count": 1,
"gpu_memory_gb": 20.0,
"packages": {},
"issues": [],
"recommendations": []
}
ready: false 时看 issues。没有 GPU 会被标记为问题,但极小的 CPU 测试仍可能运行。
第二步:检查数据
SFT:
saddle-llm inspect-data data/sft.jsonl --task sft
DPO/ORPO:
saddle-llm inspect-data data/preference.jsonl --task dpo
KTO:
saddle-llm inspect-data data/kto.jsonl --task kto
返回 ready、样本数、字段格式、文本长度、重复样本和阻断问题。SFT 数据还会报告
dominant_prompt_prefix_ratio 与 dominant_completion_shape_ratio:当同一种提示前缀或回答形态占比过高时,
命令会警告模板过拟合风险,并建议加入自然问法、改写问法和无包装问法。同一个原始样本的不同问法必须放在
同一数据切分中,避免变体泄漏到 validation/test。重复的 system message 不计作用户提示模板。数据不合格时退出码为 1;
模板集中属于质量警告,不会替用户武断阻断训练。
第三步:检查配置
saddle-llm validate-config config.yaml
返回:
{
"valid": true,
"stages": ["sft"],
"issues": [],
"warnings": [],
"data_inspections": {},
"training_estimates": {},
"normalized_config": {},
"config_path": "config.yaml"
}
它会检查阶段名、必填数据、模型后端、训练步数、精度冲突、分布式能力、动作空间和发布门禁等。只检查结构、不打开本地数据时使用:
saddle-llm validate-config config.yaml --skip-data-inspection
第四步:查看执行顺序
saddle-llm train config.yaml --dry-run
返回 stages、pipeline_plan、distributed 和数据源数量。这个参数不会加载模型或训练,只展示调度顺序;完整数据检查仍应使用 validate-config。
第五步:正式训练
saddle-llm train config.yaml
成功时返回:
{
"ok": true,
"command": "train",
"config": "config.yaml",
"output_dir": "outputs/my-sft",
"next": {
"dashboard": "saddlellm dashboard \"outputs/my-sft\" --open"
},
"results": {
"sft": {
"status": "completed",
"model_path": "outputs/my-sft/sft_checkpoints"
}
}
}
失败时返回 ok: false、异常类型和错误信息,并以退出码 1 结束。需要完整 Python 堆栈时:
saddle-llm train config.yaml --debug
2.5 基础命令
| 命令 | 做什么 | 最小用法 | 主要结果 |
|---|---|---|---|
quickstart |
创建入门训练目录 | saddle-llm quickstart .\demo |
config.yaml、样例数据、下一步命令 |
doctor |
检查环境和依赖 | saddle-llm doctor |
ready、硬件、依赖、问题和建议 |
inspect-data |
检查 SFT/偏好/RL 数据 | saddle-llm inspect-data data.jsonl --task sft |
数据质量报告 |
inspect-vla |
检查 VLA 轨迹、图像和动作维度 | saddle-llm inspect-vla robot.jsonl --image-root images |
VLA 数据报告 |
validate-config |
静态校验训练配置 | saddle-llm validate-config config.yaml |
valid、问题、警告和训练量估算 |
evaluate |
评测基座、完整模型或LoRA | saddlellm evaluate MODEL eval.jsonl |
选择题准确率或completion PPL、真实生成和Markdown报告 |
compare |
配对比较validation/test并执行门禁 | saddlellm compare --base-validation base.json --candidate-validation tuned.json |
提升、McNemar检验、泄漏检查和晋级决策 |
train |
执行配置或直接SFT | saddlellm train sft --model MODEL --data DATA |
checkpoint、指标和输出路径 |
dashboard(webui) |
查看训练进度、曲线、阶段和日志 | saddlellm dashboard outputs/my-run --open |
本地 Web 仪表盘,默认端口 7860 |
plan |
生成启动命令,不训练 | saddle-llm plan config.yaml |
launch_plan.json 和 launch.ps1 |
preflight |
针对一个后训练任务检查数据并生成计划 | saddle-llm preflight data.jsonl --stage sft |
preflight_plan.json、config.json、阻断项和估算 |
plugins |
列出内置和已安装的阶段 | saddle-llm plugins |
阶段名称、来源和加载状态 |
smoke-test |
用本地 tiny 模型检查训练主链 | saddle-llm smoke-test --in-process |
SFT、VLA、DPO、ORPO、KTO 等测试结果 |
import-data |
导入数据 manifest | saddle-llm import-data dataset_info.json |
保存位置、数据摘要和导入数量 |
plan 根据 distributed.strategy 生成启动文件。它不执行训练:
saddle-llm plan configs/sft_lora.yaml
.\configs\launch.ps1
preflight 一次只检查一个后训练任务,所以参数使用单数 --stage。真正的训练配置仍使用复数 stages:
saddle-llm preflight data/posttrain_sft_example.jsonl --stage sft --root-dir .\llm_factory
2.6 媒体和生成命令
这些命令用于单独执行某个工具;它们的参数文件只是该命令的输入,不是 train 使用的训练配置。
| 命令 | 做什么 | 最小用法 | 主要结果 |
|---|---|---|---|
media-codecs |
查看已注册的图像、音频或视频编码器 | saddle-llm media-codecs --modality image |
Codec 名称、模态和能力 |
build-media-cache |
把原始媒体清单编码成可恢复分片 | saddle-llm build-media-cache configs/media_cache_image.yaml |
cache manifest、分片路径和样本统计 |
同样的媒体处理也可以放入主训练配置:
stages: [media_cache, image_generation]
完整示例见 raw_image_to_training.yaml。
2.7 世界模型和眼动控制命令
| 命令 | 做什么 | 最小用法 | 主要结果 |
|---|---|---|---|
world-model-backends |
查看 RSSM 后端 | saddle-llm world-model-backends |
可用后端及能力 |
train-world-model |
单独训练世界模型 | saddle-llm train-world-model configs/world_model.yaml --dry-run |
推断出的维度、训练计划;去掉 --dry-run 后返回 checkpoint 信息 |
infer-world-model |
从 checkpoint 做 rollout 或动作规划 | saddle-llm infer-world-model CHECKPOINT request.json |
预测轨迹、奖励或候选动作 |
build-eye-control-data |
生成安全过滤后的双轴眼动轨迹 | saddle-llm build-eye-control-data --episodes 128 |
JSONL 数据路径和生成统计 |
simulate-eye-control |
在软件仿真器评估 PID 或 RSSM+CEM | saddle-llm simulate-eye-control --config configs/prosthetic_eye_runtime.yaml |
跟踪误差、安全事件和控制统计 |
世界模型也能作为主训练阶段运行:
saddle-llm train configs/world_model_stage.yaml
世界模型训练后立即做眼动控制评估:
saddle-llm train configs/prosthetic_eye_control.yaml
2.8 空间智能和 WorldAgent 命令
| 命令 | 做什么 | 最小用法 | 主要结果 |
|---|---|---|---|
build-spatial-world-data |
从俯视图生成空间世界模型轨迹 | saddle-llm build-spatial-world-data map.png --output data/spatial.jsonl |
轨迹数据和生成统计 |
evaluate-spatial-world-model |
评估多步占用、运动和碰撞预测 | saddle-llm evaluate-spatial-world-model CHECKPOINT data.jsonl |
分项评测指标 |
plan-spatial-route |
从地图提取占用网格并规划 Top-K 路线 | saddle-llm plan-spatial-route map.png --start 10,20 --goal 300,200 |
路线 JSON、HTML 和 PNG |
spatial-studio |
启动可视化空间工作台 | saddle-llm spatial-studio |
前台 HTTP 服务,默认端口 7865 |
world-agent-run |
一次执行分析、规划和仿真 | saddle-llm world-agent-run map.png --start 10,20 --goal 300,200 |
状态、候选路线、仿真和产物路径 |
world-agent-api |
启动无界面的 WorldAgent API | saddle-llm world-agent-api |
前台 HTTP 服务,默认端口 7866 |
dashboard、webui、spatial-studio、world-agent-api 和 serve 是持续运行的服务命令,不会像普通命令一样立即返回。按 Ctrl+C 正常停止。
2.9 评测、发布和服务命令
以下示例统一使用 saddlellm。安装包仍保留 saddle-llm 这个可执行文件名;旧子命令 evaluate-model、compare-evaluations、export-model、serve-model 也继续作为兼容别名。推荐新脚本使用短命令 evaluate、compare、export、serve。
| 命令 | 做什么 | 最小用法 | 主要结果 |
|---|---|---|---|
report |
汇总一个训练输出目录 | saddlellm report outputs/my-run |
预训练/运行报告 |
evaluate |
对本地JSONL/JSON评测模型、adapter或服务 | saddlellm evaluate MODEL eval.jsonl --local-files-only |
选择题准确率、completion PPL或声明式rubric、逐题JSON和Markdown报告 |
compare |
成对比较基座/候选的validation和封存test | saddlellm compare --base-validation base.json --candidate-validation tuned.json |
McNemar显著性、提升、checkpoint选择和发布决策 |
export |
把 checkpoint 或 adapter 打包成可验证发布目录 | saddlellm export CHECKPOINT outputs/release |
模型文件、manifest、可选权重哈希和门禁信息 |
dashboard(webui) |
查看训练目录 | saddlellm dashboard outputs/my-run --open |
进度、指标、loss 曲线、阶段、产物和日志 |
serve |
启动 OpenAI 兼容 API 和内置对话页 | saddlellm serve outputs/release --open |
/、/v1/models、流式 /v1/chat/completions、/v1/completions |
多选题评测文件默认使用 instruction、question、answer、id 字段;可用 --prompt-field、--question-field、--answer-field、--id-field 修改。answer 必须是 --choices 中的一个标签。评测基座:
saddlellm evaluate Qwen/Qwen3-0.6B data/validation.jsonl `
--local-files-only --group-field medical_discipline `
--batch-size 32 --max-length 384 `
--output outputs/base_validation.json `
--markdown-output outputs/base_validation.md
若要发现模型是否只记住一种提问模板,可以用领域项目维护的普通 JSON 模板文件,一次展开 同一批题目的多种问法:
{
"variants": [
{"name": "standard", "template": "{instruction}"},
{"name": "natural", "template": "请回答下题,只给选项字母。\n{question}\n{options}"},
{"name": "bare", "template": "{question}\n{options}"}
]
}
saddlellm evaluate Qwen/Qwen3-0.6B data/validation.jsonl `
--prompt-variants configs/prompt_variants.json `
--local-files-only --batch-size 32 `
--output outputs/base_robustness.json `
--markdown-output outputs/base_robustness.md
模板中的占位符来自每条原始记录;缺字段、重复题号或同题答案不一致会直接报错。报告包含
每种问法准确率、最差问法准确率、预测翻转率,以及“所有问法都答对”的病例比例。也可以先
在数据中自行展开变体,再用 --case-field 和 --variant-field 指定同题编号与变体名。
这些机制完全与领域无关;护理、法律等具体模板应放在各自项目中,不写进 SaddleLLM 核心。
评测LoRA并运行全部真实生成:
saddlellm evaluate Qwen/Qwen3-0.6B data/test.jsonl `
--adapter outputs/run/sft_checkpoints/checkpoint-100 `
--local-files-only --generation-all `
--output outputs/candidate_test.json `
--markdown-output outputs/candidate_test.md
completion-only PPL只计算参考回答token,不把问题token混入loss;数据默认使用 instruction 和 output 字段:
saddlellm evaluate Qwen/Qwen3-0.6B data/sft_validation.jsonl `
--task completion --local-files-only `
--generation-samples 3 --max-length 512 `
--output outputs/completion_eval.json `
--markdown-output outputs/completion_eval.md
PPL只能在相同模型tokenizer、chat template、数据和截断规则下比较;PPL更低不等于事实更正确。自由回答仍要结合生成回归和领域专家审核。指定 --generation-samples 或 --generation-indices 后,Markdown会同时展开问题、确定性生成和可折叠参考答案,便于直接审查实际回答。
开放回答可使用领域项目维护的声明式 rubric。核心只提供
contains_any、contains_all、not_contains_any、regex、not_regex 五种通用检查;
护理规则和阈值不能写进 SaddleLLM 核心:
{"id":"case-1","instruction":"...","rubric":{"pass_threshold":0.8,"checks":[{"id":"escalate","type":"contains_any","patterns":["通知医生","启动急救"],"weight":2,"critical":true,"dimension":"escalation"}]}}
直接加载本地模型评估:
saddlellm evaluate MODEL rubric.jsonl --task rubric --local-files-only `
--output outputs/rubric.json --markdown-output outputs/rubric.md
也可复用已经由 saddlellm serve 启动的 OpenAI 兼容服务,不重复占显存:
saddlellm evaluate served-model rubric.jsonl --task rubric `
--endpoint http://127.0.0.1:8000 --max-new-tokens 128 `
--output outputs/rubric.json --markdown-output outputs/rubric.md
rubric 会生成每条回答并报告通过率、加权分、分维度结果和关键失败数;空回答永不通过。
这些确定性规则只是可审计的工程筛查,不是专家评分、事实正确性或临床安全证明。比较 rubric
时可用 compare --max-critical-failures 0 阻止平均分上升但关键项仍失败的候选模型。
正式发布时同时比较 validation 和封存 test。若提供数据 manifest,指定的重叠统计必须全部为0:
saddlellm compare `
--base-validation outputs/base_validation.json `
--candidate-validation outputs/candidate_validation.json `
--base-test outputs/base_test.json `
--candidate-test outputs/candidate_test.json `
--manifest data/dataset_manifest.json `
--overlap-key exact_question_overlap_after_exclusion `
--min-gain-pp 5 --max-p 0.05 `
--output outputs/release_gate.json `
--markdown-output outputs/release_gate.md
evaluate 会同时保留每题预测与归一化标签概率;加 --generation-all 后还保存贪心生成文本和解析结果。标签概率与开放生成可能不同,因此二者不能互相替代。compare 使用同题配对变化和精确McNemar检验,不把训练loss或PPL当作实际正确率。
只传 validation 时,compare 可用于选择 checkpoint:达到阈值会写
decision=validation_passed、selection_eligible=true,但始终保持
accepted=false。只有同时提供成对的封存 test,且 validation/test 都通过阈值时,才会写
decision=promoted、accepted=true。因此 validation-only 报告不能绕过
export --require-gate;test 一旦解封也不得继续参与调参。
checkpoint、release 与部署
- 推荐让
train配置只包含训练阶段(例如stages: [sft])。评估、比较、导出和部署随后通过独立命令串联,不需要把它们塞进一次训练调用。 checkpoint是训练过程存档,适合继续训练和快速调试。release是通过export整理出的交付目录,适合复制到服务器、比赛提交和长期保存。export会整理模型权重、配置和 tokenizer。LoRA adapter 默认与基座模型合并,并生成release_manifest.json;它不会执行模型评估。serve只加载指定模型并启动服务,不执行评估,也不要求评估通过。
训练完成后可以直接启动 checkpoint,不必先导出:
saddlellm serve E:\DEV\medModel\outputs\my-run\sft_checkpoints\checkpoint-100 `
--local-files-only --device cuda --open
显存优先时可做运行时量化(不会另存量化权重):
saddlellm serve E:\DEV\medModel\outputs\my-run\sft_checkpoints\checkpoint-100 `
--local-files-only --device cuda --dtype bfloat16 --quantization 8bit --open
--quantization 可选 none、8bit、4bit。量化依赖 bitsandbytes,请安装 .[serve,qlora];量化可能改变任务答案,上线前必须重新评估该精度下的模型效果。
确认版本准备交付时,再导出成独立 release 目录:
saddlellm export `
E:\DEV\medModel\outputs\my-run\sft_checkpoints\checkpoint-100 `
E:\DEV\medModel\outputs\my-release `
--local-files-only
然后部署 release 模型:
saddlellm serve E:\DEV\medModel\outputs\my-release `
--local-files-only --device cuda `
--host 127.0.0.1 --port 8000 --open
如果团队需要在 CI 或正式发布流水线中自动阻止未达标版本,可以选择在导出阶段检查已有评估报告。普通调试、导出和部署不需要这个参数:
saddlellm export CHECKPOINT outputs/release `
--gate-result outputs/run/release_gate.json --require-gate
推荐的完整命令链如下;每一步都可以独立重跑,前一步的文件路径作为后一步输入:
saddlellm train config.yaml
└─ checkpoint
└─ saddlellm evaluate ...
└─ evaluation.json
└─ saddlellm compare ...
└─ comparison.json
└─ saddlellm export checkpoint release
└─ saddlellm serve release --open
浏览器对话和 OpenAI 兼容 API 共用同一个模型实例,不会重复占用显存。聊天接口支持 SSE 流式输出;默认关闭模型的显式思考输出,并把默认生成长度限制为 256 token。只有确实需要时才加 --enable-thinking。模型评估由 evaluate/compare 单独完成,部署命令只加载指定模型;若目录包含 release manifest,健康接口会显示其中的门禁信息但不重新评估。这个内置服务用于单机验证和低并发应用;100 并发要接入支持连续批处理的生产推理后端并实测容量。
如果需要 Bearer Token,不要把密钥直接写进命令:
$env:SADDLE_API_KEY = "your-secret"
saddlellm serve outputs/release --api-key-env SADDLE_API_KEY
训练可视化、推理页面、API 示例和生产边界见 WebUI 与快速部署。
2.10 Python 调用
直接运行配置:
from saddlellm.training.TrainingOrchestrator import TrainingOrchestrator
runner = TrainingOrchestrator.from_yaml("config.yaml")
results = runner.run()
print(results)
从字典运行:
from saddlellm.training.TrainingOrchestrator import TrainingOrchestrator
config = {
"stages": ["sft"],
"model": {
"backend": "hf",
"name_or_path": "Qwen/Qwen2.5-0.5B-Instruct",
},
"sft": {
"enabled": True,
"data_path": "data/sft.jsonl",
"use_lora": True,
"use_qlora": False,
},
"training": {"max_steps": 10},
"distributed": {"strategy": "single", "bf16": False},
"logging": {"output_dir": "outputs/python-run"},
}
results = TrainingOrchestrator.from_dict(config).run()
只做静态校验:
import yaml
from saddlellm.training.TrainingConfigValidator import TrainingConfigValidator
with open("config.yaml", encoding="utf-8") as handle:
config = yaml.safe_load(handle)
report = TrainingConfigValidator.validate(config)
print(report.to_dict())
2.11 返回状态和输出目录
阶段结果中的常见 status:
| 状态 | 含义 |
|---|---|
completed、trained |
已实际执行成功 |
planned |
只生成计划,没有训练 |
planned_no_data |
缺少数据,只保存计划 |
planned_unsupported |
已识别,但真实执行尚未接入 |
skipped |
阶段被关闭 |
rejected |
评测门禁未通过 |
blocked |
因上游条件不满足而阻止执行 |
failed |
执行失败 |
典型输出目录:
outputs/my-run/
├─ plans/
│ ├─ sft_plan.json
│ ├─ preference_plan.json
│ └─ export_plan.json
├─ sft_checkpoints/
├─ preference_checkpoints/
├─ final_model/
├─ release/
├─ pipeline_state.json
├─ release_gate.json
├─ summary.json
└─ training_summary.json
不同 stages 只生成与自己有关的目录。summary.json 和 training_summary.json 记录执行顺序、耗时、各阶段结果和产物。
3. 原理、代码逻辑和训练过程
3.1 一条命令进入系统后发生什么
执行:
saddle-llm train config.yaml
内部顺序:
cli.py
1. 读取 YAML/JSON
2. 检查顶层 stages 是非空、无重复的字符串列表
↓
TrainingOrchestrator._parse_config()
3. 把 model、training、distributed 和各阶段参数解析成配置对象
↓
StageRegistry
4. 确认每个阶段有对应实现,并读取它的能力限制
↓
PipelinePlan
5. 确定执行顺序和依赖关系
↓
TrainingOrchestrator._validate_config()
6. 在模型加载前检查数据、后端、精度、分布式和阶段组合
↓
TrainingOrchestrator.run()
7. 逐个执行阶段,保存状态和产物
↓
summary.json + 命令行 JSON
CLI 只负责读取参数和展示结果。真正的训练入口位于 TrainingOrchestrator,具体数学计算由各 Trainer 完成。
3.2 阶段如何排序
默认按 stages 的书写顺序执行:
stages: [sft, preference, eval, export]
顺序就是:
sft → preference → eval → export
存在独立分支时可以显式声明依赖:
stages: [sft, world_model, preference, eval, export]
pipeline:
dependencies:
sft: []
world_model: []
preference: [sft]
eval: [preference, world_model]
export: [eval]
此时 sft 与 world_model 没有相互依赖;eval 必须等待两条分支完成。系统会检查不存在的依赖、重复阶段和依赖环。
简单任务不需要写 pipeline.dependencies。
3.3 阶段之间怎样交接
文本模型主链:
model.name_or_path
│
├───────────────┐
▼ │
pretrain │
│ model_path │
▼ │
sft ◄────────────┘
│ model_path
▼
preference / rlhf
│ model_path
▼
eval
│ metrics + release_gate
▼
export
后一个阶段优先使用前一个阶段返回的 model_path。没有上游模型时,才使用 model.name_or_path。
数据产物也可以交接:
mopd 产生 on-policy JSONL → sft.data_path 为空时由 SFT 使用
media_cache 产生编码分片 → image/music/video generation 使用
world_model 产生 checkpoint → eye_control 使用
每个阶段返回一个普通字典。系统把结果保存在阶段结果表中,同时登记可追踪产物。
3.4 预训练逻辑
pretrain 有三种启动方式:
| 方式 | 关键配置 | 含义 |
|---|---|---|
| 从零训练 | pretrain_mode: scratch |
从内置模型规格或 model.blueprint 创建新模型 |
| 继续预训练 | pretrain_mode: continue + model.name_or_path |
载入已有权重,以新的优化任务继续训练 |
| 精确恢复 | training.resume_from_checkpoint |
在支持的 Trainer 中恢复优化器、调度器和训练步数 |
实际过程:
- 解析模型规格或 blueprint。
- 创建新模型,或加载已有模型/checkpoint。
- 加载已有 tokenizer,或使用上游
tokenizer阶段的结果。 - 从
data.sources收集数据。 - 清洗、去重和质量过滤后先划分训练/验证集,避免同一数据同时参与训练和验证。
- tokenize 时保留长文档全部 token,在每个文档末尾补 EOS,再做 sequence packing。
- 使用只屏蔽真实 padding、不会误屏蔽 EOS 的 causal-LM collator。
- 创建 Hugging Face
Trainer或原生SaddleTrainer,执行 causal language modeling。 - 开训前检查tokenizer词表、模型embedding、EOS/PAD契约,以及过滤/packing后训练集和验证集是否为空。
- 按验证 loss 选择最佳 checkpoint,并记录验证 PPL、实际全局 batch、token 吞吐、各清洗阶段样本数和最终序列数。
- 保存
final_model、tokenizer 和 Trainer state。
最小结构:
stages: [pretrain]
pretrain_mode: scratch
model:
backend: saddle
config: qwen-tiny-160m
tokenizer: Qwen/Qwen2.5-0.5B
data:
sources:
- type: local
path: data/pretrain.jsonl
text_column: text
streaming: false
append_eos: true
validation_split: 0.01
training:
max_steps: 1000
per_device_batch_size: 2
global_batch_size: 32
learning_rate: 0.0003
min_lr: 0.00003
eval_every_steps: 100
save_every_steps: 500
load_best_model_at_end: true
distributed:
strategy: single
logging:
output_dir: outputs/pretrain
没有显式设置 distributed.gradient_accumulation_steps 时,系统按
global_batch_size / (per_device_batch_size × num_gpus × num_nodes) 自动推导;不能整除或显式值
与全局 batch 不一致时会在模型加载前报错。默认 cosine 会实际使用 min_lr,映射到带最小学习率
的 cosine scheduler。validation_split: 0 可以关闭内部验证,但将无法得到验证 PPL和最佳 checkpoint。
完整原生模型结构示例见 modular_llm.yaml。
3.4.1 用简单配置表达网络结构
网络结构采用“预设继承 + 可选覆盖”,不要求每次重复几十个字段:
pretrain_mode: scratch
model:
backend: saddle
config: qwen-300m # 预设提供层数、宽度、词表等完整默认值
tokenizer: Qwen/Qwen2.5-0.5B
blueprint:
name: nursing-dense-300m
max_position_embeddings: 8192
attention:
kind: gqa
backend: sdpa
num_heads: 16
num_kv_heads: 4
rope_theta: 1000000
ffn:
kind: swiglu
intermediate_size: 2816
residual:
topology: serial
initialization: depth_scaled
配置分三档:
| 场景 | 写法 | 结构来源 |
|---|---|---|
| 继续预训练 | pretrain_mode: continue + model.name_or_path |
完全继承 checkpoint,不允许伪造新层数 |
| 常规从零预训练 | pretrain_mode: scratch + model.config |
使用已登记且测试过的完整结构预设 |
| 架构研究 | 预设再加 model.blueprint,或提供自包含 blueprint |
覆盖注意力、FFN、上下文、残差、目标和分层结构 |
blueprint.layers还能用repeat表达不同层段,例如前16层dense、后4层MoE;没有该字段时所有层采用同一默认结构。预检会验证隐藏维度能否整除头数、GQA头数关系、MoE专家数量、RoPE和上下文参数等。训练保存时同时写出model_blueprint.json与saddle_config.json,因此 checkpoint 自带真实网络结构。
开训前查看展开后的参数量、激活参数量、KV cache估算、结构轴和风险:
saddlellm validate-config configs/nursing_pretrain_scratch.yaml --skip-data-inspection
输出中的architecture_analysis就是最终生效的结构,不是仅供展示的注释。完整可运行模板见nursing_pretrain_scratch.yaml。实际护理参评项目若没有数十亿级以上高质量token和相应算力,应优先对成熟Base模型做继续预训练;从零预训练的小模型主要用于验证自主架构和训练能力。
3.5 SFT 逻辑
sft 用“输入指令 → 目标回答”训练模型遵循任务要求。
支持的数据形式包括:
{"instruction":"概括下面内容","input":"待处理文本","output":"目标回答"}
以及 messages:
{"messages":[{"role":"user","content":"问题"},{"role":"assistant","content":"目标回答"}]}
多轮 messages 中的每一个非空 assistant 回答都会形成一个 completion-only 训练样本;
该回答之前的完整对话作为上下文但不计算监督损失。因此一条 JSONL 对话可能对应多个
train_samples,不会再只训练最后一个回答。若回答在 max_seq_length 截断后完全消失,
该轮会被丢弃,不会错误地拿 prompt token 充当答案监督。
执行过程:
- 从上游
pretrain或model.name_or_path找到模型。 - 检查数据字段、空文本、重复样本和长度。
- 生成
plans/sft_plan.json。 - 根据
use_lora/use_qlora选择全参数、LoRA 或 QLoRA。 - 优先读取独立
validation_data_path;未提供时才按validation_split划分。 - HF 后端调用
PeftSFTTrainer;Saddle 后端调用原生 SFT。 - 有验证集时按最低
eval_loss恢复最佳 checkpoint,再保存根sft_checkpoints并返回新的model_path。
示例见 sft_lora.yaml。
3.6 偏好训练逻辑
preference 用于让模型在多个回答之间学习偏好。
| 方法 | 数据 | 作用 |
|---|---|---|
| DPO | prompt/chosen/rejected |
直接提高 chosen 相对 rejected 的概率 |
| ORPO | prompt/chosen/rejected |
将监督目标和偏好比率目标结合 |
| KTO | prompt/completion/label |
用可取/不可取标签学习偏好;实际 batch 必须大于 1 |
**KTO 是什么:**KTO 全称 Kahneman-Tversky Optimization,是一种偏好优化方法。
它不要求像 DPO 那样为同一个问题同时准备 chosen 和 rejected 成对回答;每条样本只需提供
一个回答,并用 label: true/false 标明“可取/不可取”。因此,当护理教师只能逐条审核回答、
而难以为每题编写严格配对答案时,KTO 更容易整理数据。KTO 的主要作用是调整回答偏好、
规范性和安全性,不负责向模型灌入大量新知识;新知识应先通过继续预训练或 SFT 学习。
--stage sft,kto 的逗号表示 SaddleLLM 严格按 SFT → KTO 执行,并把 SFT 输出交给 KTO;
这只是执行顺序,不代表 KTO 永远必须接在 SFT 后。若基座模型已经具备所需知识和指令能力,
也可以单独运行 --stage kto。
DPO/ORPO 数据:
{"prompt":"怎样排错?","chosen":"先看日志并构造最小复现。","rejected":"直接忽略错误。"}
KTO 数据:
{"prompt":"怎样排错?","completion":"先看日志。","label":true}
执行过程:
- 取得执行顺序中最近完成的前置语言模型;例如
sft → ppo → kto中 KTO 必须消费 PPO 输出。 - 按选定方法检查数据。
- 写入
plans/preference_plan.json。 - 调用对应 DPO、ORPO 或 KTO Trainer。
- 保存
preference_checkpoints,供评测或导出使用。
示例见 posttrain.yaml 和 dpo_qlora.yaml。
rlhf 阶段当前可实际执行的稳定路径也是 DPO。PPO 需要 reward model、value model、在线 rollout 和经过安全验证的奖励契约,目前实际训练会在所有阶段开始前明确失败;需要稳定离线偏好训练时直接使用 DPO、ORPO 或 KTO。
3.7 MOPD 蒸馏逻辑
mopd 的目标是先让当前学生模型生成回答,再让一个或多个教师评价或重写,最后形成新的 SFT 数据。
prompts
→ 学生生成候选
→ 教师评分/聚合
→ mopd_on_policy.jsonl
→ 可选后续 sft
mopd.dry_run: true 只写计划。设置为 false 且提供 prompts、教师和可用模型时才收集数据。
远程教师可设置 teacher_concurrency 并发数。requires_review: true 时,每条记录会标为
review_status: pending,且后续 SFT 不能直接消费该 MOPD 产物;必须由领域专家修订后通过
sft.data_path 显式传回。直接命令 saddlellm distill --mode data 默认采用这个安全语义。
示例见 mopd_sft.yaml。
3.8 多模态和 VLA 逻辑
vla_sft 处理“图像/指令/机器人动作”轨迹:
- 创建并校验动作空间,包括维度、连续/离散类型、范围、夹爪和控制频率。
- 检查图像路径、动作维度和 episode step 连续性。
- 规范化为训练 JSONL。
- 总是保存动作空间和训练计划。
- 只有
vla.train: true时才调用VLATrainer做行为克隆训练。
示例见 vla_sft.yaml。该示例默认 train: false,因此只做规范化和计划。
mllm_sft 和 vision_alignment 当前只完成图文数据规范化与计划保存,不应把返回的 planned 当作模型已经训练。
3.9 图像、音乐和视频生成逻辑
生成训练分为两步:
原始媒体 + 文本
↓
media_cache:Codec 编码媒体,文本编码器生成 condition
↓
NPZ/分片缓存
↓
image_generation / music_generation / video_generation
↓
模型 checkpoint
- 图像:读取
latents[N,C,H,W]和conditions[N,D]。 - 音乐:读取
codes[N,Q,T]、conditions[N,D]和可选 mask。 - 视频:读取
video_latents[N,C,T,H,W]和conditions[N,D]。
训练前会从缓存推断模型维度,并拒绝与手工配置不一致的通道数、码本数或条件维度。
示例:
3.10 世界模型和控制逻辑
world_model 从离线轨迹学习:
当前观测 + 动作
↓
隐状态更新
↓
下一观测、奖励和 continuation 预测
数据通常包含 observation、action、reward 和 done。rssm 使用连续随机状态;categorical_rssm 使用离散类别状态。训练结果可用于 rollout、候选动作评分和空间控制。
eye_control 不直接驱动硬件。它在软件 plant 中应用角度、速度、加速度、电流和温度限制,然后比较 PID 或 RSSM+CEM 控制效果。真实硬件仍需要单独实现安全驱动适配器。
示例:
3.11 评测和导出逻辑
eval 的模型选择顺序:
rlhf 输出
→ preference 输出
→ sft 输出
→ pretrain 输出
→ model.name_or_path
评测成功后可生成 release_gate.json。例如要求 perplexity 不超过阈值:
eval:
enabled: true
tasks: [perplexity]
gate:
enabled: true
rules:
perplexity:
max: 30.0
fail_on_rejection: true
export 使用最新上游模型。如果配置 require_gate: true,没有已接受的门禁结果就拒绝导出。
完整闭环示例见 posttrain_release.yaml。
3.12 Batch、步数和显存逻辑
有效 batch:
effective_batch
= per_device_batch_size
× gradient_accumulation_steps
× num_gpus
显存主要受模型参数量、序列长度、每卡 batch、优化器状态、是否全参数训练和精度影响。常用选择:
- 显存充足:全参数或 LoRA。
- 显存较小且有兼容 CUDA/bitsandbytes:QLoRA。
- OOM:先降低
per_device_batch_size和序列长度,再提高梯度累积保持有效 batch。 - CPU:只适合 tiny 模型、数据检查和调度测试。
bf16 与 fp16 不能同时启用。
3.13 恢复、失败和状态逻辑
阶段级恢复:
pipeline:
resume: true
rerun: []
state_path: pipeline_state.json
系统只会恢复配置指纹和依赖图一致、且上次已完成的阶段。pipeline.rerun 指定某个阶段重跑时,它的下游阶段也会失效并重新执行。
Trainer checkpoint 恢复使用:
training:
resume_from_checkpoint: outputs/run/checkpoint-1000
这与阶段级恢复不同:前者恢复单个 Trainer 内部状态,后者决定整个阶段是否跳过。
直接单阶段命令也可使用 --resume-from-checkpoint [PATH];省略 PATH 时从该阶段输出目录
选择最大的 checkpoint-*。精确恢复允许增大 max_steps,但必须保持有效训练 batch 不变,
否则数据游标已经不再等价,系统会在训练前拒绝。
任何阶段抛出异常时:
- 记录
failed_stage和错误。 - 更新
pipeline_state.json。 - 尽可能写出
summary.json。 - 停止后续阶段。
- CLI 返回非零退出码,不把失败包装成成功。
3.14 当前文本模型训练验收范围
2026-09-13 在 Windows、单张 RTX 4090 Laptop GPU、项目锁定的 Transformers/TRL/PEFT 环境中,以下路径均由真实 Trainer 执行,不是只做参数解析:
| 路径 | 证据目录 | 关键结果 |
|---|---|---|
| Saddle 原生蓝图从零预训练 + 精确续训 | E:/DEV/medModel/artifacts/training_acceptance_scratch_native_v1 |
自定义2层GQA、75,520参数,checkpoint-1恢复到step 2,验证PPL 7.9969 |
| HF模型继续预训练 + 精确续训 | E:/DEV/medModel/artifacts/training_acceptance_pretrain_resume_v1 |
checkpoint-2恢复到step 3,验证PPL 12.7266 |
| 全参数SFT + 精确续训 | E:/DEV/medModel/artifacts/training_acceptance_full_sft_v1 |
恢复到step 3,最终eval loss 3.1267 |
| QLoRA SFT | E:/DEV/medModel/artifacts/training_acceptance_qlora_eval_v2 |
4bit加载、BF16计算、训练/最终验证/保存均完成 |
| LoRA SFT→KTO串联 | E:/DEV/medModel/artifacts/training_acceptance_sft_kto_chain_v1 |
两阶段各1 step,continued_adapter=true |
| DPO + 验证 + 精确续训 | E:/DEV/medModel/artifacts/training_acceptance_dpo_eval_v1 |
恢复到step 3,DPO验证指标已写入summary |
| ORPO / KTO | E:/DEV/medModel/artifacts/training_acceptance_orpo_eval_v2、training_acceptance_kto_eval_v2 |
真实训练、最终验证和adapter保存完成 |
多轮SFT + 独立验证 + all-linear |
E:/DEV/medModel/artifacts/training_acceptance_quality_core_v1 |
HF QLoRA/DPO/ORPO/KTO与Saddle原生SFT/DPO均真实完成;2条源记录展开为3个回答样本;各路径选择最佳checkpoint |
| 安装版核心SFT复验 | E:/DEV/medModel/artifacts/training_acceptance_installed_quality_core_v1 |
从源码目录外调用saddlellm.exe;3个训练样本、2个独立验证样本、all-linear目标和最佳checkpoint均进入summary |
| logits蒸馏 + 独立评估 | E:/DEV/medModel/artifacts/direct_distill_with_eval_smoke |
训练成功,但独立completion PPL退化,报告如实标记degraded |
| PPO | E:/DEV/medModel/artifacts/training_acceptance_ppo_boundary_v1 |
仅支持dry-run;真实执行在任何阶段开始前明确失败 |
这些 tiny smoke 证明数据读取、前向/反向、优化器、验证、checkpoint、续训和报告链路可用, 不证明长时训练、多机多卡或模型业务效果。DDP/FSDP/DeepSpeed仍需在目标集群做容量验收;PPO 尚未实现;护理checkpoint的临床安全与比赛效果必须由独立题集和教师审核另行证明。
该验收对应wheel:
E:/DEV/medModel/artifacts/wheel_build_quality_core_v1/saddlellm-2.35-py3-none-any.whl
。交付时用 Get-FileHash -Algorithm SHA256 核对项目SOP中记录的最终哈希。
源码全量回归为391 passed、20条第三方warning、0 failed;安装版saddlellm.exe又完成了一次
真实LoRA SFT、独立验证和最佳checkpoint恢复。
3.15 从哪里继续阅读
开发验证:
python -m compileall -q saddlellm tests
python tools/generate_function_reference.py --check
python -m pytest -q
Metadata
Release files for saddlellm 2.36
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| saddlellm-2.36.tar.gz | 869.1 kB | Without provenance | Details for saddlellm-2.36.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| saddlellm-2.36-py3-none-any.whl | Python 3 | none | any | Details for saddlellm-2.36-py3-none-any.whl |
Total release size: 1.7 MB
Release files / saddlellm-2.36.tar.gz
| Download URL | saddlellm-2.36.tar.gz |
|---|---|
| Size | 869.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a8365741bfeb0529c01048f732302d2ea2f879da2c0007ca51800956dea533c5
|
|
BLAKE2b-256 checksum How to use checksums |
0098f0565e35d36cdca3f69321cdf76731888cf1026b956053ccd251b0f435c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.0rc2
|
Release files / saddlellm-2.36-py3-none-any.whl
| Download URL | saddlellm-2.36-py3-none-any.whl |
|---|---|
| Size | 831.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
47396a4adc8948a75ba502b8fd1ce551b8c66b23fd26dd7698a7821d11e7db7e
|
|
BLAKE2b-256 checksum How to use checksums |
c945d2b40f2fd53d1f5c597a3eb29510daa92c5d84e1ed86f64e874ceb2b9392
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.0rc2
|
Security for saddlellm 2.36
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.