大模型应用三层架构:输入层、模型层与输出层的工程实践

📅 发布时间:2026/10/18 17:35:13
大模型应用三层架构:输入层、模型层与输出层的工程实践
1. 为什么“三层架构”是理解大模型应用的万能钥匙很多人第一次接触大模型应用开发时会被各种新名词砸晕RAG、Agent、Function Calling、思维链、结构化输出、多模态……每隔几周就冒出一个新框架、新玩法感觉永远追不完。我自己刚开始也是这样看到一个新概念就急着去学它的API怎么调、库怎么装结果学了十几个框架之后发现真正能稳定跑在生产环境里的东西底层逻辑其实高度一致。后来我换了一个思路不再追“新花样”而是去拆“不变的东西”。拆到最后发现几乎所有大模型应用——不管包装得多花哨——都可以归结为三个层次输入层、模型层、输出层。模型层是厂商的事你基本动不了真正决定一个应用好不好用的全在输入层和输出层。换句话说所有AI新花样本质上只在做两件事决定给模型喂什么以及决定拿到模型吐出来的东西之后怎么处理。这个判断听起来简单但它能帮你省下大量无效学习时间。比如你看到一个新出的“智能文档问答”工具不用急着研究它的代码先问两个问题它在输入层做了什么特殊处理怎么切文档、怎么拼上下文、怎么构造提示词它在输出层做了什么加工怎么解析、怎么校验、怎么渲染把这两个问题回答清楚这个工具的核心你就掌握了八成。这篇文章就是把这个三层架构彻底拆开从输入构造、模型调用、输出处理三个环节逐一讲清楚每个环节配上我实际踩过的坑和验证过的做法。不管你是刚入门想建立全局认知还是已经做过几个Demo但总觉得不够稳这篇内容都能帮你把脑子里零散的知识点串成一条线。2. 输入层决定模型“看到什么”才是真正的技术活2.1 输入层的本质是把业务问题翻译成模型能理解的上下文很多人以为调用大模型就是“把用户问题直接丢进去”这是最大的误解。模型本身没有记忆、没有业务知识、不知道你的数据库里有什么。它唯一能依据的就是你这一次调用时塞进上下文窗口里的所有文本。所以输入层的核心任务只有一个在有限的上下文窗口内构造出能让模型给出正确答案所需的最少信息。这句话里有两个约束条件经常被忽略。第一是“有限”——主流模型的上下文窗口从几千到几十万token不等但并不是窗口越大越好后面会细说。第二是“最少”——塞得越多不一定越好无关信息会稀释关键信息甚至引入矛盾信号让模型输出质量下降。我见过一个典型场景某团队做一个客服问答机器人把整个产品手册三万多字全部塞进系统提示词然后用户问“退货政策是什么”模型回答得又慢又飘经常把不同产品的退货条款混在一起。后来改成先用关键词检索出最相关的三段条款再拼进上下文准确率立刻上了一个台阶。这就是输入层设计的价值——不是把东西全给模型而是给对的东西。2.2 上下文构造的四种常见模式与选型逻辑根据我实际做过的项目输入层的上下文构造大致可以归为四类每类适用不同场景成本和效果差异很大。第一类纯提示词模式。系统提示词加用户问题不接任何外部数据。适合通用问答、文案生成、翻译润色这类不需要私有知识的场景。优点是简单、快、便宜缺点是一旦涉及具体业务数据就无能为力。第二类检索增强模式。先从知识库中检索相关片段再拼进上下文。这是目前企业应用最主流的做法。关键在于检索质量——检索不准后面全白搭。我通常会用“向量检索关键词检索”混合的方式向量负责语义相似关键词负责精确匹配两者结果合并去重后再做一次重排序。第三类工具调用模式。不直接把数据塞进上下文而是告诉模型“你有这些工具可以调用”模型自己决定什么时候调、调哪个。适合数据实时变化、数据量大、或者需要执行操作的场景。比如查订单状态、查库存、发邮件都属于这类。第四类多轮记忆模式。把历史对话经过压缩或摘要后带入上下文。这里有个常见坑直接把所有历史对话原样拼进去几轮之后上下文就爆了。正确做法是对早期对话做摘要只保留最近几轮的原文摘要部分控制在几百字以内。选哪种模式核心看两个维度数据是否私有、数据是否实时。私有且静态的用检索增强私有且实时的用工具调用不私有也不实时的纯提示词就够了。2.3 提示词工程不是“写作文”而是信息压缩与指令对齐提示词工程被很多人误解成“会说话就行”其实它更像是一种信息压缩技术。你要在几百到几千token的预算内把任务目标、约束条件、输出格式、参考示例全部表达清楚同时还要避免歧义。我自己的提示词模板通常包含五个部分按优先级排列角色定义一句话说清楚模型扮演什么角色。比如“你是一名有十年经验的合同审核律师”。角色定义的作用是激活模型在预训练阶段学到的相关领域知识分布。任务描述用动词开头说清楚要做什么。避免“请帮我看看”这种模糊表述改成“逐条列出以下合同中的风险条款并标注风险等级”。约束条件明确不能做什么。比如“不要编造合同中不存在的内容”“如果信息不足直接说不知道”。输出格式给出具体的结构要求。能用JSON就用JSON能用表格就用表格。格式越明确输出越稳定。参考示例给一到两个输入输出示例。这是提升输出稳定性的最有效手段没有之一。这里有个经验示例的质量比数量重要得多。给三个精心设计的示例效果远好于给十个随意写的示例。示例要覆盖边界情况比如输入为空时怎么输出、输入超出范围时怎么处理。2.4 上下文窗口的“有效容量”远小于标称值这是一个很少被提及但极其重要的经验。模型标称支持128K token的上下文不代表你塞进去128K它就能全部有效利用。实际测试下来信息密度最高的区域通常在上下文的前三分之一和后三分之一中间部分容易被模型“忽略”。这个现象在学术上叫“迷失在中间”Lost in the Middle我在实际项目中也反复验证过。有一次做长文档摘要把一篇两万字的报告整篇塞进去让模型总结结果模型只总结了开头和结尾的内容中间的核心数据完全没提到。后来改成先分段摘要再合并效果立刻改善。所以我的做法是关键信息尽量放在上下文的开头或结尾。如果必须塞长文档先在输入层做分段处理每段单独摘要再把摘要拼起来。宁可多调用几次模型也不要把所有东西堆在一次调用里。3. 模型层你真正能控制的只有三个旋钮3.1 模型选型不是“越贵越好”而是匹配任务复杂度模型层是大多数人觉得最没得选的地方——模型是厂商训练的你只能调API。但实际上模型选型本身就是一道重要的决策题。不同模型在推理能力、响应速度、成本、上下文长度上差异巨大选错了要么效果差要么成本失控。我的选型框架是这样的先看任务复杂度再看延迟要求最后看成本预算。简单任务——比如文本分类、信息抽取、格式转换——用小模型就够了速度快、成本低效果和大模型差距不大。中等任务——比如摘要、翻译、简单问答——中等模型是性价比最高的选择。复杂任务——比如多步推理、代码生成、长文档分析——才需要上大模型。这里有个反直觉的经验很多团队用大模型做简单任务纯属浪费。我见过一个项目用最贵的模型做情感分类每条成本是便宜模型的几十倍但准确率只高了不到两个百分点。换成小模型之后成本降了九成业务方完全感知不到差异。3.2 温度参数不是“创意旋钮”而是确定性调节器温度Temperature是模型调用中最常被误解的参数。很多人把它当成“创意程度”的调节器温度调高就“更有创意”调低就“更保守”。这个理解不算错但不够精确。更准确的理解是温度控制的是输出的概率分布平坦程度。温度趋近于0时模型总是选择概率最高的那个词输出高度确定温度升高时低概率词也有机会被选中输出变得多样但可能不稳定。实际使用中我的经验规则很简单需要确定性输出的场景信息抽取、分类、格式转换、代码生成温度设为0或接近0。需要多样性的场景创意写作、头脑风暴、营销文案温度设在0.7到1.0之间。需要平衡的场景问答、摘要、翻译温度设在0.2到0.5之间。还有一个容易被忽略的点温度不是唯一影响确定性的参数。有些模型还有“top_p”参数控制的是累积概率阈值。我的建议是温度或top_p只调一个另一个保持默认否则两个参数互相干扰很难调出稳定效果。3.3 最大输出长度设小了会截断设大了会浪费最大输出长度Max Tokens这个参数看起来简单但实际使用中有两个坑。第一个坑是设小了导致输出被截断。模型输出到上限就停了后面的内容直接丢失。如果你做的是结构化输出截断意味着JSON不完整解析直接报错。我的做法是先估算任务需要的最大输出长度然后留出50%的余量。比如摘要任务通常输出几百字那就设2000 token的上限。第二个坑是设大了浪费成本。有些API按实际输出计费设大了不影响成本但有些按预留量计费设大了就白白多花钱。这个要看你用的具体服务的计费方式。还有一个隐藏问题输出长度和输入长度共享上下文窗口。如果输入占了100K token输出上限设了50K但模型窗口只有128K那实际可用输出就只有28K。这个账要提前算清楚。4. 输出层从“模型说了什么”到“系统能用什么”4.1 输出解析的三种策略与各自的适用边界模型输出的本质是一串文本但你的系统需要的是结构化数据。从文本到数据中间隔着一层解析。解析策略选不对后面全是坑。策略一直接使用。模型输出什么就用什么不做任何加工。适合纯文本展示场景比如聊天、文案生成。优点是简单缺点是模型偶尔会加一些“好的以下是……”之类的废话需要在前端做展示处理。策略二格式约束加解析。在提示词中要求模型按特定格式输出通常是JSON然后用代码解析。这是目前最主流的做法。关键在于格式约束要足够强——不能只说“请用JSON输出”要给出完整的JSON schema甚至给出示例。策略三后处理提取。模型输出自由文本用正则表达式或额外的模型调用从中提取关键信息。适合模型无法稳定按格式输出的场景或者你需要从大段文本中抽取多个字段的情况。缺点是链路长、成本高、稳定性依赖提取规则的质量。我的选择逻辑是能用策略二就不用策略三能用策略一就不用策略二。每多一层处理就多一个出错点。4.2 结构化输出的稳定性为什么你的JSON总是解析失败做结构化输出最让人头疼的就是模型偶尔不按格式来。明明提示词里写了“只输出JSON”它偏要加一句“好的以下是JSON格式的结果”。明明schema里定义了字段类型它偏要把数字写成字符串。我总结下来JSON解析失败通常有四个原因对应四种解法原因一提示词约束不够强。解法是在提示词里明确写“不要输出任何解释性文字”“不要使用markdown代码块包裹”“第一个字符必须是左花括号”。同时给出一个完整的输出示例。原因二模型能力不够。小模型在格式遵循上确实不如大模型稳定。如果格式要求复杂要么换模型要么简化格式。原因三schema太复杂。嵌套层级太深、字段太多、枚举值太长都会增加模型出错的概率。解法是把大schema拆成多个小schema分多次调用。原因四温度太高。温度高的时候模型更“自由”格式遵循度下降。结构化输出场景把温度调到0或接近0。还有一个工程上的技巧解析失败时不要直接报错而是做一次重试。把解析失败的输出和错误信息一起塞回给模型让它修正。这个“自修复”机制能解决大部分偶发的格式问题。4.3 输出校验模型说的不一定是对的这是最容易被忽视但后果最严重的一环。模型输出格式正确不代表内容正确。它可能编造了不存在的数据、算错了数字、引用了不存在的来源。如果不做校验直接入库或展示轻则闹笑话重则造成业务损失。我的校验清单通常包括四项格式校验JSON能否解析、字段是否齐全、类型是否正确。这是最基础的。范围校验数值是否在合理区间、枚举值是否在允许列表内、日期格式是否正确。一致性校验输出内容是否和输入矛盾。比如输入说“订单金额100元”输出说“订单金额200元”直接拦截。来源校验如果输出引用了外部信息检查这个信息是否真的存在于上下文中。这一步能有效识别模型编造。校验不通过怎么办我的做法是分级处理格式问题直接重试范围问题标记后人工复核一致性和来源问题直接拒绝输出返回兜底话术。4.4 流式输出的工程细节打字机效果背后的取舍流式输出Streaming是提升用户体验的利器让用户感觉模型在“实时思考”。但流式输出给工程实现带来了不少额外复杂度。第一个问题是结构化输出和流式输出天然冲突。流式输出是一段一段吐出来的JSON还没吐完的时候你没法解析。解法是要么放弃流式要么用“部分解析”策略——先按文本流展示等全部输出完再做一次完整解析和校验。第二个问题是错误处理变复杂。非流式调用要么成功要么失败流式调用可能中途断掉。用户已经看到一半内容了这时候报错体验很差。我的做法是在流式输出时加一个“缓冲层”先缓存一小段内容确认没有明显错误再展示给用户。第三个问题是前端渲染压力。高频的流式更新会导致页面频繁重绘在低端设备上可能卡顿。解法是控制更新频率比如每收到50毫秒的内容才更新一次UI而不是每收到一个token就更新。5. 三层架构的联动为什么单独优化一层往往没用5.1 输入和输出是“跷跷板”关系在实际项目中输入层和输出层的设计是互相影响的。你在输入层省下的功夫往往要在输出层加倍还回来反过来也一样。举个例子如果你在输入层把提示词写得非常精确明确告诉模型“只输出A、B、C三个字段每个字段一行用竖线分隔”那输出层的解析就非常简单按行分割再按竖线分割就行。但如果你输入层写得模糊只说“提取关键信息”那输出层就要面对自由文本需要复杂的提取逻辑。我的经验是输入层的确定性投入回报率远高于输出层的补救措施。与其在输出层写一堆正则和容错逻辑不如在输入层多花十分钟把提示词写清楚。5.2 模型层的变化会同时冲击输入和输出模型升级或切换是常有的事但很多人只关注“新模型效果是不是更好”忽略了模型变化对输入输出两层的连锁影响。新模型可能对提示词的敏感度不同。你在旧模型上调好的提示词换到新模型上可能效果变差因为新模型的训练数据分布变了对指令的理解方式也可能变了。同样新模型的输出风格也可能变化原本能解析的JSON格式可能因为模型“话变多了”而解析失败。所以我的做法是每次切换模型都要把输入层的提示词和输出层的解析逻辑重新跑一遍回归测试。不能假设“换个模型而已其他都不用动”。5.3 成本优化的真正杠杆在输入层很多人觉得成本优化就是换便宜模型其实模型层的成本压缩空间有限——便宜模型效果不够最后还是得换回来。真正的成本杠杆在输入层。输入token是按量计费的你塞进去的每一段无关文本都在烧钱。我做过一个统计某项目优化前平均每次调用输入3000 token优化后降到800 token输出质量没有下降成本直接降到原来的四分之一。优化手段包括去掉冗余的系统提示词、对历史对话做摘要、检索时只取最相关的片段、合并重复的指令。输出层的成本优化空间相对小主要是控制最大输出长度和避免不必要的重试。但输入层的优化是“一次投入、持续收益”值得花时间打磨。6. 几个真实场景下的三层拆解示范6.1 场景一合同关键信息抽取这个场景的目标是从一份合同文本中抽取出签约方、金额、期限、违约责任等字段。输入层合同全文可能几千到几万字不能全塞进去。我的做法是先用规则或小模型定位到包含关键信息的段落通常在合同的前几页和违约责任章节只把这些段落拼进上下文。提示词里给出明确的字段列表和输出格式温度设为0。模型层选择中等模型即可因为任务本质是信息抽取不需要复杂推理。上下文窗口要足够容纳选出的段落。输出层要求模型输出JSON解析后做范围校验——金额是否为正数、日期是否合法、签约方名称是否在输入文本中出现过。校验不通过的字段标记为“待人工确认”不直接入库。这个场景的坑在于合同里的金额可能同时出现中文大写和阿拉伯数字模型有时会混淆。解法是在提示词里明确“金额统一输出阿拉伯数字保留两位小数”。6.2 场景二多轮客服对话这个场景的目标是让用户能和客服机器人进行多轮对话解决常见问题。输入层系统提示词定义客服角色和话术规范历史对话做摘要压缩只保留最近三轮原文用户当前问题先做意图识别根据意图检索对应的知识库片段。这里的关键是意图识别要准识别错了后面全错。模型层选择响应速度快的模型因为客服场景对延迟敏感。温度设在0.3左右既保持一定的自然度又不至于太飘。输出层输出是自然语言不需要结构化解析。但要做安全检查——过滤敏感词、检查是否包含承诺性话术比如“保证退款”这种不能随便说的话。如果模型输出中包含需要调用工具的操作比如查订单解析出工具名和参数执行后再把结果拼回上下文让模型生成最终回复。这个场景的坑在于多轮对话中用户可能突然切换话题历史摘要如果没做好模型会“记混”。解法是在摘要中明确标注话题切换点。6.3 场景三批量文档摘要这个场景的目标是把一批长文档自动生成摘要供内部知识库使用。输入层文档先分段每段单独摘要再把段摘要合并成全文摘要。这是典型的“分而治之”策略。提示词里明确摘要长度和风格要求。模型层因为要处理大量文档成本敏感选择性价比高的模型。温度设在0.2保证摘要风格一致。输出层摘要文本直接入库但要做长度校验和重复度校验。长度超出预期的打回重做重复度太高的说明模型在复制原文也打回。这个场景的坑在于分段摘要再合并可能丢失段与段之间的逻辑关系。解法是在合并阶段除了段摘要之外还把每段的第一句话拼进去帮助模型理解上下文衔接。7. 我踩过的三个印象最深的坑7.1 提示词里写了“不要编造”模型还是编了早期做知识库问答时我在提示词里反复强调“只根据提供的资料回答不要编造”。但测试时发现当资料里没有答案时模型还是会编一个看起来很像的答案。后来我明白了“不要编造”是一个否定指令模型对否定指令的遵循度天然弱于肯定指令。改成“如果资料中没有相关信息直接输出‘根据现有资料无法回答’”之后编造率大幅下降。肯定指令告诉模型“应该做什么”比告诉它“不要做什么”有效得多。7.2 JSON解析失败率高达15%原因出在温度上有一个项目做信息抽取要求输出JSON。测试时发现解析失败率一直在10%到15%之间检查输出发现大部分失败案例都是模型在JSON前后加了“好的以下是结果”之类的文字。我一开始以为是提示词不够强反复修改提示词效果不明显。后来把温度从0.7降到0失败率直接降到2%以下。原来温度高的时候模型更倾向于“自由发挥”格式遵循度下降。这个教训让我之后所有结构化输出场景都默认把温度设为0。7.3 上下文塞太满模型反而“看不见”关键信息做长文档问答时我把检索到的十个片段全部塞进上下文想着“信息越多越好”。结果模型回答质量反而下降经常漏掉关键信息。后来做了对比测试分别塞3个、5个、10个片段发现塞3个片段时准确率最高。原因是片段太多时关键信息被淹没在大量文本中模型的注意力被分散了。这个经验让我之后做检索增强时严格控制片段数量宁可多检索几轮也不一次性塞太多。8. 给不同阶段从业者的实操建议如果你刚开始接触大模型应用我的建议是先把三层架构的思维框架建立起来。不要急着学框架、调API先问自己这个应用的输入是什么、输出是什么、中间模型需要做什么。把这三个问题回答清楚再去写代码。如果你已经做过几个Demo但觉得不够稳重点检查输入层和输出层。大部分不稳定问题都出在这两层——要么是输入信息不够或太多要么是输出没有做校验和容错。把这两层加固之后稳定性会有明显提升。如果你在做生产级应用除了三层本身还要关注三层之间的联动。输入层的变化会影响输出层的解析逻辑模型层的切换会同时冲击输入和输出。每次变更都要做完整的回归测试不能只测单层。最后说一个我自己的习惯每次遇到新的AI应用或框架我都会用三层架构去拆它——它的输入层做了什么特殊处理输出层有什么独特的后处理逻辑模型层选了哪个、为什么拆上十几个之后你会发现大部分“新花样”其实都是旧逻辑的新组合学习成本会大幅降低。