news 2026/10/10 4:30:11

大模型应用工程化实战:推理优化、RAG链路与Agent稳定性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大模型应用工程化实战:推理优化、RAG链路与Agent稳定性

1. 一个连载到八十四期的技术博客,为什么还在被我反复翻?

TowardsArtificialIntelligence这个博客系列,中文翻译版能连载到第八十四期,本身就说明了很多问题。它不是那种靠标题党骗点击的资讯站,也不是一天三条的AI快报,而是实打实的长文合集。我大概是从三十多期开始追的,中间换过几份工作,从算法岗转到偏工程的方向,这个系列倒是一直没落下。

第八十四期给我的整体感受很直接:这一批文章已经过了“什么是大模型”“为什么要用RAG”的阶段,开始集中聊大模型应用真正工程化之后才会遇到的事情。比如模型量化之后,精度掉得没有想象中那么少,前提是你得把校准集做对;再比如RAG系统召回不准,大概率不是Embedding模型不够强,而是分块和查询改写环节拖了后腿。这些内容如果你没亲手搭过一两个AI项目,可能觉得都是细节,但恰恰是这些细节决定了一个系统是demo级还是生产级。

这个系列默认读者有一定基础。它不会花一整篇解释Transformer的自注意力机制,也不会教你怎么跑通一个LangChain的hello world。如果你是刚接触AI的学生,这期读起来可能会吃力;如果你在公司里做过至少一个从0到1的模型项目,那这期的命中率会非常高,很多文章看到标题就知道是过来人写的。

我自己读这一类长文有个习惯:先不看结论,猜一下作者会怎么展开,然后带着“这个坑我是不是也踩过”的心态去读。读第六十期、第七十期的时候,我还得靠猜;读第八十四期,已经变成了“这不就是我上周刚从生产环境里排查出来的问题吗”。这种共鸣感,是追更一个技术博客最大的乐趣。

这一期的内容地图也比较清晰,大致可以归纳成三个支点:大模型推理性能的优化手段、检索增强生成链路里的质量瓶颈、以及Agent工具调用和多轮任务中的稳定性问题。三条线合在一起,其实就是大模型应用从“能跑”到“跑得好、跑得稳”的三个门槛。下面我按这三个方向展开,讲一讲我从这期文章里提炼出来的东西,以及那些文章没直说、但我在实际项目里反复验证过的经验。

2. 这期合集里最能直接放进项目的三个硬方向

2.1 大模型推理优化:瓶颈不在算力,在显存带宽

第八十四期里有不止一篇文章在讲LLM的推理加速,这其实是一个非常符合当下节奏的话题。模型越用越大,部署成本的压力随之而来,很多人第一反应是“加GPU”,但实际在单卡或者双卡环境下,能压榨的空间远比想象中大。

首先要建立一个概念:LLM解码为什么慢。自回归生成的时候,每一步生成一个token,都需要把所有参数的权重从显存里读一遍。这个阶段的瓶颈通常不在计算单元上,而在显存带宽上。打个比方,FP16模型100亿参数,光读一遍权重就是20GB,如果每秒生成20个token,那每秒要读的权重数据量就是400GB,这不是普通PCIe或者NVLink能轻松扛住的事。这也是为什么INT8、INT4量化的提速效果那么明显——权重的体积直接砍半甚至砍到四分之一,每个token需要搬运的字节数大幅下降,吞吐自然就上来了。

量化这个方向,这期文章里没有停留在“量化是什么”的科普层面,而是讨论了训练后量化(PTQ)和量化感知训练(QAT)的取舍,以及GPTQ、AWQ这类主流方法各自的特性。GPTQ基于二阶信息做逐层量化,量化误差控制得比较好,但校准集的选择会影响结果;AWQ的思路则是找到激活分布中的少数重要通道,优先保护这20%的通道而不量化它们。实际用下来,AWQ在4bit场景下对中文业务场景的稳定性往往比无脑GPTQ要好一点,尤其是模型里出现大量领域术语的时候。

KV Cache的优化也是这批文章反复提到的重点。很多人没意识到,解码阶段随着生成长度增加,KV Cache的显存占用是线性增长的。两万字的上下文,KV Cache可能占用几个GB甚至更多。PagedAttention这套思路本质上就是操作系统的分页管理——把显存切成更小的块,按需分配,减少碎片浪费,让更长的上下文塞进同一个卡里。如果你是在vLLM这类框架上跑服务,这部分优化基本是默认开启的,这也是我建议业务团队不要自己造推理框架轮子的原因。

