ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI应用架构设计实战:从LLM到Agent与MCP的分层落地指南

AI应用架构设计实战:从LLM到Agent与MCP的分层落地指南 1. 从一张架构图说起AI应用到底该怎么搭这两年AI应用开发的热度不用我多说但凡你身边有做后端、做前端、甚至做运维的朋友大概率都在琢磨怎么把大模型塞进自己的业务里。但真动手的时候很多人会卡在同一个地方知道LLM能干活但不知道怎么把它组织成一个能上线的应用。这就是“AI应用架构设计”要解决的问题。我自己从最早写几个脚本调API到后来带团队做Agent平台踩过的坑不算少。这篇文章不打算讲什么高深理论就是把一张典型的AI应用架构图拆开从下往上、从里到外讲清楚每一层在干什么、为什么这么分层、实际落地时哪些地方最容易翻车。核心关键词就几个AI应用、架构设计、Agent、LLM、MCP。如果你正在做AI应用开发或者想搞清楚Agent和LLM到底怎么配合这篇应该能帮你省下不少查文档的时间。先说清楚适用人群如果你是完全没接触过LLM的小白建议先补一下大模型的基本概念比如什么是token、什么是上下文窗口、什么是推理如果你已经能调通OpenAI或者国内某家模型的API但不知道下一步怎么组织代码那这篇就是写给你的。架构设计这件事本质上是在回答一个问题当模型本身不可控的时候怎么用工程手段让整个系统可控。2. AI应用架构的整体分层与设计思路2.1 为什么不能直接“前端调模型”我见过太多项目一开始就是前端直接拿API Key去调模型Demo阶段没问题一旦要上线就全是问题。首先是安全性API Key暴露在前端等于把钱包扔在大街上其次是可控性你没法做限流、没法做缓存、没法做审计最后是扩展性今天用A模型明天想换B模型前端代码得全改。所以第一层设计原则就是模型调用必须收口到服务端。这个收口层我习惯叫它“模型网关层”或者“LLM接入层”。它的职责很单纯统一不同厂商的API差异、管理密钥、做基础的限流和重试、记录调用日志。别小看这一层后面你要换模型、要做灰度、要算成本全靠它。2.2 从“调模型”到“用模型”的思维转变很多人把AI应用理解成“输入问题、输出答案”这是ChatGPT的交互方式不是应用架构。真正的AI应用里模型只是其中一个组件它需要和工具、记忆、知识库、业务逻辑配合。这就引出了Agent的概念。Agent这个词现在被用得很泛我的理解很简单Agent是一个能自己决定下一步做什么的LLM驱动循环。普通LLM调用是“你问一句它答一句”Agent是“你给个目标它自己拆步骤、调工具、看结果、再决定下一步”。这个循环里LLM是大脑工具是手脚记忆是笔记本。2.3 分层架构的完整视图把上面这些串起来一个典型的AI应用架构大概分这么几层从下往上层级职责关键组件基础设施层算力、存储、网络GPU集群、向量数据库、对象存储模型接入层统一模型调用模型网关、密钥管理、限流重试能力编排层Agent循环、工具调用Agent框架、MCP协议、工具注册业务逻辑层具体场景实现业务流程、权限、审计交互层用户界面Web、App、API这个分层不是死的小项目可能把模型接入和编排合并大项目可能把编排再拆成“规划”和“执行”。但核心思想是一致的每一层只解决一类问题层与层之间通过明确的接口通信。这样你换模型不影响业务逻辑换Agent框架不影响交互层。提示分层的目的不是增加复杂度而是隔离变化。AI领域变化太快今天流行的框架明天可能就过时了分层能让你只改一层。3. 核心组件深度拆解LLM、Agent与MCP3.1 LLM模型选型不是越贵越好选模型这件事我见过两种极端一种是无脑上最贵的觉得贵就是好另一种是只看价格哪个便宜用哪个。都不对。选型的核心是匹配场景需求。先问自己几个问题任务是生成类还是理解类需不需要函数调用能力上下文窗口要多大对延迟敏感吗预算多少把这些列清楚再去对比模型。举个例子如果你做的是客服问答主要是理解用户意图然后查知识库那一个小参数量的模型加上好的检索策略效果可能比大模型硬答还好成本还低一个数量级。如果你做的是代码生成或者复杂推理那该上大模型就上省这个钱没意义。还有一个容易被忽略的点多模型路由。同一个应用里简单任务走小模型复杂任务走大模型这是很实用的降本手段。模型网关层如果设计得好路由策略就是配置问题不用改代码。3.2 Agent架构ReAct只是起点Agent的经典模式是ReAct也就是“推理-行动”循环。LLM先想一步决定调什么工具拿到结果再想下一步直到任务完成。这个模式简单有效但实际用起来问题不少。第一个问题是循环失控。LLM可能陷入死循环反复调同一个工具。解决办法是设置最大步数以及在提示词里明确告诉它“如果连续两次结果相同就停止”。第二个问题是工具选择错误。工具一多LLM就容易选错。我的经验是工具描述要写得极其清楚包括什么时候用、什么时候不用、参数什么意思。别指望LLM能猜。第三个问题是上下文爆炸。每一步的工具返回结果都塞进上下文几轮下来就超了。这时候需要做上下文压缩比如只保留关键信息或者用摘要模型把历史压缩。现在Agent框架很多LangChain、LlamaIndex、AutoGPT各有拥趸。我的建议是先用最简单的实现跑通流程再考虑上框架。很多需求根本用不到复杂框架一个几百行的循环就够了。3.3 MCP协议工具调用的标准化尝试MCP最近讨论度很高它的全称是Model Context Protocol核心目标是标准化LLM和外部工具的交互方式。在没有MCP之前每个Agent框架都有自己的工具定义格式你为LangChain写的工具换到另一个框架就得重写。MCP想解决的就是这个问题。MCP的基本模型是有一个MCP Server暴露工具Agent作为Client去调用。Server可以用任何语言写只要遵循协议。这样工具就变成了可复用的资产而不是绑定在某个框架上。实际用下来MCP的好处是解耦坏处是多了一层通信开销而且目前生态还在早期很多工具还没有现成的MCP实现。我的建议是如果你的工具需要在多个Agent之间复用或者你想把工具作为独立服务维护那值得上MCP如果只是单个应用内部用直接函数调用更简单。注意MCP是协议不是框架它不负责Agent的决策逻辑只负责工具的描述和调用。别把两者混为一谈。4. 实操落地从零搭一个最小可用AI应用4.1 环境准备与技术栈选择假设我们要做一个“智能文档问答”应用用户上传文档然后可以针对文档提问。这是最经典的AI应用场景适合用来演示架构。技术栈我选Python原因很简单AI生态最全。Web框架用FastAPI轻量且异步支持好。向量数据库用Chroma本地跑方便不用额外部署。模型先用一家国内厂商的API便宜且稳定。Agent部分先不引入框架手写循环。目录结构大概这样app/ main.py # FastAPI入口 gateway/ # 模型接入层 llm_client.py agent/ # 编排层 loop.py tools.py rag/ # 检索增强 indexer.py retriever.py api/ # 业务接口 routes.py这个结构对应前面说的分层gateway管模型agent管循环rag管知识api管对外接口。4.2 模型接入层的实现细节模型接入层的核心是一个统一的客户端类屏蔽不同厂商的差异。关键方法就一个chat(messages, toolsNone)。内部处理重试、超时、日志。class LLMClient: def __init__(self, api_key, base_url, model): self.api_key api_key self.base_url base_url self.model model async def chat(self, messages, toolsNone, temperature0.7): # 构造请求处理不同厂商的格式差异 # 重试逻辑最多3次指数退避 # 记录token消耗和延迟 pass这里有个经验重试要区分错误类型。网络超时可以重试但如果是参数错误或者余额不足重试没意义。我一般只对5xx和超时做重试。4.3 Agent循环的手写实现不依赖框架的Agent循环其实很简单核心就是一个while循环async def run_agent(goal, tools, max_steps10): messages [{role: system, content: SYSTEM_PROMPT}] messages.append({role: user, content: goal}) for step in range(max_steps): response await llm.chat(messages, toolstools) if response.has_tool_call: tool_result execute_tool(response.tool_call) messages.append(response.message) messages.append({role: tool, content: tool_result}) else: return response.content return 达到最大步数任务未完成这段代码看起来简单但有几个关键点系统提示词要写清楚工具的使用规则工具执行要加超时和异常处理每步都要检查是否该终止。我见过有人忘了加max_steps结果LLM死循环把token烧光。4.4 RAG检索增强的接入文档问答的核心是RAG。流程是文档切块、向量化、存库查询时把问题向量化、检索相似块、塞进提示词。切块策略很关键。按固定字数切最简单但会切断语义。我一般用递归切分先按段落切段落太长再按句子切保证每块语义完整。块大小512到1024个token比较合适太小检索不准太大塞不进上下文。检索这块混合检索效果比纯向量好。也就是向量相似度加关键词匹配各占一定权重。纯向量检索对专有名词不敏感加上关键词能补这个短板。提示RAG的效果上限取决于检索质量检索不行模型再强也答不对。别把时间都花在调提示词上先看看检索出来的内容对不对。5. 性能与并发AI应用怎么扛住真实流量5.1 LLM调用的延迟特性LLM调用和普通API调用有个本质区别延迟高且不稳定。普通接口几十毫秒LLM动辄几秒甚至几十秒。这意味着传统的同步阻塞模型完全不可行一个请求占一个线程并发一上来线程池就满了。解决办法是全异步。Python用asyncioJava用WebFlux或者虚拟线程。核心是发起LLM调用后不阻塞等结果回来再继续。FastAPI天然支持异步这也是我选它的原因之一。5.2 流式输出与用户体验延迟高不代表用户体验一定差关键是流式输出。模型生成第一个token可能只要几百毫秒后面的token陆续返回。前端用SSE或者WebSocket接收用户看到文字一个个蹦出来感知延迟就低很多。流式输出对架构的影响是不能等完整结果再处理。比如你要做内容审核得边流边审要做格式化得等流结束再解析。这些都要在架构设计时考虑进去。5.3 缓存与降级策略LLM调用贵且慢能缓存就缓存。精确缓存适合重复问题比如FAQ场景。语义缓存适合相似问题用向量相似度判断但要注意阈值设置太松会返回错误答案。降级策略也很重要。模型服务挂了怎么办我的做法是准备一个备用模型主模型连续失败就切过去。虽然效果可能差一点但总比服务不可用好。策略适用场景注意事项精确缓存重复问题多的场景注意缓存过期和更新语义缓存问法多样的场景阈值要调宁严勿松模型降级主模型不可用提前测试备用模型效果限流防止滥用按用户和全局双重限流6. 常见问题与排查技巧实录6.1 模型返回格式不对怎么办这是最高频的问题。你让模型返回JSON它给你返回一段带解释的文字。解决办法有几个层次首先在提示词里明确格式要求最好给示例其次用结构化输出功能很多模型API支持指定JSON Schema最后在代码里做解析容错解析失败就重试或者用规则提取。我一般会写一个parse_json_safely函数先尝试直接解析失败就用正则提取JSON部分再失败就返回错误让上层决定是否重试。6.2 Agent不调工具或者乱调工具Agent不调工具通常是提示词没写清楚工具的存在或者工具描述太模糊。乱调工具通常是工具之间职责重叠。解决办法工具描述要包含“何时使用”和“何时不使用”工具数量控制在10个以内太多就分组或者用层级结构。还有一个坑是工具参数类型。LLM可能传字符串给你期望整数的参数代码里要做类型转换和校验别直接信。6.3 上下文超限的处理上下文超限是迟早会遇到的问题。处理策略分三种截断保留最近的对话丢掉最早的摘要用模型把历史压缩成一段话检索把历史存起来需要时再检索。实际用的时候往往是组合使用比如最近几轮保留原文更早的做摘要。6.4 成本失控的排查成本突然涨了先查这几个地方是不是有人恶意刷接口是不是Agent死循环了是不是缓存失效了是不是换了更贵的模型。我一般会在网关层做按用户和按接口的token统计每天出报表异常能及时发现。注意上线前一定要设置单次调用和单日总额的上限超过就拒绝或者降级。这是血的教训别问我是怎么知道的。7. 一些个人体会架构设计这件事最怕的就是过度设计。我见过太多项目一上来就搞微服务、搞消息队列、搞多级缓存结果业务量根本没到那个程度维护成本倒是上去了。AI应用尤其如此模型本身就在快速迭代你的架构越复杂跟进成本越高。我的建议是从单体开始把分层做清楚但别急着拆服务。等某一层真的成为瓶颈了再拆出去。模型网关层可以早点独立因为模型切换是高频需求。Agent编排层可以晚点独立因为业务逻辑和编排往往耦合很紧。另外可观测性要早点做。LLM应用的调试比传统应用难得多你不知道模型为什么这么答。所以日志要记全输入输出、工具调用、token消耗、延迟一个都别少。出了问题能回放这是排查的前提。最后说一句AI应用架构没有标准答案只有适合当前场景的答案。今天的最佳实践明天可能就被新模型的能力覆盖了。保持学习保持简单比什么都重要。
返回列表