1. 大模型三层架构到底在拆什么
1.1 从一个常见困惑说起
很多人第一次接触大模型应用开发时,都会有一种“怎么天天出新东西”的眩晕感。今天流行提示词工程,明天流行RAG,后天又冒出个Agent、Function Calling、MCP、工作流编排,再往后还有多模态、长上下文、记忆系统、思维链、反思循环……名字一个比一个唬人,教程一篇比一篇长,但真正动手做的时候,你会发现一个尴尬的事实:大部分所谓的新花样,拆到根子上,无非是在解决两个问题——输入什么,以及输出怎么处理。
我做了几年AI应用落地,从最早拿API写个问答机器人,到后来做知识库、做自动化流程、做多步推理的智能体,踩过的坑不算少。回头看,真正让我从“追热点追得心累”变成“看什么新框架都能快速上手”的转折点,就是我把大模型应用拆成了一个三层架构来理解。这个架构不是什么官方标准,是我自己在项目里反复验证后总结出来的一套心智模型,但它极其好用。
这篇文章就是把这套三层架构彻底拆开讲清楚。不管你是刚入门想搞明白这些概念之间的关系,还是已经做了一段时间但总觉得知识是散的,这篇内容都值得你花时间看完。我会用大量类比、实操细节和踩坑经验,让你看完之后再看任何AI新框架,都能一眼看穿它到底在哪一层做文章。
1.2 三层架构的全景图
先把结论摆出来。我理解的大模型应用三层架构是这样的:
- 第一层:模型层(Model Layer)—— 就是那个大模型本身,负责“理解输入、生成输出”。你用的是哪个模型、什么参数、什么能力边界,都属于这一层。
- 第二层:输入层(Input Layer)—— 所有在模型看到输入之前发生的事情。包括提示词怎么写、上下文怎么拼、知识怎么检索、工具怎么描述、历史怎么压缩,统统算这一层。
- 第三层:输出层(Output Layer)—— 模型吐出token之后发生的所有事情。包括解析、校验、格式化、调用工具、多步循环、结果渲染、错误重试,都归这一层。
你可能会问:那Agent、RAG、工作流这些热门概念放哪?答案是——它们不是独立的一层,而是横跨输入层和输出层的组合模式。RAG主要在输入层做文章(把检索到的知识塞进上下文),Agent主要在输出层做文章(解析模型的工具调用意图并执行),工作流则是把输入层和输出层串起来的多步编排。
这个视角一旦建立,你会发现市面上大部分“新概念”都能被归类。Function Calling是输出层的结构化解析,MCP是输入层和输出层的工具协议标准化,思维链是输入层的提示技巧加上输出层的多步展开,记忆系统是输入层的历史管理加上输出层的写入决策。没有例外。
1.3 为什么这个拆法比“追框架”更有效
我见过太多人学AI应用开发的方式是:看到一个热门框架,跟着教程跑一遍demo,跑通了觉得自己会了,换个场景又不会了。原因很简单——他学的是框架的API,不是问题的本质。框架会过时,API会变,但“输入什么、输出怎么处理”这两个问题永远不会变。
用三层架构来理解,你学的不再是“LangChain怎么用”“LlamaIndex怎么配”,而是“我现在的输入够不够模型理解”“我的输出解析够不够健壮”。前者是记忆,后者是能力。记忆会遗忘,能力会迁移。
而且这个拆法还有一个实际好处:排查问题的时候定位极快。模型回答不对,你先问自己——是输入层没给够信息,还是输出层解析错了,还是模型层本身能力不够?三个问题一过,方向基本就清楚了。不用像无头苍蝇一样到处改代码。
2. 第一层:模型层——能力边界决定一切
2.1 模型层到底负责什么
模型层是整个系统的“大脑”,但它比很多人想象的要“单纯”。它做的事情只有一件:给定一段输入token序列,预测下一个token的概率分布,然后采样输出。就这么简单。它不负责检索、不负责记忆、不负责调用工具、不负责格式化输出。所有这些“看起来像模型在做”的事情,其实都是输入层和输出层在配合。
理解这一点非常关键。很多人会抱怨“模型怎么记不住之前的对话”,其实模型本身是无状态的,它每次看到的只是你这次传给它的完整上下文。所谓“记忆”,是输入层每次把历史对话拼进去的结果。模型没有记忆,是输入层在帮它“回忆”。
同样,模型也不会“主动”调用工具。它只是在输出层被引导着生成了一段符合工具调用格式的文本,然后输出层解析这段文本并执行。模型本身不知道工具的存在,它只是在“续写”你给它的输入。
2.2 模型选型的核心考量
既然是模型层,就绕不开选型。我一般从四个维度来评估:
| 维度 | 关键问题 | 实际影响 |
|---|---|---|
| 能力上限 | 复杂推理、代码、多语言表现如何 | 决定输入层能偷多少懒 |
| 上下文窗口 | 能塞多少token | 决定输入层的拼接策略 |
| 输出稳定性 | 格式遵循、指令遵循是否可靠 | 决定输出层解析的复杂度 |
| 成本与延迟 | 每百万token多少钱、首token多快 | 决定整体架构的经济性 |
这四个维度里,输出稳定性是最容易被低估的。我踩过一个大坑:早期用某个模型做结构化输出,提示词里写清楚了JSON格式,大部分时候没问题,但偶尔会多输出一段解释文字,导致解析失败。后来换了一个指令遵循更强的模型,同样的提示词,解析成功率从85%直接拉到99%以上。输出层代码一行没改,整体稳定性天翻地覆。
所以选型的时候,不要只看“跑分”,要拿你自己的真实任务去测。特别是输出格式的稳定性,一定要用几十上百条真实输入压测一遍,看失败率。这个数据比任何榜单都靠谱。
2.3 模型层不是越强越好
新手容易有一个误区:既然模型是大脑,那是不是越强越好?答案是——看情况。模型越强,通常越贵、越慢,而且很多时候你根本用不到它的全部能力。
举个例子。如果你只是做一个意图分类任务,把用户输入分成“咨询、投诉、查询”三类,用一个中等模型甚至小模型就够了,准确率可能只比顶级模型低一两个百分点,但成本和延迟可能只有十分之一。这时候把预算花在模型层,不如花在输入层——把分类的类别定义写清楚、给几个示例,效果提升比换模型明显得多。
我的经验法则是:先用中等模型跑通全流程,找到瓶颈在哪一层,再决定要不要升级模型。如果瓶颈在输入层(信息不够),换模型没用;如果瓶颈在输出层(解析不稳),换模型可能有用但不如优化解析逻辑;只有当输入输出都优化到位了,模型能力才成为真正的瓶颈。
2.4 模型层的参数调优实操
模型层能调的参数其实不多,但每个都有讲究。我拿最常见的几个来说:
温度(Temperature)控制输出的随机性。做事实性问答、结构化输出,温度调到0到0.3;做创意写作、头脑风暴,可以到0.7到1.0。我见过有人做客服机器人温度设0.9,结果同一个问题每次回答都不一样,用户投诉“你们机器人是不是有病”。这种场景温度必须低。
最大输出长度(Max Tokens)这个参数很多人不设,结果模型啰嗦起来没完。我的习惯是根据任务设一个合理上限,比如摘要任务设500,分类任务设50。设太小会截断,设太大会浪费。有个技巧:先不设上限跑一批,看输出长度的分布,取95分位数作为上限。
Top-p和温度配合使用,一般调一个就行。我通常固定Top-p为1,只调温度,减少变量。
这些参数没有“最优值”,只有“适合你任务的值”。建议做一个简单的参数扫描:固定其他变量,只调一个,跑20条测试用例,人工评估效果。花不了多少时间,但能让你对模型行为有直觉。
3. 第二层:输入层——决定模型能看到什么
3.1 输入层的核心职责
输入层是整个架构里最被低估、但实际影响最大的一层。它的核心职责只有一个:在模型生成之前,把所有它需要的信息,以它能理解的形式,塞进上下文窗口。
听起来简单,做起来全是细节。信息塞少了,模型答不对;塞多了,模型被干扰;格式不对,模型理解偏;顺序不对,模型抓不住重点。我做过统计,在我经手的项目里,超过60%的效果问题最终都归因到输入层,而不是模型能力。
输入层要做的事情包括但不限于:系统提示词设计、用户输入预处理、历史对话管理、知识检索与拼接、工具描述注入、少样本示例选择、上下文压缩与摘要。每一项都有讲究。
3.2 提示词工程只是输入层的一部分
很多人把提示词工程等同于输入层的全部,这是个误解。提示词工程主要解决的是“怎么把指令说清楚”,但输入层还要解决“把什么信息放进来”和“怎么组织这些信息”。
我习惯把输入层的内容分成四块来管理:
- 指令块(Instruction):告诉模型要做什么、怎么做、有什么约束。这部分相对稳定,通常就是系统提示词。
- 知识块(Knowledge):模型需要参考的事实信息。可能是检索来的文档片段,可能是数据库查询结果,可能是用户上传的文件内容。
- 历史块(History):之前的对话轮次。需要决定保留几轮、怎么压缩、什么时候摘要。
- 示例块(Examples):少样本示例,帮模型理解输出格式和任务边界。
这四块的顺序、比例、格式都会影响效果。我的默认顺序是:指令 → 示例 → 知识 → 历史 → 当前输入。但这个顺序不是固定的,要根据任务调整。比如做多轮对话,历史可能要紧挨着当前输入;做知识问答,知识块要放在显眼位置。
3.3 上下文窗口的分配策略
上下文窗口是输入层最硬的约束。假设模型支持128K token,你不能真的塞满128K,因为输出也要占空间,而且太长的上下文会导致“中间遗忘”——模型对上下文中间部分的信息注意力下降。
我的分配策略是这样的:先预留输出空间(比如4K),剩下的按比例分。指令块通常1K到2K够了,示例块看情况1K到4K,知识块是弹性最大的,历史块要设上限。
具体操作上,我会给每一块设一个token预算,超了就压缩。知识块超了,就减少检索条数或截断文档;历史块超了,就把早期对话做摘要。这个预算不是拍脑袋定的,要跑测试看效果。我一般会做几组对比:知识块给2K、4K、8K,看效果和成本的平衡点在哪。
有个实用技巧:用tokenizer先算一遍各块的实际token数,别靠字数估算。中英文token比例差异很大,估算容易翻车。大部分模型都有对应的tokenizer库,几行代码就能算。
3.4 检索增强(RAG)在输入层的实现细节
RAG是输入层最典型的应用模式。它的核心思想是:模型不知道的知识,我检索出来塞给它。但RAG做得好不好,差距巨大。
我见过很多RAG项目效果差,问题往往出在几个地方:
切块策略太粗暴。按固定字数切,把一句话切成两半,检索出来语义不完整。我的做法是按语义切块,比如按段落、按标题层级,再配合重叠窗口。切块大小也要试,256、512、1024都跑一遍看效果。
检索只用了向量。纯向量检索对关键词匹配不敏感,用户问“XX型号的参数”,向量可能召回一堆语义相似但型号不对的内容。我通常用混合检索:向量加关键词(BM25),再加重排序。这套组合下来,召回质量提升明显。
检索结果直接拼接。检索出来的片段直接塞进上下文,没有去重、没有排序、没有标注来源。模型看到一堆重复信息,反而困惑。我的做法是去重后按相关性排序,每条前面加个编号,提示词里告诉模型“参考以下编号内容回答”。
忽略了“检索不到”的情况。用户问的问题知识库里没有,检索出来一堆不相关的,模型硬着头皮编。我的做法是设一个相关性阈值,低于阈值就不塞知识块,提示词里加一句“如果参考资料不相关,请如实说不知道”。
3.5 历史对话管理的实操技巧
多轮对话是输入层的另一个难点。模型无状态,每次都要把历史拼进去。但历史不能无限拼,会超窗口,也会稀释当前问题的注意力。
我的历史管理策略分三档:
- 最近N轮完整保留。N一般取3到5,保证近期上下文完整。
- 更早的对话做摘要。用一个便宜的模型把早期对话压缩成一段摘要,放在历史块开头。
- 关键信息抽取。从历史里抽取实体、偏好、已确认的事实,以结构化形式保留,比如“用户偏好:中文回答;已确认订单号:XXX”。
这三档配合使用,既控制了token,又保住了关键信息。实测下来,比单纯截断最近N轮效果好很多,特别是长对话场景。
有个坑要注意:摘要本身也可能丢信息。我一般会在摘要后面保留最近几轮的原文,形成“摘要+近期原文”的结构。另外,摘要的生成也要用提示词约束,明确告诉它“保留事实、数字、用户偏好,去掉寒暄”。
4. 第三层:输出层——决定模型吐出来的东西怎么用
4.1 输出层的核心职责
模型吐出token之后,事情才做了一半。输出层要负责:解析模型输出、校验合法性、格式化、执行动作、处理异常、决定是否继续循环。
这一层最容易被新手忽略,因为demo里模型输出直接打印出来就完事了。但真实项目里,模型输出是要被程序消费的。你要从里面提取结构化数据、要判断是否调用工具、要处理格式错误、要在多步任务里决定下一步。这些全是输出层的活。
我有个观点:输出层的健壮性,决定了一个AI应用能不能上生产。demo可以容忍模型偶尔抽风,生产不行。输出层的核心任务就是把模型的不确定性“兜住”。
4.2 结构化输出的解析与校验
结构化输出是最常见的需求。你让模型输出JSON,然后程序解析。但模型不是每次都给合法JSON,可能多一段解释、可能少个括号、可能用了单引号。
我的处理流程是这样的:
- 提示词层面约束。明确说“只输出JSON,不要任何其他文字”,并给一个示例。
- 解析层面容错。用宽松的解析器,能处理常见问题。比如先尝试提取第一个
{到最后一个}之间的内容,再解析。 - 校验层面严格。解析出来后用schema校验,字段类型、必填项、取值范围都查一遍。
- 失败层面重试。校验失败就把错误信息拼回提示词,让模型重新生成,最多重试2到3次。
- 兜底层面降级。重试还失败,就走降级逻辑,比如返回默认值、转人工、或者用规则解析。
这套流程下来,结构化输出的成功率能做到99.9%以上。关键是每一步都要有,不能省。我见过只做第1步的,成功率85%就上线,结果线上天天报错。
4.3 工具调用(Function Calling)的输出层实现
工具调用是输出层的重头戏。模型本身不执行工具,它只是生成一段“我想调用某个工具,参数是XXX”的文本。输出层解析这段文本,执行真正的工具,再把结果拼回输入层,进行下一轮。
这里的关键是工具描述的格式和调用结果的回传格式。工具描述要清晰:工具名、功能说明、参数名、参数类型、是否必填、参数说明。这些信息会作为输入层的一部分注入,模型根据这些描述决定调不调用、怎么调。
调用结果回传也有讲究。我一般会把结果包装成结构化格式,比如{"tool": "search", "status": "success", "result": "..."},再拼回上下文。这样模型能清楚知道工具执行成功了没有、结果是什么。
有个坑:模型可能编造工具名或参数。输出层解析的时候要校验工具名是否在注册表里、参数是否符合schema。不符合就返回错误信息让模型重试,而不是直接执行。我早期没做这个校验,结果模型编了个不存在的工具名,程序直接崩了。
4.4 多步循环与终止条件
Agent类应用的核心是输出层的多步循环:模型输出 → 解析 → 执行 → 结果回传 → 模型再输出 → ……直到任务完成或达到终止条件。
这个循环最容易出问题的地方是终止条件。如果不设好,模型可能陷入死循环,反复调用同一个工具;也可能过早终止,任务没完成就停了。
我的终止条件一般设这几个:
- 模型输出中明确表示完成。比如输出
{"status": "done", "answer": "..."}。 - 达到最大步数。一般设5到10步,防止无限循环。
- 连续N步没有新信息。如果连续两步的工具调用和结果都一样,说明卡住了,强制终止。
- 超出token预算。整个循环的累计token超过预算,终止。
这几个条件要同时监控,任何一个触发就停。停的时候要给用户一个合理的反馈,不能直接报错。
4.5 输出格式化的实战经验
模型输出最终要展示给用户,格式化很重要。但格式化不只是加个markdown,还要考虑:
流式输出。用户等不及模型全部生成完,要边生成边显示。流式输出下,输出层要处理“半截JSON”“半截markdown”的情况。我的做法是流式阶段只做纯文本展示,等生成完了再做结构化解析和渲染。
多模态输出。模型可能输出图片链接、表格、代码块。输出层要识别这些内容并正确渲染。我一般会在提示词里约定输出格式,比如图片用,表格用markdown表格,代码用代码块。
敏感内容过滤。输出层要过一遍敏感词和合规检查,这个不用多说,但要注意别过度过滤,把正常内容也拦了。我一般用白名单加黑名单结合的方式。
引用标注。如果输入层塞了检索知识,输出层要把模型回答里的引用标注出来,让用户知道哪句话来自哪个来源。这个要在提示词里约定引用格式,输出层解析后渲染成可点击的链接。
5. 三层架构的联动:为什么新花样都逃不出这个框架
5.1 RAG、Agent、工作流的架构定位
现在回头看那些热门概念,定位就清楚了:
| 概念 | 主要作用层 | 核心机制 |
|---|---|---|
| RAG | 输入层 | 检索知识塞进上下文 |
| Function Calling | 输出层 | 解析工具调用意图并执行 |
| Agent | 输入层+输出层 | 多步循环,每步都涉及输入拼接和输出解析 |
| 工作流 | 输入层+输出层 | 预定义的多步编排,每步的输入输出都受控 |
| 记忆系统 | 输入层+输出层 | 输入层读记忆,输出层写记忆 |
| 思维链 | 输入层+输出层 | 输入层引导,输出层展开多步推理 |
| MCP | 输入层+输出层 | 工具描述的标准化协议 |
你看,没有一个逃出三层。所谓“新花样”,要么是在某一层做优化,要么是把两层组合出新模式。理解了这个,你再看新框架,就能快速判断它到底解决了什么问题、值不值得学。
5.2 一个完整案例:智能客服系统的三层拆解
我拿一个实际做过的智能客服系统来串一遍。需求是:用户提问,系统检索知识库,必要时调用订单查询工具,最后给出回答。
输入层设计:
- 指令块:客服角色设定、回答风格、禁止事项。
- 知识块:检索到的FAQ片段,按相关性排序,带编号。
- 历史块:最近3轮对话原文加更早对话摘要。
- 工具描述:订单查询工具的参数说明。
- 当前输入:用户问题。
模型层选择:中等模型,温度0.3,最大输出500 token。
输出层设计:
- 解析模型输出,判断是直接回答还是调用工具。
- 如果调用工具,校验工具名和参数,执行查询,结果回传,进入下一轮。
- 如果直接回答,校验是否引用了知识块编号,格式化输出。
- 最多循环3步,超时降级转人工。
这套系统上线后,问题解决率比纯模型回答提升了40%多,核心提升就来自输入层的知识检索和输出层的工具调用。模型层反而没怎么动。
5.3 常见误区:把三层混在一起
我见过最常见的架构错误,就是把三层混在一起。比如:
- 在提示词里写“如果不知道就调用搜索工具”——这是把输出层的决策逻辑塞进了输入层,导致模型输出不稳定。
- 在输出层解析的时候重新检索知识——这是把输入层的活干了,导致逻辑混乱。
- 模型层选型的时候考虑“它能不能记住历史”——模型层根本不负责记忆,这是输入层的活。
分层清晰的好处是,每一层的问题在每一层解决。输入层的问题不要指望换模型解决,输出层的问题不要指望改提示词解决。定位准了,解决起来就快。
6. 实操中的常见问题与排查技巧
6.1 效果问题的三层定位法
模型回答不对,怎么快速定位?我的三步法:
第一步:看输入层。把实际传给模型的完整上下文打印出来,人工读一遍。信息够不够?格式对不对?有没有干扰信息?我敢说,一半以上的问题在这一步就能发现。
第二步:看输出层。如果输入没问题,看模型原始输出是什么,解析后是什么。是不是解析错了?是不是格式没约束好?是不是工具调用参数错了?
第三步:看模型层。输入输出都没问题,那就是模型能力不够。这时候才考虑换模型或调参数。
这个顺序不能反。很多人一上来就怀疑模型,换了一圈模型发现没用,最后才发现是输入层少塞了一段关键信息。
6.2 常见问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 模型答非所问 | 输入层指令不清或知识干扰 | 检查提示词和知识块 |
| 输出格式不稳定 | 输出层解析太严或提示词约束不够 | 加示例、加容错解析 |
| 多轮对话失忆 | 输入层历史管理有问题 | 检查历史拼接和摘要 |
| 工具调用失败 | 输出层校验太严或工具描述不清 | 检查工具schema和错误回传 |
| 响应太慢 | 输入层上下文太长或模型太大 | 压缩上下文、换小模型 |
| 成本太高 | 输入层塞太多或输出层循环太多 | 优化检索条数、设循环上限 |
6.3 几个我踩过的坑
坑一:提示词越长越好。早期我写系统提示词,恨不得把所有情况都覆盖,写了2000多字。结果模型反而抓不住重点,效果下降。后来精简到500字以内,只保留核心指令和关键约束,效果反而好了。提示词不是越长越好,是越准越好。
坑二:检索条数越多越好。做RAG的时候,我一开始检索top 10塞进去,觉得信息越多越好。结果模型被不相关的内容干扰,回答质量下降。后来改成top 3加相关性阈值,效果好很多。信息不是越多越好,是越相关越好。
坑三:输出解析越严越好。我一开始用严格的JSON schema校验,模型稍微格式不对就报错重试,导致延迟很高。后来改成宽松解析加关键字段校验,非关键字段容错,成功率和延迟都改善了。校验要抓大放小。
坑四:循环步数越多越好。做Agent的时候,我把最大步数设到20,觉得给模型足够空间。结果模型经常在无关的步骤上打转,浪费token。后来改成8步,并且加了“连续无新信息就终止”的条件,效率提升明显。循环要有边界。
6.4 性能与成本的平衡技巧
三层架构里,每一层都有成本和性能的权衡。我的经验是:
输入层是成本大头。上下文越长,成本越高。优化输入层的token效率,比换模型省钱多了。具体做法:压缩历史、精简提示词、控制检索条数、用更高效的格式。
输出层是延迟大头。多步循环、重试、工具调用都会增加延迟。优化输出层的逻辑,比换更快的模型有效。具体做法:减少不必要的重试、并行执行独立工具、流式输出。
模型层是能力上限。前两层优化到位了,再考虑模型层。换模型之前,先问自己:输入输出还有没有优化空间?
7. 把这套框架用起来
7.1 新项目的架构设计清单
如果你现在要开始一个新项目,我建议按这个清单过一遍:
输入层:
- 指令块写清楚了吗?有没有示例?
- 知识块从哪来?检索策略是什么?怎么排序去重?
- 历史块保留几轮?怎么压缩?
- 上下文预算怎么分配?超了怎么处理?
模型层:
- 选哪个模型?为什么?
- 温度、最大输出长度设多少?
- 输出稳定性测过了吗?
输出层:
- 输出格式是什么?怎么解析?
- 校验规则是什么?失败了怎么重试?
- 有没有工具调用?怎么校验和执行?
- 有没有多步循环?终止条件是什么?
- 异常怎么兜底?
这个清单过一遍,架构基本就清晰了。
7.2 老项目的优化切入点
如果你手上已经有一个跑着的项目,想优化,我建议按这个顺序:
- 先看输入层。把实际上下文打印出来,人工评估信息质量和格式。这一步往往能发现最大的优化空间。
- 再看输出层。统计解析失败率、重试率、循环步数。这些指标能告诉你输出层的健壮性。
- 最后看模型层。前两层优化完了,再评估模型是否成为瓶颈。
我做过一个项目,什么都没换,只是把输入层的检索策略从纯向量改成混合检索,输出层的解析加了容错,整体效果提升了30%多,成本还降了。模型一行没动。
7.3 后续可以怎么扩展
这套三层框架不是终点,是一个起点。你可以在此基础上继续深入:
- 输入层深入:研究更高效的上下文压缩算法、更精准的检索策略、更智能的历史管理。
- 输出层深入:研究更健壮的结构化输出方案、更灵活的工具编排、更智能的循环控制。
- 跨层优化:研究输入输出联合优化,比如根据输出反馈动态调整输入。
但不管怎么深入,记住核心:所有AI新花样,只在“输入什么”和“输出怎么处理”。抓住这两个问题,你就抓住了大模型应用开发的命脉。
我个人在实际操作中的体会是,这套框架最大的价值不是让你多懂几个概念,而是让你在面对新东西的时候不慌。你知道它一定在某一层或某两层做文章,你只需要问自己:它解决了输入的什么问题,还是输出的什么问题?问完,你就懂了。