news 2026/10/5 8:47:21

图解AI应用架构设计:从LLM到Agent的分层实践指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
图解AI应用架构设计:从LLM到Agent的分层实践指南

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为什么重要

MCP(Model 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_iterations=10): 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, tools=self.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里用asyncio,Java里用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应用,不妨先用低代码平台快速搭一个原型,验证想法。等想法验证了,再用代码实现生产版本。这样能省很多时间,也能避免过早陷入技术细节。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 8:47:16

语音到音频文件全链路:从麦克风采集到嵌入式落地

1. 语音到文件的真相:不是一条单行道先说一个容易被忽略的事实:当我们说“把语音变成音频文件”,大多数人脑子里只有一个画面——对着麦克风说话,保存成MP3。但真正做过语音和音频相关项目的人会告诉你,这只是其中一条…

作者头像 李华
网站建设 2026/10/5 8:47:12

UE4程序化生成六边形星球:戈德堡多面体与PMC实战

很多UE4开发者第一次做星球,第一反应是拉一个球体模型,或者用蓝图生成一个经纬球(UV Sphere),再往上叠地形噪声。我也这么干过,结果两极顶点挤成一团、三角形大小不一,想做六边形蜂窝风格更是无…

作者头像 李华
网站建设 2026/10/5 8:47:01

企业多模型API统一管理实战:AI网关架构设计与落地

1. 企业多模型 API 管理的真实困境1.1 从“单点接入”到“多模型混用”的必然趋势我最早接触大模型 API 管理是在一个中型电商团队的项目里。当时业务方提的需求很简单:给客服系统加一个智能问答。我们选了当时效果最好的一个模型,写了个 Python 脚本直接…

作者头像 李华
网站建设 2026/10/5 8:44:51

DeepSeek Harness桌面端从安装到内网部署全链路实战指南

1. 桌面端来了,为什么这件事比想象中重要DeepSeek Harness 这个工具,圈内人一般直接叫它 DSH。它最早是以命令行形态出现的,核心定位是给大模型应用做一层"编排外壳"——把模型调用、工具调用、文件读写、Skill 扩展这些东西统一管…

作者头像 李华
网站建设 2026/10/5 8:44:51

单日300万沙盒训练Agent:大规模环境工程实践与架构解析

1. 从标题拆解:300万单日沙盒到底在说什么第一次看到“单日 300 万沙盒养出一个 V4”这个说法,我脑子里蹦出来的第一个念头是:这得是多大的并发量。300 万这个数字放在任何系统里都不是小数目,更何况是“沙盒”——意味着每一个都…

作者头像 李华
网站建设 2026/10/5 8:44:51

DeepSeek Harness桌面端上手实战:API Key配置、插件与skill部署全解析

1. 桌面端来了,为什么这件事比想象中重要DeepSeek Harness 出官方桌面端这件事,我第一反应不是“终于有 GUI 了”,而是“终于不用再跟终端里的环境变量和 provider route 死磕了”。如果你最近在技术社区里刷到过llm-deepseek: no api key fo…

作者头像 李华