AI智能体架构优化:将LLM移出检索路径,提升性能与降低成本

张开发
2026/6/10 18:48:42 15 分钟阅读

分享文章

AI智能体架构优化:将LLM移出检索路径,提升性能与降低成本
1. 项目概述从狂热到反思的架构抉择最近和几个做AI应用的朋友聊天发现一个挺有意思的现象大家好像都默认把大语言模型LLM塞进了智能体Agent的记忆检索路径里。无论是做客服机器人、代码助手还是个人知识库架构图里总少不了“用户提问 → 向量化 → LLM理解并检索 → 返回答案”这个经典流程。半年前我也是这个模式的坚定拥护者觉得用LLM来理解用户意图、重写查询语句、甚至直接生成检索结果简直是天衣无缝的设计。但经过几个真实项目的迭代和线上流量的考验我彻底改变了这个想法并且决定在未来的所有Agent架构中将LLM从核心的记忆检索路径中移除。这不是一个轻率的决定背后是实实在在的延迟飙升、成本失控和稳定性噩梦换来的教训。如果你正在设计或优化一个依赖记忆无论是向量数据库、图数据库还是传统SQL的AI智能体那么我踩过的这些坑或许能帮你省下不少研发资源和云服务账单。简单来说这个“停止”动作的核心是将LLM从“检索”这个需要高确定性、低延迟、高并发的关键路径中剥离转而将其定位为“检索后”的加工、润色、决策与交互层。记忆检索本身应该由更轻量、更稳定、更廉价的技术组件来承担。这听起来像是一种退步仿佛放弃了LLM的“智能”但实际运行下来整个系统的综合表现——包括用户体验、技术指标和商业成本——都得到了质的提升。接下来我就从设计思路、实操细节、问题排查和最终方案这几个层面详细拆解我为什么这么做以及具体是怎么做的。2. 核心架构思路的演变与权衡2.1 初始方案LLM作为“智能检索大脑”的诱惑最初的设计非常直观也符合当时的技术潮流。我们构建了一个多轮对话智能体它需要根据对话历史记忆和知识库来回答问题。架构流程如下用户输入用户提出一个问题例如“我们公司去年Q3在华东区的销售政策是什么”历史记忆加载系统从对话记录中加载最近几轮的历史作为上下文。查询理解与重写LLM介入将用户原始问题历史上下文发送给LLM如GPT-4指令是“请根据对话历史将用户问题转化为一个更适合知识库检索的查询语句。可能需要补充隐含信息、纠正指代、明确时间范围。”向量化检索将LLM生成的“优化后查询”进行向量化然后在向量数据库如Pinecone, Weaviate中进行相似性搜索获取Top K个相关片段。答案生成LLM再次介入将检索到的相关片段、历史上下文和原始问题再次发送给LLM指令是“请根据提供的资料生成一个准确、友好的回答。”返回与记忆存储将LLM生成的答案返回给用户并将本轮QA存入对话历史。这个设计的初衷很美让最聪明的LLM去理解用户复杂的、口语化的、有上下文依赖的意图生成一个“标准”的检索查询从而提升检索的准确性。理论上这能解决“用户问法”和“知识库存储表述”之间的语义鸿沟。在Demo和小流量测试中效果也确实不错显得很“智能”。2.2 理想与现实的裂痕三大核心痛点当系统进入灰度测试和正式上线面对真实、复杂的用户流量时问题接踵而至痛点一延迟的不可控与用户体验的崩塌这是最直观的打击。一次用户请求需要串行调用两次LLM API查询重写和答案生成。即使每次LLM调用只有2-3秒加上网络延迟、检索时间整个链路轻松突破5-8秒。在对话场景中这是用户无法忍受的。更糟糕的是LLM API的响应时间存在长尾效应偶尔一次10秒以上的响应就会导致请求超时用户看到的是“服务无响应”。我们尝试了各种优化流式输出、设置更严格的超时、使用更快的模型如从GPT-4切到GPT-3.5-Turbo但治标不治本。LLM作为检索路径的一部分直接成为了系统延迟的瓶颈和最不稳定的一环。痛点二成本的无底洞与商业模型的压力成本以惊人的速度攀升。每一次用户交互无论问题简单或复杂都需要为“查询重写”这个步骤支付LLM API的费用。假设使用GPT-3.5-Turbo一次查询重写消耗约500 tokens每天1万次请求仅这一项成本就非常可观。而很多简单的、明确的查询例如“帮我查一下订单号12345的状态”根本不需要LLM来重写一个简单的规则或关键词提取就能搞定。让LLM去处理所有请求就像用高精度数控机床去切水果不仅浪费而且慢。在检索路径中使用LLM使得系统的边际成本始终居高不下严重影响了商业模式的可持续性。痛点三稳定性的“阿喀琉斯之踵”LLM服务的稳定性不完全可控。提供商可能限流、可能宕机、可能更新模型导致输出格式变化。当LLM成为检索的必经之路它的任何不稳定都会直接导致整个智能体服务瘫痪。我们经历过因为LLM服务商临时维护导致所有用户问题都无法检索的窘境。此外LLM的“创造性”在检索场景成了双刃剑。它有时会过度“理解”将简单的查询改写得面目全非甚至引入错误的前提假设导致检索结果完全偏离主题。这种不确定性对于要求高准确性的知识问答来说是致命的。注意这里说的稳定性不仅仅是服务可用性更包括输出行为的确定性。检索需要的是“精确命中”而LLM的本质是“概率生成”这两者在根本上是存在矛盾的。2.3 思路转变解耦“检索”与“理解”基于上述痛点我的架构思路发生了根本转变将“记忆检索”视为一个需要高吞吐、低延迟、高确定性的基础设施而将“语义理解与交互”视为其上的智能增强层。两者应该解耦而非耦合。检索层Retrieval Layer职责是快速、准确、廉价地根据输入找到最相关的记忆片段。它应该轻量、稳定、可预测。输入是什么就应该尽最大可能找到与之匹配的内容。这一层应避免使用LLM。理解与交互层Reasoning Interaction Layer职责是处理检索到的信息。包括对多个检索结果进行综合、去重、排序判断检索结果是否充分是否需要发起新的、更精确的检索即“思考-行动”循环将原始信息组织成自然、友好的语言回复给用户。这一层是LLM的主场。这个转变的核心在于不再要求LLM去“猜”用户想要什么然后帮ta检索而是让一个更可靠的检索系统先把可能相关的东西都找出来再让LLM这个“聪明的大脑”来判断哪些有用、并组织答案。这样检索的失败不会导致整个流程崩溃LLM还可以基于检索失败这一事实进行回复如“我暂时没找到相关信息您可以尝试这样问…”而LLM的波动也不会阻塞检索。3. 新架构的核心细节与实操要点3.1 轻量级检索引擎的选型与优化移除了LLM检索路径的核心就变成了一个高效的“召回器”。我们的目标是用最低的成本和延迟实现尽可能高的召回率Recall。精确度Precision可以稍后由LLM来筛选。1. 双路召回策略Hybrid Search这是提升召回效果的关键。我们不再单纯依赖向量语义搜索。向量检索路用于处理语义相似性。使用开源的嵌入模型如BAAI/bge-small-zh-v1.5或thenlper/gte-base在本地进行向量化然后查询向量数据库如Chroma, Qdrant。这一步解决“不同说法相同意思”的问题。关键词检索路用于处理精确匹配和关键词权重。使用经过优化的全文检索引擎如Elasticsearch, Meilisearch或轻量级库如Whoosh。对用户查询进行分词、去除停用词、计算TF-IDF等。这一步解决“特定术语、编号、名称”的精确查找问题。两路检索结果并行获取然后进行融合Fusion。常用的融合算法有加权分数融合给向量检索和关键词检索的结果分别赋予权重计算综合分。RRFReciprocal Rank Fusion不依赖绝对分数只根据各自结果列表中的排名进行融合对异构检索系统更鲁棒。 我们实测下来RRF的效果更稳定避免了不同检索系统分数尺度不一致的问题。2. 查询预处理管道Query Pre-processing Pipeline这是替代LLM进行查询重写的轻量级方案。一个典型的管道包括标准化转小写、去除特殊字符、统一标点。拼写纠正使用轻量级库如pyspellchecker处理明显的拼写错误。实体识别与扩展使用本地NER模型如spaCy识别出人名、地名、产品名等实体。对于产品名、内部术语可以配置同义词词典进行扩展。例如用户输入“苹果手机”可以扩展为“iPhone, Apple iPhone”。意图分类可选但推荐训练一个简单的文本分类模型如FastText或小型的BERT将查询分为“事实查询”、“操作指令”、“闲聊”、“多轮澄清”等类别。不同类别的查询可以触发不同的检索策略和后处理逻辑。这个预处理管道全部在本地运行延迟在毫秒级成本几乎为零却能解决大部分简单的查询优化问题。3. 向量模型与数据库的优化模型选型放弃追求顶级效果的大型嵌入模型如OpenAI的text-embedding-3-large转而使用效果足够好、速度更快的开源小模型。对于中文场景BAAI/bge-small-zh系列是很好的平衡点。将其部署在本地GPU甚至CPU上消除网络延迟。索引优化对于向量数据库选择合适的索引类型如HNSW和参数ef_construction,M。在召回率和查询速度之间取得平衡。定期对索引进行重建以纳入新数据并优化性能。分片与过滤根据业务逻辑对记忆数据进行分片例如按部门、按时间。检索时先根据用户上下文或元数据过滤到特定分片再执行搜索能极大减少搜索空间提升速度和准确度。3.2 LLM在新架构中的精准定位在新的架构中LLM被移到了检索路径之后其角色更加清晰和强大1. 检索后处理器Post-RetrieverLLM接收的是“检索系统返回的、可能相关的原始材料列表”。它的任务包括相关性精排判断每个检索片段与用户问题的真实相关性过滤掉误召回的结果。信息综合从多个相关片段中提取、总结、去重合成一个连贯的信息体。答案生成基于合成后的信息生成最终的自然语言回答。这是LLM最擅长的工作。2. 检索决策器Retrieval-Decision Maker这是实现“智能”的关键。LLM可以分析当前检索结果的质量并决定下一步行动形成一个闭环判断充分性“当前检索到的信息足够回答用户问题吗”决定是否重试如果不够LLM可以分析原因并生成一个新的、更精确的查询语句触发系统进行第二轮检索。注意这个新查询是给轻量级检索引擎的而不是LLM自己再去检索。例如LLM可能判断“需要更近期的信息”从而在新查询中加上“2024年”这个过滤器。多跳查询对于复杂问题LLM可以规划多步检索。例如先检索“公司A的主要产品”得到产品名“X1”再自动以“X1的技术白皮书”为查询进行第二次检索。3. 交互与安全层处理无结果当检索系统返回空或极低相关性结果时LLM可以生成得体的回应引导用户提供更多信息或换种问法而不是直接报错。内容安全与合规检查LLM可以在最终答案生成前检查其是否包含不安全、不恰当或与检索源矛盾的内容。多模态整合如果答案需要结合文本、数据图表LLM可以规划调用相应的工具如绘图API、数据查询API。这种定位下LLM的调用不再是每次交互的“必选项”。对于非常简单的、答案明确的查询系统甚至可以通过规则模板直接组装答案完全绕过LLM实现极速响应。3.3 系统流程与数据流设计以下是新的、去LLM化的核心检索路径的详细数据流接收请求系统接收用户查询Q和会话上下文C。轻量预处理对Q进行标准化、拼写纠正。运行NER识别实体并通过同义词库扩展。使用轻量级意图分类模型对Q进行分类。生成检索查询根据意图分类结果选择策略生成检索查询。事实查询将预处理后的Q直接用于双路检索。操作指令如“订一张票”可能触发工具调用不进入记忆检索流。多轮澄清从上下文C中提取上一轮的关键信息合并到当前查询Q中。并行双路检索路径A语义用本地嵌入模型将查询向量化在向量库中进行近似最近邻搜索。路径B关键词将查询分词在全文检索引擎中进行搜索。可选路径C元数据过滤根据实体识别结果如时间、人物对检索范围进行过滤。结果融合与粗排使用RRF等方法融合A、B两路的结果得到Top N例如N10的候选记忆片段列表[Doc1, Doc2, ...]及其原始分数、来源。交付LLM进行精加工将用户原始问题Q、上下文C以及候选片段列表[Doc1, Doc2, ...]一同发送给LLM。Prompt设计如下你是一个专业的助手。请基于以下用户问题和参考资料生成回答。 用户问题{Q} 对话历史{C} 参考资料列表 [1] 内容{Doc1.content} (相关性分数{Doc1.score}) [2] 内容{Doc2.content} (相关性分数{Doc2.score}) ... 请遵循以下步骤 1. 判断每个参考资料与用户问题的相关性。忽略那些明显不相关的。 2. 从所有相关参考资料中提取、整合关键信息。 3. 如果现有资料不足以回答问题请明确指出缺少什么信息。 4. 基于整合后的信息生成一个准确、清晰、完整的回答。 回答LLM决策与行动可选如果LLM在步骤6中判断信息不足它可以生成一个“思考过程”其中包含一个新的、更精确的检索查询NewQuery。系统捕获这个NewQuery跳回第4步执行新一轮检索然后将新旧结果一起再次提交给LLM。返回最终答案将LLM生成的结果返回给用户并将本轮交互存入记忆库。4. 性能对比与问题排查实录4.1 量化指标对比新旧架构的差异我们在一个内部知识库问答系统上对两种架构进行了为期一周的A/B测试各50%流量。核心指标对比如下指标旧架构 (LLM在检索路径中)新架构 (LLM在检索路径后)提升/变化平均响应时间 (P50)4200 ms950 ms降低77%长尾延迟 (P95)12500 ms2100 ms降低83%单次请求成本 (估算)0.012 USD0.004 USD降低67%检索召回率 (Recall5)88%85%轻微下降3%答案准确率 (人工评估)91%94%提升3%服务可用性99.2%99.95%显著提升结果分析延迟与成本提升是颠覆性的。这主要归功于移除了串行的、高延迟高成本的LLM调用查询重写并用本地化、并行的轻量级组件替代。召回率新架构的召回率略有下降这在意料之中。因为LLM的查询重写有时确实能神奇地匹配到一些边缘case。但这个差距远比我们想象的小通过优化本地预处理管道和双路检索我们几乎追平了LLM的效果。答案准确率不降反升这是最关键的发现。旧架构中LLM在检索前重写查询一旦重写出现偏差后续检索就是“垃圾进垃圾出”且难以纠正。新架构中LLM在检索后工作它能看到更全面的原始材料并行使“裁判”和“编辑”的职责过滤错误信息综合多源信息从而生成更可靠的答案。4.2 典型问题排查与解决技巧在架构迁移和优化过程中我们遇到了不少具体问题以下是其中三个典型的排查案例问题一关键词检索路召回大量无关结果拉低了整体精度。现象用户问“如何报销差旅费”关键词检索路返回了大量包含“报销”、“费”但内容是关于“采购费”、“软件费”的文档。排查分析发现中文分词器将“差旅费”切分成了“差旅”和“费”而“费”这个词的TF-IDF权重在全局很高导致很多包含“费”的文档被召回。解决自定义词典将“差旅费”、“iPhone 15”等业务核心复合词加入分词器的自定义词典确保其作为一个整体被识别。提升字段权重在全文检索中对文档的“标题”、“摘要”字段赋予比“正文”更高的权重。使用BM25算法调参调整BM25中的k1和b参数控制词频和文档长度归一化的影响使其更适合短查询。查询时Boosting在构建查询时对识别出的实体词如“差旅费”给予更高的权重。问题二向量检索路对特定领域术语不敏感。现象内部项目代号“阿波罗计划”在向量空间中与通用的“阿波罗”或“计划”语义接近导致误召回。解决领域微调嵌入模型收集一批公司内部的问答对、文档对开源的嵌入模型如BGE进行轻量级的继续预训练Continue Pre-training或对比学习微调让模型更好地理解内部术语的语义。混合检索的权重调整对于这类专有名词在融合策略中提高关键词检索路的权重。因为专有名词的精确匹配比语义相似更重要。元数据辅助为文档添加“项目名称”等元数据字段。检索时先通过NER识别出“阿波罗计划”作为实体然后将其作为过滤条件只检索project_name包含“阿波罗计划”的文档再在这些文档中进行语义搜索。问题三LLM作为后处理器时有时会“虚构”答案忽略提供的参考资料。现象即使检索到了正确答案的片段LLM生成的回答中仍包含一些资料中不存在的信息。排查这是LLM的“幻觉”问题。在Prompt设计上我们虽然提供了参考资料但指令不够强硬LLM还是会依赖自己的知识。解决强化Prompt指令在Prompt中明确且强硬地要求“你的回答必须严格且仅基于提供的参考资料。如果资料中没有相关信息请直接说‘根据现有资料无法回答该问题’不要自行编造任何信息。”引用溯源要求LLM在回答中的每一句关键陈述后注明引用的资料编号如[1]。这不仅能遏制幻觉还能增加答案的可信度。我们在后端可以解析这些引用并做验证。设置低“温度”参数将LLM API调用时的temperature参数设为0或接近0如0.1减少生成的随机性。后处理校验开发一个简单的校验模块将LLM生成的答案中的关键事实如日期、数字、名称与检索到的原文进行快速匹配如果匹配度过低则触发警告或重生成。5. 总结与个人实践心得将LLM移出Agent的记忆检索路径不是一个关于“LLM强不强”的争论而是一个关于“如何正确使用工具”的架构哲学。LLM是强大的生成式大脑但它昂贵、缓慢且有一定不确定性。检索系统是高效的记忆提取器它需要稳定、快速和确定。让两者各司其职在清晰的边界下协同工作才能构建出既智能又健壮的应用。我个人最大的体会是在AI应用架构中“解耦”和“边界划分”比“堆砌智能”更重要。初期我们总想用最强大的模型去解决所有问题但这往往会导致系统脆弱且昂贵。一个稳健的架构应该像一台精密的机器每个部件都有明确的职责和性能指标检索部件追求速度和召回率理解部件追求深度和准确性它们通过定义良好的接口如检索结果列表、格式化Prompt进行通信。对于正准备构建类似系统的朋友我的建议是从一开始就设计一个没有LLM参与的、独立的检索核心。先把这个核心的召回率和速度优化到极致。然后再将LLM作为一个“增强插件”接入让它来处理检索核心之上的、需要真正智能的任务比如信息整合、逻辑推理、多轮决策和人性化交互。这样你的系统基础才是牢固的也更容易在未来替换或升级其中的任何一个部件无论是检索模型还是LLM本身。最后这个选择也让我们团队更加关注数据本身的质量。当检索不再依赖LLM的“魔法”来弥补缺陷时我们就必须下功夫去优化知识库的结构、文档的清洗和索引的构建。这反过来又进一步提升了整个系统的最终效果。技术决策往往就是这样退一步反而能海阔天空。

更多文章