从零训练1B参数LLM:小团队完整技术路线拆解 📅 发布时间:2026/8/27 7:03:33 👁 浏览次数: 最近在 Hacker News 上看到一个很有意思的项目AQ。它的标题信息量很大——一个来自印度的两人团队从零训练了一个 1B 参数的学术 LLM。没有套壳开源模型没有基于 Llama 做 LoRA 微调而是真正从数据、tokenizer、预训练一路做到对齐和评估。这个项目让我想写一篇比较完整的拆解文章。一方面“1B 参数”是个人开发者和小团队最容易摸到的模型规模档位另一方面“from-scratch”这条路虽然辛苦但对理解 LLM 底层机制非常有帮助。在动笔之前先声明一点本文不是对 AQ 项目代码的逐行解析而是围绕“一个 2 人小团队如何从零训练 1B 学术 LLM”这个主题把完整技术路线拆开讲清楚。文章会覆盖数据工程、分词器、模型架构、预训练、指令微调、对齐、评估、量化和部署最后附上常见问题排查和工程建议。即使你没有自己的训练集群也可以把这里的思路用在小型实验、课程项目或者开源模型研究中。1. 项目背景为什么 1B 学术 LLM 值得关注1.1 “from-scratch”与小团队定位过去两年里大模型领域的“造词运动”很盛行很多项目标称“自研大模型”实际只是把开源模型拿来做 SFT监督微调。从训练视角来看这属于微调不是预训练。AQ 的价值在于它选择了更硬核的路线——从随机权重开始经过数据清洗、tokenizer 训练、预训练、指令微调、偏好对齐等完整流程。这种做法的优点是团队能完全掌握模型行为不会被上游模型的数据分布和偏见绑架缺点是成本高、周期长、坑多。两位开发者能完成这件事说明他们对整个链路有非常系统的理解。对于国内开发者来说这个项目最大的参考价值不是“我也要复刻一个 AQ”而是“在有限的算力下如何用工程手段把 1B 模型做到可用”。1.2 为什么 1B 参数是“甜蜜点”1B 左右的模型在消费级显卡上可以做推理甚至在 CPU 上也能跑出可接受的速度。训练成本比 7B、13B 低一个数量级小团队可以负担。学术场景中1B 模型适合做可控实验可以快速验证数据配比、架构改动、对齐方法。它具备基本的推理、问答、摘要能力虽然不如大模型全面但作为研究基座足够。在当前的 LLM 生态里1B 模型通常被当作研究工具或垂直领域底座。你做 RAG检索增强生成、Agent 工具调用、领域知识问答1B 模型配合外部知识库往往能打出不错的性价比。1.3 “academic LLM”意味着什么AQ 标注“academic LLM”说明它的设计目标偏向学术研究与可复现性而不是追求商业级综合能力。这意味着项目会更重视数据配比的记录、训练过程的透明度、评估基准的公开性。这一点对研究者和学生非常友好。通过这类项目你能摸清一套开源小模型从零训练的完整工程闭环这比直接读论文更容易落地。2. 1B 级 LLM 从零训练的总体技术路线2.1 训练流水线全景从零训练一个 1B 模型大致可以划分成以下阶段数据收集与过滤。Tokenizer分词器训练。预训练Pre-training。指令微调SFT。偏好对齐DPO/RLHF。评估与迭代。量化压缩与部署。每个阶段都会直接影响最终模型质量。数据决定上限模型架构决定拟合能力训练策略决定收敛效率对齐决定可用性。2.2 三个核心规模决策在小团队资源有限的情况下最先要确认三个规模数据规模对 1B 模型常见的预训练数据量在 100B500B token 之间取决于算力。数据太少模型欠拟合太多则算力浪费。批量大小与学习率一般使用较大 batch配合 cosine 学习率调度。训练步数通常训练 13 个 epoch多轮重复数据容易导致过拟合。规模决策是经验与算力的折中不能盲目照搬大模型配置。2.3 项目时间与资源规划两人团队做这件事合理的规划是数据准备24 周。Tokenizer 与模型代码验证12 周。预训练小规模试跑验证 loss 下降1 周。正式预训练26 周取决于 GPU 数量。SFT 与对齐12 周。评估与迭代2 周以上。如果只有 12 张消费级显卡完整预训练 1B 模型会很吃力通常需要用到多卡并行或云上租用算力。即便 AQ 是两人团队大概率也依赖了多卡训练环境。3. 数据工程从零训练最关键的生命线很多项目失败不是因为模型结构没选对而是数据太脏。下面拆解数据环节的几个关键动作。3.1 数据来源与版权筛选学术 LLM 通常希望数据尽可能公开、可追踪、版权清晰。常见的数据源包括Wikipedia、Arxiv、PubMed 等学术公开数据。开源代码仓库以及开源许可证允许的数据集。公开的书籍、论文、专利摘要。各机构发布的开放数据集如 RedPajama、The Pile 的子集。在筛选时必须确认许可协议。学术用途不等于可以随意抓取版权风险在发布模型权重时会被放大。3.2 数据清洗与去重数据清洗的几个常用步骤去除 HTML 标签、乱码字符、不可见 Unicode 字符。统一换行和空格处理全半角符号。检测并去除低质量段落过短、重复、无语义内容。MinHash 去重消除网页之间的重复内容。根据困惑度过滤低质量文本。下面的代码演示了一个简化版数据清洗流程import re import hashlib from typing import Iterable def clean_text(text: str) - str: # 去除 HTML 标签 text re.sub(r[^], , text) # 去除控制字符 text re.sub(r[\x00-\x08\x0b\x0c\x0e-\x1f], , text) # 统一换行 text text.replace(\r\n, \n).replace(\r, \n) # 合并多余空行 text re.sub(r\n{3,}, \n\n, text) return text.strip() def is_low_quality(text: str, min_len: int 200) - bool: # 过短、连续重复、标点占比过高等都可以视为低质量 if len(text) min_len: return True if len(set(text)) 50: return True return False def minhash_deduplicate(texts: Iterable[str], threshold: int 5): seen set() for text in texts: # 简化版去重用句子集合的 hash 做粗筛 sentences set(re.split(r[。.!?], text)) sig hashlib.md5( |.join(sorted(sentences)[: threshold]).encode(utf-8) ).hexdigest() if sig in seen: continue seen.add(sig) yield text实际工程会使用更复杂的 MinHash LSH 方案但核心思想一致去掉重复内容保留多样性。3.3 数据配比与采样不同来源的数据对模型能力的影响不同。常见的配比逻辑是通用网页数据占大头保证语言能力和知识广度。学术论文、书籍提升推理和深度知识。代码数据提升逻辑能力和指令跟随能力。对话数据虽然量少但直接影响模型交互质感。配比不是一次定死的通常需要做小规模预训练实验观察不同配比在 benchmark 上的表现差异。3.4 数据格式与流式读取预训练数据通常保存为 JSONL 格式每个样本是一个 JSON 对象包含text字段。为了高效流式读取建议使用datasets库或自研内存映射读取器。{text: Transformer is a neural network architecture based on self-attention...} {text: In this paper, we propose a novel method for language modeling...}流式加载的参考代码from datasets import load_dataset from torch.utils.data import DataLoader dataset load_dataset( json, data_filesdata/train.jsonl, streamingTrue, ) def tokenize_fn(example): return tokenizer( example[text], truncationTrue, max_length2048, ) dataset dataset.map(tokenize_fn) loader DataLoader(dataset, batch_size8)这里需要注意tokenizer必须在进入map前完成加载流式数据集不会自动缓存 tokenize 结果所以每次迭代都会重复计算。生产环境建议先做离线 tokenize 再开始训练。4. 分词器与模型架构设计4.1 训练自己的 tokenizer很多人会忽略 tokenizer 的重要性。对于英语和代码BPEByte Pair Encoding效果稳定如果要支持中文还要考虑是否混入中文字符级 token。对于 1B 模型词表大小一般选择 32K128K。词表太小会导致序列过长、训练变慢词表太大会让 embedding 矩阵占大量显存。训练一个 SentencePiece tokenizer 的参考代码import sentencepiece as spm spm.SentencePieceTrainer.train( input[data/corpus.txt], model_prefixaq_tokenizer, vocab_size32768, model_typebpe, character_coverage0.9995, max_sentence_length4096, pad_id0, unk_id1, bos_id2, eos_id3, )训练完成后会生成aq_tokenizer.model和aq_tokenizer.vocab。需要注意tokenizer 的训练数据要覆盖预训练语料的分布否则会出现大量 unknown token严重降低模型效果。4.2 1B 模型架构选择当前中小型 LLM 的主流架构基本都基于 Transformer但会做一些调整RMSNorm 替代 LayerNorm训练更稳定。SwiGLU 激活函数提升非线性表达能力。RoPE旋转位置编码更好处理长序列。GQA分组查询注意力降低推理显存开销。移除 bias 项减少参数并提升训练稳定性。以 1B 参数为例常见配置大致如下超参数常见取值hidden_size2048intermediate_size5632num_hidden_layers24num_attention_heads16num_key_value_heads8GQAvocab_size32768max_position_embeddings4096rms_norm_eps1e-5不同框架的命名略有差异实际以你使用的库为准。4.3 模型配置文件示例以下是一个基于 Hugging Face Transformers 风格的config.json示例可以帮助你理解参数之间的关系{ architectures: [LlamaForCausalLM], bos_token_id: 2, eos_token_id: 3, hidden_act: silu, hidden_size: 2048, initializer_range: 0.02, intermediate_size: 5632, max_position_embeddings: 4096, model_type: llama, num_attention_heads: 16, num_hidden_layers: 24, num_key_value_heads: 8, pad_token_id: 0, rms_norm_eps: 1e-5, tie_word_embeddings: false, torch_dtype: bfloat16, vocab_size: 32768 }这里model_type写llama是为了利用开源库中已经实现的 Llama 类并不是说你的模型就是 Llama。如果你改了架构细节需要自定义模型类。5. 预训练实操配置、训练脚本与监控5.1 预训练环境与并行策略1B 模型单卡 BF16 训练激活显存至少需要 20GB 以上实际建议使用多卡。小团队通常选择 DeepSpeed ZeRO-2 或 ZeRO-3也可以用 PyTorch FSDP。训练过程中的核心监控指标loss主损失应平稳下降。grad norm梯度范数过大说明训练不稳定。learning rate当前学习率观察调度器是否正常。throughput tokens/s每秒处理 token 数衡量训练效率。5.2 DeepSpeed 训练脚本示例下面给出一个简化但完整的预训练脚本框架。它不是一个可以直接跑通所有环境的生产代码而是一个可以参照的骨架。# train.py import torch from transformers import ( AutoTokenizer, AutoConfig, LlamaForCausalLM, Trainer, TrainingArguments, ) from datasets import load_dataset model_config AutoConfig.from_pretrained(config.json) tokenizer AutoTokenizer.from_pretrained(aq_tokenizer) model LlamaForCausalLM(configmodel_config) model.train() dataset load_dataset( json, data_filesdata/tokenized/train.jsonl, streamingFalse, ) def tokenize(example): return tokenizer( example[text], truncationTrue, max_length2048, ) dataset dataset.map(tokenize, remove_columns[text]) training_args TrainingArguments( output_dir./checkpoints, per_device_train_batch_size4, gradient_accumulation_steps8, learning_rate3e-4, warmup_steps500, weight_decay0.1, num_train_epochs2, bf16True, logging_steps10, save_steps500, save_total_limit5, report_towandb, deepspeedds_config.json, ) trainer Trainer( modelmodel, argstraining_args, train_datasetdataset, tokenizertokenizer, data_collatorlambda data: { input_ids: torch.stack([torch.tensor(d[input_ids]) for d in data]), attention_mask: torch.stack([torch.tensor(d[attention_mask]) for d in data]), labels: torch.stack([torch.tensor(d[input_ids]) for d in data]), }, ) trainer.train()对应ds_config.json{ bf16: { enabled: true }, zero_optimization: { stage: 2, allgather_partitions: true, reduce_scatter: true, overlap_comm: true }, train_batch_size: 64, train_micro_batch_size_per_gpu: 4, gradient_accumulation_steps: 8, optimizer: { type: AdamW, params: { lr: 3e-4, betas: [0.9, 0.95], eps: 1e-8, weight_decay: 0.1 } }, scheduler: { type: WarmupCosine, params: { warmup_min_lr: 0, warmup_max_lr: 3e-4, warmup_num_steps: 500, total_num_steps: 100000 } } }注意train_batch_size是全局批量大小等于micro_batch_size × gradient_accumulation_steps × GPU 数。这个值直接影响模型收敛质量不建议随意调小。5.3 Loss 曲线怎么看从零训练时loss 通常会在前几百步快速下降之后进入缓慢下降区间。如果 loss 在很早期就停滞检查学习率是否过大或过小。检查数据是否存在大量重复。检查 tokenizer 是否把文本切得过于细碎。检查数值稳定性尝试降低初始学习率。如果 loss 出现突然飙升大概率是数据批次中混入了异常样本或者学习率调度设置不合理。5.4 中途评估预训练不是训完再测而是每隔固定步数做一次评估。对于学术模型建议至少保留以下几个维度训练集上的 loss。留存验证集上的 loss。少量通用 benchmark如 HellaSwag、MMLU 子集。验证集必须和训练集严格去重否则评估结果会虚高。6. 指令微调与对齐6.1 SFT 数据构建预训练完成后模型只会续写文本不会“回答问题”。要让它变成可对话的助手需要 SFT监督微调。SFT 数据通常组织为对话格式{ conversations: [ { from: human, value: 什么是 Transformer }, { from: gpt, value: Transformer 是一种基于自注意力机制的神经网络架构最早由 Vaswani 等人在 2017 年提出。它通过自注意力机制建模序列中任意两个位置之间的依赖关系同时支持并行计算。 } ] }SFT 阶段不需要太多数据几万条高质量对话足以让模型具备对话能力。重点在于数据多样性包括问答、写作、翻译、代码生成、总结、推理等任务。6.2 LoRA 与全参微调取舍小团队在 SFT 阶段通常会面临 LoRA 与全参微调的取舍全参微调效果上限高资源消耗大容易遗忘预训练知识。LoRA显存占用小训练快适合快速迭代但如果 rank 太小会限制表达能力。对 1B 模型如果显存允许推荐先做全参 SFT再使用 LoRA 做 DPO。这样既能保证基础能力又能快速迭代对齐策略。6.3 DPO 对齐DPODirect Preference Optimization是目前小团队最常用的对齐方法比 RLHF 简单很多。你不需要训练 Reward Model也不用搭建复杂的强化学习环境只需要构造chosen和rejected数据对。一个简化的 DPO 训练数据项{ prompt: 请解释一下贝叶斯定理。, chosen: 贝叶斯定理描述了在已知某些条件下如何更新事件发生的概率。其公式为 P(A|B) P(B|A) * P(A) / P(B)。, rejected: 贝叶斯定理是一种数学工具可以用来计算概率它很有用。 }DPO 训练代码可以基于trl库实现from trl import DPOTrainer, DPOConfig from transformers import AutoModelForCausalLM, AutoTokenizer model AutoModelForCausalLM.from_pretrained(checkpoints/sft_final) ref_model AutoModelForCausalLM.from_pretrained(checkpoints/sft_final) tokenizer AutoTokenizer.from_pretrained(checkpoints/sft_final) training_args DPOConfig( output_dir./dpo_checkpoints, per_device_train_batch_size2, learning_rate5e-6, max_length2048, max_prompt_length1024, bf16True, logging_steps10, save_steps200, ) dpo_trainer DPOTrainer( modelmodel, ref_modelref_model, argstraining_args, train_datasetdpo_dataset, tokenizertokenizer, ) dpo_trainer.train()DPO 对学习率比较敏感常用学习率在 1e-6 到 1e-5 之间。过大的学习率会把模型训崩导致回答退化。6.4 学术模型的安全与拒答即使是学术模型也需要基本的对齐策略不回答涉及个人隐私、医疗诊断、金融投资建议等高风险问题。对明显有害内容做拒答处理。不编造“公司内部资料”或“虚构事实”。学术模型可以开放更多边界探索但发布时应在 README 中明确说明适用场景与局限。7. 评估、量化与部署7.1 学术基准评估评估 1B 模型不能只用主观对话体验要结合标准 benchmark。常用评估包括HellaSwag常识推理。MMLU多学科知识。HumanEval代码生成。GSM8K数学推理。IFEval指令跟随能力。评估代码可以参考lm-evaluation-harnesslm_eval --model hf \ --model_args pretrained./checkpoints/sft_final \ --tasks hellaswag,mmlu,gsm8k \ --batch_size 8 \ --output_path ./eval_results评估结果需要与开源同尺寸模型横向对比例如 0.5B、1B、2B 的模型。这里需要注意的是不同版本的 benchmark 结果差异很大对比时尽量使用相同评估脚本和相同版本。7.2 量化与推理服务1B 模型 FP16 权重约 2GB量化到 4bit 后约 500MBCPU 也能跑。常用方案GPTQ适合 GPU 推理。AWQ激活感知量化效果稳定。GGUF配合 llama.cpp适合 CPU 与边缘设备。使用 llama.cpp 量化的简化流程# 1. 转为 GGUF 格式 python convert.py checkpoints/sft_final --outfile models/aq-1b.gguf --outtype q8_0 # 2. 使用 llama.cpp 启动本地服务 ./llama-server -m models/aq-1b.gguf --host 127.0.0.1 --port 80807.3 上线后的持续观测部署只是开始。上线后要持续关注回答长度、拒答率。是否出现有害内容。是否存在上下文记忆混乱。用户输入分布与训练集分布的差异。学术模型的部署通常不追求高并发更多是验证和演示。如果用到生产环境建议加一层内容安全过滤。8. 常见问题与排查思路问题现象常见原因解决思路预训练 loss 不下降学习率过大或过小数据太脏模型结构错误先跑小数据过拟合测试确认 loss 能收敛再逐步放大loss 突然飙升学习率调度异常数据批次混入异常样本检查数据 pipeline临时降低学习率恢复 checkpoint显存溢出batch size 过大序列过长优化器状态占用高减小 micro batch开启 gradient checkpointing使用 ZeROtokenizer 大量输出 unk词表与语料不匹配tokenizer 训练数据不充分重新训练 tokenizer增加领域数据覆盖SFT 后模型能力下降学习率过大SFT 数据分布单一降低学习率增加数据多样性保留部分通用语料DPO 后回答退化学习率过大chosen/rejected 差异不明显降低学习率重新清洗偏好数据评估结果与其他模型不可比评估 prompt 不同数据集版本不同采样参数不同统一评估脚本、数据集版本、解码参数9. 最佳实践与工程建议9.1 小团队的项目管理两人团队最大的风险不是技术而是迭代失控。建议每次实验只改一个变量记录实验结果。用实验管理工具跟踪 loss、benchmark、训练配置。每周固定一次 checkpoint 评估和模型试玩。9.2 数据与实验的可复现性学术模型的立足点之一是可复现性。建议做到数据清洗代码和版本全部入库。数据配比写进配置文件。训练脚本和依赖锁版本。发布时附上 tokenizer、config、评估脚本。9.3 成本与算力控制训练 1B 模型时算力消耗比 7B 小得多但依然建议先做小规模 smoke test再上全量训练。定期保存 checkpoint并清理冗余副本。使用 bf16 混合精度节省显存和带宽。如果预算有限优先租用短期 GPU训练完立即释放。9.4 安全与合规边界任何模型发布都建议注意以下边界明确模型的训练数据来源与许可。在模型卡中列出已知局限和可能偏见。高风险场景医疗、金融、法律只做研究辅助不做最终决策。涉及个人隐私数据的场景需要额外的匿名化和脱敏处理。10. 总结与学习路线AQ 这个项目的意义不在于“印度团队做出了 1B 模型”这个结果而在于它用最小规模复现了从零训练 LLM 的完整流程。对国内开发者来说这是一个非常值得参考的路线图从数据工程开始到 tokenizer、预训练、SFT、DPO、评估、量化每一步都有对应的工程挑战和优化空间。如果你也想尝试类似项目建议按下面的顺序推进先拿 1000 万 token 级别的数据做过拟合测试跑通代码链路。再扩展到 10 亿 token 级别验证数据 pipeline 的吞吐和稳定性。然后尝试完整预训练期间穿插评估。最后做 SFT 和 DPO把模型变成可对话的助手。1B 参数是个人开发者、学术团队和中小企业最容易切入的档位。无论你最终的目标是研究、垂直领域应用还是教育项目这条路都值得完整走一遍。希望这篇文章能帮你在从零训练 LLM 的路上少踩几个坑。