2.2 RAG链路:回答的上限,在检索那一步就定死了

第八十四期里关于RAG的文章,几乎没有一篇在讲“RAG是什么”,清一色在讨论“为什么RAG的效果没想象中好”。这非常符合我过去一年做项目的体感。

很多团队搭RAG的第一个错误,是把所有精力都花在调Prompt上。问出来的答案不对,就反复改Prompt;改完还是不对,就换更大的模型;再不行就怪Embedding模型不够强。但真实情况往往是,你的检索系统从源头就没有把正确的上下文捞出来。大模型再聪明,你喂给它的八个文档片段里只有两个相关,它也很难从噪声里找出规律。

这期文章对检索质量的分析很细,我挑三个值得直接落地到项目里的点说。

第一是分块策略。固定按512个token切分是最省事的做法,但也是最容易切坏语义的做法。一个表格被切成上下两半、一个代码示例和它的报错说明被拆到两个chunk里,这类问题在真实文档里太常见了。更好的做法是结构化分块:优先保留Markdown标题层级、表格结构、代码块边界,再在单个块内部控制长度。块大小也不是越小越好,太小会导致语义不完整,太大又会让准确率被不相关信息稀释。

第二是混合检索。只依赖向量检索,对纯语义匹配的问题效果好,但遇到精确词匹配、编号、型号这类查询时反而不如传统的关键词检索。BM25和向量检索结合,用RRF(倒数排名融合)合并结果,是性价比很高的方案。我见过很多项目在向量模型上花了大量时间调优,结果加一个BM25的召回路,指标一下子蹿上去好几个点。

第三是查询改写。用户真正在对话里说出来的问题,和文档里原生的表述方式往往差得很远。比如文档里写的是“服务启动失败时,检查端口占用”,用户可能会问“我这边怎么起不来,是不是被占了”。查询改写模块可以把口语问题转成更适合检索的表述,再进检索器,最后补一个可选的Rerank重排。重排模型虽然慢一点,但先用便宜方式召回一百条,再用交叉编码器精排到五条,这个成本是完全值得花的。

2.3 Agent与工具调用:多步任务最怕的不是模型笨,是状态失控

这期合集里的Agent相关文章,讨论的方向和我预期不太一样。原以为会讲Prompt工程或者工具调用的写法,实际上更多在讲状态管理和失败恢复。

去年深度使用过几轮Agent框架之后,我对这个话题有一个很深的体会:LLM本身不是一个可靠的状态机。你给它堆了一大段工具调用记录,它是真的会忘记自己原来要干什么的。多轮调用里最经典的翻车现场,是Agent在第三步拿到了一个特定格式的返回值,第四步就把它当成了答案输出给用户,完全不管最初的目标还没达成。

针对这类问题,文章里反复出现的一个关键词是“显式状态管理”。不要把Agent所有的记忆都压在对话历史上,而是把用户目标、当前已收集的信息、下一步计划这些要素单独拆出来,放到结构化的State对象里。每一步工具调用之前先读一次State,调用之后再更新一次State。这样做最大的好处是,即使中间某一步出错,系统也知道自己做到哪儿了、该从哪里恢复。

面向工具调用的工程细节也值得复盘。LLM输出的工具调用参数不是每次都合法,JSON解析会失败,字段名会幻觉,甚至工具本身超时了也没返回东西。这些场景每个都必须有兜底逻辑:解析失败就走重试,重试之后还是失败就把错误信息明确反馈给用户,而不是让Agent带着错误信息继续往下跑。还有一点很多人会忽略:一定要设置最大轮次。一个任务最多跑十步,十步之内没做完就直接终止并告诉用户哪里没跑通,胜过让Agent在错误路径上无限循环,浪费token也浪费用户的耐心。

3. 从博客到线上环境,把思路落地时踩过的坑

看文章是一回事,把文章里的思路搬回自己的项目,又是另一回事。这期内容我读的时候觉得句句在理,真正落地时还是踩了不少坑。我把三个最有代表性的坑写出来,全部是实测复盘后的结论。

3.1 量化之后效果崩了?先检查校准集,别急着骂量化

