1. 从零上手LLM:先搞清楚你手里拿的是什么牌
很多人第一次接触LLM,脑子里蹦出来的第一个问题就是“我该用哪个模型”。这个问题本身没错,但顺序搞反了。你得先弄明白自己到底要解决什么问题,再去挑模型,而不是反过来。我见过太多人一上来就盯着排行榜,哪个分数高就用哪个,结果跑起来发现要么成本扛不住,要么延迟高得没法用,要么根本不适合自己的业务场景。
LLM,也就是大语言模型,本质上是一个“基于海量文本训练出来的概率预测机器”。你给它一段输入,它根据训练时学到的模式,一个token一个token地往外吐输出。听起来简单,但真正用起来,里面的门道比你想象的多得多。这篇文章面向的是那些已经决定要把LLM用在实际项目里的人——不管你是做应用开发、数据分析、自动化流程,还是想在自己的产品里嵌入智能对话能力,下面这些内容都能帮你少走弯路。
我自己的经验是,LLM的使用可以拆成四个层次:选型与接入、提示词工程、应用架构设计、以及运维与调优。这四个层次不是孤立的,而是层层递进的。很多人只关注第一层,觉得“能跑通API就行了”,结果到了第二层发现输出不稳定,到了第三层发现架构撑不住,到了第四层发现成本失控。所以咱们从头开始,一层一层往下拆。
2. 模型选型与接入:别被排行榜牵着鼻子走
2.1 闭源API还是本地部署,先算三笔账
选模型的第一道分叉路口就是:用云端API,还是本地部署开源模型?这个问题没有标准答案,但你可以通过算三笔账来快速判断。
第一笔账是成本账。云端API按token计费,输入和输出的单价通常不一样。以目前主流的价格区间来看,输出token的单价往往是输入token的2到4倍。如果你的应用是“长输入短输出”型,比如文档摘要、信息抽取,那API的成本其实相当可控。但如果是“短输入长输出”型,比如创意写作、代码生成,那成本会迅速攀升。本地部署呢?前期硬件投入是大头,但边际成本几乎为零。如果你每天的调用量足够大,本地部署的摊薄成本会远低于API。
第二笔账是延迟账。API的延迟取决于网络状况和服务商的负载,通常在几百毫秒到几秒之间波动。本地部署的延迟则取决于你的硬件配置,GPU显存带宽和算力直接决定了推理速度。如果你做的是实时交互类应用,延迟超过2秒用户就会明显感到卡顿。这种情况下,本地部署一个小参数量的模型,往往比调用远端大模型体验更好。
第三笔账是数据账。这个不用展开说,涉及敏感数据的场景,本地部署是唯一选择。但我要提醒一句:本地部署不等于绝对安全,模型本身、推理框架、日志系统都可能成为泄露点,这个后面会细说。
2.2 参数量的选择:7B、13B还是70B
参数量是模型能力的一个粗略指标,但不是唯一指标。7B级别的模型,在消费级显卡上就能跑起来,适合做分类、抽取、简单对话这类任务。13B级别是一个甜点区,能力明显上一个台阶,对硬件的要求又不算离谱。70B级别的模型,能力接近顶级闭源模型,但需要多卡并行或者大显存的专业卡才能跑得动。
这里有个常见的误区:很多人觉得参数量越大越好,实际上不是。一个经过良好指令微调的7B模型,在特定任务上完全可以吊打一个没调好的13B模型。而且参数量越大,推理速度越慢,显存占用越高。我个人的建议是:从小的开始试,不够用再往上加。先用7B跑通整个流程,确认提示词和架构没问题了,再考虑换更大的模型来提升效果。这样你的调试周期会短很多。
2.3 量化:让大模型跑在小硬件上的关键手段
量化是本地部署绕不开的话题。简单说,量化就是把模型权重从高精度浮点数(比如FP16)转换成低精度格式(比如INT8、INT4),从而大幅减少显存占用和计算量。代价是精度损失,但只要量化方法得当,损失通常很小。
目前主流的量化方案有GPTQ、AWQ、GGUF等。GGUF格式特别适合在消费级硬件上运行,因为它支持CPU和GPU混合推理,甚至可以在纯CPU上跑。如果你用的是安卓设备,GGUF也是目前最成熟的本地运行方案之一。量化等级方面,Q4_K_M是一个比较均衡的选择,显存占用大约是FP16的四分之一,效果损失在可接受范围内。如果硬件实在紧张,可以降到Q3或Q2,但效果下降会比较明显,需要自己权衡。
注意:量化后的模型在数学推理和代码生成任务上容易出现更明显的性能下降,如果你的应用场景对这两类任务要求高,建议至少用Q5以上的量化等级,或者干脆用FP16。
3. 提示词工程:把模型当人看,但别当聪明人看
3.1 提示词的基本结构:角色、任务、约束、示例
提示词工程不是什么玄学,它本质上是一种“用自然语言编程”的方式。一个好的提示词,通常包含四个部分:角色设定、任务描述、约束条件、输出示例。
角色设定是告诉模型“你是谁”。比如“你是一个资深的法律文书助手”,这会让模型在生成时偏向使用法律领域的表达习惯。任务描述是告诉模型“你要做什么”,要具体、明确,避免模糊词汇。约束条件是告诉模型“你不能做什么”,比如“不要编造不存在的法条”、“输出不超过200字”。输出示例是给模型一个参照,让它知道你想要什么格式的结果。
我试过很多次,发现一个规律:示例的质量比数量重要。给一个精心构造的示例,效果往往好过给三个粗糙的示例。而且示例最好覆盖边界情况,比如输入为空、输入格式异常时应该怎么处理。
3.2 少样本学习与思维链:什么时候用,什么时候别用
少样本学习就是在提示词里给几个“输入-输出”对,让模型模仿。思维链是让模型在给出最终答案之前,先展示推理过程。这两个技术都很有效,但不是万能的。
少样本学习适合那些“规则明确但难以用文字描述”的任务。比如你要把一段非结构化的文本转成特定的JSON格式,与其写一大堆格式说明,不如直接给两个转换示例。但要注意,示例会占用token,如果你的输入本身就很长,示例太多会导致上下文窗口不够用。
思维链适合需要多步推理的任务,比如数学题、逻辑推理、复杂决策。但思维链有一个副作用:它会增加输出token的数量,从而增加成本和延迟。而且对于简单任务,思维链反而可能让模型“想太多”,给出过度复杂的答案。我的经验是:先不加思维链跑一遍,如果效果不行再加。不要一上来就默认开启。
3.3 输出格式控制:JSON、XML还是纯文本
如果你要把LLM的输出接入到下游系统,格式控制就至关重要。最常用的是JSON,因为大多数编程语言都能方便地解析。但LLM生成JSON时经常出问题,比如多一个逗号、少一个引号、该用双引号的地方用了单引号。
解决办法有几个:一是用支持结构化输出的API,很多服务商现在都提供了JSON mode,能保证输出是合法JSON。二是在提示词里明确给出JSON schema,并强调“只输出JSON,不要输出任何其他内容”。三是在解析端做容错处理,比如用正则表达式提取JSON部分,或者用宽松的解析库。
XML是另一个选择,它的容错性比JSON好一些,但解析起来更麻烦。纯文本最简单,但下游处理成本最高。我的建议是:能用JSON就用JSON,但一定要做好解析失败的兜底方案。
4. 应用架构设计:别把LLM当数据库用
4.1 RAG架构:检索增强生成的核心逻辑
RAG是目前最主流的LLM应用架构之一。它的核心思想很简单:模型本身的知识是有限的、静态的,但你可以通过外部检索来给它“喂”最新的、私有的知识。
一个典型的RAG流程是这样的:用户提问 -> 把问题转成向量 -> 在向量数据库中检索最相关的文档片段 -> 把检索结果和原始问题一起塞进提示词 -> 模型基于这些上下文生成答案。
这里面有几个关键决策点。第一是切分策略,文档切得太碎会丢失上下文,切得太大又会引入噪声。通常建议按语义段落切分,每段控制在200到500字之间。第二是检索数量,检索太多片段会撑爆上下文窗口,太少又可能漏掉关键信息。一般检索3到5个片段比较合适。第三是重排序,初步检索出来的结果未必是最相关的,可以用一个小的重排序模型做二次筛选,效果提升很明显。
提示:RAG的效果上限取决于检索质量,而不是生成模型的能力。很多人花大量时间调模型,却忽略了检索环节的优化,这是本末倒置。
4.2 Agent架构:让LLM自己决定用什么工具
Agent架构比RAG更进一层。在Agent模式下,LLM不只是一个“回答问题”的模块,而是一个“决策中枢”。你给它一组工具(比如搜索、计算、调用API),它根据用户的需求,自己决定调用哪个工具、按什么顺序调用、什么时候停止。
Agent的核心难点在于容错控制。LLM的决策不是100%可靠的,它可能调用错误的工具、传入错误的参数、陷入循环。所以一个健壮的Agent系统必须有多层防护:输入验证、输出解析、超时控制、重试机制、以及人工兜底。
我踩过的一个坑是:Agent在调用外部API失败后,会不断重试同一个调用,直到耗尽token预算。后来我在提示词里加了明确的指令:“如果同一个工具连续失败两次,停止调用并告知用户”。这个问题才得到缓解。所以如果你要做Agent,一定要在提示词里写清楚失败处理逻辑。
4.3 记忆管理:短期记忆与长期记忆的取舍
LLM本身是无状态的,每次调用都是独立的。但很多应用需要“记住”之前的对话,这就涉及到记忆管理。
短期记忆就是把最近的几轮对话直接塞进上下文窗口。简单有效,但受限于上下文长度。长期记忆则是把历史对话总结、压缩、存储到外部数据库,需要时再检索回来。长期记忆的实现复杂度高很多,但能支持更长的对话历史。
我的建议是:先用短期记忆,够用就别上长期记忆。因为长期记忆会引入额外的检索延迟和不准确性,而且总结过程本身也可能丢失关键信息。只有当对话轮次确实很长、或者需要跨会话记忆时,才考虑上长期记忆方案。
5. 运维与调优:上线只是开始
5.1 成本控制:token预算与缓存策略
LLM应用的成本很容易失控,尤其是当你的用户量上来之后。控制成本的手段有几个:一是设置token预算,每次调用限制最大输入和输出长度,防止异常请求消耗大量token。二是启用缓存,对于相同的输入,直接返回缓存结果,避免重复调用。三是选择合适的模型,不是所有任务都需要用最大的模型,简单任务用小模型完全够用。
缓存策略需要根据业务特点来设计。如果你的应用是问答类的,用户问题重复率可能很高,缓存命中率会不错。但如果是创意生成类的,每次输入都不同,缓存基本没用。另外要注意缓存的失效策略,如果底层知识更新了,缓存也要跟着失效。
5.2 效果评估:LLM as Judge的利与弊
评估LLM的输出质量是一个难题,因为很多任务是开放式的,没有标准答案。目前比较流行的做法是“LLM as Judge”,就是用一个LLM来给另一个LLM的输出打分。
这个方法有它的优势:成本低、速度快、可以处理开放式任务。但它的局限性也很明显:评判模型本身可能有偏见,比如倾向于给更长的回答打高分,或者对某些表达风格有偏好。而且评判模型的判断不一定和人类判断一致。
我的做法是:LLM as Judge用来做粗筛,人工评估用来做精筛。先用LLM快速过一遍大量样本,把明显有问题的筛出来,然后对剩下的样本做人工抽查。这样既能控制成本,又能保证评估质量。
5.3 常见故障排查速查表
| 故障现象 | 可能原因 | 排查方向 |
|---|---|---|
| 输出乱码或重复 | 解码参数设置不当 | 检查temperature和repetition_penalty |
| 请求超时 | 输入过长或服务端负载高 | 缩短输入、增加超时时间、切换服务节点 |
| 输出格式不符合预期 | 提示词约束不够明确 | 增加格式示例、启用结构化输出模式 |
| 模型拒绝回答 | 触发了安全过滤 | 调整提示词措辞、检查是否涉及敏感内容 |
| 显存不足 | 模型太大或量化等级不够 | 换更小的模型、提高量化等级、减少并发 |
| 回答质量突然下降 | 上下文窗口溢出或缓存污染 | 检查上下文长度、清理缓存、回滚提示词版本 |
这张表是我在实际运维中总结出来的,基本上覆盖了80%的常见问题。遇到故障时先对照这张表排查,能省不少时间。
6. 几个容易被忽略的实操细节
6.1 温度参数不是越高越有创意
Temperature控制的是输出的随机性。温度越低,输出越确定;温度越高,输出越多样。很多人觉得“创意任务就要调高温度”,其实不完全对。温度太高会导致输出逻辑混乱、前后矛盾。我的经验是:事实类任务用0到0.3,创意类任务用0.7到1.0,代码生成用0到0.2。超过1.0的温度基本不可控,不建议使用。
6.2 系统提示词和用户提示词要分开
系统提示词是设定模型行为规范的,用户提示词是具体任务的输入。把两者混在一起,会导致提示词难以维护,而且容易被用户输入覆盖。正确的做法是:系统提示词里写角色、约束、输出格式,用户提示词里只放具体任务内容。这样即使换了任务,系统提示词也不用改。
6.3 流式输出不只是为了好看
流式输出让用户能实时看到生成过程,体验更好。但它还有一个隐藏好处:降低超时风险。如果一次性等待完整输出,长文本生成很容易触发超时。流式输出可以边生成边传输,连接不容易断。而且如果生成到一半发现方向不对,可以提前中断,节省token。
6.4 日志记录要脱敏但不要阉割
日志是排查问题的关键,但日志里可能包含用户隐私数据。我的做法是:记录输入输出的哈希值和长度,不记录原文。同时记录模型版本、参数配置、耗时、token用量这些元数据。这样既能追溯问题,又不会泄露隐私。如果确实需要记录原文用于调试,要设置自动过期删除策略。
7. 关于微调:什么时候该做,什么时候不该做
微调是很多人的第一反应:“模型效果不好?微调一下就好了。”但实际上,微调应该是最后的手段,而不是首选。
微调适合的场景是:你有大量高质量的标注数据,而且任务风格非常固定,提示词工程已经无法进一步提升效果。微调不适合的场景是:你只是想注入新知识(用RAG更好)、你只有少量数据(容易过拟合)、你的任务需求还在频繁变化(微调成本太高)。
如果决定要微调,数据质量比数据数量重要得多。1000条高质量样本,效果往往好过10000条低质量样本。而且微调后的模型需要重新评估,不能假设它一定比原模型好。我见过不少案例,微调后模型在特定任务上提升了,但在通用能力上下降了,这就是所谓的“灾难性遗忘”。
提示:微调之前先用提示词工程把效果推到极限,记录下基线指标。微调后再对比,如果提升不明显,说明微调不值得。
8. 本地运行GGUF模型的实操要点
如果你打算在本地设备上运行GGUF格式的模型,有几个实操细节值得注意。首先是内存和显存的分配,GGUF支持把部分层加载到GPU上,剩下的放在内存里。你需要根据自己设备的显存大小,调整GPU层数。层数越多,推理越快,但显存占用也越大。
其次是线程数的设置。在CPU推理时,线程数不是越多越好。通常设置为物理核心数比较合适,超线程反而可能拖慢速度。你可以通过多次测试找到最优值。
最后是上下文长度的设置。上下文越长,内存占用越大。如果你的应用不需要很长的上下文,把上下文长度调小可以显著降低内存压力。很多GGUF运行工具都支持动态调整上下文长度,根据实际需要设置就行。
9. 一些个人体会
我在实际项目里用LLM已经有挺长时间了,最大的感受是:LLM不是魔法,它是一个需要精心调教的工具。你对它的输入越清晰、约束越明确、架构越合理,它的输出就越可靠。反过来,如果你指望它“自己理解”你的意图,那大概率会失望。
另一个体会是:不要追求一步到位。先用最简单的方案跑通,然后根据实际效果逐步优化。很多人一上来就想搭一个完美的RAG加Agent加微调的复杂系统,结果卡在某个环节动弹不得。不如先用API加提示词跑起来,看看效果怎么样,再决定下一步往哪走。
最后再分享一个小技巧:建立自己的提示词库和评估集。每次调出一个好用的提示词,就存下来,标注适用场景和效果。每次遇到bad case,就加到评估集里。时间长了,你会有一套属于自己的“武器库”,遇到新任务时能快速找到参考方案,而不是从零开始试。这个习惯看起来简单,但坚持下来收益巨大。