1. 大模型技术全景的认知地图
1.1 为什么需要一张完整的技术图景
很多人接触大模型是从一句提示词开始的,写个问题,等它回答,觉得神奇,然后就没有然后了。但如果你真的想把这个东西用起来、调得好、甚至自己动手改一改,光会写提示词是远远不够的。你需要知道它从哪来、中间经过了什么、最后怎么变成一个能帮你干活的Agent。
我刚开始接触大模型的时候,也是东一榔头西一棒子。今天看人讲Transformer架构,明天刷到LoRA微调教程,后天又听说Agent能自动订机票。信息全是碎片,拼不到一起。后来花了不少时间把整条链路捋了一遍,才发现从预训练到Agent其实是一条非常清晰的流水线,每一环解决什么问题、用什么方法、有什么坑,都是有章可循的。
这篇文章就是把我自己走过的这条路完整地摊开来讲。从最底层的预训练开始,到微调怎么选框架、怎么省显存,再到提示词工程和上下文工程的区别,最后到Agent到底是什么、怎么扛并发。不管你是刚入门想建立体系认知,还是已经在一线做微调部署想查漏补缺,应该都能找到对你有用的东西。
1.2 从预训练到Agent的五层结构
整个大模型技术栈可以粗略分成五层,每一层都有自己核心要解决的问题:
- 预训练层:让模型学会语言的基本规律和世界知识。这一层决定了模型的“底子”好不好。
- 微调层:让通用模型适配具体任务或领域。这一层决定了模型“能不能干你的活”。
- 对齐层:让模型的输出符合人类偏好,有用、诚实、无害。这一层决定了模型“听不听话”。
- 提示与上下文层:通过输入设计激发模型能力,不改权重。这一层决定了模型“能不能干得漂亮”。
- Agent层:让模型自主规划、调用工具、多步执行。这一层决定了模型“能不能自己干活”。
这五层不是严格串行的,实际项目中经常交叉。比如你做Agent的时候可能发现底层模型能力不够,回头去做微调;微调完了发现提示词设计也有优化空间。但整体认知框架是清晰的,先建立这个框架,再往里填细节,效率会高很多。
提示:不要试图一次性把每一层都学透。先跑通一个最小闭环——比如用现成模型加提示词做一个简单应用——然后再逐层深入。这样学起来有正反馈,不容易放弃。
2. 预训练:大模型的地基是怎么打的
2.1 预训练到底在做什么
预训练这个词听起来很唬人,但核心思想其实很朴素:给模型看海量的文本,让它学会预测下一个词。就这么简单。但就是这么一个简单的任务,当数据量足够大、模型参数足够多的时候,模型就“涌现”出了理解语言、推理、甚至写代码的能力。
为什么预测下一个词能学到这么多东西?你可以这样理解:要准确预测下一个词,模型必须理解语法、语义、常识、逻辑关系,甚至一些世界知识。比如“今天天气很___”,模型要知道填“好”或“差”都行,但填“桌子”就不对。再比如“中国的首都是___”,模型需要知道这个事实。这些能力不是专门教的,而是在预测任务中自然学到的。
预训练的数据量通常是TB级别的。以主流开源模型为例,训练数据动辄几万亿个token。token是模型处理文本的基本单位,可以粗略理解为“词片”。一个中文汉字大约对应1到2个token,一个英文单词大约对应1到1.5个token。几万亿token是什么概念?相当于把整个互联网的文本内容翻来覆去看了好几遍。
2.2 预训练模型选型:从BERT到GPT到多模态
预训练模型不是只有一种。不同架构适合不同任务,选错了方向后面会很痛苦。
BERT系列(包括RoBERTa中文预训练模型)是双向编码器,擅长理解任务,比如分类、抽取、问答。它看一个句子的时候,每个词都能同时看到左边和右边的上下文。但BERT不擅长生成,因为它不是从左到右逐词生成的架构。如果你要做文本分类、情感分析、命名实体识别,BERT系列依然是性价比很高的选择。
GPT系列是自回归解码器,从左到右逐词生成,天生适合文本生成、对话、代码生成。现在大家说“大模型”通常指的就是这一类。LLaMA、Qwen、ChatGLM这些主流开源模型都是这个架构。
多模态大模型在文本之外还处理图像、音频等模态。比如CLIP模型可以理解图像和文本的对应关系,常用于图像分类、检索。多模态模型的预训练通常需要配对的图文数据,训练成本更高,但应用场景也更广。
Spatial LLM是最近比较热的方向,专门处理三维空间信息,用于机器人导航、自动驾驶等场景。这类模型在传统LLM基础上增加了空间感知和推理能力。
选型的时候先问自己:我的任务是需要理解还是生成?是纯文本还是多模态?是通用场景还是特定领域?回答完这三个问题,方向基本就清楚了。
2.3 预训练权重的获取与使用
大多数人不需要自己从头预训练,直接用开源的预训练权重就行。Hugging Face是主要的权重集散地,Open LLM Leaderboard等公开榜单可以帮你对比不同模型的性能。
下载权重的时候注意几点:第一,确认许可证是否允许你的使用场景;第二,检查模型卡上的训练数据截止日期,太老的模型可能缺少近期知识;第三,注意权重的精度格式,fp32、fp16、int8、int4各有取舍,精度越低显存占用越小但效果可能下降。
以ResNet预训练模型为例,虽然它是视觉领域的,但思路一样:ImageNet上预训练的ResNet权重可以直接拿来做特征提取,也可以在你的数据集上微调。DEIM的COCO预训练权重也是类似逻辑,目标检测任务直接加载预训练权重再微调,比从头训练快得多也好得多。
注意:下载权重时务必核对文件的哈希值,避免下载到损坏或不完整的文件。大文件下载中断是常事,很多框架加载失败其实就是权重文件没下完。
3. 微调:让通用模型变成你的专属模型
3.1 什么时候需要微调
预训练模型虽然知识广博,但它不知道你的业务细节。你问它你们公司的报销流程,它只能瞎编。这时候就需要微调。
但微调不是万能的。先判断你的需求属于哪种:
- 知识注入:模型不知道某个事实。这种情况优先考虑RAG(检索增强生成),把知识放在外部数据库里,需要的时候检索出来塞进上下文。微调也可以注入知识,但更新麻烦,成本高。
- 风格适配:模型回答太啰嗦或太正式,你想要更简洁或更口语化的风格。微调很有效。
- 格式约束:你需要模型输出严格的JSON、SQL或特定模板。微调效果通常比提示词好。
- 能力提升:模型在某个特定任务上表现不好,比如医疗问答、法律文书生成。微调可以显著提升。
我的经验是:能用提示词解决的就别微调,能用RAG解决的就别微调,实在不行了再微调。微调是最后的手段,不是第一选择。
3.2 主流微调工具框架选型
微调框架这两年冒出来很多,选哪个取决于你的硬件、技术栈和需求。
| 框架 | 适合场景 | 显存要求 | 上手难度 |
|---|---|---|---|
| Hugging Face Transformers | 通用微调,生态最全 | 较高 | 低 |
| PEFT | 参数高效微调,LoRA/QLoRA | 低 | 中 |
| LLaMA-Factory | 一站式微调,支持多种模型 | 中 | 低 |
| Axolotl | 配置驱动,适合批量实验 | 中 | 中 |
| Unsloth | 极致显存优化,速度快 | 很低 | 低 |
| DeepSpeed | 大规模分布式训练 | 高 | 高 |
如果你是个人开发者,显卡只有一张24G甚至更少,优先考虑Unsloth或LLaMA-Factory配合QLoRA。如果你在团队里做生产级微调,DeepSpeed加Hugging Face Transformers是更稳妥的选择。
基于Ollama的模型微调代码最近也比较火,Ollama本身是推理工具,但可以配合微调后的模型使用。流程通常是:用PEFT或LLaMA-Factory微调出LoRA权重,合并到基础模型,导出为GGUF格式,再导入Ollama运行。
3.3 LoRA微调实战:从参数到代码
LoRA是目前最流行的参数高效微调方法。核心思想是不改原始权重,而是在旁边加两个小矩阵,训练时只更新这两个小矩阵。这样可训练参数从几十亿降到几百万,显存需求大幅下降。
关键参数就几个:
- r(秩):LoRA矩阵的秩,通常8到64。越大表达能力越强,但参数越多。一般任务16或32够用。
- alpha:缩放因子,通常设为r的2倍。它控制LoRA权重的更新幅度。
- target_modules:哪些层加LoRA。通常注意力层的q_proj、v_proj是必加的,k_proj、o_proj可选。全加效果更好但参数更多。
- dropout:防止过拟合,通常0.05到0.1。
以Qwen模型为例,用PEFT做LoRA微调的核心代码大概长这样:
from peft import LoraConfig, get_peft_model from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen2-7B", torch_dtype=torch.float16, device_map="auto" ) tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B") lora_config = LoraConfig( r=16, lora_alpha=32, target_modules=["q_proj", "v_proj", "k_proj", "o_proj"], lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) model = get_peft_model(model, lora_config) model.print_trainable_parameters()打印出来你会看到可训练参数只占总参数的不到1%。这就是LoRA的威力。
QLoRA更进一步,把基础模型量化到4bit,再在上面加LoRA。这样一张24G的卡就能微调7B甚至13B的模型。代价是训练速度稍慢,效果略有损失,但性价比极高。
3.4 微调规模减少的策略与取舍
“微调规模减少”是很多人关心的问题。除了LoRA和QLoRA,还有几种思路:
- 冻结底层:只训练最后几层。底层特征通用性强,不需要大改。
- Adapter:在每层插入小模块,只训练这些模块。效果稳定但推理时增加延迟。
- Prefix Tuning:在输入前加可训练的前缀向量。参数极少,但效果对任务敏感。
- IA3:缩放激活值,参数比LoRA还少。
选择哪种取决于你的约束。显存极度受限就QLoRA加IA3;追求效果就LoRA加全target_modules;需要快速实验就Prefix Tuning。
实操心得:微调学习率通常设1e-4到2e-4,比全量微调大一个数量级。因为LoRA参数是随机初始化的,需要更大的步长。但太大容易震荡,建议配合warmup和余弦退火。
4. 提示词工程与上下文工程:不改变权重的能力激发
4.1 提示词工程的核心原则
提示词工程不是玄学,它有明确的原则可循。
第一,明确任务。不要说“帮我写点东西”,要说“帮我写一封给客户的道歉邮件,原因是发货延迟了三天,语气要诚恳但不卑躬屈膝,200字以内”。
第二,提供示例。Few-shot prompting比zero-shot效果好得多。给两三个输入输出示例,模型就能模仿格式和风格。
第三,分步思考。对于推理任务,让模型“一步一步想”能显著提升准确率。这就是Chain-of-Thought提示。
第四,指定角色。让模型扮演某个角色,比如“你是一位有十年经验的儿科医生”,输出质量会不一样。
第五,约束输出。明确要求JSON格式、字数限制、禁止事项。
4.2 上下文工程:比提示词更广的范畴
提示词工程关注的是“怎么问”,上下文工程关注的是“给模型看什么”。后者范围更大,包括:
- 系统提示:定义模型的角色、能力边界、行为准则。
- 检索内容:从知识库检索的相关文档片段。
- 对话历史:之前几轮对话的摘要或全文。
- 工具描述:Agent可调用工具的说明。
- 记忆:长期记忆的摘要或向量检索结果。
上下文工程的核心挑战是窗口有限。模型能处理的token数是有上限的,虽然现在动辄128K甚至1M,但塞得越多推理越慢、成本越高,而且中间内容容易被“遗忘”。所以需要做上下文压缩、摘要、优先级排序。
LLM的token机制可以用三个点来理解:Key是“我是谁”,Query是“我在找什么”,Value是“我能提供什么”。注意力机制就是拿Query去匹配所有Key,然后加权求和Value。理解这个机制,你就知道为什么上下文里重要的信息要放在开头或结尾,因为中间位置容易被忽略。
4.3 LLM as Judge:用模型评估模型
当你有多个模型或多个提示词方案时,怎么选?人工评估太慢,自动指标又不准。LLM as Judge是一个实用方案:用一个能力强的模型来给其他模型的输出打分。
具体做法是设计一个评分提示词,包含评分标准、待评输出、参考输出,让Judge模型给出分数和理由。注意几点:Judge模型的能力要明显强于被评模型;评分标准要具体可操作;最好做位置交换消除顺序偏差。
这个方案不是完美的,Judge模型也有偏见,但在快速迭代阶段非常有用。
5. Agent:让大模型自己干活
5.1 Agent到底是什么
Agent这个词被用得很泛,但核心定义很简单:一个能感知环境、做出决策、执行动作、并根据反馈调整的智能体。在大模型语境下,Agent就是让LLM不只是回答问题,而是能规划步骤、调用工具、多轮执行直到完成任务。
举个例子:你让普通LLM“帮我查一下明天北京的天气然后提醒我带伞”,它只能告诉你“我无法查询实时天气”。但Agent可以:第一步调用天气API查询,第二步判断是否下雨,第三步调用日历API设置提醒。这就是区别。
Agent和Harness的区别经常被问到。简单说,Harness是Agent的运行框架和基础设施,负责管理工具注册、消息路由、状态维护、错误处理。Agent是运行在Harness上的具体智能逻辑。打个比方,Harness是操作系统,Agent是运行在上面的应用程序。
5.2 Agent的核心组件与开发框架
一个完整的Agent通常包含:
- 规划模块:把大任务拆成小步骤。常用ReAct、Plan-and-Execute等模式。
- 工具集:可调用的外部函数,如搜索、计算、API调用。
- 记忆模块:短期记忆存对话历史,长期记忆存向量数据库。
- 执行引擎:按规划逐步执行,处理工具返回结果。
- 反思模块:检查执行结果,失败时重试或调整计划。
主流Agent框架有LangChain、LlamaIndex、AutoGen、CrewAI等。吴恩达的Agent教程里推荐从简单模式开始:先做单Agent加工具调用,再考虑多Agent协作。多Agent虽然听起来酷,但调试复杂、成本高,很多场景单Agent就够了。
5.3 Agent怎么扛并发:工程化落地的关键
Agent从Demo到生产,最大的坎就是并发。一个Agent请求可能涉及多次LLM调用和工具调用,耗时几秒到几十秒。如果每个请求都占一个线程,并发量一上来就崩了。
扛并发的核心思路:
异步化:用asyncio或类似机制,LLM调用和工具调用都是IO密集型的,异步可以大幅提升吞吐。
队列与限流:请求进队列,按模型API的速率限制消费。避免打爆上游。
缓存:相同或相似的查询结果缓存起来。工具调用结果、LLM输出都可以缓存。
状态外置:Agent的会话状态存Redis等外部存储,服务实例无状态,方便水平扩展。
超时与降级:每个步骤设超时,失败时走降级逻辑,不要让一个慢请求拖垮整个系统。
批处理:多个请求的LLM调用可以合并成batch,提高GPU利用率。
实测下来,一个设计良好的Agent服务在单张A100上可以支撑几十到上百QPS,具体取决于任务复杂度和模型大小。关键是把异步和缓存做扎实。
避坑提醒:Agent的循环调用很容易失控。一定要设最大步数限制和总超时,否则模型可能陷入死循环,烧钱又烧时间。
6. 常见问题与排查技巧实录
6.1 微调与部署高频问题速查
| 问题 | 可能原因 | 排查方向 |
|---|---|---|
| 微调后模型输出重复 | 学习率过高、数据质量差 | 降低学习率,清洗数据 |
| 显存OOM | batch size太大、精度太高 | 减小batch,用QLoRA,开梯度检查点 |
| 推理速度慢 | 模型太大、未量化 | 用量化版本,开vLLM等推理加速 |
| Agent工具调用失败 | 工具描述不清、参数格式错 | 优化工具schema,加few-shot示例 |
| 上下文超长 | 检索内容太多 | 做摘要压缩,限制检索条数 |
| 模型胡编乱造 | 知识不足、提示词不明确 | 加RAG,明确要求“不知道就说不知道” |
6.2 独家避坑经验
数据质量比数量重要。我试过用一万条低质量数据微调,效果不如一千条精标数据。微调数据要多样、准确、格式统一。重复数据会导致模型过拟合,噪声数据会教坏模型。
先跑通再优化。不要一上来就追求最优参数。先用小数据、小模型跑通全流程,确认没问题再放大。我见过太多人卡在环境配置上就放弃了。
版本管理要严格。模型权重、训练数据、配置文件、评估结果都要版本化。不然过两周你都不知道哪个模型是哪个数据训出来的。
评估要自动化。人工看输出太慢,建一个自动评估流水线,每次微调后自动跑测试集,看指标变化。LLM as Judge在这里很好用。
Agent的工具要幂等。工具可能被重复调用,设计时要保证多次调用结果一致。比如“查询余额”是幂等的,“转账”不是,后者需要加去重机制。
本地部署大模型让个人电脑智能化是很多人的入门项目。用Ollama或llama.cpp在本地跑量化模型,配合简单的Agent框架,就能做一个离线可用的智能助手。虽然能力不如云端大模型,但隐私好、无成本、可定制。
这个领域变化很快,今天的最佳实践明天可能就过时了。但底层原理和工程思路是相对稳定的。把预训练、微调、提示工程、Agent这条链路理解清楚,新东西出来你也能快速判断它处在哪个位置、解决什么问题。我在实际项目中最深的体会是:不要追新,要追深。把一个环节吃透,比每个环节都浅尝辄止有价值得多。