我之前有一个项目,要把一套7B模型从FP16压到INT4,用GPTQ做训练后量化。跑业务评测集的时候发现,有几个核心场景的回答质量明显下降,甚至出现了答非所问。当时第一反应是“4bit是不是压得太狠了”,又去找INT8的对比方案,但效果依然不理想。

后来冷静下来,直接做A/B对照:同一个Prompt,分别问FP16版和INT4版,发现两者在部分case上确实有差异,但也有一部分case两个模型答得都不好,说明有些锅并不在量化本身。真正的问题出在校准集上。我用的是模型量化包自带的默认校准数据,只有128条通用语料,而我的业务场景里全是专业术语和特定表达。量化算法生成scale和zero point的时候,参考的是校准集的分布,分布和真实业务不匹配,量化误差就会在专业语义上集中爆发。

解决办法也不复杂:从线上真实请求里采样200到500条多样化的文本作为校准集,重新量化。换了之后,量和精度都在可接受范围内,评估指标也回到了基准线附近。从那以后,我对所有团队定了一条规矩:量化不是模型部署的独立环节,它必须和业务数据绑在一起验证。而且不要只看通用基准,一定要在冻结的业务评测集上跑回归。

3.2 召回不准先别换Embedding,先看分块和查询改写

另一个项目是做内部知识库问答,文档以技术方案和故障复盘为主。最初上线那段时间,召回准确率一直卡在65%左右,团队讨论的第一方案就是“换更强的Embedding模型”。我当时拦了一下,原因是我翻了最近一周的bad case,发现相当一部分问题出在文档解析和分块上。

典型案例是,一份故障复盘文档里有一张表格,前半部分是“故障现象”,后半部分是“解决方案”,自动分块的时候表格被拦腰截断,检索“怎么修复”的时候,召回了前半张表,里面根本没有修复步骤。再比如,用户问“部署的时候需要开哪些端口”,文档里写的是“安全组需放通8080/8443端口”,这两种表述在向量空间里距离并不近,尤其当用户用了口语化的表达。

后续的改动其实很朴素:替换成一棵基于Markdown标题结构的解析器,表格、代码块、列表优先整体保留,再控制每一块的最大长度和overlap。然后加了一个查询改写模块,把用户的口语问题先转写成更接近文档表述的关键词组合,再进检索引擎。这两步做完,召回指标从65%涨到78%,效果比直接换Embedding模型明显得多。

这件事让我养成了一个习惯:任何检索问题,先做bad case归因。如果检索结果里根本没有正确答案,那就是召回问题,再往下拆是分块问题、查询改写问题还是向量化问题;如果检索结果里有正确答案但生成答错了,那才是生成阶段的问题。归因错了,后面全是白忙。

3.3 离线指标好看,用户却觉得“答非所问”

评测是第八十四期里单独一块内容。我的真实体验是,离线指标和线上感受之间的落差,经常大到让人怀疑是不是做错项目了。

之前有一个问答系统,接的是内部文档,离线评测每项指标都很好看,准确率超过90%。结果放出来给用户试用,反馈里最集中的一句话是“答非所问”。后来人工去翻对话记录,发现问题出在评测集的设计上。离线评测集里的问题大多是可以直接从单篇文档里找到答案的事实题,比如“这个接口的参数是什么”“这个配置文件的默认值是多少”,这类问题只要检索命中,大模型基本不会翻车。但用户真正爱问的是跨文档的推理题,比如“两个模块都调用同一个Redis,会不会有性能风险”,这类问题在评测集里占比太低,所以离线指标根本反映不了真实体验。

修复方式是重建评测集。把问题按类型分成事实查询、步骤操作、跨文档推理、多轮澄清四类,每类分别抽样,再用多人背对背打分。主观评价维度也要拆细,不能只有一个“好不好”的总分,而是分成回答完整性、准确性、可操作性三个维度。LLM-as-Judge可以做初筛,但它有很强的bias,比如偏好长回答、偏好结构清晰的回答,一定不能单独用它的分数下结论,要和人工抽检校准。

4. 手把手复刻:把这一期的思路用在一个内部知识库问答项目上

这一章我把第八十四期那几篇工程向文章的思路整合起来,复刻到一个真实场景里。场景是:给团队做一个内部技术文档问答助手,知识库覆盖多个代码仓库的README、架构设计文档、故障复盘报告,大概几千篇文档。这个体量不大不小,正好能验证RAG和推理优化的多数问题。

4.1 系统链路与选型逻辑

