在过去的一两年里,大语言模型(LLM)的发展让 AI Agent 迎来了寒武纪大爆发。然而,当我们将 Agent 从简单的“单点对话”推向诸如“端到端旅游规划”这样长链路、多异构数据源的复杂生产场景时,传统基于单体 LLM 的 ReAct (Reason+Act) 模式迅速暴露出其工程瓶颈:响应极慢、状态易崩、逻辑与执行深度耦合。
本文将分享我们团队如何跳出“用一个无所不能的上帝 Prompt 解决所有问题”的思维陷阱,通过引入确定性的代码编排中枢(Orchestrator)、内容感知(Content-Aware)的调度决策以及多智能体异步协作,构建出千万级并发下的新一代旅游规划系统架构。
在重构之前,我们和业界许多团队一样,试图构建一个“全能旅行管家”。我们给 GPT-4 塞入了一个长达几千 Token 的系统提示词(涵盖了意图识别、规划逻辑、各种 Search 工具的使用、数据聚合格式等)。
结果在生产环境中,我们遭遇了“灾难级”的体验:
- 串行阻塞导致的性能灾难:规划一次旅行需要查天气、订酒店、排景点。LLM 只能“思考-调用天气-等待-思考-调用酒店-等待”。这种纯串行机制使得总耗时等于所有外部 API 耗时的简单叠加,用户往往需要等待几分钟才能看到结果。
- 状态丢失与幻觉:在长达几十轮的内部 Tool Calling 循环中,LLM 极易忘记最初的用户约束(如“不坐飞机”),或者在最后一步整合数据时发生幻觉。
- “知识重复抓取”带来的算力浪费:用户问“故宫的历史背景”,Agent 跑去实时抓取网页;下一个用户问同样的请求,Agent 依然去抓网页。LLM 无法区分哪些是高时效的个性化数据(如今天希尔顿的房价),哪些是高通用的静态知识。
我们的核心洞察是:LLM 极其擅长自然语言理解和非结构化数据的抽取,但它绝对不是一个合格的“状态机”或“任务调度器”。
为了解决上述问题,我们彻底重构了系统,提出了一种基于中心化编排 + 多智能体协作的架构。
在这个架构中,我们定义了五类核心组件,明确了各自的边界:
- 需求分析智能体 (Requirement Analysis Agent):一个极轻量级的 LLM 节点,唯一职责是将用户的自然语言(“想去海边玩三天,预算三千”)提取并补全为结构化的任务简报 (Task Brief) JSON。
- 旅行规划编排器 (Travel Orchestrator) [核心]:一个基于 Java 和 RxJava 构建的纯确定性代码服务。它不依赖 LLM 生成执行路径,而是根据 Task Brief 动态生成任务执行图 (DAG),进行并发调度。
- 任务类型决策模块与旅游知识库 (Task Decision & Knowledge Base):编排器内的智能拦截器,负责缓存命中与异构任务的路由。
- 专业任务智能体 (Specialized Task Agents):被剥离了复杂规划逻辑的“打工人”,分为基于 MCP 协议的直连型 Agent 和基于浏览器自动化的抓取型 Agent。
- UI 渲染智能体 (UI Rendering Agent):专门负责将 JSON 转化为精美行程单 HTML,实现数据与表现层的彻底解耦。
下面,我们将深入代码底层,看看这些架构理念是如何落地的。
在单体架构中,LLM 决定先查机票再查酒店。在我们的系统中,编排器接管了调度权。当接收到任务简报后,编排器会将其拆解为独立的子任务,利用 RxJava 的异步响应式流和远端 Agent 通信(A2A Client)实现并行抓取。总耗时从 \(O(N)\) 锐减为 \(O(max(T))\)。
以下是我们的核心调度代码片段缩影(基于 A2AClientService 与并发组合):
{ A2AClientService a2aClient; TaskDecisionModule decisionModule; SupabaseManager supabaseManager; / * 接收任务简报,构建执行图并异步并行拉取数据 */ Single
{
log.(, threadId); <> subTasks .decompose(brief); <<>> taskFutures subTasks.stream() .map(task -> CompletableFuture.supplyAsync(() -> parseToJson(resultRaw); } })) .(Collectors.toList()); CompletableFuture<> allOf = CompletableFuture.allOf( taskFutures.toArray( CompletableFuture[]) ); Single.fromCompletionStage(allOf.thenApply(v -> { TripDataJson finalData = TripDataJson(); taskFutures.forEach(future -> finalData.(future.())); finalData; })); }}
这是竞争对手短期内难以逾越的壁垒。通用的编排框架(如 LangChain 的 SequentialChain)是“无感知”的,它不知道自己调度的内容是什么。
我们的 TaskDecisionModule 引入了领域知识。在分发任务前,它会拦截任务并进行判断:这究竟是一个需要实时挂载无头浏览器去抓取的“动态个性化任务”,还是一个可以直接走 Redis/Supabase 知识库的“静态通用任务”?
GPT plus 代充 只需 145 if (task.getCategory() == Category.STATIC_KNOWLEDGE) ", task.()); ExecutionStrategy(, , cachedInfo); } } ExecutionStrategy(, , ); } ExecutionStrategy(, , ); }}
通过这种知识库前置拦截+按需执行的机制,对于热门城市的常规规划请求,我们的系统能将超过 60% 的子任务直接通过内存返回。这带来了意想不到的技术效果:复杂行程的生成速度从分钟级直接拉升到了秒级(Sub-Second 级别体验)。
在早期版本中,我们要求核心 LLM 直接输出带有复杂交互逻辑的 HTML 页面。结果是灾难性的:HTML 标签极易闭合错误,样式混乱,而且极大地消耗了主流程的 Token 额度。
我们最终意识到,AI 应用也必须遵循传统软件工程的 MVC (Model-View-Controller) 原则。
在我们的架构中,编排器(Controller)产出的是一份纯粹的、严格结构化的 trip_data.json(Model)。最后,我们通过 A2AClient 将这份 JSON 通过任务转移(task_transfer)交给专门的 UI 渲染智能体(View Agent):
Flowable
{
jsonData = objectMapper.writeValueAsString(tripData); htmlRendered = a2aClient.callAgentSync( , + jsonData, … ); AdkPart part = Resources.HtmlView.createPart(UUID.randomUUID().toString(), .of(, htmlRendered)); Flowable.just(responseFactory.wrapEvent(requestId, part, invocationId, ));}
将“数据整合的终点”和“视觉呈现的起点”进行硬切分,使得我们可以随时更换前端模板,且彻底杜绝了数据处理逻辑与 UI 代码混杂导致的崩溃。
时至今日,随着 MCP (Model Context Protocol) 的普及以及各类小参数特化模型的成熟,AI Agent 的架构正在发生深刻的范式转移。
我们构建的这套多智能体旅游规划系统证明了一个观点:未来的复杂 AI 应用,绝不是靠一个巨大的模型加无数的 Prompt 堆砌出来的,而是靠优秀的软件工程架构设计出来的。
通过将不确定的规划逻辑剥离给确定性的代码编排器,将异构数据获取下放给多模态专业智能体,并引入基于知识库的智能拦截机制,我们成功解决了异构数据整合难、响应速度慢、系统扩展性差的痛点。
“不写代码”的纯 Prompt 工程师时代正在过去,懂得如何将 AI 能力(Agentic APIs)作为组件,完美融入分布式、高并发、基于状态机制的现代工程架构中的架构师,才是这个时代真正的主力军。
作者简介:深耕大后端与 AI 架构领域,致力于探索 LLM 在高并发业务场景下的工程化落地。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/244915.html