LOCAL MODEL LAB / 学习入口

本地训练与服务起步手册

这是一条研究过当前文档和发布源码的候选执行路线。尚未安装训练环境、下载模型、运行模型训练或启动训后服务。 先完成 第一课,之后随短课逐项实作;不要把命令存在当成实测通过。

场景协议见 任务速查,模型与工具来源见 RESOURCES。shell 命令从工作区根目录执行。正式实验使用新目录,避免覆盖冒烟和历史权重。

1. 不加载模型,先验证规则

cd ~/ai_learning/project_local_llm_training
python3 assets/lab.py self-check
python3 assets/lab.py data --out data/price-v1 --seed 42

会生成 600 条 SFT 训练、120 条 SFT 验证、300 条 RL 训练、80 条 RL 验证,以及 160 条固定测试题;保存原始 case、seed 与 SHA-256。所有分区的完整订单参数互不重复;测试集包含门槛 ±1 和保留的表述方式。合成分布仍相近,不能据此声称真实电商泛化。

SFT 文件是 messages,包含正确 assistant JSON。RL 文件是 system/prompt/answer,answer 只用于评分;优化的输出来自当前模型实际采样。显式的 system 覆盖社区 trainer 默认的思考/XML 提示。

2. 独立训练环境与原始权重

候选版本:Python 3.11+、mlx 0.32.3、mlx-lm 0.32.0、mlx-lm-lora 5.8.6。先检查依赖,再做加载冒烟。使用 Apple Silicon 原生 Python,不借用现有业务环境。

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r assets/requirements-training.txt
python -m pip check
mkdir -p runs models
python -m pip freeze > runs/environment.txt
python -c 'import platform, mlx.core as mx; print(platform.machine()); print(mx.default_device()); print(mx.array([1.0]) + 1)'
mlx_lm.lora --help
mlx_lm_lora.train --help
mlx_lm.convert --hf-path Qwen/Qwen2.5-0.5B-Instruct --mlx-path models/original --dtype bfloat16

转换会联网下载官方权重;模型源 revision 应在下载时记录,转换产物也做 hash。约 0.98 GB 是 BF16 权重估算,磁盘还会包含下载缓存、SFT 与最终权重。没有实测训练峰值内存或耗时承诺。

