公司动态
从全量注入到智能路由:LLM应用架构优化实战
1. 从“全量注入”到“智能路由”一次架构思维的转变最近在折腾一个基于大语言模型的应用框架名字叫 OpenClaw。这个名字挺有意思直译过来是“开放的爪子”听起来就很有抓取和操控的意味。它的核心设计理念或者说我最初接触它时最吸引我的地方是所谓的“全量上下文注入”。简单来说就是不管用户问什么系统都会把当前会话里所有相关的历史对话、知识库文档、工具调用记录一股脑儿地塞给大模型让它自己去“大海捞针”从中找出答案。这个模式听起来很强大对吧理论上模型拥有全部信息应该能做出最全面的判断。但实际用起来尤其是在处理稍微复杂一点的业务流程或者多轮对话时问题就暴露出来了。最直观的感受就是“慢”和“贵”。每次请求都携带海量上下文不仅增加了网络传输和模型处理的负担导致响应延迟更重要的是大模型是按输入和输出的 token 数量计费的这种“全量”模式简直就是“烧钱”模式。更隐蔽的问题是“噪声干扰”。当上下文过长、信息过载时模型反而容易被无关的历史信息带偏或者因为信息冗余而无法聚焦于当前任务的核心导致回答质量下降甚至出现“幻觉”——编造一些不存在的信息。所以我决定动手改造它。我的目标很明确把这种简单粗暴的“全量上下文注入”升级为一种更精细、更智能的“路由 记忆 编排”架构。这不仅仅是技术上的优化更是一次架构思维的转变——从“给模型所有数据让它自己找”转变为“由系统智能地管理数据流只给模型它当下最需要的那部分”。接下来我就详细拆解一下我是如何一步步实现这个转变的以及在这个过程中踩过的坑和总结的经验。2. 架构拆解理解“路由”、“记忆”与“编排”的核心角色在动手之前我们必须先厘清这三个核心概念在优化后的架构中分别扮演什么角色以及它们是如何协同工作的。这就像组建一支特种部队每个成员都有明确的职责和协作机制。2.1 路由智能的流量分发与决策中枢“路由”是整个架构的“大脑”和“交警”。它的核心职责是分析用户的当前请求Query并决定接下来应该走哪条“路”。这里的“路”可以指向不同的处理模块、工具、知识库甚至是不同的对话策略。工作流程当一个新的用户请求进来时路由模块首先会对其进行分析。这个分析可以基于简单的关键词匹配、意图识别Intent Classification或者更复杂的语义理解。例如用户问“帮我查一下上个月的销售额报告”路由模块需要识别出这是一个“数据查询”意图并且需要“上个月”这个时间范围和“销售额报告”这个数据实体。决策输出基于分析结果路由模块会生成一个明确的“指令集”。这个指令集可能包括调用哪个工具Tool比如调用“数据库查询工具”并附上查询条件时间范围、报告类型。检索哪部分记忆Memory比如从长期记忆中检索用户之前对“销售额”定义的特殊偏好或者从短期记忆中提取上一轮对话中提到的“本月目标”。采用哪种对话策略Orchestration Policy比如这是一个需要分步确认的复杂任务还是一个可以直接返回结果的简单查询。技术实现选型路由的实现可以有很多层次。对于简单场景可以用规则引擎Rule Engine或决策树。但对于OpenClaw这种希望处理复杂、开放域对话的应用我强烈推荐使用一个轻量级的、专门用于路由的LLM。这个路由LLM的模型可以很小比如7B甚至更小的参数它的提示词Prompt被精心设计为只做“分类”和“指令生成”这一件事这样成本低、速度快、准确率高。它的输入是当前用户Query和可用的工具/记忆列表输出就是一个结构化的路由指令JSON。注意路由模块的成功与否很大程度上取决于你对业务场景的“意图”拆解得是否足够细粒度。意图划分太粗路由就失去了意义划分太细又会增加复杂度和维护成本。这是一个需要权衡的艺术。2.2 记忆分层化的信息存储与检索系统“记忆”是架构的“知识库”和“记事本”。在“全量注入”模式下记忆是混沌一团的。现在我们需要对它进行分层管理让系统能快速、精准地找到所需信息。我将记忆系统分为三层这借鉴了人类记忆和许多成熟AI系统的设计短期记忆Short-term Memory / Conversation Buffer功能存储当前对话轮次例如最近10轮的原始对话历史。它的容量小存取速度快。用途主要用于维持对话的连贯性让模型理解“刚才我们说到哪了”。例如用户说“把它改成红色”模型需要从短期记忆中知道“它”指的是上一句提到的“那件衬衫”。实现通常用一个固定长度的队列FIFO来实现新的对话内容进入最老的被挤出。长期记忆Long-term Memory / Vector Database功能存储跨越多个会话的、重要的用户信息、事实知识、业务规则等。容量大但检索需要计算。用途用于个性化服务和深度知识问答。例如记住用户的偏好“不喜欢电话沟通”、公司的产品手册内容、历史订单信息等。实现这是优化的关键。我使用向量数据库如Chroma, Pinecone, Weaviate。所有需要长期记忆的文本都被转换成向量Embedding存储起来。当路由模块判定需要长期记忆时系统会将当前Query也转换成向量然后在向量数据库中进行相似性搜索Similarity Search只召回最相关的几条记忆片段而不是全部。这极大地减少了上下文长度。工作记忆Working Memory / State功能这是一个动态的、结构化的“便签本”存储当前复杂任务执行过程中的中间状态和临时变量。用途在多步骤任务编排中至关重要。比如一个“订机票酒店租车”的旅行规划任务工作记忆会记录“已选定航班班次”、“酒店待支付”、“租车车型偏好”等状态。实现可以用一个简单的键值对Key-Value存储或者更结构化的对象Object来管理。它在单次任务会话中有效任务结束后通常被清理或归档到长期记忆。2.3 编排动态的任务流执行引擎“编排”是架构的“指挥家”和“粘合剂”。它接收来自路由模块的指令然后协调“记忆”和“工具”等各个组件按照一定的逻辑顺序执行任务并管理整个对话状态。核心能力编排模块的核心是管理控制流Control Flow。这包括了顺序执行、条件分支if-else、循环loop等。例如路由指令是“生成周报”编排模块可能会分解为1) 从长期记忆检索上周任务列表2) 调用“总结工具”生成每项任务总结3) 调用“文档生成工具”整合成报告4) 询问用户是否发送。与状态管理编排器紧密依赖“工作记忆”。它读取当前状态来决定下一步做什么并在每一步执行后更新状态。这实现了对话的“有状态性”让AI能处理复杂的、多轮交互的任务。技术实现对于简单逻辑可以用硬编码的状态机State Machine。但对于OpenClaw期望的灵活性我采用了基于LLM的规划器Planner或智能体Agent框架如LangChain的Agent、AutoGen。这些框架本质上是一个高级的编排器它们能理解自然语言指令动态地决定下一步调用哪个工具并处理工具的返回结果。三者关系总结用户Query触发路由路由分析后生成指令给编排器编排器根据指令从记忆系统中精准提取所需信息短期/长期/工作记忆并调用相应的工具执行任务执行结果可能更新记忆并生成最终响应给用户。整个流程形成了一个高效、可控的闭环。3. 实战改造在OpenClaw中逐步替换“全量注入”理论清晰后我们进入实战环节。对OpenClaw的改造不是一蹴而就的我采取了渐进式的策略核心是拦截原有的“上下文组装”环节用新的智能管道替换它。3.1 第一步构建独立的路由决策层首先我需要让系统学会“做选择”。我在请求处理流水线的最前端插入了一个路由决策模块。创建路由分类器我没有直接用主业务LLM来做路由而是单独部署了一个小模型例如Qwen-7B-Chat-Int4。为它编写专门的提示词你是一个高效的路由分类器。请根据用户问题判断其意图并生成结构化指令。 可用工具[“知识库查询”, “计算器”, “天气查询”, “日程管理”, “闲聊”] 可用记忆类型[“对话历史”, “用户档案”, “产品知识”] 用户问题{user_query} 请以JSON格式输出包含字段 - primary_intent: 主要意图从可用工具中选择或“纯对话” - needed_memory: 需要检索的记忆类型列表从可用记忆类型中选择 - parameters: 提取的关键参数对象如时间、地点、名称等集成到OpenClaw修改OpenClaw的请求入口函数。在将用户输入和传统上下文拼接发送给主LLM之前先调用这个路由分类器。结果解析与传递解析路由分类器返回的JSON将primary_intent、needed_memory、parameters这些信息作为“元数据”附加到请求中传递给后续环节。此时主LLM的上下文仍然是全量的但我们已经有了路由信息。实操心得路由提示词的设计是关键。你需要用大量示例Few-shot去“教”这个小模型如何准确分类。示例要覆盖边界情况比如模糊的提问“今天怎么样”可能指天气也可能指心情。一开始路由准确率可能只有80%需要通过bad case不断迭代提示词。3.2 第二步实现分层记忆的动态检索有了路由指令下一步就是按需获取记忆而不是全量注入。改造记忆管理系统短期记忆维持原有的对话历史队列但将其从主上下文中剥离变成一个独立的、可按需引用的模块。长期记忆引入向量数据库。将原有的静态知识库文档、用户资料等通过嵌入模型如text-embedding-3-small批量转换为向量存入向量数据库我选用了Chroma因其轻量易用。工作记忆在会话中创建一个全局的状态字典State Dict用于存储任务执行过程中的变量。构建记忆检索器编写一个MemoryRetriever类。它的retrieve方法接收路由指令中的needed_memory列表和当前user_query。如果needed_memory包含“对话历史”则从短期记忆队列中取出最近N条。如果包含“用户档案”或“产品知识”则将user_query转换为向量在对应的向量集合中进行相似度搜索返回Top K个最相关的片段例如K3。将检索到的所有记忆片段按照一定的模板如“相关用户信息{info}”格式化准备注入。替换上下文组装逻辑这是最关键的一步。找到OpenClaw中原来那个把所有历史对话和知识拼接成一个长字符串的函数。将其重写def build_intelligent_context(user_query, conversation_history, full_knowledge_base): # 1. 路由决策 route_instruction route_classifier.predict(user_query) # 2. 按需检索记忆 retrieved_memories memory_retriever.retrieve( queryuser_query, needed_typesroute_instruction[‘needed_memory’] ) # 3. 组装精炼上下文 new_context f“”” 当前用户问题{user_query} [系统指令] 根据分析本次对话的核心意图是{route_instruction[‘primary_intent’]}。 以下是为你筛选的相关背景信息请基于此回答问题 [相关对话历史] {retrieved_memories.get(‘conversation’, ‘无’)} [相关知识与信息] {retrieved_memories.get(‘knowledge’, ‘无’)} 请直接针对问题结合上述信息进行回答。 ““” return new_context, route_instruction # 同时返回路由指令供编排器使用可以看到新的上下文非常精炼只包含路由认为必要的信息。3.3 第三步集成编排引擎串联工具与多步任务最后我们需要一个“指挥官”来利用路由信息协调工具调用和复杂任务流。我将一个轻量级的Agent框架如LangChain的Tool-calling Agent集成到OpenClaw中。封装工具将OpenClaw原有的或新增的业务功能查数据库、调用API、运行代码等包装成标准的“工具”函数并为其提供清晰的名称和描述。创建编排器Agent配置一个主LLM作为Agent的核心并将上一步封装好的工具列表提供给Agent。同时将我们构建的build_intelligent_context函数作为Agent的“预处理”环节。改造主流程最终的请求处理流程变为def process_request(user_query): # 1. 智能构建上下文 (包含路由和记忆检索) context, route_instruction build_intelligent_context(user_query, ...) # 2. 将精炼上下文、用户问题、路由参数一同交给Agent agent_response orchestration_agent.run( inputf“背景{context}\n\n问题{user_query}”, additional_parametersroute_instruction[‘parameters’] ) # 3. Agent自动决定是否及如何调用工具并生成最终回答 # 4. 更新短期记忆和工作记忆 update_memory(user_query, agent_response, route_instruction) return agent_response现在当用户问“帮我对比产品A和产品B的最新价格并总结优劣”时路由会识别出“对比分析”意图检索长期记忆中产品A和B的规格书。Agent编排器收到后可能会先调用“价格查询工具”获取实时价格再调用“文本分析工具”对比规格最后组织语言生成报告。整个过程是动态、多步的。4. 性能对比与优化效果实测架构改造完成后不能光凭感觉必须用数据说话。我设计了一系列测试用例从简单问答到复杂多轮任务对比优化前后的关键指标。测试场景优化前全量注入优化后路由记忆编排效果提升单轮简单问答(e.g., “你好”)上下文长度约500 token响应时间~1200msAPI成本~0.001美元上下文长度~150 token响应时间~450msAPI成本~0.0003美元响应速度提升62.5%单次成本降低70%多轮带历史参照的对话(e.g., “我上次说的那件事怎么样了”)上下文长度随轮次线性增长模型易受早期无关历史干扰第10轮响应时间~2500ms路由精准提取最近相关历史2-3条上下文长度稳定在~300 token响应时间稳定在~500ms抗干扰能力显著增强性能不再随轮次劣化需要深度知识检索的任务(e.g., “根据Q2财报分析市场风险”)注入全部知识库数万token响应慢成本极高模型可能“迷失”路由触发向量检索仅注入Top 3相关文档片段(~600 token)响应快答案更聚焦成本降低一个数量级答案准确性和相关性大幅提升复杂多步骤工具调用(e.g., “订明天北京飞上海的机票选靠窗座位”)难以处理。模型可能一次性输出不完整的指令或无法记住多步状态。编排器Agent分步执行1.查询航班 2.选择航班 3.选择座位 4.确认。工作记忆跟踪状态。从不可行变为可行任务完成率从10%提升至85%核心优化点总结Token消耗与成本平均减少60%-90%的输入token这是最直接的经济效益。响应延迟因处理数据量减少和并行检索向量检索可与路由计算并行端到端延迟降低50%以上。回答质量由于上下文噪声降低模型输出更加专注、准确幻觉率有所下降。系统能力边界从单一的“问答机”扩展为可处理复杂、有状态工作流的“智能助手”。5. 避坑指南改造过程中遇到的典型问题与解决方案这次改造并非一帆风顺以下是几个印象深刻的“坑”及其解决方法。5.1 路由决策的“摇摆”与“模糊查询”处理问题初期路由小模型对于边界模糊的查询处理不稳定。比如“讲个笑话”它有时会归类为“闲聊”有时又会因为知识库里有“笑话大全”文档而被归类为“知识库查询”。根因定位提示词中对意图的界定不够清晰且缺少对“默认”或“兜底”路径的引导。同时模型对用户Query的语义理解存在轻微偏差。解决方案细化意图定义与优先级在提示词中明确“闲聊”意图的优先级高于“知识库查询”除非用户明确说“从你的知识库里找个笑话”。可以定义意图置信度阈值低于阈值则进入“澄清”流程。引入少样本示例在路由提示词中增加几个典型的模糊查询示例及其正确输出让模型学会处理。设计澄清流程当路由置信度不高时不强行决策而是让编排器生成一个澄清问题例如“您是想让我随便讲个笑话还是从笑话库里为您挑选一个”。这虽然增加了一轮交互但体验远比给出错误答案要好。最终方案我采用了“路由 轻量验证”的模式。路由首先给出初步意图和参数然后由一个极简的规则层或另一个更小的分类器进行快速校验。例如如果路由输出是“知识库查询”且参数中包含“笑话”、“故事”等词则强制覆盖为“闲聊”。这个规则层作为安全网有效解决了大部分摇摆问题。5.2 向量检索的“相关性陷阱”与“信息缺失”问题有时向量检索返回的Top 3片段看似语义相关但并未包含回答问题的关键信息。或者关键信息被分散在多个片段中只召回其中一个导致答案不全。根因定位嵌入模型Embedding Model的语义表示能力有局限且检索时只考虑Query与片段的相似度没有考虑片段之间的关联性。解决方案优化文本分块Chunking策略不要简单按固定长度分块。对于结构化文档如产品手册按章节或主题分块对于非结构化文本使用语义分割模型或至少基于标点、段落进行自然分块保证块内语义完整性。采用混合检索Hybrid Search不单纯依赖向量相似度搜索。我结合了关键词检索如BM25。先通过关键词快速筛选出候选文档再对候选文档进行向量相似度精排。这样可以确保包含关键术语的片段不被遗漏。实施重排序Re-ranking检索出Top N例如N10个片段后使用一个更精细的、专门用于重排序的小模型Cross-Encoder计算Query与每个片段的相关性得分重新排序后取Top KK3。这虽然增加了少量计算但显著提升了召回片段的质量。设计备用降级策略当编排器发现检索到的信息不足以回答问题时可以触发一个“扩大检索范围”的指令或者直接告知用户“我找到的信息可能不完整建议您提供更详细的关键词”。5.3 编排器Agent的“循环调用”与“任务失控”问题在复杂任务中Agent有时会陷入死循环反复调用同一个工具或者在一个简单问题上分解出过多不必要的步骤。根因定位LLM作为Agent的“大脑”其思维过程具有不确定性。当工具返回的结果不明确或Agent对任务分解的理解出现偏差时就容易失控。解决方案为工具调用设置严格限制在Agent框架中明确设置最大迭代次数Max Iterations比如10次。达到上限后强制终止并返回当前已收集的信息和“任务未完成”的提示。增强工具的反馈清晰度确保每个工具在失败或结果为空时返回结构化的错误信息或明确的状态如{“status”: “error”, “message”: “未找到符合条件的数据”}而不是简单的None或异常。这有助于Agent理解情况并调整策略。设计更精细的Agent提示词在提示词中明确强调“效率”和“必要性”。例如加入“请用最少的步骤解决问题”、“如果第一步工具调用已获得足够信息请直接给出最终答案无需继续调用其他工具”等指令。引入人工监督或确认点对于高风险或关键操作如发送邮件、修改数据在编排流程中设计“人工确认”步骤。Agent在执行到该步骤时会暂停并生成一段需要用户确认的文本。我的经验我发现在Agent的提示词中加入一个“思维链Chain-of-Thought自省”的要求很有效。即要求Agent在每一步决定调用工具前先用一句话说明“我为什么要调用这个工具我希望得到什么”。虽然这会增加少量token但大大提高了动作的可解释性和可控性我可以在日志中监控这些“自省”语句及时发现异常苗头。6. 进阶思考架构的扩展性与未来优化方向将OpenClaw改造为“路由记忆编排”架构后系统的可扩展性变得非常好。这里分享几个进一步的优化思路。1. 路由的进化从分类到规划目前的静态意图分类只是第一步。更高级的路由应该能进行初步的任务规划。例如用户说“我想策划一个周末团队建设活动”高级路由应该能输出一个初步的计划序列[“检索团队偏好记忆”, “调用活动推荐工具”, “调用预算计算工具”, “生成提案草案”]为后续的编排器提供一个高层次的“蓝图”。2. 记忆的融合从检索到推理现在的记忆检索主要是“查找-返回”模式。未来可以引入记忆融合与推理层。例如当检索到“用户喜欢登山”和“上周团队反馈需要加强沟通”两条记忆时系统能自动推理出“本次团建可考虑户外登山沟通工作坊的组合方案”并将这个推理结论作为新生成的“衍生记忆”提供给模型而不仅仅是原始片段。3. 编排的协同从单智能体到多智能体对于极其复杂的任务单个编排Agent可能力不从心。可以引入多智能体Multi-Agent协作。例如一个“规划Agent”负责拆解任务一个“研究Agent”负责信息检索一个“写作Agent”负责整合成文一个“审核Agent”负责检查质量。它们之间通过共享的工作记忆和消息队列进行协作类似一个项目组各司其职。4. 持续学习与自适应当前的系统参数如路由规则、检索的Top K值大多是静态设置的。可以引入简单的在线学习机制。例如如果用户频繁对某类问题的回答进行“点赞”或“点踩”系统可以微调路由策略或该领域知识的检索权重让系统越来越适应用户的个性化需求。这次对OpenClaw的改造让我深刻体会到构建一个强大的LLM应用核心不在于堆砌最庞大的模型而在于设计一个精巧的、能够高效管理和运用模型能力的软件架构。“路由记忆编排”这个模式正是将LLM从“全能但低效的巨兽”驯化为“专业且高效的伙伴”的关键。它通过分层与调度实现了成本、速度和效果的最佳平衡。如果你也在为上下文爆炸、成本高昂或任务处理能力有限而烦恼不妨从引入一个简单的路由器开始逐步重构你的系统管道相信你也能收获显著的性能提升和更可控的用户体验。