
1. 从一张架构图说起AI应用到底该怎么搭这两年我参与过不少AI应用项目的架构评审也帮朋友从零搭过几个Agent产品。说实话大部分团队在动手之前脑子里其实没有一张清晰的架构图。大家一上来就讨论用哪个模型、要不要上RAG、Agent框架选LangChain还是别的结果做到一半发现数据流对不上、工具调用乱成一锅粥、并发一上来整个系统就崩了。“图解AI应用架构设计”这个主题我想聊的不是画一张好看的PPT架构图而是把AI应用从输入到输出这条链路上每一层到底在干什么、层与层之间怎么衔接、哪些地方最容易出问题用图解的思路给你拆明白。核心关键词就几个AI应用、架构设计、Agent、LLM、MCP。这几个词基本构成了当下AI应用开发的主干。这篇文章适合谁看如果你是一个正在做AI应用开发的程序员或者是一个想从传统后端/运维转向AI应用方向的工程师又或者你是一个技术负责人需要评估AI项目的架构方案那这篇内容应该能帮你建立起一套完整的认知框架。我不会只讲概念每个层次我都会给出具体的选型建议、参数考量、实操中踩过的坑以及可以直接参考的代码结构。先说一个我自己的判断AI应用的架构设计本质上是在解决“不确定性管理”的问题。传统软件是确定性的输入输出你调一个函数给定参数就一定有确定的返回。但LLM不一样同样的prompt两次调用可能给出不同的结果。Agent更甚它自己决定调什么工具、调几次、什么时候停。所以架构设计的核心目标就是在这个不确定的基础上构建出稳定、可观测、可扩展的系统。2. AI应用架构的整体分层与核心思路2.1 为什么需要分层架构我见过不少团队一开始把AI应用写成一个巨大的函数接收用户输入拼prompt调LLM解析结果返回。这种写法在demo阶段没问题但一旦要加记忆、加工具调用、加多轮对话、加权限控制代码就会变成一团乱麻。分层架构的价值在于关注点分离。每一层只负责自己的事层与层之间通过明确的接口通信。这样做的好处是换模型不用改业务逻辑加工具不用动prompt管理调并发不用重写整个链路。我通常把AI应用分成这么几层从下往上说模型层LLM本身包括模型选型、推理部署、token管理能力层把LLM的能力封装成可复用的组件比如RAG检索、工具调用、记忆管理编排层Agent的核心决定什么时候调什么能力、怎么组织多步推理协议层MCP这类标准化协议解决工具和数据的接入问题应用层面向用户的接口包括对话管理、权限、前端交互基础设施层贯穿所有层的可观测性、缓存、限流、安全这六层不是必须全部都有小项目可能只有模型层和应用层。但只要你的AI应用开始涉及工具调用和多轮交互这套分层就能帮你理清思路。2.2 模型层LLM选型的三个关键维度模型选型是架构设计的第一步也是最容易纠结的一步。我的经验是不要一上来就追求最强模型而是从三个维度来评估第一个维度是任务复杂度。如果你的任务只是简单的文本分类、信息抽取那一个小参数量的模型就够了成本低、延迟低。如果涉及复杂的推理、多步规划、代码生成那就需要更强的模型。我一般会建议团队先用一个中等模型跑通链路再根据效果决定是否升级。第二个维度是延迟要求。在线交互场景用户能接受的首次响应时间大概在2-3秒以内。如果模型推理本身就要5秒那架构上就必须考虑流式输出让用户先看到部分结果。流式输出不是可选项是交互类AI应用的标配。第三个维度是成本。这里要算一笔账假设你的应用每天有1万次调用每次平均消耗2000个token输入输出那一天的token消耗就是2000万。不同模型的单价差异可能达到几十倍一个月下来成本差距非常可观。所以架构设计时一定要把token消耗纳入考量该用便宜模型的地方不要用贵的。关于token有个很形象的类比LLM的注意力机制里key是“我是谁”query是“我在找什么”value是“我能提供什么”。输入文本被映射成这三组向量通过query和key的匹配来决定关注哪些value。理解这个机制你就能明白为什么prompt的写法对结果影响这么大——你给的query越明确模型越能匹配到正确的信息。2.3 能力层RAG、工具调用与记忆管理能力层是把LLM的原始能力包装成业务可用的组件。最核心的三块是RAG、工具调用和记忆管理。RAG检索增强生成解决的是模型知识不足和幻觉问题。它的基本流程是把文档切块、向量化、存入向量数据库用户提问时先检索相关片段再把片段作为上下文喂给LLM。这里的关键参数是切块大小和检索数量。切块太大检索精度下降切块太小上下文不完整。我的经验是中文文档切块大小在300-500字比较合适检索返回top 3-5个片段。工具调用让LLM能够与外部系统交互。比如查天气、查数据库、发邮件。工具调用的架构设计要点是工具的输入输出schema要严格定义工具的执行要有超时和重试机制工具的结果要能被LLM理解。我见过最常见的坑是工具返回的数据格式不统一导致LLM解析失败。记忆管理分短期记忆和长期记忆。短期记忆就是当前对话的上下文通常直接放在prompt里。长期记忆需要持久化存储用户下次来的时候能回忆起之前的信息。长期记忆的实现方式有向量检索、摘要压缩、结构化存储等选择哪种取决于你的场景。2.4 编排层Agent的核心逻辑Agent是这两年最热的概念但很多人对它的理解停留在“能调工具的LLM”。其实Agent的核心在于自主决策它根据当前状态决定下一步做什么而不是按照预设的流程走。一个典型的Agent循环是观察当前状态 - 思考下一步行动 - 执行行动 - 观察结果 - 继续循环直到任务完成或达到终止条件。这个循环的实现方式有很多种常见的有ReAct、Plan-and-Execute、Reflexion等。架构设计时编排层要解决几个问题循环终止条件是什么最大迭代次数设多少工具调用失败怎么处理中间结果怎么存储这些问题不解决Agent很容易陷入死循环或者产生不可控的行为。2.5 协议层MCP为什么重要MCPModel Context Protocol是最近很火的一个概念。简单说它是一套标准化协议让LLM应用能够以统一的方式接入各种工具和数据源。在没有MCP之前每接一个工具就要写一套适配代码有了MCP工具提供方按照协议暴露接口应用方按照协议调用双方解耦。MCP的核心价值在于标准化。它定义了工具的描述格式、调用方式、返回结构让不同的AI应用能够复用同一套工具生态。我最近在做的几个项目都开始接入MCP最直观的感受是接入新工具的时间从原来的半天缩短到半小时。2.6 应用层与基础设施层应用层是用户直接接触的部分包括对话界面、会话管理、权限控制、多租户隔离等。这一层的架构设计要特别注意会话状态的管理。用户的每一轮对话都不是孤立的需要把历史上下文带上。但上下文不能无限增长要有截断或摘要策略。基础设施层是贯穿所有层的包括日志、监控、追踪、缓存、限流、安全。AI应用的可观测性比传统应用更重要因为LLM的输出是不确定的你需要记录每次调用的输入输出、token消耗、延迟、工具调用链路才能定位问题。3. 核心细节解析与实操要点3.1 Prompt工程在架构中的位置很多人把prompt工程当成一个独立的事情但在架构视角下prompt应该是可配置、可版本化、可测试的资产。我的做法是把prompt模板存在配置中心或数据库里每个prompt有唯一的key和版本号。应用运行时根据场景加载对应的prompt模板填充变量后发给LLM。这样做的好处是调整prompt不需要发版可以做A/B测试可以回滚到历史版本。Prompt模板的设计要注意几点系统提示词定义角色和约束用户提示词包含具体任务和上下文few-shot示例帮助模型理解输出格式。对于需要结构化输出的场景我会在prompt里明确给出JSON schema并在应用层做校验和重试。3.2 工具调用的参数设计与错误处理工具调用是Agent能力的核心但也是最容易出问题的地方。我总结了几条实操经验工具描述要精确。LLM是根据工具的名称和描述来决定是否调用的。如果描述模糊模型可能在不该调用的时候调用或者该调用的时候不调用。我的做法是给每个工具写一段清晰的描述说明它做什么、什么时候用、输入参数是什么格式。参数校验要严格。LLM生成的参数可能不符合预期比如该传数字的传了字符串该传枚举的传了不存在的值。应用层必须做参数校验校验失败时把错误信息返回给LLM让它重新生成。超时和重试要设置。外部工具可能超时或失败不能让Agent卡死。我一般设置单次工具调用超时5秒失败后重试1次重试还失败就把错误信息返回给LLM让它决定下一步。结果要截断。工具返回的结果可能很长直接塞进prompt会消耗大量token。我的做法是对结果做截断或摘要只保留关键信息。3.3 上下文窗口管理与token优化上下文窗口是LLM应用最稀缺的资源之一。一个对话轮次多了历史消息就会撑爆窗口。管理上下文窗口有几种策略滑动窗口只保留最近N轮对话。简单但会丢失早期信息。摘要压缩把早期对话用LLM总结成一段摘要替代原始消息。效果好但增加一次LLM调用。向量检索把历史消息存入向量库需要时检索相关片段。适合长期记忆场景。混合策略近期消息保留原文远期消息做摘要关键信息做结构化存储。我的经验是对于大多数对话场景滑动窗口摘要压缩的组合就够了。窗口大小根据模型能力定一般保留最近10-20轮对话更早的做摘要。3.4 Agent循环的终止条件设计Agent循环如果没有正确的终止条件很容易陷入死循环。我一般设置三重保险最大迭代次数硬性限制比如最多循环10次。超过就强制终止返回当前结果。任务完成检测Agent输出中包含特定的完成标记或者调用了特定的终止工具。无进展检测如果连续两轮的行动和结果高度相似说明Agent卡住了强制终止。这三重保险要同时设置不能只靠一个。我踩过的坑是只设了最大迭代次数结果Agent在10次循环里反复调同一个工具浪费了大量token。3.5 MCP接入的实操要点MCP的接入流程大致是工具提供方实现MCP Server暴露工具列表和调用接口应用方实现MCP Client连接Server并获取工具列表把工具描述注入到LLM的上下文中。实操中要注意几点连接管理要做好MCP Server可能断开要有重连机制工具列表缓存不要每次调用都去拉取工具列表权限控制不是所有工具对所有用户都开放错误隔离一个MCP Server挂了不能影响整个应用。4. 实操过程与核心环节实现4.1 一个最小可用AI应用的架构搭建假设我们要做一个智能客服Agent能回答产品问题、查询订单状态、转接人工。我按分层架构来搭模型层选一个中等规模的模型支持function calling。配置流式输出。能力层RAG把产品文档向量化存入向量库工具查询订单API、转接人工API记忆短期用滑动窗口长期用向量检索编排层用ReAct模式Agent根据用户问题决定是检索文档还是调工具。协议层工具通过MCP Server暴露应用通过MCP Client接入。应用层WebSocket接口支持流式输出会话状态存在Redis。基础设施层日志记录每次LLM调用和工具调用Prometheus监控延迟和token消耗。4.2 关键代码结构示例下面是一个简化的Agent循环实现用Python伪代码展示核心逻辑class Agent: def __init__(self, llm, tools, max_iterations10): self.llm llm self.tools tools self.max_iterations max_iterations def run(self, user_input, history): messages self.build_messages(user_input, history) for i in range(self.max_iterations): response self.llm.chat(messages, toolsself.tools.schemas) if response.is_final: return response.content if response.has_tool_call: tool_result self.execute_tool(response.tool_call) messages.append(response.message) messages.append(tool_result) if self.no_progress(messages): break return self.fallback_response(messages) def execute_tool(self, tool_call): tool self.tools.get(tool_call.name) try: result tool.execute(**tool_call.arguments) return format_tool_result(result) except Exception as e: return format_tool_error(e)这个结构的关键点是循环有最大次数限制工具执行有异常处理每轮都把工具结果追加到消息历史中。4.3 并发处理的设计AI应用的并发处理和传统应用不太一样因为LLM调用是长耗时操作。我一般从几个层面来处理请求队列用户请求先入队列后端worker从队列消费。这样可以控制并发数避免打爆LLM的rate limit。异步调用LLM调用用异步IO不要阻塞线程。Python里用asyncioJava里用CompletableFuture。流式输出对于长文本生成用SSE或WebSocket流式返回用户不用等全部生成完。缓存相同的输入可以缓存LLM的输出减少重复调用。但要注意缓存的key要包含完整的上下文。降级策略当LLM调用失败或超时时返回兜底回复不要让用户看到错误。4.4 可观测性的落地AI应用的可观测性我一般记录这几类数据数据类型记录内容用途LLM调用日志输入prompt、输出结果、token数、延迟调试、成本分析工具调用日志工具名、参数、结果、耗时排查工具问题Agent轨迹每轮思考、行动、观察分析Agent行为用户反馈点赞点踩、转人工率评估效果系统指标QPS、错误率、P99延迟监控告警这些数据要能关联起来通过一个trace_id串起一次完整的请求链路。我一般用OpenTelemetry做追踪日志存Elasticsearch指标存Prometheus。5. 常见问题与排查技巧实录5.1 LLM输出格式不稳定的排查这是最常见的问题。明明prompt里要求输出JSON模型有时候输出markdown代码块有时候输出纯文本有时候字段名还拼错。排查思路先看prompt是否足够明确给出完整的JSON schema和示例。如果还不行在应用层做解析容错用正则提取JSON部分解析失败时重试。重试时把错误信息加到prompt里告诉模型上次输出哪里不对。我的经验是对于结构化输出用function calling比纯prompt更稳定。因为function calling的schema是强约束的模型必须按照schema生成。5.2 Agent陷入死循环的处理Agent反复调同一个工具或者在不同工具之间来回跳就是死循环。排查时先看Agent的思考过程理解它为什么这么决策。常见原因有几个工具返回的结果不符合预期Agent以为没成功所以重试prompt里的终止条件不明确Agent不知道什么时候该停任务本身无法完成Agent一直在尝试。解决方法设置最大迭代次数在prompt里明确终止条件对工具结果做标准化处理让Agent能正确理解无进展检测连续相似行动就终止。5.3 并发上不去的问题AI应用的并发瓶颈通常在LLM调用。排查时先看LLM的rate limit是多少再看自己的并发数是否超了。如果没超但并发还是上不去可能是同步调用阻塞了线程。解决方法用异步IO加请求队列控制并发对LLM调用做连接池复用考虑多模型路由把请求分散到不同模型。5.4 常见问题速查表问题现象可能原因排查方向解决方案LLM输出格式错误prompt不明确检查prompt schema用function calling加解析容错Agent死循环终止条件缺失看Agent轨迹设最大迭代加无进展检测工具调用失败参数错误或超时看工具日志参数校验超时重试并发上不去同步阻塞看线程状态异步IO请求队列上下文超限历史消息太长看token数滑动窗口摘要压缩响应延迟高模型推理慢看LLM延迟流式输出模型降级成本超预算token消耗大看token统计缓存小模型路由5.5 几个独家避坑技巧技巧一prompt版本管理。每次改prompt都要记录版本和效果对比不然改着改着就不知道哪个版本效果好了。技巧二工具结果标准化。所有工具返回的结果都统一成一种格式比如{status, data, error}这样LLM更容易理解。技巧三灰度发布。新的prompt或新的Agent逻辑先对少量用户开放观察效果再全量。技巧四成本监控。按用户、按场景统计token消耗发现异常及时排查。技巧五降级预案。LLM服务不可用时要有兜底方案比如返回缓存结果或转人工。6. 架构演进与扩展方向6.1 从单Agent到多Agent协作当任务复杂度上升单个Agent可能搞不定。这时候可以考虑多Agent架构每个Agent负责一个子领域通过消息传递协作。多Agent的架构设计要点是角色划分要清晰每个Agent的职责边界明确通信协议要统一Agent之间怎么传递消息协调机制要设计好谁来决定任务分配和结果汇总。我见过比较成功的多Agent架构是“主管专家”模式一个主管Agent负责理解用户意图、拆解任务、分发给专家Agent专家Agent各自处理自己的领域结果汇总给主管Agent。6.2 Agent安全的设计考量Agent安全是最近越来越受关注的话题。Agent能调工具、能访问数据如果被恶意利用后果很严重。安全设计要从几个层面考虑输入过滤防止prompt注入工具权限Agent只能调授权范围内的工具数据隔离不同用户的数据不能混行为审计记录Agent的所有行动便于追溯输出审查防止敏感信息泄露。6.3 架构的可扩展性设计AI应用的技术栈变化很快今天用的框架明天可能就过时了。架构设计时要考虑可扩展性把易变的部分抽象成接口方便替换。我的做法是模型调用抽象成LLM Provider接口工具调用抽象成Tool接口记忆存储抽象成Memory接口。这样换模型、换工具、换存储都不用改业务逻辑。7. 我个人的一些实操体会做AI应用架构这几年最大的体会是不要过度设计但要有演进的空间。一开始不要想着把所有层都搭全先把核心链路跑通再根据实际需求逐步完善。另一个体会是可观测性要尽早做。AI应用的问题往往很难复现没有日志和追踪排查问题就是大海捞针。我一般从第一天就把LLM调用日志和工具调用日志加上后面省很多事。还有一点prompt和Agent逻辑要当成代码来管理。版本控制、测试、灰度发布这些软件工程的实践同样适用于prompt和Agent。我见过太多团队prompt改来改去最后不知道哪个版本效果好。最后分享一个小技巧如果你刚开始做AI应用不妨先用低代码平台快速搭一个原型验证想法。等想法验证了再用代码实现生产版本。这样能省很多时间也能避免过早陷入技术细节。