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条高质量上下文的效果好过一堆低质量候选。上线之前我固定了一套回归集两百条真实业务问题每类问题都有覆盖。每次改动无论大小都要在这套回归集上跑一遍对比回答质量和耗时。这里放一个我常用的小脚本片段用来评估检索环节的RecallKdef 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, k3)) # 输出 0.334.3 方案对比和成本取舍我做了三个方案的对比测试结果非常有意思。方案A是用大模型API加简单RAG省事但每次调用贵、延迟高而且开放域能力虽然强在处理内部格式化文档时并没有明显优势。方案B就是上面的自部署中小模型加高质量RAG一次性投入采购GPU的成本但单次调用成本几乎可以忽略延迟也更稳定。方案C在B的基础之上加了一个小模型路由先判断问题类型简单问题走更小的模型复杂问题再走7B进一步压低成本。大多数情况下方案B是更适合企业内部知识库的答案。原因在于这类场景的文档垂直度高答案是否准确主要取决于检索系统能不能把对的文档捞出来而不是模型有多聪明。如果问题是完全开放域的闲聊或者创意写作那大模型API确实是省事的选择没有必要自部署。对比维度方案A大模型API 简单RAG方案B中小模型 高质量RAG方案CB 问题路由部署成本低无需自建GPU中等需单卡或双卡较高需要额外维护小模型单次调用成本高几乎为零几乎为零延迟受外部网络影响稳定可控稳定可控垂直领域回答质量依赖检索质量检索调好后非常稳同B开放域能力强弱一些弱一些这个对比想说明的其实是第八十四期里反复出现的一句话在垂直场景里工程优化带来的收益往往大于换一个更大模型的收益。5. 读这类连载技术博客的正确姿势聊聊方法论最后聊一点个人方法论。追更了这么多期踩过的坑也不少我慢慢摸索出一套读这类长文的方式。技术博客和论文不一样它通常默认读者能跟上作者的思路但也正因为这样很多人容易读得太舒服、太被动看完觉得“学到了”实际上什么都没留下来。我的第一个习惯是“反向摘要”。拿到一篇文章先不要逐字读先看小标题和核心论断然后用一句话回答三个问题这篇文章要解决什么问题它建议我别用什么方案它在什么条件下成立回答完这三个问题再回到正文看细节。这样做的好处是你在读正文之前就有了自己的假设读的过程中不断验证或者推翻假设印象会深得多。第二个习惯是“一次只改一个变量”。文章里给的方案往往是一整套组合拳比如“混合检索加Rerank加查询改写”你要是同时把这三样都改了效果提升了根本不知道哪个环节在起作用。我复现时会先按原方案整体跑通再一项一项往回撤每撤一项就评估一次最后得出这个系统里最关键的杠杆点在哪里。第三个习惯是把文章里的坑沉淀成自己的检查清单。第八十四期读完之后我给自己列了一张单子量化前先准备业务数据校准集量化后跑业务回归集召回出问题先查分块和查询改写最后才考虑换Embedding改任何一个环节都在固定回归集上对比不凭感觉判断好坏Agent必须设置最大轮次工具调用必须有重试和失败兜底评测集要覆盖事实查询、操作步骤、跨文档推理、多轮澄清不能全是简单题这张清单后来直接变成了团队的Review规范的一部分。每次有人提“我想换个方案”第一件事就是对照清单确认现在的系统里哪些环节是被验证过的哪些纯粹是拍脑袋选的。这个过程比读十篇文章都值钱。