整体链路是:文档解析 → 结构化分块 → 向量化索引 → 查询改写 → 混合检索 → 重排 → LLM生成 → 引用溯源。

选型上,我有自己的偏好。向量数据库直接用团队现成的PostgreSQL加pgvector插件,没有引入独立的向量数据库,理由很简单:团队已经有一套成熟的PostgreSQL运维体系,不需要为几千篇文档的规模再维护一个Milvus或者es集群。Embedding模型用开源的bge系列中文模型,效果与商用API在一个量级,而且支持内网部署,不依赖外部调用。主模型选了7B级别的开源模型,做INT8量化部署,单卡可以搞定,延迟也在可接受范围。Rerank模型同样选了同系列的开源交叉编码器,参数不算大,但精排能力对回答质量的提升非常明显。

这套方案的核心逻辑是:用比例更高的工程手段去补模型规模的不足。7B模型本身知识量有限,但我把检索质量做上去、上下文给得准,它在垂直领域的表现就完全够用。反过来,如果无脑上一个大模型API,又不控制检索质量,成本更高,也不一定更稳。

4.2 关键参数和回归评测

分块策略我选了“结构化优先,默认长度兜底”的方式。解析器先把Markdown标题、列表、表格、代码块识别出来,表格和代码块整体保留,如果一个块太长就按字符数截断,同时保留前后64个字符的overlap,避免关键信息被切穿。不同来源的文档还会带上来源路径和标题作为元数据,召回后可以溯源到具体文档,用户点了引用能直接跳转。

检索阶段,粗召回用向量检索加BM25各取50条,再用RRF合并。Rerank阶段保留Top 5,把这5条上下文塞给LLM生成答案。为什么要做这一步而不是直接把50条全给模型?一是Token成本,二是上下文过长会导致模型注意力分散,5条高质量上下文的效果好过一堆低质量候选。

上线之前我固定了一套回归集,两百条真实业务问题,每类问题都有覆盖。每次改动无论大小,都要在这套回归集上跑一遍,对比回答质量和耗时。这里放一个我常用的小脚本片段,用来评估检索环节的Recall@K:

def recall_at_k(retrieved_ids, relevant_ids, k): """计算检索结果在Top K内的召回率""" retrieved_top_k = set(retrieved_ids[:k]) relevant = set(relevant_ids) if not relevant: return 0.0 hits = retrieved_top_k & relevant return len(hits) / len(relevant) # 示例:某条问题标注了3个相关文档ID retrieved = ["doc_102", "doc_087", "doc_005", "doc_120"] relevant = ["doc_102", "doc_120"] print(recall_at_k(retrieved, relevant, k=3)) # 输出 0.33

4.3 方案对比和成本取舍

我做了三个方案的对比测试,结果非常有意思。方案A是用大模型API加简单RAG,省事但每次调用贵、延迟高,而且开放域能力虽然强,在处理内部格式化文档时并没有明显优势。方案B就是上面的自部署中小模型加高质量RAG,一次性投入采购GPU的成本,但单次调用成本几乎可以忽略,延迟也更稳定。方案C在B的基础之上加了一个小模型路由,先判断问题类型,简单问题走更小的模型,复杂问题再走7B,进一步压低成本。

大多数情况下,方案B是更适合企业内部知识库的答案。原因在于这类场景的文档垂直度高,答案是否准确,主要取决于检索系统能不能把对的文档捞出来,而不是模型有多聪明。如果问题是完全开放域的闲聊或者创意写作,那大模型API确实是省事的选择,没有必要自部署。

对比维度方案A:大模型API + 简单RAG方案B:中小模型 + 高质量RAG方案C:B + 问题路由
部署成本低,无需自建GPU中等,需单卡或双卡较高,需要额外维护小模型
单次调用成本高几乎为零几乎为零
延迟受外部网络影响稳定可控稳定可控
垂直领域回答质量依赖检索质量检索调好后非常稳同B
开放域能力强弱一些弱一些

这个对比想说明的其实是第八十四期里反复出现的一句话:在垂直场景里,工程优化带来的收益往往大于换一个更大模型的收益。

5. 读这类连载技术博客的正确姿势,聊聊方法论

最后聊一点个人方法论。追更了这么多期,踩过的坑也不少,我慢慢摸索出一套读这类长文的方式。技术博客和论文不一样,它通常默认读者能跟上作者的思路,但也正因为这样,很多人容易读得太舒服、太被动,看完觉得“学到了”,实际上什么都没留下来。

