大模型应用开发三层架构:输入层、模型层与输出层全解析

发布时间:2026/10/22 5:13:19
大模型应用开发三层架构:输入层、模型层与输出层全解析
1. 为什么“三层架构”是理解大模型应用的万能钥匙很多人第一次接触大模型应用开发时会被各种新名词砸晕提示工程、RAG、Agent、Function Calling、思维链、结构化输出、工作流编排……每隔几个月就冒出一批新概念感觉永远追不完。但如果你把这些东西全部摊开来看会发现一个让人安心的事实几乎所有大模型应用本质上都在做同一件事——控制输入什么以及处理输出成什么。我把它拆成三层来看输入层、模型层、输出层。模型层是那个黑盒你改不了它的权重也控制不了它内部每一层注意力怎么算。你能动的只有两头——进去之前给它喂什么出来之后拿它产出的东西怎么办。所有花里胡哨的“新玩法”归根结底都是在这两头做文章。这个认知对我帮助极大。以前看到一个新框架、新工具我会焦虑“又要学新东西了”现在我会先问一句它到底是在改输入还是在改输出大部分情况下答案都很清晰。比如RAG核心是往输入里塞检索到的资料Function Calling核心是把模型的输出解析成结构化调用Agent则是把“输入-输出”这个循环跑很多遍每一轮的输出变成下一轮的输入。这篇文章适合两类人一类是刚进入大模型应用领域、被各种概念绕晕的开发者另一类是做了一段时间、但总觉得知识是散点、拼不成体系的人。我会用大量实际场景和代码示例把这三层架构彻底拆开讲清楚让你以后再看到任何新名词都能三秒钟定位它属于哪一层、解决什么问题。提示本文讨论的是应用层开发不涉及模型训练和微调。训练是另一条线但即便是训练数据准备输入和损失计算输出同样遵循这个框架。2. 输入层你喂进去的每一个字都在决定输出质量2.1 系统提示词不是“客套话”是最高优先级的约束很多人写系统提示词System Prompt时很随意写几句“你是一个有用的助手”就完事了。但系统提示词是输入层里权重最高的部分它决定了模型的行为边界、角色定位和输出风格。我见过一个团队做客服机器人系统提示词只写了“你是客服助手”结果模型经常用非常口语化、甚至带情绪的方式回复用户。后来他们把系统提示词改成包含具体约束的版本比如“你代表某公司语气专业且克制不评价任何竞品遇到无法回答的问题时引导用户联系人工”输出质量立刻稳定了。系统提示词的核心作用是设定约束条件而不是描述任务。任务应该放在用户消息里系统提示词负责的是“你是谁、你不能做什么、你说话什么风格”。这个区分很重要因为很多模型对系统提示词的遵循度远高于用户消息。你把约束写在用户消息里模型可能因为上下文太长而忽略写在系统提示词里它会被优先处理。我通常会把系统提示词分成几个模块来写角色定义、能力边界、输出格式要求、安全约束、兜底策略。每个模块用简短的分段或列表表达避免写成一大段散文。实测下来结构化的系统提示词比散文式的遵循度高出一大截。2.2 上下文注入RAG的本质就是“把答案提前放在桌上”RAG检索增强生成是这两年最火的应用模式之一但它的本质极其简单在用户提问之前先把可能相关的资料检索出来拼接到输入里。模型并没有变聪明它只是看到了更多信息。我做过一个内部知识库问答的项目最初直接把用户问题扔给模型回答准确率大概只有四成。后来加了检索环节把相关文档片段拼在问题前面准确率直接拉到八成以上。模型还是那个模型输入变了输出就变了。但RAG有几个容易踩的坑。第一个是检索质量决定上限。如果检索出来的内容本身不相关模型再强也答不对。我见过有人用向量检索但文档切分粒度太粗一个片段里混了好几个主题检索出来反而干扰模型。后来改成按语义段落切分每个片段控制在300到500字效果明显提升。第二个坑是上下文长度不是越长越好。很多人觉得把十篇文档全塞进去模型总能找到答案。但实际上无关信息会稀释注意力模型可能被干扰项带偏。我的经验是检索结果控制在3到5个片段总长度不超过模型上下文窗口的一半留出空间给用户问题和系统提示词。第三个坑是拼接顺序有讲究。把最相关的片段放在最前面或最后面模型利用效率更高。中间位置的内容容易被忽略这是注意力机制的特性决定的。我通常按相关度排序最相关的放最前面次相关的放最后面。2.3 少样本示例用“演给它看”代替“告诉它”有些任务很难用文字描述清楚比如“用某种特定的语气回复”“按照某种格式输出”。这时候少样本示例Few-shot比纯文字指令有效得多。你给模型看两三个输入输出的例子它就能模仿出类似的模式。我做过一个把用户反馈分类成“功能建议”“Bug报告”“投诉”“咨询”四类的任务。一开始用文字描述每类的定义模型经常把“功能建议”和“咨询”搞混。后来我每类给了两个例子准确率立刻上去了。模型不需要理解定义它只需要看到模式。少样本示例的挑选有几个原则。示例要覆盖边界情况不能只给典型例子。比如分类任务里要故意给一些模棱两可的例子让模型学会处理模糊地带。示例的格式要一致输入输出的分隔方式、标签的写法都要统一否则模型会困惑。示例数量控制在3到5个太少不够形成模式太多浪费上下文窗口。还有一个细节示例的顺序会影响结果。把最想强调的类别放在最后模型对最后看到的模式印象更深。这是近因效应在起作用和人类记忆的规律类似。2.4 输入层的“隐藏操作”预处理与改写用户输入往往是不规范的有错别字、有口语化表达、有省略、有指代不明。直接扔给模型效果会打折扣。所以在输入层加一道预处理是很多成熟应用的标配。预处理包括几个常见操作。查询改写把用户的口语化问题改写成更规范的表达。比如用户问“那个东西怎么弄”你需要结合上下文改写成“如何配置某某功能”。指代消解把“它”“那个”替换成具体的实体名称。拼写纠正修正明显的错别字。意图识别先判断用户想干什么再决定走哪条处理链路。这些操作可以用小模型来做也可以用规则引擎甚至可以用大模型自己来做。我通常会用一个小模型做意图分类和查询改写成本低、速度快然后把改写后的查询送给大模型处理。这样大模型的输入更干净输出质量更稳定。注意预处理环节本身也可能引入错误。如果改写把用户的原意改偏了后面全错。所以改写结果最好保留原始查询作为备选或者在改写置信度低时直接使用原始查询。3. 模型层你控制不了它但可以理解它的“脾气”3.1 温度与采样同一个输入为什么每次输出不一样模型层的参数你改不了权重但可以调采样策略。最常用的就是温度Temperature。温度低的时候模型倾向于选概率最高的词输出稳定但可能死板温度高的时候模型会选一些概率较低的词输出多样但可能跑偏。我一般这样设做信息抽取、分类、代码生成这类需要准确性的任务温度设0到0.3做创意写作、头脑风暴这类需要多样性的任务温度设0.7到1.0。还有一个参数叫Top-p控制候选词的累积概率阈值通常和温度配合使用。我的习惯是温度调好之后Top-p设0.9左右不要两个都调得很极端。很多人忽略的一点是即使温度设为0输出也不一定完全确定。因为并行计算、浮点数精度等原因同样的输入在不同时间调用结果可能有细微差异。所以如果你的应用对确定性要求极高不能只靠温度还要在输出层做校验和兜底。3.2 上下文窗口模型的“工作记忆”有多大上下文窗口决定了模型一次能看多少内容。这个窗口包括系统提示词、历史对话、检索资料、用户问题、以及模型已经生成的输出。所有东西加起来不能超过窗口上限。窗口大小直接影响应用设计。窗口小的时候你需要做更激进的摘要和压缩窗口大的时候你可以塞更多参考资料但也要注意“迷失在中间”的问题——模型对长上下文中间部分的内容利用率会下降。我做过一个长文档问答的项目文档有几十页。最初把全文塞进去模型经常漏掉中间章节的信息。后来改成两阶段先让模型定位相关章节再把相关章节的详细内容塞进去做问答。虽然多了一次调用但准确率提升明显。这就是在模型层能力受限的情况下用输入层的设计来弥补。3.3 模型选型不是越大越好而是越合适越好现在模型种类很多有超大参数的通用模型有中等规模的均衡模型也有小参数量的轻量模型。选型的时候不能只看“哪个最强”要看任务需求。简单任务比如文本分类、关键词提取、格式转换小模型完全够用而且速度快、成本低。复杂任务比如多步推理、代码生成、长文写作才需要大模型。我通常的做法是先用大模型跑通流程、验证效果然后尝试用小模型替换看效果下降多少。如果下降在可接受范围内就换小模型成本和延迟都能大幅优化。还有一个策略是模型级联先用小模型处理如果置信度低或者任务复杂再升级到大模型。这样大部分请求用小模型解决只有少数难题才动用大模型整体性价比很高。3.4 模型层的“不可控”与应对心态必须承认模型层有很多你控制不了的东西。你不知道它训练数据里有什么偏见不知道它对某些话题的敏感度不知道它什么时候会“幻觉”。这些不可控因素意味着永远不要完全信任模型的输出。我的应对心态是把模型当成一个能力很强但偶尔会犯糊涂的实习生。你可以给它派活但关键结果一定要检查。在应用设计上这意味着输出层必须有校验机制。模型层的不确定性正是输出层存在的意义。4. 输出层从“能说话”到“能干活”的关键一跃4.1 结构化输出让模型返回JSON为什么这么难大模型天生是生成文本的不是生成JSON的。你让它返回JSON它可能给你返回带Markdown代码块的JSON可能给你返回带解释文字的JSON可能字段名拼错可能少一个括号。这些在人类看来是小问题在程序解析时就是致命错误。让模型稳定返回JSON有几种做法。第一种是提示词约束在系统提示词里明确写“只返回JSON不要任何其他文字”并给出JSON的schema示例。第二种是用模型的JSON模式很多模型API提供了强制JSON输出的参数开启后模型会保证输出是合法JSON。第三种是输出后处理用正则表达式提取JSON部分或者用JSON修复库尝试修复。我通常三种一起用提示词约束打底JSON模式保底后处理兜底。即使这样偶尔还是会有意外所以解析失败时要有重试机制。重试的时候可以把错误信息也塞回输入让模型知道上次哪里错了这次修正。4.2 函数调用把模型的“意图”变成“动作”Function Calling函数调用是让模型从“聊天”走向“干活”的关键机制。它的原理是你告诉模型有哪些函数可用每个函数叫什么、参数是什么。模型在生成时如果判断需要调用某个函数就输出一个结构化的调用请求而不是普通文本。你的程序解析这个请求执行实际函数再把结果返回给模型模型继续生成最终回复。这个机制让模型可以查数据库、调API、发邮件、操作文件。但实际用起来有几个坑。第一个坑是参数类型模型可能把数字写成字符串把布尔值写成“true”而不是true。你的函数实现要能容错。第二个坑是幻觉调用模型可能调用一个不存在的函数或者传入不存在的参数。你的解析逻辑要能识别并拒绝。第三个坑是循环调用模型可能反复调用同一个函数陷入死循环。你需要设置最大调用次数。我的经验是函数描述要写得极其清晰每个参数的类型、含义、是否必填都写明白。函数数量不要太多控制在10个以内太多模型会混淆。函数命名要有语义不要用f1、f2这种无意义的名称。4.3 输出校验用规则和模型双重把关模型输出可能包含事实错误、格式错误、安全违规。输出层必须有一道校验关卡。校验分两类规则校验和模型校验。规则校验用代码做检查格式、长度、关键词黑名单、数值范围等。比如输出必须是JSON那就用JSON解析器试一下输出不能包含某些敏感词那就做字符串匹配。规则校验快、便宜、确定性强但只能查表面问题。模型校验用另一个模型来做检查内容质量。比如让一个模型判断“这个回答是否准确回答了用户问题”“这个回答是否包含有害内容”“这个回答的语气是否符合要求”。模型校验能查深层问题但慢、贵、本身也可能出错。我通常的做法是规则校验做第一道过滤拦截明显问题模型校验做第二道处理需要理解语义的判断。两道都通过才返回给用户任何一道不通过就触发重试或降级策略。4.4 后处理与格式化让输出适配下游系统模型输出的原始文本往往需要加工才能给下游系统用。比如模型返回了一段Markdown但你的前端需要纯文本模型返回了中文但你的数据库需要英文模型返回了长文但你的界面只能显示摘要。后处理包括格式转换Markdown转HTML、JSON转表格、语言转换调用翻译模型、长度控制截断或摘要、敏感信息脱敏替换手机号、身份证号、引用标注把模型引用的来源标出来。这些操作看起来琐碎但直接影响用户体验。我见过一个应用模型回答质量很高但输出里总是带一堆Markdown符号前端显示出来全是星号和井号用户观感很差。后来加了一个Markdown清洗步骤体验立刻上去了。输出层的细节往往决定产品的专业度。5. 把三层串起来Agent和复杂工作流的本质5.1 Agent就是一个“输入-输出”循环Agent听起来很高级但拆开看就是把用户的原始输入给模型模型输出一个动作比如调用某个工具程序执行动作得到结果把结果作为新的输入再给模型模型再输出下一个动作……如此循环直到模型输出最终答案。每一轮循环输入层在变上一轮的结果被拼进来输出层在变这一轮要解析的是动作而不是文本。模型层没变还是那个模型。所以Agent的复杂度不在模型而在循环控制和状态管理。我做过一个自动数据分析的Agent用户上传表格后问问题。Agent第一轮输出“需要查看列名”程序执行查看列名的操作把结果返回第二轮Agent输出“需要计算某列平均值”程序执行计算返回结果第三轮Agent输出最终答案。整个过程就是三轮输入输出的循环。5.2 工作流编排把多个“输入-输出”串成流水线复杂任务往往需要多个步骤每个步骤可以是一个独立的模型调用。比如先分类、再抽取、再生成、再校验。每个步骤有自己的输入和输出上一步的输出是下一步的输入。这就是工作流编排。工作流编排的关键是定义清楚每一步的输入输出契约。第一步输出什么格式第二步必须能解析第二步输出什么格式第三步必须能解析。任何一步格式不对整条流水线就断了。所以工作流里每一步都要有校验和重试。我通常会用代码而不是纯提示词来编排工作流。代码可以精确控制每一步的输入输出可以加条件分支、循环、异常处理。提示词编排适合简单场景复杂场景还是代码更可靠。5.3 多Agent协作本质是多个“输入-输出”循环的交互多Agent系统听起来更玄乎但拆开看还是一样每个Agent是一个独立的“输入-输出”循环Agent之间通过消息传递来交互。一个Agent的输出变成另一个Agent的输入另一个Agent的输出又传回来。多Agent的价值在于分工。一个Agent负责规划一个负责执行一个负责检查。每个Agent的提示词不同、可用工具不同、输出格式不同。但底层机制还是输入输出的传递。多Agent的坑在于通信开销和错误累积。Agent之间传话可能失真一个Agent理解错了后面全错。所以多Agent系统需要更强的校验机制和更清晰的通信协议。我的经验是能用单Agent加工作流解决的就不要上多Agent。多Agent的复杂度往往超过它带来的收益。6. 实战中的几个关键决策点6.1 什么时候该加一层什么时候该减一层三层架构不是越复杂越好。每加一层都有成本延迟增加、费用增加、出错概率增加。所以每次想加东西之前先问不加行不行我见过一个项目在输入层加了查询改写、意图识别、实体抽取三道预处理结果延迟从1秒涨到5秒用户等不及就跑了。后来砍掉两道只保留最关键的查询改写延迟回到2秒效果没降多少。加层容易减层难一开始就要克制。判断标准很简单如果加这一层能显著提升核心指标准确率、用户满意度而且成本可接受就加如果只是“感觉更完善”就不加。大部分场景下把系统提示词写好、把输出校验做好就能解决八成问题。6.2 提示词工程和代码工程的分界线在哪提示词能做的事很多但不是什么都能做。我的分界线是需要精确控制、需要确定性、需要复杂逻辑的用代码需要理解语义、需要灵活应变的用提示词。比如格式转换用代码写个函数比让模型做更可靠。比如判断一段话的情感倾向用模型比写规则更准。比如多步计算用代码一步步算比让模型心算更准。比如开放式问答用模型比检索更灵活。实际项目中提示词和代码是交织的。提示词负责“理解”和“生成”代码负责“控制”和“校验”。两者配合才能做出稳定可靠的应用。6.3 成本、延迟、质量的三方博弈做应用永远在成本、延迟、质量之间权衡。用大模型质量高但贵且慢用小模型便宜快但质量可能不够。用长上下文信息全但贵且慢用短上下文便宜快但可能漏信息。用多轮校验质量高但慢用单轮校验快但可能出错。我的策略是分层处理简单请求走轻量路径复杂请求走重量路径。先用小模型或规则做快速判断如果置信度高就直接返回置信度低再升级到大模型。这样大部分请求快速低成本解决少数难题才动用重资源。还有一个策略是缓存。同样的输入如果之前处理过直接返回缓存结果。对于常见问题、热门查询缓存命中率可以很高能大幅降低成本。7. 我踩过的几个印象深刻的坑7.1 系统提示词太长反而被忽略有一次我写了一个非常详细的系统提示词列了二十多条规则。结果模型经常违反其中一些规则。后来我做了个实验把提示词精简到五条最关键的违反率反而下降了。原因是模型对长提示词的注意力是分散的规则太多它记不住反而每条都记不牢。现在的做法是系统提示词只放最核心的约束控制在500字以内。次要规则放到用户消息里或者用少样本示例来体现。如果规则确实很多就分组每组用一个小标题让模型有结构感。7.2 JSON解析失败的重试策略做结构化输出时JSON解析失败是家常便饭。最初我的做法是直接报错用户体验很差。后来改成重试把解析错误信息和原始输出一起塞回给模型让它修正。重试一次成功率大概七成重试两次能到九成。但重试也有坑。如果模型第一次输出格式错了第二次可能还错甚至错得更离谱。所以重试次数要限制最多两次。两次都失败就降级要么返回一个默认值要么把原始文本直接给用户要么转人工。永远要有兜底方案不能让用户看到报错页面。7.3 函数调用的参数类型陷阱有一次做天气查询的函数调用模型把城市名和日期都传对了但把“天数”参数从数字5传成了字符串“5”。我的函数实现里用的是严格类型检查直接报错。后来改成宽松类型检查字符串数字自动转成整数问题解决。这个坑让我意识到模型的输出是文本不是编程语言里的类型。它说“5”的时候可能是数字5也可能是字符串“5”还可能带单位“5天”。你的解析逻辑要足够宽容能处理各种变体。当然宽容不等于不校验关键参数还是要检查范围。7.4 上下文窗口的“中间迷失”问题前面提过长上下文中间内容容易被忽略。我实际测试过把一份关键信息放在上下文的不同位置让模型回答相关问题。放在开头和结尾时准确率有九成放在中间时准确率掉到六成。这个差距非常大。所以我现在设计输入时会把最重要的信息放在开头或结尾。如果信息很多就分段每段加小标题让模型有结构感。如果还是太长就做摘要把摘要放开头详细内容放后面。不要假设模型会平等对待上下文里的每一句话。8. 给不同阶段开发者的建议8.1 刚入门先把一层做透如果你刚开始做大模型应用不要一上来就搞三层架构、多Agent、复杂工作流。先把一层做透。我建议从输出层开始学会让模型稳定返回结构化结果学会校验和重试。这一层做熟了你就能做出很多有用的工具。然后练输入层学会写系统提示词学会用少样本示例学会做简单的上下文注入。输入层和输出层都熟了再考虑模型层的参数调优和选型。最后才是工作流和Agent。8.2 有经验建立自己的“模式库”做了一段时间之后你会积累一些反复用到的模式。比如“分类-抽取-生成”三段式、“检索-拼接-问答”RAG模式、“规划-执行-检查”Agent模式。把这些模式整理成模板下次遇到类似任务直接套用效率会高很多。我的模式库里大概有十几种常用模式每种模式有对应的提示词模板、代码骨架、校验规则。新项目来了先匹配模式再根据具体情况调整。这样不用每次从零开始。8.3 带团队统一三层架构的语言如果你带团队三层架构可以成为团队沟通的共同语言。讨论需求时先问“这是输入层的问题还是输出层的问题”。做技术方案时明确每一层用什么策略。代码评审时检查每一层是否有对应的校验和兜底。统一语言能减少很多无效讨论。大家不再纠结“用哪个框架”“用哪个模型”而是聚焦在“输入怎么设计”“输出怎么校验”这些真正影响效果的问题上。9. 最后分享几个实用技巧第一个技巧用模型自己来优化提示词。把你写的提示词和几个测试用例给模型让它分析哪里可能导致误解然后给出改进版本。模型对自己的“脾气”比人类更了解它提的建议往往很准。第二个技巧建立回归测试集。每次改提示词或改流程都跑一遍测试集看效果是升是降。没有测试集你就是在盲改。测试集不用很大几十个代表性用例就够但要覆盖边界情况。第三个技巧记录每次调用的输入输出。出问题时可以回溯看是输入的问题还是输出的问题。这些日志也是优化的重要素材你能从中发现模型的常见错误模式。第四个技巧给输出加置信度。让模型在输出答案的同时输出一个置信度分数。低置信度的结果走人工审核或降级处理。虽然模型的置信度不一定准但比没有强能帮你过滤掉一部分明显不可靠的输出。第五个技巧定期换模型试试。模型迭代很快今天的最优解可能下个月就被超越了。保持关注定期用测试集跑一下新模型看是否有提升。但不要频繁换每次换都要重新调提示词和校验规则成本不低。这些技巧都是我在实际项目中反复验证过的不是什么高深理论但确实能省很多时间。大模型应用这个领域变化快但底层逻辑变化慢。抓住“输入什么、输出怎么处理”这条主线再多的新花样你也能快速看懂、快速上手。