经常有人带着“大模型系统入门”这个需求来找我:想转行做LLM应用开发的、运维想搞私有化部署的、学生手里只有一张4GB显存旧显卡的。大家要的东西其实高度一致,不是某一个单一教程,而是一条能把“原理、部署、微调、应用”串起来的完整链路。这篇内容就是我自己带新人时反复用的那套大模型学习路线,顺着走,能少踩很多我当年踩过的坑。
我先说结论:大模型入门最大的障碍不是数学,也不是论文,而是没有主线。今天这篇文章会把主线铺开,从底层原理讲到工具选型,从本地部署讲到LoRA微调,从提示词工程讲到Agent和SSE流式输出,最后还整理了高频问题排查表。你不需要一次读完,但建议按章节顺序动手做一遍。
1. 先画地图:大模型的系统性学习路线长什么样
1.1 一套三层结构的知识体系
我习惯把大模型的技能树拆成三层,对应不同阶段的学习重点:
| 层级 | 核心内容 | 典型工具/关键词 | 入门目标 |
|---|---|---|---|
| 理论层 | Transformer、Token、注意力机制、预训练、对齐 | LLM、多模态、上下文窗口 | 能解释模型为什么能生成文字 |
| 部署层 | 模型下载、量化、显存估算、推理服务 | GGUF、Ollama、llama.cpp、vLLM、CUDA | 能让模型在自己机器上跑起来 |
| 应用层 | 提示词工程、上下文工程、微调、Agent、工具调用 | LoRA、RAG、SSE、Function Calling | 能做出可用的产品原型 |
三层不是割裂的。理论层决定你遇到问题时的判断力,部署层决定你能不能在有限硬件下跑起来,应用层决定模型到底能解决什么实际问题。很多人的学习路线只盯着第一层,天天啃注意力公式,结果连7B模型要占多少显存都不知道;也有人直接从第三层开始,天天调API,换成本地模型就懵了。
我建议的次序是:先建立理论层的基本框架,立刻进入部署层做一次完整实战,再回到应用层做微调和Agent开发。每层都不需要深挖到极致,但必须亲手跑通闭环。
1.2 为什么多数人学到一半就卡住
上面三层看似简单,实际操作时绝大多数人卡在同一个地方:没有目标感。收藏夹里存了一堆教程,今天看一篇“Transformer通俗理解”,明天看一篇“LLM微调实战”,后天又刷到一个“本地部署教程”,每篇都懂一点,串不起来。
我自己当年也是这样,直到后来带人才想明白:系统入门必须有一个“总任务”。我的建议是——目标定为“在一台普通电脑上跑通一个7B开源模型,并对它做一次行业微调,最后封装成一个带网页聊天的服务”。这个任务同时覆盖部署层、微调层和应用层,每一步遇到的问题都会逼着你回去补对应的知识。这也是这篇文章的主线。
另外要提醒一句:收藏不等于学会。我见过太多人收藏了几百篇资料,动手时连虚拟环境都不会建。资料的作用是“按需查阅”,不是“囤积”。下面进入正题。
2. 底层逻辑:大模型为什么“大”
2.1 Transformer、Token与上下文窗口
大模型的核心是一个叫Transformer的神经网络结构,它做的事情可以简化为“猜下一个词”。你给它一句话“今天天气”,它预测下一个词可能是“不错”还是“很好”,生成一个词后再拼回去继续猜,于是一段话就像打字机一样被吐出来。
输入的文字会先被切成Token。一个Token可能是半个词、一个完整的词,甚至是一个标点符号。比如“大模型真有趣”可能被切成“大模型”、“真”、“有趣”三到四个Token。切分的规则取决于分词器,中文模型和英文模型用了不同策略。这直接关系到一个重要指标:上下文窗口。
上下文窗口是指模型一次能“看到”的最大Token数量。Qwen2.5-7B的上下文长度通常是32K,这看起来很大,但你要知道,过长的历史对话、贴进去的代码、RAG检索回来的文档片段都会占用窗口。窗口塞满后,最早的内容会被“忘掉”。这也是实际开发中最常见的问题来源之一。
参数规模也好理解:7B代表70亿参数,70B代表700亿参数。参数量大,模型容量大,学到的模式也更丰富,但显存占用和推理延迟都会直线上升。入门阶段别一味追求大模型,先掌握小模型全链路,再来考虑规模扩展。
2.2 预训练、指令微调与对齐:三步养成一个会聊天的模型
我一直用“读书”和“做人”来打比方。预训练阶段就像让模型读了海量书籍,学到语言的统计规律,但它这时候只会“续写”,不会回答问题。你给它“中国的首都是”,它能接上“北京”,但你让它写一篇周报,它只会茫然地继续写流水账。
指令微调(SFT)就是教会它“听指令干活”。我们会准备几千到几万条指令-回答对,比如“你是客服,请回复以下用户投诉”,让模型学会按照指令格式输出。这一步是行业微调的关键,也是后文LoRA实战的焦点。
对齐阶段(比如RLHF)则是教模型“做人”——什么话该说、什么话不该说、怎么拒绝不合理请求、怎么表达得更符合人类偏好。对齐不是万能的,它只能降低坏输出的概率,不能彻底消除。这也是后面第7章要讲判别器和投毒测试的原因。
2.3 世界有哪些知名的大模型,入门阶段关注哪些
聊到具体选型,我在教学中从不建议新手盯着榜单第一去追。2025年前后,闭源阵营里GPT-4o、Claude、Gemini是绕不开的名字;开源阵营里有Llama、Qwen、DeepSeek、GLM等。作为入门,我更推荐从开源中文生态入手,尤其是Qwen系列。
理由很简单:中文效果好、社区资料多、模型权重在HuggingFace和ModelScope都能直接下,而且从1.5B到72B各种尺寸都有,适配不同显存。DeepSeek也很香,技术报告写得很勤奋,适合进阶时拆解。Llama的英文能力依然是开源标杆,多模态可以看Qwen-VL这类模型。
闭源模型适合做产品验证和集成测试,开源模型适合学习原理和本地化改造。这两个不是二选一,是一条路上都要用的工具。
3. 工具链选型:推理和部署的常用组合
3.1 Ollama、llama.cpp、vLLM:三套工具的适用场景
很多教程一上来就让你装这个装那个,但没说清楚每个工具解决什么问题。我按场景给你分个类:
| 工具 | 适用场景 | 特点 | 学习成本 |
|---|---|---|---|
| Ollama | 个人电脑、新手体验、快速原形 | 一行命令跑模型,自带API和CLI | 极低 |
| llama.cpp | CPU/低成本设备、嵌入式、移动端 | 纯C++实现,支持GGUF量化,CPU也能跑 | 中等 |
| vLLM | 生产环境、高并发、多用户推理服务 | 显存管理优秀,continuous batching提升吞吐 | 偏高 |
| AirLLM | 极小显存跑超大模型 | 让模型层在CPU/GPU之间换入换出,很慢 | 中等 |
入门我建议先装Ollama,10分钟就能体验ChatGPT本地版。等你想深入研究推理性能、接口兼容性,再转到vLLM。llama.cpp适合研究量化原理,以及做Android端集成——比如你想把GGUF模型塞进App,llama.cpp的Android库就是常见选择。AirLLM这类方案能用极低显存跑大模型,比如6GB显存跑70B,但推理速度很感人,只适合“能不能跑起来”的验证,不适合生产。
3.2 量化与GGUF:小显存跑大模型的关键
量化是把模型权重从高精度降到低精度。模型权重默认是FP16,即每个参数占2字节。你的7B模型FP16权重就要占14GB。转成INT8后占7GB,转成INT4后大概4.5GB。价格是模型变“笨”一点,但这个损失在很多场景下完全可接受。
GGUF是llama.cpp社区设计的量化模型格式,它能把权重、分词器、超参数打包成一个文件,还支持CPU/GPU混合推理。现在Ollama、llama.cpp、以及很多推理框架都原生支持GGUF。你从模型平台下载到的后缀为.gguf的文件,就是这种格式。
说到Android集成AI大模型,很多人问GGUF能不能塞进手机App。答案是能。你可以在Android端用llama.cpp的封装库加载GGUF模型,通过JNI调用推理,再把文字流式返回给UI。整体流程就是“下载GGUF文件 + 加载模型 + 调用生成接口”,复杂度主要集中在进程管理和内存优化上。
3.3 显卡驱动模式:TCC还是WDDM
这个知识点在普通教程里几乎看不到,但实际部署时非常关键。Windows下NVIDIA显卡有两种驱动模式:WDDM(Windows Display Driver Model)和TCC(Tesla Compute Cluster)。
WDDM是普通显卡和笔记本常用的模式,它能同时承担显示和计算;TCC则是专门为计算卡设计的模式,绕开图形子系统的开销,让CUDA直接管理显存,远程桌面时不渲染桌面内容,显存占用更稳,长时间运行推理任务更可靠。
选择逻辑很简单:如果你用的是专业计算卡或数据中心卡,而且机器不需要用这张卡接显示器,就把它切成TCC。普通游戏卡和笔记本显卡不支持TCC,强行切换会报错。
切换方法:管理员权限打开命令提示符,执行nvidia-smi -gpu 0 -cc 1切换到TCC,nvidia-smi -gpu 0 -cc 0切回WDDM,重启后生效。切之前记得确认GPU编号,别切错卡。
4. 本地部署实战:从下载模型到跑通对话
4.1 模型下载:HuggingFace、ModelScope与Ollama Registry
部署本地模型的第一步是下载权重。最常见的三个入口:
- HuggingFace:全球最大的模型社区,资源最全,但国内访问速度可能不稳定。
- ModelScope:阿里开源的模型平台,中文生态好,下载速度快,适合日常使用。
- Ollama Registry:Ollama自带的模型库,执行一条命令就能自动拉取GGUF模型。
如果你用Ollama,部署体验是非常顺滑的。安装Ollama后,打开终端执行:
ollama run qwen2.5:7b它会自动下载Qwen2.5-7B的量化版本并启动对话。跑通之后,Ollama还会在本机暴露一个HTTP API,默认地址是http://localhost:11434,可以直接用OpenAI兼容接口调用。这也是我最推荐新手做的第一个实操作业。
如果你要部署Hermes这类社区微调模型,先用模型平台搜索“Hermes gguf”,下载到本地后修改Ollama的Modelfile指向该文件即可。Windows 11下操作逻辑完全一致,无需特殊配置。
4.2 显存估算、并发与上下文长度配置
跑通之后你要学会算显存,不然开个生产服务必挂。核心公式如下:
- FP16权重 = 参数量 × 2字节
- INT8权重 = 参数量 × 1字节
- INT4权重 = 参数量 × 0.5字节
- KV Cache(缓存KV,占显存的另一个大头)和推理临时缓冲另算。
举例,7B模型FP16权重约14GB,INT8约7GB,INT4约4.5GB。如果你的显卡是8GB显存,想跑Qwen2.5-7B,选INT4量化模型,再把上下文长度限制在4K以内,基本能转得动。想留更多空间,就换1.5B或3B的小模型。
生产环境用vLLM时,关键参数有三个:
vllm serve Qwen/Qwen2.5-7B-Instruct \ --gpu-memory-utilization 0.9 \ --max-model-len 8192 \ --served-model-name qwen-chat--gpu-memory-utilization 0.9的意思是允许vLLM占用90%显存,给其他进程留点余地;--max-model-len 8192限制了模型窗口长度,防止偶发超长请求把显存打爆;--served-model-name是给服务起一个对外暴露的模型名,客户端调用时用这个名字。启动后,服务默认监听8000端口,提供一个OpenAI兼容的/v1/chat/completions接口。
4.3 给本地模型装一个“联网搜索”能力
很多人跑通本地模型后第一句话就是:“它只能聊训练时见过的知识,新的消息一概不知。”想解决这个问题,核心思路是工具调用(Function Calling)。原理很简单:模型不直接联网,而是“决定”调用你的搜索函数,你执行搜索后把结果塞回给模型,它基于结果生成回答。
我用一段示意代码说明整体流程:
tool = { "type": "function", "function": { "name": "web_search", "description": "搜索互联网获取最新信息", "parameters": { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"] } } } def chat_with_tools(user_input): messages = [{"role": "user", "content": user_input}] resp = client.chat.completions.create( model="qwen2.5:7b", messages=messages, tools=[tool] ) msg = resp.choices[0].message if msg.tool_calls: query = eval(msg.tool_calls[0].function.arguments)["query"] search_result = run_web_search(query) # 这里换成你的搜索实现 messages.append(msg) messages.append({"role": "tool", "content": search_result}) resp = client.chat.completions.create( model="qwen2.5:7b", messages=messages ) return resp.choices[0].message.content注意,这里的client是支持OpenAI兼容接口的SDK。你可以在本地用vLLM或Ollama起的服务,把base_url改为本地地址,api_key随便填一个占位符即可。run_web_search可以去接搜索服务的API,也可以直接写一个调用公开搜索接口的小函数,效果非常直观。
另外提一句,本地大模型让个人电脑智能化的玩法远不止联网搜索。你还可以把它接入文件管理、邮件读写、日程安排的脚本,相当于把一个能“理解自然语言”的调度器装进了自己的电脑。核心组件就是“模型 + 工具调用 + 你的业务逻辑”。
5. 微调实战:训练一个懂行业的大模型
5.1 为什么首选LoRA和QLoRA
部署只解决“让模型跑起来”的问题,要让模型“懂你的行业”,就需要微调。全量微调需要极高的算力和显存,7B模型的全参微调一块24GB的卡都很难跑得舒服。实际项目中,LoRA是首选方案。
LoRA的原理可以简化理解为:不训整个模型,只训练一小部分低秩矩阵,相当于在原模型的权重旁边加了一条“旁路适配器”。训练时只更新适配器的参数,适配器参数往往只有原模型的1%甚至更低。训练完只把这个小文件保存下来,部署时叠加到原模型上就能生效。
QLoRA是在LoRA基础上进一步抠显存的做法:基座模型先量化到4BIT,再挂LoRA训练。它能把7B模型的微调显存压到10GB以下,这对个人开发者的意义非常大。我做过多次测试,QLoRA微调后的模型在行业术语完整性上提升明显,日常对话能力损失可以接受。
5.2 从Qwen2.5-7B到行业模型的全流程
接下来我用Qwen2.5-7B-Instruct作为基座,演示一个“行业微调”的最小闭环。整个流程包括:环境配置、数据准备、微调、部署、效果展示。
先准备数据。微调用的标准格式是JSONL,每一行是一个样本,常见结构如下:
{"instruction": "根据合同条款,判断违约金比例是否合理,并给出解释。", "output": "本合同约定违约金为合同总额的20%。根据行业惯例,该比例属于合理范围,理由如下……"}英文社区常见的ShareGPT格式是带对话历史的数组结构,但入门阶段先用“指令+输出”两字段格式就够。数据量不需要贪多,几千条高质量样本效果远好于几万条低质量样本。
微调代码用transformers + peft + trl这套组合即可。我常用的SFT训练配置大致如下:
from peft import LoraConfig from trl import SFTTrainer, SFTConfig from datasets import load_dataset model_path = "Qwen/Qwen2.5-7B-Instruct" dataset = load_dataset("json", data_files="industry_data.jsonl", split="train") lora_config = LoraConfig( r=16, lora_alpha=32, lora_dropout=0.05, target_modules=[ "q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj" ], task_type="CAUSAL_LM" ) trainer = SFTTrainer( model=model_path, args=SFTConfig( output_dir="./qwen-industry-checkpoint", per_device_train_batch_size=1, gradient_accumulation_steps=8, max_seq_length=2048, logging_steps=20, save_steps=200, num_train_epochs=1 ), train_dataset=dataset, peft_config=lora_config ) trainer.train()几个关键参数我展开解释:target_modules指定LoRA作用于哪些层,Qwen系列的通用做法是把注意力层和MLP层的线性投影都加上,r是低秩矩阵的秩,r=16是常用起点,显存紧张就降到8;max_seq_length一定要和你的数据长度匹配,不要盲目设置成8192,否则显存浪费很大;gradient_accumulation_steps用来模拟更大的batch size,不是每个batch都有那样大的显存压力。
训练完成后,用merge_and_unload()把LoRA权重合并回模型,然后存成完整权重。这样就能用Ollama或vLLM直接加载微调后的模型,整体效果和基座的差异可以通过实测对话来感受。比如微调一个“合同审核助手”后,让它看一段合同文本,模型会主动引用条款原文并给出结构化意见,而不是像基座模型那样泛泛而谈。
5.3 过拟合与灾难性遗忘怎么躲
行业微调最常见的两个坑,一个是过拟合,一个是灾难性遗忘。
过拟合的表现是:训练集上的损失降得很低,但实际对话一开口就是“背题”,几乎复读训练样本,没有泛化能力。应对方法很简单:控制训练轮数,7B模型配上几千条数据,1个epoch通常足够;学习率别拉太高,1e-4到2e-4是常见区间;训练集里多做去重,不要放50条几乎一模一样的样本。
灾难性遗忘的表现是:模型学会了行业知识,但“性格”变了,逻辑推理变差,常识问答也退化。这不是模型坏了,而是微调时只喂了垂直领域的样本,把通用知识挤掉了。我常用的缓解办法是在训练数据里掺入20%-30%的通用对话数据,来自开源SFT数据集即可,让模型在适应行业任务的同时不忘掉“说人话”。
还有一个小技巧:在指令微调时,把行业样本的指令写得多样化一些。比如同样一个“判断违约金是否合理”的问题,换成三种不同的问法和场景,模型学到的就不只是一个机械映射,而是一种可以迁移的能力。
6. 应用开发:从提示词工程到智能体与流式交互
6.1 提示词工程与上下文工程
等模型跑通、微调完成,你就要开始琢磨怎么让模型输出符合预期。这里有两个容易被混为一谈的概念:提示词工程和上下文工程。
提示词工程关注“怎么问”,核心是角色设定、任务拆解、输出格式约束和思维链引导。比如你要模型看股票K线图写分析,直接问“分析这几天的走势”,模型只会泛泛而谈;换成“请你以技术分析师身份,结合MACD和RSI指标,用3个要点分析最近20根日K线是否有顶背离信号”,输出质量立刻不一样。模型本身不擅长精确计算,你把指标值算好放进提示词,它就能做判断。
上下文工程关注“给它什么”。模型记不住你的业务数据,你需要把检索到的资料、历史记录、知识片段组织成合适的上下文喂给它。RAG就是上下文工程的典型实现:先用向量检索把相关文档找出来,再拼接到提示词里。上下文窗口有限,塞太多不相关的内容反而会干扰回答,所以要做摘要、压缩和去重。
有博主开玩笑说现在的提示词岗位应该改叫“上下文工程师”,我觉得有一定道理。做PPT、写邮件、做旅游推荐这类办公场景,选多模态和工具调用能力强的模型往往体验更好,因为它能看文件截图、查地图、搜攻略,模型本身的能力只是底座,上下文组织方式才是决定体验的关键。
6.2 Agent框架、工具调用和多模态
模型再聪明,不接工具也只能在文本世界里打转。智能体(Agent)的核心是让模型学会“规划 + 调用工具 + 观察结果 + 再规划”的循环。
目前主流的Agent框架有:LangChain、LlamaIndex、AutoGen、MetaGPT等。LangChain生态最全,适合快速集成搜索、数据库、代码执行器等;AutoGen擅长多智能体协作,比如让一个“规划者”和一个“执行者”互相配合;MetaGPT则把智能体拆成产品经理、架构师、工程师等角色,适合生成复杂项目文档。
在复现社区玩法的过程中,很多人会尝试把Codex CLI这类编程助手接入自己的大模型服务。实现的本质就是OpenAI兼容接口的替换:把默认的模型地址改成你本地vLLM的服务地址,把模型名改成你微调后的模型名,Codex CLI就能用你自己的模型做代码补全和修改。这个配置过程非常值得做一次,能帮你把“模型只是API”这个概念落地成自己的东西。
多模态是这几年最明显的趋势。从Qwen-VL这类开源视觉模型可以看出,大模型不再只是处理文字,还能看图、读表格,甚至理解视频。多模态模型在内部把图像切成Patch当成“视觉Token”,与文字Token混在一起过Transformer,原理上并没有跳出“猜下一个Token”的框架。入门没必要被多模态吓住,把它当成输入格式更丰富的大模型即可。
旅游推荐就是智能体一个很好的实战场景。“帮我规划南京三天两夜行程”这种问题,模型需要同时调用地图搜索、景点信息、天气接口,再根据用户预算生成结构化行程单。没有工具调用能力时,模型只能“编”;有了工具调用能力,它至少能保证推荐景点的真实存在。
6.3 SSE流式输出:让回答像打字机一样逐字渲染
部署完模型后,你会发现长回答要等好几秒甚至几十秒,用户根本等不了。解决方式是流式输出,让Token一边生成一边送到前端,这就是大家熟知的“打字机效果”。
从前后端技术栈的角度,我强烈推荐用SSE(Server-Sent Events)而不是WebSocket。大模型对话本质上是服务器向客户端单向推送Token流,SSE基于普通HTTP协议,天然适合这种场景,断线还能自动重连,而且不用额外维护一个长连接协议栈。
后端用FastAPI实现很简洁:
from fastapi import FastAPI from fastapi.responses import StreamingResponse import json app = FastAPI() async def event_generator(prompt: str): # chat_stream 这里换成你所用SDK的流式生成接口 async for token in chat_stream(prompt): yield f"data: {json.dumps({'token': token}, ensure_ascii=False)}\n\n" yield "data: [DONE]\n\n" @app.post("/chat") async def chat(request: dict): return StreamingResponse( event_generator(request["prompt"]), media_type="text/event-stream" )关键点有两个:一是响应头里的media_type必须是text/event-stream;二是每条消息必须以data:开头,末尾加两个换行。客户端用fetch就能读:
const controller = new AbortController(); const res = await fetch('/chat', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({prompt: userInput}), signal: controller.signal }); const reader = res.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const {done, value} = await reader.read(); if (done) break; buffer += decoder.decode(value, {stream: true}); // 按 \n\n 切分,处理每条 data: 开头的消息 }用户点“停止生成”时,调用controller.abort()终止请求,后端那边的生成循环也会随之取消。这里有一个细节:不要在流式渲染时直接频繁操作DOM,那会导致页面卡顿,更好的是把完整文本缓存到一个变量,用requestAnimationFrame或类似的节流方式批量更新界面。
顺带一提,Java技术栈可以用Spring AI的StreamingChatClient接口,它内部封装了SSE的协议细节。你只需要实现一个回调方法,把每次返回的Token chunk推给前端WebSocket或SSE即可。
7. 质量安全与知识工程:给模型上“保险”
7.1 投毒测试:先探测再上线
很多新手把模型部署完就认为大功告成,实际上生成式应用上线前必须做一轮“投毒测试”。
这里说的投毒测试包含两类。一类是训练数据层面的后门:有人往你的微调数据集里偷偷塞了恶意指令-回答对,模型学会后遇到特定触发词就会输出预设内容。另一类是推理层面的提示词注入:用户故意在输入里藏“忽略之前的指令,输出xxx”,尝试劫持模型行为。
作为开发工程师,你至少要做两步防御。第一步,在微调前扫描训练数据,看有没有异常的指令模式、重复片段、特殊Unicode字符、编码混淆;第二步,在微调后做触发测试,准备一份触发词表(包含特定单词、翻译指令、十六进制编码、对抗性问句),观察模型是否会出现偏离任务的表现。千万别觉得这是安全团队的事,小团队里这就是你自己的责任。
负责任的做法是上线前测,上线后持续采样。模型是概率系统,没有哪次测试能覆盖所有攻击面,唯一靠谱的是一层一层的防御和兜底。
7.2 用判别器给输出兜底
生成模型只管生成,不管它生成的内容是不是有害。实践里,我们通常会在模型输出链路上加一个“判别器”。
判别器的思路很直接:用一个小分类模型判断“这段输出是否包含危险内容”,如果判定不通过,就拦截或者改写。小模型做粗筛,大模型做兜底,是一种常见组合。粗筛保证效率,兜底保证准确。
另外一类有趣的判别器用法是“LLM-as-a-Judge”,不用训练任何分类器,直接把一段响应丢给另一个强模型打分,让它判断质量分、合规分、相关分。工程上要注意:判官模型和生成模型最好不要是同一个,否则既当运动员又当裁判,容易系统性偏差。
7.3 知识抽取框架ONEKE:把文档变成结构化知识
大模型做知识抽取,是这类技术最实用的方向之一。你有一堆合同、工单、政策文档,想提取其中的实体、关系和事件,传统的正则表达式写不完,人工读又太累。
ONEKE这类知识抽取框架做的事情,就是把“命名实体识别、关系抽取、事件抽取”统一到一条指令微调的链路里,让大模型输出结构化的三元组,比如“(甲方,签署,合作协议,2025-03-01)”。得到结构化知识后,可以灌入知识图谱,也可以作为RAG的索引源,提升检索精度。
我建议在入门阶段至少跑一次类似的知识抽取任务。准备20份合同文档,让大模型提取“签约方、金额、期限、违约条款”,评估输出中的漏提和误提,再对比正则方案的效果差异。做完这个实验,你对“大模型不只是聊天机器人”这句话会有非常直观的感受。
8. 高频问题排查:我踩过的坑和应对方法
8.1 常见问题速查表
最后把我在实践中踩过的高频问题整理成一张速查表,方便你对照排查:
| 问题现象 | 常见原因 | 处理思路 |
|---|---|---|
| Ollama跑模型时GPU利用率很低 | 没有安装GPU版驱动或CUDA运行库 | 检查驱动版本,卸载重装;确认安装的是GPU版Ollama |
| 启动推理几秒后直接被系统kill | 显存溢出,进程被OOM机制杀掉 | 换INT4量化、缩小上下文长度、关闭桌面程序释放显存 |
| 生成速度越来越慢 | 上下文被填充,KV Cache显存压力增大 | 限制max length;生产环境换vLLM |
| 微调loss剧烈波动不下降 | 学习率过高或数据质量差 | 学习率降到1e-4以下;清洗数据、去除重复样本 |
| 长文档对话总说“想不起来” | 上下文被截断,模型看不到早期内容 | 用RAG分段检索,或升级到更长上下文的模型 |
| 量化后回答质量显著下降 | INT4精度损失在敏感任务上被放大 | 换INT8;或在关键任务上用全精度模型,普通任务用量化模型 |
| SSE流式中文乱码 | 前端TextDecoder没有用UTF-8解码 | 显式声明new TextDecoder('utf-8') |
| 多轮对话答非所问 | 没有正确维护历史消息列表 | 把历史消息按角色拼装到messages数组,注意超长时做截断 |
这四条里的前两条几乎是每个本地部署新手都会遇到的。我自己的习惯是部署前先跑nvidia-smi确认显存余量,再算一遍模型权重占多少、KV Cache大概会占多少,最后再决定用哪个量化级别。别高估显卡,也别把上下文设置得过于夸张。
8.2 排错方法论:先隔离变量,再动手改
排查生成式应用的问题,我有一条铁律:一次只改一个变量。这个习惯能救你无数次。
模型不回复,先看是网络问题、API调用问题还是模型推理问题。最简单的方式是直接到终端跑一次模型对话,如果终端能回复,说明问题出在后端封装或前端调用;终端也不能回复,再去看显存、日志和模型文件是否完整。很多人遇到问题就重装环境,装到一半发现之前的问题还复现,纯粹是浪费一个下午。
再举一个例子:同样的提示词,昨天正常今天胡言乱语。先别怀疑模型变笨,先确认是不是上下文被别的请求污染了,或者服务端的随机采样参数(temperature)被改高了。把temperature固定下来,很多“幻觉”问题会立刻可控。对入门者来说,把系统提示词、历史消息、采样参数全部打日志,比任何花哨的调试工具都实用。
还有一点要强调:日志不是给别人看的,是给自己排查用的。哪怕只是个人项目,我也建议把每次请求的“模型名、上下文长度、耗时、首Token延迟”记录下来。时间长了,你会比任何人都了解你的模型服务。
我最近带人做本地部署,发现最有成就感的一刻不是模型跑通了,而是看到一个学生自己排查出OOM,然后回头去重算显存,最后换了一套量化方案把模型救了回来。这个时刻说明他真正建立了“系统认知”——他不再依赖教程里的命令,而是自己成了那个能解决问题的人。大模型入门最值钱的东西,就是这个能力。希望这份资料,能帮你早点走到这一步。