我的第一个习惯是“反向摘要”。拿到一篇文章,先不要逐字读,先看小标题和核心论断,然后用一句话回答三个问题:这篇文章要解决什么问题?它建议我别用什么方案?它在什么条件下成立?回答完这三个问题,再回到正文看细节。这样做的好处是,你在读正文之前就有了自己的假设,读的过程中不断验证或者推翻假设,印象会深得多。

第二个习惯是“一次只改一个变量”。文章里给的方案往往是一整套组合拳,比如“混合检索加Rerank加查询改写”,你要是同时把这三样都改了,效果提升了,根本不知道哪个环节在起作用。我复现时会先按原方案整体跑通,再一项一项往回撤,每撤一项就评估一次,最后得出这个系统里最关键的杠杆点在哪里。

第三个习惯是把文章里的坑沉淀成自己的检查清单。第八十四期读完之后,我给自己列了一张单子:

  • 量化前,先准备业务数据校准集,量化后跑业务回归集
  • 召回出问题,先查分块和查询改写,最后才考虑换Embedding
  • 改任何一个环节,都在固定回归集上对比,不凭感觉判断好坏
  • Agent必须设置最大轮次,工具调用必须有重试和失败兜底
  • 评测集要覆盖事实查询、操作步骤、跨文档推理、多轮澄清,不能全是简单题

这张清单后来直接变成了团队的Review规范的一部分。每次有人提“我想换个方案”,第一件事就是对照清单,确认现在的系统里哪些环节是被验证过的,哪些纯粹是拍脑袋选的。这个过程,比读十篇文章都值钱。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 4:30:11

Windows运行库修复原理:DirectX、.NET与VC++三大依赖体系解析

1. 运行库不是“插件”,而是程序启动前必须签到的“通行证”你有没有遇到过点开一个游戏,弹出“MSVCP140.dll 丢失”;双击一个老软件,提示“无法定位程序输入点于动态链接库 vcruntime140.dll”;甚至刚装完系统&#x…

作者头像 李华
网站建设 2026/10/10 4:29:52

claude-mem:让终端AI拥有持久记忆,告别重复交代项目背景

如果你也习惯在终端里跟 Claude CLI 打交道,肯定撞过这么一堵墙:昨天还在聊服务拆分方案,今天重新打开一个会话,模型一脸无辜地反问“你们这个项目的技术栈是什么”。这不是能力问题,是记忆问题。Claude CLI 默认是“无…

作者头像 李华
网站建设 2026/10/10 4:29:50

重试机制才是省token的最大黑洞,如何设计调用层防成本失控?

省 token 这个事,我问过不少做 AI 应用的朋友,十有八九都拍着胸脯说"我一个月把 token 成本砍了 40%"。但你再追问一句"你失败重试一次会多花多少钱",大多数人会愣住。这个愣住就是问题所在:大家把精力全放在…

作者头像 李华
网站建设 2026/10/10 4:29:28

AcWing快排四步工程化改造:从超时到稳AC

1. 为什么“AcWing快排”不是一道普通题目,而是一把解题思维的钥匙在算法学习的早期阶段,很多人对“快排”这个词的印象还停留在教科书里那段二十行左右的递归代码:选个基准、分区、递归左右——写完能跑通,但一到实际刷题就卡壳。…

作者头像 李华
网站建设 2026/10/10 4:29:28

Hadoop图书推荐系统源码实战:从HDFS到MySQL的离线推荐链路搭建

简介:本资源为基于Hadoop的图书推荐系统完整源码与数据库压缩包,面向大数据、分布式计算方向的学习者与开发者,可用于课程设计、毕业设计或推荐算法实践。包内共346个文件,涵盖37个Java源文件、86个JavaScript脚本、52个CSS样式、…

作者头像 李华
网站建设 2026/10/10 4:29:28

Delphi 6.0安装盘虚拟机安装指南:从环境配置到避坑排查

简介:这份资源是 Delphi 6.0 的经典安装盘镜像,面向希望学习 Object Pascal 与 Windows 快速应用开发的初学者及需要复现旧项目的开发者。Delphi 6.0 由 Borland 推出,在 COM/COM、数据库开发与企业级 CORBA 支持上较为成熟,配合 …

作者头像 李华