图解AI应用架构设计:从能跑通到能上线的分层实践

发布时间:2026/10/28 15:00:48
图解AI应用架构设计:从能跑通到能上线的分层实践 1. 从一张架构图说起AI应用到底该怎么搭很多人第一次接触AI应用开发脑子里冒出来的第一个念头是“调个API就完事了”。我刚开始也这么想直到把一个demo交给真实用户跑了三天才发现事情远没有那么简单。模型会胡说八道、工具调用会失败、上下文会溢出、多轮对话会失忆、并发一上来响应时间直接爆炸。这些问题不是靠换一个更强的模型就能解决的它们本质上是架构问题。“图解AI应用架构设计”这个题目核心要解决的就是一件事把AI应用从“能跑通”推进到“能上线”。它面向的是已经了解LLM基本调用方式、但在构建真实产品时感到力不从心的开发者。你需要的不只是会写prompt而是理解一个AI应用从用户输入到最终输出之间到底经过了哪些层、每层负责什么、层与层之间怎么协作。这篇文章我会按照我自己实际做项目的思路把AI应用架构拆成几个关键层次来讲。从最上层的交互入口到中间的Agent编排再到LLM调用层、工具与MCP协议层、记忆与状态管理层最后到可观测性和安全兜底。每一层我都会说清楚它为什么存在、不做好会出什么问题、以及实际落地时我会怎么选型。文中涉及的具体参数和配置我会给出计算过程或选择依据方便你直接对照自己的项目做决策。先给一个整体视角。一个典型的AI应用架构大致可以画成这样一条链路用户输入 → 接入层鉴权/限流/路由→ 会话管理记忆/状态→ Agent编排规划/决策→ LLM调用推理/生成→ 工具执行MCP/API/函数调用→ 结果聚合 → 输出后处理格式化/审核→ 返回用户这条链路上每一个环节都有坑而且坑与坑之间会相互放大。比如记忆层没做好Agent就会反复问用户同样的问题工具层没有超时和重试一次外部API抖动就能让整个对话卡死LLM调用层没有做降级主力模型一限流整个应用直接不可用。所以架构设计的核心不是把每一层做到完美而是让每一层都能在出问题的时候把影响控制在最小范围。2. 核心分层拆解每一层到底在解决什么问题2.1 接入层别让请求直接打到模型上接入层是很多个人项目最容易忽略的一层。大家习惯性地把前端直接连到后端的一个接口接口里直接调LLM看起来链路最短、开发最快。但一旦有真实流量进来问题就来了有人恶意刷接口怎么办同一个用户短时间发了几十条请求怎么处理不同用户要用不同的模型配置怎么路由接入层要做的第一件事是鉴权和限流。鉴权不用多说限流这块我一般会按用户维度做令牌桶比如每个用户每分钟最多20次请求突发允许到30次。这个数值不是拍脑袋定的而是根据你的LLM调用成本和响应时间来算的。假设你的平均响应时间是3秒后端并发处理能力是50路那么理论上每分钟最多处理1000次请求。如果你有100个活跃用户平均每人每分钟10次请求就是1000次刚好打满。所以限流阈值要留出至少30%的余量设在每人每分钟7次左右比较稳妥。第二件事是模型路由。不同场景用不同模型这个思路大家都懂但路由策略要提前设计好。我的做法是在接入层根据请求的元数据打标签比如“简单问答”走小模型“复杂推理”走大模型“代码生成”走代码专用模型。路由规则可以配置化不要硬编码在代码里否则每次调整都要重新部署。第三件事是请求预处理。包括输入长度检查、敏感内容过滤、格式规范化。输入长度检查特别重要很多人不注意这个用户粘贴一篇长文进来直接超出模型上下文窗口调用报错。我一般会在接入层就做截断或分段截断策略要看业务场景问答类可以保留首尾摘要类必须全量分段。2.2 Agent编排层从“一问一答”到“自主决策”Agent是这两年AI应用架构里变化最大的部分。早期的AI应用基本就是“用户问、模型答”的单轮模式现在稍微复杂一点的产品都在往Agent方向走。但Agent不是万能药用不好反而会让系统变得不可控。先说Agent的核心组成。一个Agent至少包含四个部分规划器、执行器、记忆、工具集。规划器负责把用户目标拆成步骤执行器负责一步步执行记忆负责保存中间状态和历史信息工具集负责与外部世界交互。这四者缺一不可少了任何一个Agent都会退化成普通的对话机器人。规划器的实现方式有好几种。最简单的是ReAct模式就是让模型在每一步输出“思考-行动-观察”的循环。这种方式实现简单但token消耗大因为每一步都要把完整历史塞进上下文。另一种是Plan-and-Execute模式先让模型生成一个完整的执行计划然后按计划逐步执行。这种方式token效率高但灵活性差计划一旦生成就很难调整。我实际项目中用得比较多的是混合模式先让模型生成粗粒度计划执行过程中允许动态调整兼顾效率和灵活性。执行器的关键点是错误处理和重试。Agent执行过程中工具调用失败是常态网络抖动、API限流、参数错误都会导致失败。我的做法是给每个工具调用设置三级重试策略第一次失败后立即重试第二次失败后等待2秒重试第三次失败后放弃并让Agent决定是否换一种方式。重试次数不要超过3次否则容易陷入死循环。记忆管理是Agent架构里最容易被低估的部分。短期记忆就是当前会话的上下文这个大家都会做。长期记忆就需要额外设计我一般会用向量数据库存历史交互的摘要每次新会话开始时检索相关记忆注入上下文。这里有个经验不要存原始对话要存摘要。原始对话太长检索出来注入上下文会挤占宝贵的token预算。摘要的粒度控制在100-200字左右保留关键信息和结论即可。2.3 LLM调用层稳定比强大更重要LLM调用层看起来最简单不就是发个HTTP请求吗但实际项目里这一层出的问题最多。我总结下来主要有四类问题超时、限流、格式错误、内容异常。超时问题很好理解模型响应时间不稳定有时候快有时候慢。我的做法是设置分级超时首token超时设为10秒如果10秒内没有收到第一个token就断开重试整体超时设为60秒超过就放弃。这两个数值是根据实际观测调整的大部分正常请求首token在2-3秒内到达60秒足够生成一篇长文。限流问题需要提前和模型服务方确认配额然后在代码里做好队列和降级。我一般会维护一个请求队列当并发超过阈值时新请求排队等待而不是直接失败。降级策略是准备一个备用模型主力模型不可用时自动切换。备用模型可以弱一些但必须保证可用性。格式错误是很多人踩过的坑。你让模型输出JSON它有时候会多输出一段解释文字有时候会少一个括号。我的做法是在调用层做输出解析和修复。先用正则提取JSON部分如果解析失败再调用一次模型让它修复格式。修复调用的prompt要简单直接“请将以下内容修复为合法JSON只输出JSON不要任何解释。”内容异常包括模型胡说八道、输出敏感内容、偏离主题等。这一层能做的主要是输出后处理包括关键词过滤、长度检查、相关性打分。相关性打分可以用一个小模型来做判断输出是否和用户问题相关不相关就重新生成。2.4 工具与MCP层让AI真正“动手做事”MCP是最近很热的一个概念全称是Model Context Protocol。简单说它是一套标准化的协议让AI应用能够以统一的方式连接外部工具和数据源。在没有MCP之前每接一个工具就要写一套适配代码接十个工具就是十套代码维护成本极高。MCP的价值在于把工具接入标准化工具提供方按照MCP规范实现一次所有支持MCP的AI应用都能直接使用。MCP的核心概念有三个Resources、Tools、Prompts。Resources是只读的数据源比如文件内容、数据库查询结果Tools是可执行的操作比如发送邮件、创建日历事件Prompts是预定义的提示模板方便用户快速调用常用功能。这三个概念覆盖了AI应用与外部交互的主要场景。实际落地MCP时我建议先从Tools开始做因为工具调用是最刚需的。一个典型的MCP工具定义包含名称、描述、参数schema三部分。描述要写得足够清晰因为模型是根据描述来决定是否调用这个工具的。我见过很多工具调用失败就是因为描述写得太模糊模型不知道什么时候该用。工具调用的超时和错误处理要和LLM调用层一样严格。我一般给每个工具设置5秒超时超时后返回一个标准错误信息给模型让模型决定下一步怎么做。不要让工具调用阻塞整个Agent流程所有工具调用都应该是异步的有结果了再继续。2.5 记忆与状态层让AI“记住”该记住的记忆层解决的是“AI失忆”问题。没有记忆层每次对话都是全新的开始用户要反复说同样的背景信息体验极差。但记忆不是越多越好存太多会挤占上下文存太少又不够用。我的记忆分层策略是这样的会话内记忆保存在内存或Redis里生命周期就是当前会话存最近N轮对话的原文N一般取10-20。跨会话记忆存在向量数据库里存历史对话的摘要和关键实体每次新会话开始时检索Top-K条相关记忆注入上下文K一般取3-5。用户画像记忆存在关系型数据库里存用户的偏好、习惯、常用配置这部分是结构化的直接拼接到system prompt里。记忆的检索策略也很关键。我一般用混合检索向量相似度占70%权重时间衰减占30%权重。时间衰减的意思是越近的记忆权重越高衰减函数用指数衰减半衰期设为7天。这样既能找到语义相关的历史信息又能优先使用最近的记忆。状态管理是另一个容易出问题的地方。Agent执行多步任务时中间状态需要持久化否则一旦服务重启或请求超时整个任务就丢了。我的做法是用一个状态机来管理任务生命周期每个状态转换都持久化到数据库。状态包括待处理、规划中、执行中、等待工具返回、已完成、已失败。每个状态都有超时时间超时后自动进入失败状态并触发告警。3. 实操落地从零搭一个可用的AI应用骨架3.1 技术选型与项目结构假设我们要搭一个通用的AI助手应用支持多轮对话、工具调用、记忆管理。技术选型上后端我用Python框架选FastAPI因为异步支持好、生态成熟。LLM调用层用官方SDK加一层封装方便切换模型。向量数据库用Milvus或Qdrant看团队熟悉程度。缓存用Redis存会话状态和限流计数器。数据库用PostgreSQL存用户信息和任务状态。项目结构我一般这样组织app/ api/ # 接入层路由、鉴权、限流 agent/ # Agent编排规划器、执行器 llm/ # LLM调用封装重试、降级、解析 tools/ # 工具定义与MCP客户端 memory/ # 记忆管理短期、长期、画像 models/ # 数据模型 core/ # 配置、日志、异常 utils/ # 通用工具这个结构的好处是每一层职责清晰替换某一层的实现不影响其他层。比如你想把LLM从一家换到另一家只需要改llm/目录下的代码其他层不用动。3.2 关键配置与参数计算配置管理我推荐用Pydantic的BaseSettings支持环境变量和配置文件两种方式。关键配置项包括配置项说明推荐值计算依据max_input_tokens最大输入token数3000模型上下文窗口的60%留出输出空间max_output_tokens最大输出token数1500根据业务需求一般回答不超过1000字llm_timeout_first_token首token超时10s观测P95首token延迟约3s留3倍余量llm_timeout_total整体超时60s长文生成场景实测P99约45stool_timeout工具调用超时5s外部API P99延迟约2s留2.5倍余量max_retries最大重试次数3超过3次重试成功率提升不明显session_ttl会话过期时间3600s用户平均会话时长约20分钟memory_top_k记忆检索条数5每条记忆约100token5条占500token这些数值不是固定的你要根据自己的业务场景调整。调整的依据是观测数据不是感觉。我建议在接入层和LLM调用层都打点记录每次请求的耗时、token消耗、成功失败状态跑一周就有足够的数据来做决策了。3.3 Agent执行流程的代码骨架下面是一个简化的Agent执行流程用Python伪代码展示核心逻辑async def execute_agent(user_input, session_id): # 1. 加载会话状态和记忆 session await load_session(session_id) memories await retrieve_memories(user_input, session.user_id) # 2. 构建上下文 context build_context( system_promptAGENT_SYSTEM_PROMPT, memoriesmemories, historysession.recent_messages, user_inputuser_input ) # 3. 规划 plan await llm_call( promptPLANNER_PROMPT, contextcontext, max_tokens500 ) # 4. 执行计划 results [] for step in plan.steps: if step.type tool: result await execute_tool_with_retry( tool_namestep.tool_name, paramsstep.params, timeoutsettings.tool_timeout, max_retriessettings.max_retries ) elif step.type llm: result await llm_call( promptstep.prompt, contextcontext, max_tokenssettings.max_output_tokens ) results.append(result) context update_context(context, step, result) # 5. 聚合结果并生成最终回复 final_response await llm_call( promptAGGREGATOR_PROMPT, contextcontext, resultsresults ) # 6. 保存状态和记忆 await save_session(session_id, user_input, final_response) await save_memory(session.user_id, user_input, final_response) return final_response这段代码的关键点在于每一步都有超时和重试上下文在每一步都会更新状态和记忆在最后统一保存。实际项目中还要加上异常处理和日志记录这里为了简洁省略了。3.4 MCP工具接入实操接入一个MCP工具大致分三步。第一步是发现工具MCP客户端连接到MCP服务器后可以列出所有可用的工具及其schema。第二步是注册工具把工具的schema转换成LLM能理解的格式注入到system prompt或工具调用参数里。第三步是调用工具当模型决定调用某个工具时MCP客户端把调用请求转发给MCP服务器拿到结果后返回给模型。以接入一个“查询天气”的MCP工具为例工具定义大概长这样{ name: get_weather, description: 查询指定城市的当前天气情况, parameters: { type: object, properties: { city: { type: string, description: 城市名称如北京、上海 }, unit: { type: string, enum: [celsius, fahrenheit], description: 温度单位默认摄氏度 } }, required: [city] } }描述要写得让模型一看就知道什么时候该用这个工具。我见过有人把描述写成“天气工具”模型根本不知道什么时候该调用。描述里要包含功能说明、参数含义、使用场景三个要素。4. 常见问题与排查技巧实录4.1 模型输出格式不稳定怎么办这是最高频的问题。你让模型输出JSON它十次里有两次会多输出一段解释。我的解决方案是三层防护第一层在prompt里明确要求“只输出JSON不要任何解释”并且给出示例第二层在代码里用正则提取JSON部分兼容模型多输出解释的情况第三层如果解析还是失败调用一次修复模型把原始输出和错误信息一起给它让它修复。修复调用的prompt我一般这样写“以下内容应该是一个合法的JSON对象但解析失败了。请修复它只输出修复后的JSON不要任何解释。原始内容{raw_output}”。实测下来三层防护能把格式错误率从15%降到1%以下。4.2 工具调用超时或失败怎么处理工具调用失败的原因很多排查思路是先看日志再看网络最后看参数。日志里要记录工具名称、参数、耗时、错误信息。如果错误是超时检查工具服务端的响应时间如果是连接失败检查网络和DNS如果是参数错误检查模型生成的参数是否符合schema。处理策略上我一般设置三级重试立即重试、延迟2秒重试、延迟5秒重试。三次都失败就返回标准错误给模型让模型决定是换工具还是告诉用户暂时不可用。不要让工具调用无限重试否则会拖垮整个Agent。4.3 上下文溢出怎么预防上下文溢出是指输入token数超过模型窗口限制。预防措施有三个接入层截断、记忆层压缩、调用层检查。接入层对超长输入做截断或分段记忆层只存摘要不存原文调用层在发请求前计算token数超过阈值就触发压缩或拒绝。token数的估算可以用tiktoken库不同模型的tokenizer不一样要用对应模型的。估算公式是总token 系统提示token 记忆token 历史token 用户输入token 预留输出token。预留输出token一般设为max_output_tokens的值。如果总token超过模型窗口的90%就要触发压缩。4.4 常见问题速查表问题现象可能原因排查方法解决方案模型输出乱码编码问题或模型异常检查请求和响应的编码统一用UTF-8异常时重试工具调用不触发工具描述不清晰检查工具描述是否包含使用场景完善描述增加示例响应时间过长模型负载高或上下文太长查看各阶段耗时压缩上下文切换备用模型记忆检索不相关向量模型不匹配或阈值太低检查检索结果的相关性调整相似度阈值换向量模型并发上不去同步阻塞或连接池太小检查代码是否异步改异步增大连接池成本超预期token消耗大或调用频繁统计token消耗和调用次数优化prompt增加缓存4.5 几个踩过的坑第一个坑是过度依赖模型做决策。我早期做Agent的时候把所有决策都交给模型结果模型有时候会陷入循环反复调用同一个工具。后来我在执行器里加了循环检测如果连续三次调用同一个工具且参数相同就强制中断并返回错误。第二个坑是忽略冷启动问题。向量数据库和模型服务都有冷启动时间第一次请求特别慢。我的做法是在服务启动时预热提前加载模型和建立连接避免第一个用户请求超时。第三个坑是日志打太多。为了排查问题我一开始把每次LLM调用的完整输入输出都打到日志里结果日志量爆炸存储成本比模型调用还高。后来改成只记录关键信息请求ID、模型名称、token数、耗时、状态完整内容只在调试模式下记录。第四个坑是没有做成本监控。LLM调用是按token计费的如果不监控很容易超预算。我现在的做法是每天统计token消耗按用户和场景维度拆分设置日预算告警超过80%就发通知。5. 可观测性与安全兜底上线前的最后一道关5.1 可观测性建设可观测性包括三个部分日志、指标、追踪。日志记录离散事件指标记录聚合数据追踪记录请求链路。三者结合才能快速定位问题。日志我一般分级别DEBUG记录完整请求响应INFO记录关键节点WARN记录可恢复异常ERROR记录不可恢复异常。生产环境默认INFO级别排查问题时临时开DEBUG。指标要覆盖几个核心维度请求量、成功率、延迟分布、token消耗、工具调用次数。延迟分布用P50、P95、P99三个分位数P99超过阈值就告警。追踪用OpenTelemetry每个请求生成一个trace_id贯穿接入层、Agent层、LLM层、工具层。这样出问题的时候拿trace_id一查就知道卡在哪一层。5.2 安全兜底策略安全兜底包括输入过滤、输出审核、权限控制、熔断降级。输入过滤拦截明显的恶意输入比如超长文本、特殊字符注入。输出审核检查模型生成的内容是否合规可以用关键词过滤加小模型审核双重保障。权限控制确保用户只能访问自己有权限的工具和数据。熔断降级在系统压力过大时自动关闭非核心功能保证核心功能可用。熔断器的配置我一般这样设错误率超过50%且请求数超过20时触发熔断熔断后30秒进入半开状态允许少量请求试探如果成功率恢复就关闭熔断否则继续熔断。这个配置要根据实际业务调整核心业务可以放宽阈值非核心业务可以收紧。5.3 上线检查清单上线前我一般会过一遍这个清单限流配置是否生效阈值是否合理超时和重试策略是否覆盖所有外部调用降级方案是否可用备用模型是否配置日志和指标是否接入监控系统告警规则是否配置通知渠道是否畅通成本预算是否设置告警阈值是否合理安全过滤是否开启审核规则是否更新压力测试是否通过瓶颈是否明确这个清单看起来简单但每一条都对应着实际踩过的坑。我见过太多项目因为限流没配好被刷爆、因为降级没做导致全站不可用、因为成本没监控一个月烧掉几万块。架构设计不只是画图更是把这些细节都考虑到。我个人在实际项目中的体会是AI应用架构设计最难的从来不是技术选型而是对不确定性的管理。模型输出不确定、工具响应不确定、用户行为不确定架构的价值就在于把这些不确定性框在一个可控的范围内。你不需要一开始就做到完美但每一层都要有兜底每一个失败都要有退路。先让系统能跑再让系统跑得稳最后才是跑得快。这个顺序不能反。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询