
从去年开始我算是亲眼看着LLM应用开发从“调API的玩具脚本”慢慢长成了正经的软件工程。最开始大家写一个问答机器人无非是拿OpenAI的接口封装一层prompt里塞点背景能聊就行。可一旦要做到知识库问答、多工具调用、带记忆的Agent代码规模瞬间膨胀逻辑散落在各处改一处崩三处。后来我把整套项目按分层思路重新拆了一遍才发现LLM应用真的和传统后端分层异曲同工。无论你是刚接触AIGC的入门者还是已经在写Agent的老手脑子里有没有一张“架构地图”决定了你的项目能走多远。这篇文章我把自己的实践和盘托出围绕LLM应用开发五层架构逐个展开顺带整理我真实用过的工具箱。不吹不黑全部是踩过坑之后留下的。1. 先看清全局LLM应用为什么需要“分层”思维1.1 从单体脚本到分层架构的演进刚接触LLM开发的人最常见的状态是一个main.py文件走天下。读用户输入、拼prompt、调模型、解析输出最后返回给前端全部堆在一个文件里。如果只是做个demo这种方式完全没问题毕竟五分钟就能跑通。但业务场景一复杂问题就出来了。以最简单的知识库问答为例你至少要做文档加载、文本切分、向量化、存储、检索、重排、提示词构造、模型调用、引用溯源、会话管理。这些东西全部绞在一起其实是把“数据层”“模型层”“编排层”混为一谈了。你今天想换一个向量库要改数据库连接、改数据同步、改检索逻辑、改返回格式牵一发动全身。我自己的转折点是在做一个模拟项目X的客服助手时——需求不断叠加代码从几百行膨胀到几千行调试一个上下文丢失的问题查了两天才发现根源不在模型而在记忆模块的状态维护。那一刻我意识到LLM应用开发要先解决复杂度的组织问题再谈智能化。1.2 五层架构速览一句话讲清每一层我把自己的项目反复整理后最终沉淀出一套实用的五层架构。它不是某本教科书上的标准定义而是从大量实践里长出来的通用骨架层级核心职责一句话总结第一层 交互层用户界面、输入输出、渠道适配让用户能“用起来”第二层 编排层Agent逻辑、工作流、提示词管理、任务规划决定模型“干什么、怎么干”第三层 模型层模型选型、多模型路由、推理参数、微调接入决定“由谁思考”第四层 数据层RAG检索、向量库、记忆、知识库、缓存给模型“喂什么”第五层 支撑层评测、监控、安全、成本治理让应用“跑得稳”这五层不是物理隔离的微服务概念而是逻辑分层。也就是说你写代码时不必拆成五个独立服务但头脑里必须清楚这段逻辑属于哪一层它的依赖方向是什么上层能否直接绕过下层去访问数据这个分层方法最大的好处是“替换友好”。数据层的向量库从Chroma换成Milvus代码改动被限制在数据层内部模型层从A模型切到B模型只要接口协议不变编排层可以完全不动。对我来说分层思维带来的效率提升远大于任何单一工具。2. 逐层拆解从交互到基础设施到底在做什么2.1 第一层 交互层别把界面当作附属品很多做LLM应用的人天然轻视交互层觉得“反正核心是模型前端随便写写就行”。这个观念我建议尽早纠正。交互层是用户与模型能力的触点它直接决定了用户对你产品的第一印象。交互层不只是聊天窗口。它包含的内容很杂Web页面、小程序、钉钉/飞书/企微机器人、命令行CLI、语音助手甚至可以把LLM能力嵌入到传统的表单系统里。每一种渠道都有不同的交互范式背后对应的是不同的消息解析和响应格式处理。这个层级的核心技术点有三个流式输出LLM推理耗时长如果不做SSE流式返回用户干等几秒到几十秒体感非常差。流式输出的难点在于中间态的处理——用户看到一半输出就想点“停止”前后端协议要做好配合。会话上下文管理用户刷新页面、切走再回来对话历史能不能恢复这牵扯到session的存储和后端接口设计很多团队是在这层把多轮对话能力初步做上去的。交互友好性比如引用标注、思维链可视化、token消耗展示。这些虽然不影响模型能力但对用户建立信任感很有帮助。我在做客服助手时光是用户消息的“多模态输入”就折腾了很久。用户发来一张截图里面有问题文字系统要先调用视觉模型识别再进入文本问答流程。这在交互层就要做好消息类型的分流。提示不要把交互层的状态管理想得太简单。尤其是流式输出和“用户关闭页面后重新进入”的场景状态恢复方案要在设计阶段预留否则后期补会非常痛苦。2.2 第二层 编排层提示词、工作流与Agent的核心地带如果说交互层是“皮肤”编排层就是LLM应用的“大脑中枢”。它可以简单到一句话把用户请求拼接成prompt发给模型也可以复杂到让模型自主规划任务、调用多个工具、根据结果自我修正。编排层最核心的组件是提示词管理和工具调用协议。提示词管理不是把prompt写在代码字符串里这么简单。我见过太多项目prompt散落在各种文件里改一个语气描述要全局搜索替换。规范做法是把prompt模板化管理——按场景拆分system prompt、user prompt、few-shot示例存成独立配置甚至做版本管理。每次改动prompt都要对应一个可回溯的版本号这样才能评估改动对效果的影响。工具调用是编排层的另一个重头戏。当Agent需要查询数据库、调用计算器、访问外部API时模型本身不具备这些能力只能通过Function Call或Tool Use机制来间接完成。编排层要做的是把工具清单和参数描述传给模型模型决定调用哪个工具编排层再执行该工具、把结果回传给模型继续生成。这里有个经常被忽略的细节工具描述本身就是一种“提示词”它的质量直接影响模型的选择准确率。好的工具描述要包含功能说明、适用场景、参数含义和典型示例。我自己调试过的一个案例——一个库存查询工具描述写得太泛结果模型老是让用户去查“所有商品”却忽略了用户输入的筛选条件。把工具描述改精确准确率立竿见影。再往上就是复杂Agent的编排思维链分解任务、子任务派发、结果合并、多轮反思修正。这个方向能力上限很高但复杂度也成指数级上升。我的建议是新手不要一上来就冲Complex Agent先把“单工具调用-多工具协作-自主规划”这条路一步步走通再把复杂度加上去。2.3 第三层 模型层选型、路由与推理参数模型层是整个架构里最容易被“玄学化”的一层但落到实处无非是三个决策选哪个模型、怎么控制推理参数、不同场景怎么分配模型资源。模型选型的关键不是“哪个最强”而是“哪个最合适”。强模型往往意味着高成本和高延迟如果一个小任务非要上最强的旗舰模型经济账完全算不过来。我常用的策略是任务分级简单分类、信息抽取任务用轻量模型复杂推理、创意生成用旗舰模型极端敏感的场景再考虑私有化部署的开源模型。多模型路由是模型层的进阶玩法。比如设置一个路由器先让轻量模型判断任务类型然后动态转发给对应的模型。这个过程听起来高大上实际上核心就是“分类 转发”。路由判断既要看意图分类也可以结合用户输入的关键词、上下文长度、甚至成本预算来做综合决策。推理参数的控制也值得认真对待。temperature、top_p、max_tokens、presence_penalty、frequency_penalty每一个参数都有明确的行为含义temperature控制随机性越高越有发散性top_p控制候选集累积概率presence_penalty抑制重复内容。很多人调参靠感觉我建议先搞懂参数的数学含义再结合任务场景设定基线最后用评测数据来迭代。模型层还包含一个隐性任务统一接口和降级处理。由于模型服务会有限流、超时、间歇性不可用模型层要设计好重试机制、熔断降级和备用模型切换。这些工程细节在demo里可以不管但在生产环境里就是保命绳。2.4 第四层 数据层RAG、向量库与记忆数据层是我投入精力最多的一层也是决定LLM应用是否能“专业”的关键。LLM自己的知识有截止日期无法覆盖私有业务数据而数据层就是解决“信息如何进入模型决策链”的问题。RAG是目前最主流的技术方案。它的核心思想——并不把所有知识塞进模型而是在回答前先检索相关信息然后拼接进prompt让模型参考。这个“先检索再生成”的流程把知识更新成本从“重新训练模型”降到了“更新知识库索引”工程上要可控得多。RAG的技术链条不短文档导入 - 文本切分 - 向量化(Embedding) - 向量存储 - 检索召回 - 重排序 - 生成。每个环节做不好都会直接拉低回答质量。文本切分是最容易被低估的环节。切得太短语义不完整切得太长向量检索精度下降还容易超过上下文窗口。我的经验是结构化文档表格、合同要按结构边界切长文本按语义段落切同时做好重叠区确保跨段信息不丢失。向量库的选择也是一门学问。Chroma、FAISS适合轻量场景和快速原型Milvus、Qdrant适合大规模生产PGVector则适合你想省去额外基础设施、直接复用PostgreSQL的场景。没有绝对好坏关键看你的数据规模、并发要求和团队技术栈。记忆机制其实也属于数据层。短期记忆是对话历史的管理要处理“截断、摘要、关键信息持久化”三个问题长期记忆则是把用户偏好、项目历史等结构化保存需要时再注入prompt。这个模块我强烈建议单独建模它和RAG虽然共享存储设施但读写模式和更新策略完全不同混在一起后期会很乱。2.5 第五层 支撑层评估、观测、安全与成本治理支撑层是很多人做LLM应用时“以后再说”的部分但它恰恰是应用能不能长期稳定运营的分水岭。小demo可以没有支撑层稍微上点规模的应用少了支撑层等于裸奔。LLM应用的评测与传统软件测试完全不同。传统测试有明确的输入、预期输出和断言而LLM的输出有大量合法变体。评测体系至少包含三个层次单轮问答的准确性、多轮对话的一致性、下游任务的成功率。我自己维护了一套评测集每条用例标注了“标准答案”和“评分标准”每次改动模型、提示词或RAG链路都跑一遍回归评测用分数说话而不是凭感觉。可观测性在LLM应用里的范畴也比普通后端更广。我们不仅要监控服务器指标CPU、内存、错误率还要追踪一次完整请求内部的链路用户输入是什么、检索出了哪些文档、最终拼出的prompt是什么、模型返回了什么。这些日志是定位问题的第一手材料。安全方面最基础的是prompt注入防护——用户输入里可能包含恶意指令试图覆盖系统提示词。这类问题没有百分百的解决方案只能做多层防御输入侧过滤、prompt结构加固、输出侧合规检查、敏感操作二次确认。成本治理本质上是个技术问题。LLM的cost跟token数强相关优化方向包括上下文压缩、语义缓存、局部任务用小模型、把频繁使用的模型响应结果固化成预计算结果。我见过最夸张的项目就是没做语义缓存一个月token费用翻了几十倍。3. 实战工具箱推荐小白到进阶的选型清单3.1 编排框架降低开发门槛的“脚手架”我经常被问到一个问题“新手学LLM应用要不要用框架”我的答案始终是先徒手调几次API感受一下完整链路然后再用框架提速。如果一上来就套框架你只学会了框架的API没有建立起底层直觉。编排框架现在有很多我最常用的是LangChain和LlamaIndex。LangChain的生态最丰富链式组装、工具调用、记忆模块、Agent机制都有成熟实现但它的抽象层次很多新手很容易迷失在各类概念中。LlamaIndex则在数据索引和RAG方向做到了很深文档加载器、索引结构、检索策略都很完善特别适合做知识库问答。如果你更倾向于“少写代码、多拉配置”Dify和Flowise这类低代码平台也很能打。它们把Agent、知识库、工作流可视化集成在一起很适合快速验证业务想法。不过低代码平台也存在扩展受限和黑盒化的问题长期维护要留意。我的建议组合是个人研究阶段用LangChain或直接徒手写团队产品阶段自定义一套轻量编排框架只保留自己真正需要的组件。框架是好工具但别让它牵着走。3.2 模型接入与网关统一入口化解碎片化当你同时使用多家模型服务时模型网关就特别重要。每家厂商的接口协议略有不同如果业务代码直接耦合后续换模型要改动的地方太多。我建议在模型层引入统一的调用抽象层。比如定义一个通用的chat_completion接口输入是messages和params输出是content和usage内部封装各家供应商的实现。这个抽象不需要多复杂一个客户端库加几个适配器就够但它的价值会在模型切换时瞬间体现出来。如果你需要更完善的功能——限流、重试、多租户配额、成本统计、模型路由策略可以考虑直接部署开源的模型网关服务。这类中间件通常支持把OpenAI、Anthropic、国产模型等统一在一个面板下管理运维效率高很多。3.3 向量库与数据处理RAG的关键地基数据准备工具同样不可忽视。文档解析尤其要选好——PDF、Word、Excel、PPT每种格式都有各自的解析难点。表格类文档尤其闹心直接按文本读会丢掉二维结构我做过测试同样的表格数据结构化解析后再embedding检索准确率比普通文本解析高出一大截。文本切分我推荐结合语义自动切分工具不要只用固定字符数硬切。固定切分做demo没问题但真实文档结构复杂硬切会把语义割裂得厉害。重排序环节也很重要初召回可能有一堆无关文档先粗召回再精排效果提升非常明显。3.4 可观测与评测给应用装上“仪表盘”上线之后我最依赖的是可观测工具。它们可以记录每次请求的全链路traceprompt是什么、检索了哪些chunk、模型返回了什么、token消耗多少。没有这套系统线上问题排查基本靠猜。评测这块建议尽早搭建自己的回归评测集把典型问题、边界情况、Bad Case全部记录下来。我自己的习惯是每个项目维护一个JSON格式的评测集字段包含输入、标签、预期行为、评分维度。哪怕最初只有五十条用例也比完全没有强得多。迭代时跑一遍用对比报告看效果变化这是对抗“prompt玄学”的最有效手段。4. 一个真实的完整Demo从0到1搭一个知识问答应用4.1 需求定义和架构选型拿一个实际做过的场景举例给某个内部团队做一个“产品知识库问答机器人”希望员工直接用自然语言查询产品文档、FAQ和操作手册。需求拆解下来很简单用户提问系统检索知识库相关段落模型结合检索结果生成回答需要标引用来源。在五层架构里看就是完整走一遍交互层做Web页面编排层做RAG问答流程模型层接入主力模型数据层建文档索引和存储支撑层放日志与评测。这里我没有直接用重型框架而是保持轻量自定义。数据层用向量库做语义索引编排层手工写一个“检索-拼接-回答”的流程模型层统一封装调用入口。这样做的原因是项目规模不大框架引入的额外复杂度会超过收益。4.2 数据准备与Embedding这一步是整个项目最花时间的环节。文档从多个来源汇集过来有PDF手册、有网页版FAQ、还有几十篇内部实践总结。我先做了文档格式归一化全部转成纯文本或结构化Markdown然后再切分。切分时我用了分层策略每个文档先按章节拆成逻辑块块过长的再按段落切段落的长度在200到500字之间重叠20到50个字。切完之后我给每个chunk补了元数据来源文件名、章节路径、更新时间。这些元数据在后续“引用溯源”功能里直接排上了用场。Embedding模型我选了一个性价比高的本地向量化方案。跑通流程后我特别留意了一个问题文档里的专业缩略词向量检索对它们不敏感。比如用户问“订单超时怎么处理”文档里写的是“交易流程异常”虽然语义相关但字面差异大初召回效果不好。后面靠扩展同义词和重排序才补救回来。4.3 编排与模型调用编排层我做了一个简单但稳定的流水线对用户问题做意图判断是否与知识库相关。改写问题生成更适合检索的查询词。向量检索Top K个相关chunk。用重排序模型对召回结果精排。构造带引用标注的prompt。调用模型生成最终回答。其中问题改写这个步骤很关键。用户的日常提问比较口语化直接拿原文去检索效果往往不如改写后的结构化查询。比如“这个软件到底咋收费的”改写为“软件收费模式、价格策略”检索结果质量就上来了。模型调用时我对temperature设了0.2保持回答稳定性max_tokens限制在500以内避免无意义的扩散。同时做了超时重试和备用模型降级。4.4 交互与测试交互层最核心的体验是流式输出。我用SSE把模型输出实时推送到前端用户等待时间从“干等几秒”变成了“看着字蹦出来”体感提升非常明显。引用来源做成下划线标注用户点击就能看到原始文档片段这个功能上线后好评率意外地高。测试阶段暴露的问题很多。最典型的一次文档里某段落说“支持在线支付”另一段说“暂不支持自动扣款”两个chunk都召回了模型直接把两句信息拼在一起生成了一个自相矛盾的回答。我后来在prompt里加了“请识别检索内容之间的矛盾并以最具体的信息为准”矛盾率降了不少但没有完全根除。这也说明LLM应用不能追求完美要接受一定比例的错误靠流程和提示词不断优化。4.5 上线后的踩坑实录上线初期真金白银换来的教训主要是三个。第一个坑是上下文爆炸。用户连续问几十个问题后历史记录把上下文窗口占满了新知识放不进去回答效果断崖式下跌。后来做了“滑动窗口历史摘要”结合的策略完整历史放最近几轮更早的压缩成摘要。第二个坑是检索结果质量波动。某次修改了文档没有重新跑embedding导致新旧版本内容混杂检索返回了大量过时信息。我在数据管线上加了一道“文档变更即触发增量索引”的自动化流程才止住了这个问题。第三个坑是评测不足导致回归。一次升级模型配置离线看单例回答都正常上线后才发现大量边缘case的处理变了味。原因就是没有及时跑回归评测。那次之后我养成了每次变更都跑评测集、看对比报告的习惯。5. 新手最容易踩的坑与避坑指南5.1 提示词万能论的误区新玩家最常见的迷思是“只要prompt写得好模型什么都干得好”。说实话prompt确实能解决很多问题但它的能力边界是有限的。业务逻辑、工具调用、数据准确性、多轮一致性本质上要靠架构和工程手段来保证prompt只能做“临门一脚”。我自己就遇到过一个案例想靠prompt约束模型“必须从给定文档中提取答案不许自己编”但在没有强制引用机制的情况下模型还是会编。最后是引入了“回答必须附引用chunk id”的要求再在拦截层校验引用是否真实存在才算解决。这就是典型的“越过prompt改架构”。5.2 向量库的“幻觉”很多人以为RAG就是“把文档扔进向量库然后查询”实际上向量检索本身是模糊匹配召回结果会包含大量无关或弱相关片段。我见过有人觉得“反正模型能判断喂多一点没关系”结果主流模型在长上下文里对大量无关信息确实会“选择性失明”回答被噪音带偏。正确做法是控制好召回数量优先保证精度。宁可少召回几段也要保证召回的段落高度相关。对于关键业务场景重排序环节不能省初召回Top 50精排后保留Top 5效果和直接用Top 5完全不一样。5.3 把评测当作了可选项如果你问我一个LLM应用项目哪个环节最容易被偷工减料答案一定是评测。因为它不直接产出用户可见的功能又需要持续投入。但没有评测的迭代就是原地打转。今天改个prompt感觉效果好明天换个模型感觉更好了到底好在哪里有没有引入回归问题全凭感觉说了算。我强烈建议从第一天就开始建评测集不用多几十条关键场景就够起步。关键变更是先跑评测再上生产这个习惯能帮你躲掉一大半线上事故。5.4 成本失控没人告诉你token会烧得这么快成本问题往往在项目做大后才爆发。每轮对话都携带完整历史用户一多token消耗呈线性甚至超线性增长。我给出的建议非常具体实现语义缓存把常见问题和标准回答缓存起来命中直接返回对话历史做动态裁剪超过一定长度就摘要化优先用轻量模型处理简单请求定期分析token消耗报表找出Top级别的消耗场景定向优化。6. 五层架构之外我的工程经验与学习路径建议6.1 分层架构的本质是管理复杂度聊到这里你可能会发现所谓的LLM应用开发五层架构本质上不是什么惊天动地的创新它就是在说一件事——把复杂系统拆成职责清晰的模块让每一部分都能独立演进、独立替换、独立测试。不要觉得分层是过度设计。哪怕你只是写一个个人工具用分层思维去组织代码也会更清爽。我的经验是交互层和编排层至少要在代码目录上分开编排层和数据层的接口契约先定好支撑层的评测从第一天就开始写。这样一来后续迭代和新需求加入永远是在局部做加法而不是在泥潭里翻锅。6.2 给新玩家的路径建议如果你刚刚接触LLM应用开发我建议的学习顺序是这样的第一步先徒手调通一个大模型API理解prompt和参数的含义感受token的消耗。第二步用Python写一个最朴素的RAG脚本加载文档、切分、embedding、检索、拼prompt、生成答案。第三步给脚本穿上Web交互外衣实现流式输出。第四步引入状态管理和记忆机制把单轮问答升级成多轮对话。第五步再回头看LangChain、LlamaIndex这类框架你会发现它们的很多设计都似曾相识。最后一句话送给大家不要被层出不穷的模型和工具搅乱心神模型会换代工具会过时但分层架构的方法论会一直在。把自己的项目当成一个工程系统去搭建而不是一次次地拼prompt碰运气这才是稳定产出高质量AIGC应用的真正路径。