shasum -a 256 models/original/*.safetensors > runs/original-weights.sha256

3. 先做原始模型的验证集基线

python assets/lab.py evaluate --model models/original --cases data/price-v1/cases/sft_valid.jsonl --out runs/original-valid.jsonl

脚本固定 system、chat template、temperature=0、max_tokens=64,保存每条原始 completion 和 summary。报告格式通过率、格式合格条件下金额准确率、全体样本联合正确率、边界桶、时间与 MLX 峰值分配。MLX 峰值不是系统总占用,还要查看活动监视器内存压力与 swap。

先检查任务难度:如果原始模型已接近满分,不把训练当作必要条件。依然可以做训练教学,但若要研究增益,应在看最终测试集前,版本化增加题目难度。

4. SFT:先小步,再正式运行

assets/sft.yaml 用最后 8 层的 rank 8 LoRA、prompt masking、batch 1 和短序列。学习率是实验起点。官方操作依据:MLX-LM LoRA 指南。

set -o pipefail
mlx_lm.lora --model models/original --train --data data/price-v1/sft --config assets/sft.yaml --iters 5 --save-every 5 --adapter-path runs/sft-smoke 2>&1 | tee runs/sft-smoke.log

检查有限 loss、可训练参数、实际参数变化、保存与重载。模型只能在解码阶段给出评估;训练 loss 不是金额正确率。冒烟通过后,从原始模型重新做正式实验,避免把冒烟状态隐式混入。

mlx_lm.lora --model models/original --train --data data/price-v1/sft --config assets/sft.yaml --iters 300 --adapter-path runs/sft 2>&1 | tee runs/sft.log
mlx_lm.fuse --model models/original --adapter-path runs/sft --save-path models/sft
shasum -a 256 models/sft/*.safetensors > runs/sft-weights.sha256
python assets/lab.py evaluate --model models/sft --cases data/price-v1/cases/sft_valid.jsonl --out runs/sft-valid.jsonl

融合会产生独立 SFT 权重。下一阶段以它为起点,不能重新从原始模型开始而声称“在 SFT 后做 RL”。验证结果决定是否继续或调整,调整使用新实验目录。

5. GRPO:真实采样与奖励更新

本阶段使用社区项目 mlx-lm-lora,不能替换为不存在的 mlx_lm.lora --grpo。

mlx_lm_lora.train --model models/sft --train --data data/price-v1/rl --config assets/grpo.yaml --iters 5 --save-every 5 --adapter-path runs/grpo-smoke 2>&1 | tee runs/grpo-smoke.log

配置用同题 4 个采样、temperature=0.8、64 token 上限、较小学习率、KL 系数 0.04;epsilon: 0.2 是该版本 ratio clipping 参数。fuse: false 显式关闭社区工具默认自动融合,保留 adapter 与原 SFT 分离。自定义 callback 的参数名是 answer(单数)。上述配置都需要小步实测。

除完成命令外,还要带回:SFT 起点 hash、同题真实采样、各奖励、组内方差或优势、梯度和新权重。若默认日志缺少采样/优势明细,在下一课添加 callback 留证;目前的起步配置不保证自动保存全部明细。只有最后训练 loss 或 reward 汇总不够。

若组内奖励全相同,先核查任务难度、采样与评分器。非有限 loss/gradient、明显的内存压力或参考模型偏离都应保留日志后停下诊断。明确检查“RL 真的更新了 adapter”,不要仅看程序退出码。

mlx_lm_lora.train --model models/sft --train --data data/price-v1/rl --config assets/grpo.yaml --iters 100 --adapter-path runs/grpo 2>&1 | tee runs/grpo.log
mlx_lm.fuse --model models/sft --adapter-path runs/grpo --save-path models/grpo
shasum -a 256 models/grpo/*.safetensors > runs/grpo-weights.sha256
python assets/lab.py evaluate --model models/grpo --cases data/price-v1/cases/rl_valid.jsonl --out runs/grpo-valid.jsonl

参考模型默认从同一个 models/sft 路径读取并固定。重载与融合是跨工具边界,必须实际验证。若分组奖励没信号,记录一次无效实验并修正原因,不能宣称 RL 有收益。

6. 冻结方案,比较三个阶段

python assets/lab.py evaluate --model models/original --cases data/price-v1/cases/test.jsonl --out runs/original-test.jsonl
python assets/lab.py evaluate --model models/sft --cases data/price-v1/cases/test.jsonl --out runs/sft-test.jsonl
python assets/lab.py evaluate --model models/grpo --cases data/price-v1/cases/test.jsonl --out runs/grpo-test.jsonl
模型阶段 格式通过率 金额准确率(格式合格) 联合正确率 边界错误 耗时 / 峰值
原始 待测 待测 待测 待测 待测
SFT 待测 待测 待测 待测 待测
SFT → GRPO 待测 待测 待测 待测 待测

至少保留失败样本与一次重复实验。若要讨论 GRPO 独立于额外计算的价值,增加“继续 SFT”的预算对照。看过测试集后再改方案,需生成一个新的未见测试集做最终复验;原集保留作回归。160 条合成题不足以代表真实业务。

7. 服务加载最终权重,真实回读

下列命令在前面产物存在且能重载后执行。服务实现依据:MLX-LM 官方源码。

mlx_lm.server --model models/grpo --host 127.0.0.1 --port 8088

保持此终端运行,在另一个激活了同一环境的终端执行:

curl --fail http://127.0.0.1:8088/health
curl --fail http://127.0.0.1:8088/v1/models
lsof -nP -iTCP:8088 -sTCP:LISTEN
python assets/lab.py api-check --model models/grpo --out runs/service-receipt.jsonl

检查 /v1/models 的实际模型 ID;必要时将 api-check --model 换成该 ID。脚本保存完整请求与回包,独立检查模型输出,既不修复答案也不用 oracle 替模型返回结果。报告中同时保存服务启动路径、最终权重 hash、监听证据和 receipt。它只能证明一次调用,再用固定题做批量服务回归才能检查覆盖。

停止服务:在服务终端按 Ctrl+C,再确认 8088 不再监听。将来若要局域网/公网访问,再另做鉴权、限流与容量验证。

当前验证边界

起步 helper 可以不装任何训练包运行规则与数据检查;evaluate 和 api-check 必须有真实模型/服务才算通过。自定义奖励也需要用所选 trainer 实际调用。课程内演示只计算奖励与简化优势,不执行参数更新,不生成学习完成记录。

学习入口 · 阶段路线