1. 大模型全链路:从预训练到二次开发的整体思路
1.1 为什么不能只盯着一个环节
我做了半年多大模型相关的事情,尤其最近一直在跟的 Loongwise 项目,把预训练、微调、推理、开源二次开发四段链路完整走了一遍,收获和踩坑都很多。先说一句很直接的话:现在市场上很多人把"大模型"等同于"调API",这是最大的认知偏差。
预训练、微调、推理这三件事,表面上都是"用同一个模型",实际上是完全不同性质的工程问题。预训练解决的是模型的常识和基础能力,微调解决的是让它说人话、干正事,推理解决的是把模型变成服务并保证速度和稳定性。三步用的硬件、工具、评估标准都不一样。
比如你拿一个基座模型去做行业问答,如果上下文总是乱答,你以为是微调的问题,结果发现是预训练阶段的知识覆盖不足;如果模型训练完效果不错,但线上推理时首字延迟高到没法用,那问题可能出在推理引擎和量化方案上。这种"环节错位"的排查成本极高。所以做Loongwise的第一天,我就逼着自己把技术路线画成一张完整地图:底座选型、数据准备、微调方式、推理框架、二次开发路径,每一段都要能回答"为什么这么做、成本多少、边界在哪"。
1.2 Loongwise项目的路线全景
简单交代一下背景。Loongwise项目的目标,是在一台单卡工作站上落地一个垂直场景的智能助手,具体做的是工业质检场景的缺陷描述与原因分析。为什么选这个场景?因为工业现场数据敏感、网络环境受限、对响应稳定性要求高,非常不适合纯云端大模型调用,必须走开源模型本地化这条路。
于是我定的技术路线是:
- 选一个开源基座模型(偏好中文能力强的,比如 Qwen 系列);
- 用 QLoRA 在单卡上做垂直场景微调;
- 用 vLLM 做推理服务化,暴露 OpenAI 兼容接口;
- 在之上做 RAG + 工具调用,把质检知识库、历史缺陷库挂进去;
- 整个系统打包成私有化部署方案,可以在无外网的隔离环境运行。
这套路线不是拍脑袋定的。预训练我都不会碰——那是超大公司用海量算力烧出来的能力,以项目资源不可能复现。微调是必要的,因为通用模型对"缺陷描述"这类垂直表达不够熟悉,但微调也不能解决所有问题,比如让模型实时查询最新的工艺参数,这种事情更适合交给检索增强。推理则是保证整个系统的可用性底线,这一环如果崩了,前面训得再好也白搭。
后面所有内容,我都会沿着这条路线展开。这不是什么教科书流程,是一个项目在被性能、成本、场景要求反复蹂躏之后得出的实际方案。
2. 预训练:底座模型的瓶颈与边界
2.1 预训练语言模型到底练出了什么
大模型的起点是预训练语言模型,技术上模式很简单:给模型一段文本,让它预测下一个 token,然后反复做这件事。但就是这种简单的自监督目标,在百亿级 token 语料上反复训练后,模型会内化出语法规则、世界知识、逻辑推理乃至部分思维链能力。
听起来很玄学,我的理解是:预训练本质上是在压缩人类语料中的统计规律。模型参数量越大、训练数据越多,它能记住的模式就越复杂。这也是为什么"预训练语言模型"几乎成了所有大模型产品的底盘,它决定了模型的基础智商,后续的微调只是在这个底盘上做定向的装修。
这里有个关键概念需要区分:基础模型(Base Model)和对话模型(Instruct Model)。之前的 Qwen、Llama 等开源模型都会同时放出 Base 和 Instruct/Chat 两个版本。Base 只会续写文本,你问它问题它不一定会按指令回答;Instruct 经过指令微调和人类对齐,才像"助手"。
对大多数二次开发项目,我不建议拿 Base 模型直接做产品,除非你的微调数据非常充足且质量很高。相比之下,用 Instruct 模型作为微调起点,通常只需要几百到几千条高质量数据就能把垂直能力拉起来,省时省力。
2.2 从头预训练的硬件账与技术门槛
很多人问:既然预训练这么重要,我能不能自己从头训一个?技术上不是不能,问题在于账算不过来。
以目前主流的 7B~8B 参数模型为例,从头预训练需要大约1~2万亿 token的数据(轻量版也至少几千亿 token),在单张 H100/A100 上以每秒几千 token 的速度算,要跑几十万小时。就算租到 8 卡 H100 集群,整个预训练过程也要跑几十天,仅算力成本就在百万人民币量级。如果再算上数据收集、清洗、去重、混入比例实验,周期至少是数月级别。
这不是给个人或者中小团队的东西。所以我一直建议,除非你有明确的技术壁垒和大规模算力投入,否则不要自研预训练。你能碰的边界是:
- 直接使用成熟开源基座(如 Qwen、Llama、DeepSeek、Mistral 等);
- 在开源基座上做领域继续预训练(Continue Pretraining),用领域语料让模型补足专业词汇和知识;
- 在基座之上做微调,让模型适配任务格式和交互方式。
领域继续预训练是一个容易被低估的方案。比如工业场景里有大量专业术语"表面划伤、针孔、毛刺、氧化色差",通用模型没见过或理解不深。这时候不一定要微调,可以拿几 GB 到几十 GB 的行业文档,以较低学习率在 Base 模型上继续训几个 epoch,模型的领域知识就会有明显提升。之后再叠加一轮轻量微调,效果往往比直接微调更好。
2.3 数据配比与训练基建的实践经验
如果真要碰预训练或继续预训练,有两点经验值得记下来。
第一,数据质量优先级远高于数据量。我见过很多同学拿着一堆爬下来的网页直接开训,结果是 loss 不降、生成文本全是乱码。正确做法是至少做一遍:去掉HTML标签、过滤广告和无意义文本、按长度和重复率去重、语言识别过滤低质量语料。工业领域尤其要小心 PDF 表格的解析效果,表格化信息一旦乱了,模型的数字理解能力会变得很差。
第二,继续预训练的学习率要低。正常微调的学习率在1e-5到1e-4区间,而继续预训练建议降到1e-5以下,甚至用1e-6到5e-6,同时增加 warmup 比例。否则模型会把原有的世界知识忘掉,出现"灾难性遗忘",哪怕你喂给它的领域语料再专业,整体能力也会退化到没法用。
预训练这一层,我的结论很简单:**理解它、敬畏它、但不要轻易碰它。**把精力花在如何利用好现有底座模型,才是性价比最高的策略。
3. 微调:贴近场景的关键一跃
3.1 全量微调、LoRA、QLoRA之间怎么选
微调是大部分中小团队真正会做的事情,但一上来就会被各种名词搞晕:全量微调、LoRA、QLoRA、PEFT、Adapter……到底用哪个?
它们的本质区别在于:改多少参数、花多少显存、效果差多少。
全量微调(Full Fine-tuning):所有模型参数都参与训练,效果上限最高,但显存和训练成本巨大。一个 7B 模型,即便用 BF16 训练,光权重就要占 14GB,加上优化器状态(AdamW 大约三倍权重大小)和梯度,单卡 40GB 都显得紧张。除非你有 A100 80G 或多卡并行,否则不建议。
LoRA(Low-Rank Adaptation):冻结原始权重,只训练注入的低秩矩阵。通常只占原模型参数的百分之几,显存占用大幅下降。在 24GB 显卡上就能跑 7B 模型的 LoRA 微调,消费级硬件即可上手。
QLoRA:在 LoRA 的基础上更进一步,先把基础模型的权重做 4-bit 量化存储,再在反量化后的层上挂 LoRA 训练。显存占用进一步压缩到接近推理水平,双卡甚至单卡 16GB 都能微调 7B 模型。
具体到选型,我的建议是一张表说清楚:
| 方案 | 可训练参数 | 显存需求(7B模型) | 适用场景 | 效果 |
|---|---|---|---|---|
| 全量微调 | 全部参数 | 40GB+,最好多卡 | 数据量大、领域差异大、算力充足 | 上限最高 |
| LoRA | 约1% | 24GB可跑 | 数据量中等、需要快速迭代 | 接近全量 |
| QLoRA | 约1% | 12~16GB可跑 | 消费级显卡、显存受限 | 略低于LoRA,实际可用 |
如果条件允许,我优先推荐 LoRA;显卡紧张就用 QLoRA。最痛苦的不是效果差那一点,而是全量微调一旦显存溢出、训练中断,前面几小时全部白费。LoRA 的 checkpoint 只有几十到几百 MB,方便存、方便换、方便多个任务并存,这才是工业化微调的正确形态。
3.2 一份可复现的LoRA微调实战配置
下面这套配置是我在 Loongwise 项目里实际用过的,基于 Qwen2.5-7B-Instruct,单张 4090 24GB 跑下来没有任何问题。直接抄步骤就能复现大半。
依赖安装:
pip install transformers peft accelerate bitsandbytes trl datasets核心训练脚本(省略了数据加载部分,只展示关键参数):
from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, BitsAndBytesConfig ) from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training from trl import SFTTrainer bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype="bf16", bnb_4bit_use_double_quant=True, ) model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen2.5-7B-Instruct", quantization_config=bnb_config, device_map="auto", ) lora_config = LoraConfig( r=16, # 低秩矩阵的秩,越大表示容量越大 lora_alpha=32, # LoRA缩放系数,一般取r的2倍 target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], lora_dropout=0.05, bias="none", ) peft_model = prepare_model_for_kbit_training(model) peft_model = get_peft_model(model, lora_config) trainer = SFTTrainer( model=peft_model, train_dataset=dataset, args=TrainingArguments( output_dir="./qwen-lora-checkpoint", num_train_epochs=3, per_device_train_batch_size=4, gradient_accumulation_steps=4, learning_rate=2e-4, warmup_ratio=0.1, logging_steps=10, save_steps=200, bf16=True, report_to="none", ), ) trainer.train()几个参数的选择逻辑说一下:
r=16是当前比较通用的起点。调大可以提高模型表达能力,但训练更慢、风险更高;调小能省显存,但可能学不进去。lora_alpha=32等于2*r,这是大家用出来的经验值,控制最终注入权重的强度。target_modules只设了注意力层的四组投影,省略了 MLP 层。加上 MLP 效果不一定更好,训练开销却明显增加。- 学习率
2e-4针对 LoRA 比较合适;全量微调一般只用1e-5到5e-5。
训练结束后,LoRA 权重会单独保存,加载时用AutoPeftModelForCausalLM把基础模型和 LoRA 权重合并或使用加载。实际部署可以直接合并,省掉推理时加载 adapter 的开销。
3.3 微调数据集的构建思路与常见翻车点
不少人在微调上栽跟头,根子不在训练参数,而在数据。
Loongwise 在做质量缺陷问答时,我把数据从最早的 200 条一路做到 3000 条,对比下来发现几个规律:
- **几百条高质量指令数据,足以让模型学会一种固定的回答格式。**比如缺陷描述、可能成因、建议措施三个段落,只需几百条样例就能稳定输出结构。
- **知识性内容不要指望微调灌输。**如果模型要回答"某某工序的标准参数"这种具体数值,微调不但成本高,还容易更新不及时,改用 RAG 检索效率更高。
- **数据格式要统一。**最好用最朴素的 JSON 对象:
{"instruction": "...", "input": "...", "output": "..."},然后按对话模板转成 token。 - **重复数据要去掉。**如果同一批样本反复出现,模型会对这些文本过拟合,生成结果会退化成记忆复读机,甚至输出一模一样的话。
这里必须提一个训练过程中的假象:**训练 loss 降得漂亮,不代表效果提升。**我见过太多人只看 loss 曲线就宣布训练成功,结果一测生成内容全是空话。
正确做法是留出一部分验证集,在训练中定期做生成测试。比如每 200 步让模型回答几个固定问题,观察输出有没有偏离结构、有没有幻觉。微调完成后,再用几十条没参与训练的测试样本做人工评估。这一步虽然土,但能避免你拿着一个 loss 很低、实战零分的模型去上线。
4. 推理部署:从张量到服务的最后一公里
4.1 推理引擎与量化方案选型
模型训练完,只完成了一半。你还需要把它部署成能对外提供服务的接口。这里面的坑,比微调还多。
最直白的结论:**别用 HuggingFace Transformers 自带的generate做生产服务。**它的吞吐太低,并发稍微上来就排队。生产环境要用专门的推理引擎。
主流的开源推理引擎里,我重点用过的有三个:
- vLLM:把显存中的 KV Cache 做了分页管理,配合 Continuous Batching(连续批处理)大幅提高吞吐。是目前部署大模型 API 最主流的方案,兼容 OpenAI 接口,开箱即用。
- llama.cpp / GGUF:在 CPU 和 Apple Silicon 上运行友好,量化格式为 GGUF,适合个人电脑本地部署、嵌入式设备、低显存场景。
- MLX:Apple 自研框架,在 M 系列芯片上跑量化模型效率很高。我试过在 MacBook 上用 MLX 跑 4-bit 量化的 Qwen 系列模型,速度基本可以接受。
选择逻辑很简单:服务器上有 NVIDIA GPU,上 vLLM;个人电脑、边缘设备,用 llama.cpp 或 MLX。
量化是另一个绕不开的话题。模型训练时通常是 FP16/BF16,但推理时如果也保持 FP16,一个 7B 模型的权重就占 14GB,加上 KV Cache,24GB 显卡根本撑不起多少并发。量化把权重从 16bit 压到 8bit 或 4bit,显存占用直接砍到一半甚至四分之一。
我常用的量化方案是:
- AWQ / GPTQ:支持 vLLM,适合 GPU 伺服;AWQ 在 4-bit 下精度损失较小。
- GGUF Q4_K_M:llama.cpp 生态,CPU/GPU 混合推理,均衡度和速度。
- MLX 4-bit:Apple 芯片专用。
有个必须说清楚的常识:量化会带来精度损失,但 4-bit 下对大部分对话、问答、摘要任务影响不大。真正敏感的是代码生成、数学推理和长文本精确记忆场景,这类任务建议至少用 8-bit 或直接保持 FP16。
4.2 显存预估与单卡部署实操
部署前最怕显存爆掉。我总结了一个粗估公式:
所需显存 ≈ 模型权重大小 + KV Cache 大小 + 激活余量
举例:7B 模型 FP16 权重 14GB,4-bit 量化后约 3.5~4.5GB。假设并发 16 路、上下文长度 4096,KV Cache 大约还需要 2~4GB。所以 24GB 显卡跑 4-bit 量化的 7B 模型,是完全可以胜任的;但跑 FP16 就会非常紧张。
部署 vLLM 的真实命令大概是这样的:
pip install vllm python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --quantization awq \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --port 8000启动之后,模型会自动暴露一个与 OpenAI 兼容的接口,调用方式:
from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY") resp = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=[{"role": "user", "content": "描述这张图中针孔缺陷的可能成因"}], temperature=0.3, ) print(resp.choices[0].message.content)这套方式的好处是,二次开发只需要面向 OpenAI 接口写代码,底层引擎想换就换。Loongwise 里的质检助手就是通过这个接口对接上层业务系统的,后端完全不用关心模型是 vLLM 还是 ollama。
4.3 推理工程里的加速手段和权衡
不要以为装上 vLLM 就万事大吉,实际部署还会遇到几个明显影响体验的因素。
第一是并发与吞吐的权衡。vLLM 的 Continuous Batching 会让多个请求同时在一个 batch 里推理,并发提高后单卡吞吐会显著上升。如果发现响应变慢,优先调低max_model_len(比如从 8192 降到 4096),让显存腾出来给 batch 用。长上下文的代价比很多人想象中大得多,除非业务真的需要,否则别把上限拉满。
第二是首 token 延迟(TTFT)和生成速度(TPS)是两组不同指标。代码生成、语义搜索对首 token 延迟很敏感,客服问答对生成速度更敏感。调试时用 vLLM 自带的 metrics 接口分别观测,不要混为一谈。
第三是量化精度和下游效果的关系。4-bit 的模型跑业务没问题,但如果下游要做情感分析、抽取结构化字段,建议每换一个量化档位就跑一遍验证集,防止精度下降带入上游。Loongwise 里有一版 AWQ 4-bit 量化后,缺陷等级的判断准确率掉了 2 个百分点,后来我把分类逻辑从"模型直接分类"改成了"模型生成 + 规则校验",才稳住效果。
5. 开源二次开发:技术路线与应用边界
5.1 开源协议与模型可改性边界
所谓"开源二次开发",经常被误解成"开源 = 随便改随便商用"。这个想法要纠正。
开源模型的"开源"分几个层次:权重是公开的、架构是公开的、训练代码是否公开则不一定。拿到一个模型之后,第一件事应该是看它的开源许可证和商用条款。
我自己的操作习惯是:把模型卡页面里 License 字段截图存档,并核对这些条款:
- 是否允许商用;
- 是否有月活用户规模限制;
- 是否要求衍生模型保持同协议开源;
- 是否对特定区域有附加限制。
对于企业私有化部署,还要考虑:模型及微调产物是否允许部署在无外网的隔离环境?大部分开源模型允许本地私有化,但有些云服务商会要求在它们平台托管。这些边界如果没有提前确认,后面等业务上线了再看,代价非常大。
还有一个实际问题是基座模型的更新换代。比如今天基于 Qwen 某个版本微调的 LoRA,明年模型升级后,LoRA 能不能继续用?大概率不能直接迁移,需要重新训练。所以二次开发时要有意识地做接口隔离:业务逻辑层不直接依赖某个模型的具体版本,而是通过我们前文搭建的 OpenAI 兼容接口访问模型服务。这样底层模型换版本,上层业务改动最小。
5.2 二次开发的典型套路:RAG、工具调用、垂直微调
开源模型到手后,往业务上落地的技术路线其实有章可循,万变不离三招。
第一招:RAG(检索增强生成)。当业务知识更新频繁、答案需要精确引用时,用 RAG 比微调靠谱。做法很直接:把文档切块、向量化存入向量数据库,用户提问时先检索相关片段,然后拼进 Prompt 让模型基于片段回答。
Loongwise 里挂了一个历史缺陷知识库,遇到新缺陷时,系统先把相似历史案例检索出来,再让模型结合检索结果写分析报告。最终效果中,幻觉明显减少,因为模型的回答被限定在检索内容范围内。RAG 的难点在于切块粒度、检索召回率和 Prompt 拼接,这块值得单独花时间调优。
第二招:工具调用(Function Calling/Tool Use)。让模型具备调用外部接口的能力,比如查数据库、执行脚本、调用工厂的 MES 系统接口。开源模型通过微调可以学会工具调用格式,然后在推理时由外层 Agent 框架来执行决定。Loongwise 的质检助手可以触发"生成缺陷统计报表"这个工具,模型自己决定什么时候调用、传什么参数,这在传统规则系统里做不到。
第三招:垂直微调。当模型的表达风格、输出结构、专业术语确实不符合业务要求时,才用第三节的 LoRA 微调去纠正。微调解决的是"模型的表达习惯"问题,不是"知识缺乏"问题,这个边界必须想清楚。
三招不是互斥的,实际落地经常会两两组合,比如"领域继续预训练 + LoRA微调 + RAG检索 + 工具调用"四件套全上。但每加一层,系统的排查复杂度也会上升,要克制。
5.3 云部署、私有化、边缘单机怎么选
部署形态直接决定了整个技术架构。同一个模型,在云端、私有化和边缘单机上的玩法完全不同。
- 云端部署:算力弹性、可在多卡扩容,适合用户量大、业务波动明显的场景。缺点是数据出域、网络依赖、费用随调用量涨。如果数据敏感,先排除。
- 私有化部署:在客户机房内网跑一朵小型 GPU 集群或一台工作站,数据不出门,模型长期在线。工业质检、医疗、金融领域基本都是这个需求。Loongwise 最终就是私有化部署,机器的 GPU 不强,但模型量化到 4-bit,再限制并发和上下文长度,完全可以稳定支撑一个几十人规模的产线班组。
- 边缘单机:单张消费卡甚至无 GPU 机器,跑小模型或低量化模型,延迟敏感但任务简单。像"轴承外观初筛""设备异常提示"这类简单分类任务,用小模型反而比 7B 大模型更合适。
你如果在纠结"工业AI检测、服装检测是用云联网还是单机,用多大模型够用",我的经验是:能单机就单机,模型先从中型 7B/8B 量化版起步。工业场景对实时性要求高,网络抖动一次停产一次,代价远超那点算力成本。7B 量化模型配合针对性微调,在大多数视觉/文本混合任务里已经够用。把大模型拉进产线时,稳定比聪明重要得多。
6. 常见问题与避坑实录
6.1 高频故障与排查速查
把我在 Loongwise 和其他项目里遇到的高频故障整理成了一张速查表,未必能覆盖你的全部问题,但大概率能救急:
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 微调 loss 不降甚至升高 | 学习率过高/数据集噪声太大 | 降低学习率到5e-5,清洗明显乱码样本 |
| 微调完后生成全是重复话 | 数据重复度太高/epoch过长 | 去重,epoch降到2以内,检查数据集 |
| vLLM 启动就 OOM | 显存分配过高或上下文太长 | 调低gpu_memory_utilization和max_model_len |
| 量化后效果大幅下降 | 4-bit量化对原任务过于敏感 | 改8-bit,或把敏感逻辑拆出来用规则处理 |
| 请求并发一高就超时 | KV Cache被打满/排队过多 | 减并发、调max_model_len、换更大显存卡 |
| 中文输出出现乱码 | 分词器与模型不匹配 | 确认加载时指定的tokenizer与模型对应 |
| RAG检索不到相关内容 | 切块太小/向量模型不适配 | 调整chunk_size,换更强embedding模型 |
| LoRA训练后模型能力退步 | 基础模型选择错误/灾难性遗忘 | 用Instruct版做起点,降低训练数据中劣质内容比例 |
这里面有一件事值得展开说:训练时完全正常的模型,部署后行为变了怎么办。多半不是模型真的变了,而是推理端的采样参数不一样。训练时 的生成评估默认用的 temperature、top_p 和线上服务设置不一致,会导致观感差距很大。我的习惯是把评估阶段和线上服务的采样参数配置成同一组,避免"开发挺好,上线抽风"的怪现象。
另一个经验是把模型的输入输出全部做日志留痕,特别是二次开发上线初期。每次异常输出,都能从日志里还原当时的 Prompt、检索内容和生成结果,排查效率提升一个量级。没有日志的大模型系统,在出问题时就是黑箱。
6.2 我的几点个人心得
在我自己的整理时间,最后分享几条不一定写在文档里的体会:
第一条,先做端到端最小验证,再决定要不要微调。很多需求其实用 Prompt 工程、RAG 就能解决,不用动训练。先部署好基座模型,把业务问题跑一遍,你会发现 60% 的问题可以通过 Prompt 和检索优化解决,剩下 40% 才轮到微调出手。直接一上来就微调,等于拿高射炮打蚊子,还容易把问题搞复杂。
第二条,分清"知识"和"能力"的边界。微调擅长改变模型的输出格式、交互方式、术语表达,但要让它记住大量实时更新的业务数据,效果很差且维护负担重。知识部分交给 RAG,能力部分交给微调和推理优化,两边配合才稳定。
第三条,不要迷恋大模型,有时候小模型加好流程更实用。Loongwise 前期我用过 70B 级别的模型做实验,效果确实好,但单卡根本跑不动,量化后速度也拉胯,最后换回 7B 量化版加上 RAG 和工具调用,实际效果反而更符合产线要求。模型大小不是指标,业务能不能稳定跑起来才是。
大模型这条链路很长,从预训练到微调到推理部署再到二次开发,每一步都有自己特有的坑。把边界搞清楚,把每一步选型的逻辑想明白,比堆参数、堆数据更重要。希望这篇文章能帮你少走一些弯路。