☰
提示工程架构师实战:从提示词到灵活可扩展的AI应用系统
2026/10/24 7:49:12 网站建设 项目流程

最近这段时间,我和几位搞AI应用的朋友反复聊同一个问题:为什么同样的模型,有人拿来只能做几个一次性的小Demo,有人却能搭出一套能应对好几种业务场景的成熟产品?聊到最后,大家基本都会落在一个词上——提示工程。但说实话,很多人对提示工程的理解还是停留在“写一段让模型听话的话术”,而真正的价值,在于你能不能围绕模型去建一套灵活的系统。

这篇文章我想聊聊,站在一个提示工程架构师的角度,怎么去拆解“创建灵活系统”这件事。这里的核心不只是一句写得很妙的提示词,而是角色设计、上下文结构、模板编排、评估反馈一整套方法。它适合正在做AI应用落地的人,也适合刚入门但不想走弯路的朋友。我会把思路、细节和实际踩过的坑一次性讲清楚。

1. 整体设计与思路拆解

1.1 从“写提示词”上升到“设计提示系统”

我见过太多这样的情况:产品经理丢过来一个需求,说要做一个智能客服助手,然后大家就开始“写提示词”——你一句“你是一个客服助手”,我一句“请用礼貌的语气回答”,凑在一起就上线了。结果呢?换一个业务场景,效果崩掉;加一个输入条件,原有的提示词就失灵了;想复用一段逻辑,发现全部代码都写死在那个字符串里。

问题就出在这里:你在写一段话,没有在设计一个系统。提示工程做到后期,本质上和软件工程没有区别,你需要考虑可维护性、可扩展性、可观测性,甚至版本管理。灵活系统的第一原则,就是把提示词当作代码来对待,而不是当作一次性话术。

我在搭建这类系统时,一般会先在纸面上画清楚几个层次:

  • 模型能力层:底层模型擅长什么、边界在哪,这是地基。
  • 规则与策略层:什么时候该用什么样的提示策略,是给模型一个角色,还是给一组约束条件,抑或是给它一段示例做few-shot。
  • 数据与上下文层:外部知识、用户输入、历史记录如何注入。这是决定输出质量的上限。
  • 模板与编排层:各种提示片段如何拼接、如何组合、如何做路由。

这四层听起来抽象,实际上决定了系统“灵活”的程度。很多人只盯着第一层的模型,或者只盯着某一条提示词本身,忽略了其他三层才是拉开差距的地方。

1.2 为什么“灵活”是提示工程的核心命题

提示词领域的失败案例,大多死于僵硬。举个例子,你设计了一个提示词:“你是某电商平台的客服,顾客问退款问题时,请引导他们去售后页面。”这句话只适合这个平台、这种问题。如果某天业务方说,我们现在还支持了“以旧换新”服务,怎么办?改提示词。下个月又加了“赠品补发”场景,怎么办?再改。

改多了,代码里那一堆提示词字符串就成了没人敢动的地雷区。这时候你会真正意识到,架构师思维不是装腔作势,而是被逼出来的。

我做过的模拟项目X里,最核心的一条经验是:把“稳定不变的东西”和“频繁变化的东西”分离。

稳定的部分包括:

  • 模型的角色定义(如“你是一名专业的售前顾问”)
  • 通用的行为边界(如“请基于以下事实回答,不要编造”)
  • 输出格式的骨架(如JSON结构或Markdown结构)

变化的部分包括:

  • 具体的业务规则
  • 参考的知识片段
  • 当前用户的上下文

这两类内容混在一起,就是僵硬。拆开了,系统就活了。后面我搭的模板系统,本质上就是把这两类内容放在不同的“插槽”里组装。

1.3 架构师视角的关键取舍:指令与外挂知识

值得注意的是,不要试图把知识全部塞进提示词。某些团队喜欢把一份几十页的PDF全文贴进提示词,让模型“学习”完再回答问题。这有几个问题:一是上下文窗口有限,二是噪声太多反而会干扰模型判断,三是成本和延迟都会飙升。

正确的做法是把知识切成合适的块,通过检索或者路由的方式,只拿与当前用户问题最相关的片段注入。这就是所谓的“外挂知识”,或者叫检索增强生成。在灵活系统里,提示词负责“怎么思考”,检索到的知识负责“知道什么”,两者配合,才算完整。

2. 核心细节解析与实操要点

2.1 提示词核心组件拆解:别再写“万能咒语”了

我拆过不少优秀提示词案例,也和同行做过大量对比实验,发现一个结构清晰的提示词通常包含七个组件。不是每次都需要全用,但你要知道每个组件是干什么的,以及什么时候该用。

角色定义。给模型一个人设,能有效约束语气和视角。比“帮我看看这段文案”更好的写法是“你是一名电商转化文案编辑,擅长从用户痛点出发撰写商品卖点”。角色要具体到“这个角色在这样的场景下会怎么说话”,而不是贴标签。

任务描述。说明“你要干什么”,尽量用行为动词:生成、改写、分类、抽取、总结。注意区分“不要做什么”和“要做什么”,负向指令要放在正向指令之后,否则模型对负向指令的注意力会被分散。

约束条件。范围、风格、字数这些都属于约束。但约束不要整成“十要十不要”,模型对超过五条的规则记忆和遵循效果会明显下降。把最重要的约束放在开头,次要的放后面,或者干脆只保留三条核心约束。

输入数据。也就是用户传来的query、业务参数等。这一部分最好是结构化格式化之后接入,用明确的标记包裹,例如用户输入:,让模型能清晰区分“指令”和“待处理数据”。这个我在第五节会细说。

示例(few-shot)。一到三个高质量示例,往往比一百句抽象描述更有效。示例的价值在于给模型提供一个“照猫画虎”的参考参照系。注意示例要覆盖边界情况,而不仅仅是常规情况。

输出格式。JSON、Markdown、纯文本、表格,先想清楚你要什么格式。格式定义越明确,下游解析越省心。如果你要JSON,就把JSON模板写进提示词,并且要求模型只输出JSON,不要额外解释。

兜底逻辑。当模型不知道答案、遇到无关输入时该怎么办。比如“如果用户的问题不在你的知识范围内,请明确回答‘暂不支持该问题’”。这一条最容易省略,但省略了之后,生产环境里模型就会一本正经地胡说八道。

这七个组件不是每次都全用。我的经验是:常规场景至少要有角色、任务、约束、输出格式四件套;涉及专业判断就加few-shot;涉及外部知识就加数据槽位;涉及未知情况就加兜底。

2.2 模板变量与分支逻辑:让提示词“活”起来

灵活系统的第二个技术支柱是模板变量。在我搭过的系统里,提示词既不是整段字符串,也不是每个场景单独写一个完全不同的模板,而是一套基础提示词+动态变量注入的结构。

举个实际例子,模拟项目X里有个功能模块叫“商品问答助手”。它的核心提示词是这样的:

你是一名电商售前顾问,服务在线咨询用户。 当前店铺主营品类为:{{category}}。 店铺已开通的服务包括:{{services}}。 请用友好的语气回答用户问题。 如果用户询问价格、库存等信息,请依据下面资料中最新的数据回答: {{reference_chunks}} 如果以上资料无法回答用户的问题,请回答:“该问题暂无法解答,建议您联系在线客服。”

这里的{{category}}、{{services}}、{{reference_chunks}}都是变量。业务方要增加“以旧换新”服务,我只需要在配置中心里更新services的数据,提示词完全不用改。这就是变量带来的灵活。

更进一步,我还会用条件分支。比如用户是VIP客户,系统希望回答中嵌入专属福利;普通客户则不显示。逻辑是这样的:

{% if user_level == "vip" %} 当前用户为VIP会员,可在回答末尾附带专属折扣信息:{{vip_discount}} {% else %} 请为用户提供符合公开规则的答复。 {% endif %}

模板引擎(Jinja2或简单字符串拼接都可以)负责这里的逻辑控制。提示词此刻已经具备了“代码感”——有变量、有分支、有复用,也有可测试性。

2.3 上下文管理:一次对话要带哪些信息,带多少

上下文的合理管理,是判断一个人是否具备提示工程架构思维的关键分水岭。我见过某些同学的代码,每次调用模型时把用户的历史聊天记录全部甩进去,从第一天问候“你好”到最新一句全部粘贴。结果就是上下文越滚越长,模型越到后面越分不清重点,甚至开始“遗忘”开头的角色指令,费用也高得惊人。

我习惯用的上下文管理策略是:分层携带、动态截断、压缩记忆。

第一步,把瞬时性信息(当前这个问题、当前页面URL、当前操作的业务单据)和持续性信息(用户偏好、会员等级、对话主题)分层。瞬时信息每次都传,持续性信息由上层应用管理,只注入需要的那一部分。

第二步,长对话做截断。保留最近4到6轮对话,加上一个“历史摘要字段”,由模型或者规则在上一次对话结束时生成一段简短的摘要。下次调用时,只带摘要和最近的原文,这就够了。

第三步,重要信息做结构化提取。比如对话中用户透露出“我平时发货到重庆”“我习惯用顺丰”这类偏好,系统需要先通过一次小模型调用或规则提取,抽成结构化的用户画像,后续再注入。不要指望模型每次从原始聊天记录里自行判断哪些是关键信息——省事一时,后期错误率会让你头痛。

3. 实操过程与核心环节实现

3.1 从需求到系统:一个完整的搭建路径

下面我用一个我实际搭过的“客户咨询自动分级系统”来串一遍完整过程。这个系统做的事情很简单:用户发来一段咨询,系统需要判断其意图、紧急程度、应转给哪个团队、是否需要引用知识库,并给出答复草稿。拆开来看,就是经典的多意图分类+信息抽取+生成任务的组合。

第一步,明确需求边界。我和业务方关了会议室,拿白板把能想到的场景全部列出来:售前咨询、售后退换、物流催单、投诉维权、合作洽谈、无关闲聊。每一个场景都要定义清楚“什么输入算这类”“输出给谁用”“答错会有什么代价”。这一步结束后,我们才敢碰提示词。

第二步,设计角色模板。系统全局定义了一个基础角色:“你是一名专业的客服流程引擎,负责识别用户请求并输出结构化处理建议。”所有下游任务共享这个角色定义,再通过任务字段区分意图分类、信息抽取、答复生成。

第三步,写核心分类模板。这是系统里最重要的一个提示词,我把它单独抽出来展示一下结构:

请阅读用户的咨询内容,完成以下任务: 1. 判断用户意图,从候选列表中选择: {{intent_candidates}} 2. 判断紧急程度,取值为 high / medium / low 3. 抽取关键实体,输出为JSON对象,包含:订单号、商品名、收货地址、联系电话(如果存在) 4. 根据判断结果,生成一个简短的工作台备注,供人工客服查看 用户咨询内容: {{user_query}} 请严格按照如下JSON格式输出,不要输出其他内容: { "intent": "", "urgency": "", "entities": {}, "note": "" }

这个模板的精髓在于:机器可解析、人工也可读。模型输出的是结构化JSON,下游可以直接做类型判断和分流,不再需要正则解析散文。

第四步,配置外部知识检索。当模型判断用户意图属于“售后退换”时,编排层会把该用户所属订单状态、最新的售后政策、常见问题FAQ检索出来,注入到知识字段。这一步属于动态路由加动态检索,在整个系统里的工作量占比最大,但收益也最高。

第五步,建立质量评估回路。我们人工标注了200条测试样本,每次改动模板后,都会跑一遍测试集,对比模型的意图识别准确率和JSON格式合法率。没有这个测试集,改动后你不知道是优化还是回退。

3.2 编排层的实现:别把逻辑堆在模型里

模型是用来做判断和生成的,它不应该负责程序的复杂流程逻辑。很多提示词写得啰嗦,本质上是想用自然语言去描述一段if-else,这是把编排层的职责硬塞给了模型。

我的编排层长这样:一组Python函数,每个函数负责一件事。分类函数调用模型完成意图识别;实体抽取函数在分类完成后执行;检查函数判断是否需要检索知识库;路由函数根据分类结果决定走哪个下游流程;答复生成函数接收所有中间结果,最后组装输出。

这套编排有个直接的好处——可观测性暴涨。因为每一步都是独立函数,日志里可以看到每一步的输入输出。如果用户的订单状态没有查出来,我在日志里立刻就能定位是检索函数的问题,还是实体抽取失败,而不是对着整条提示词猜。

3.3 参数选择与模型调用细节

在调用模型时,我会把几个参数写进配置而不是写死。temperature通常是重灾区。做分类任务时,我希望输出稳定,temperature设为0到0.2;做创意生成时,比如写营销文案,我再把temperature调到0.7以上。很多同学一把temperature调0.8从头用到尾,分类任务就跑得忽好忽坏。

max_tokens也要按任务单独定。让模型输出一个JSON分类结果,给512就够,给4096反而会出现“话痨”倾向,输出一堆无关解释。输出长度的限制也是约束模型行为的一种手段。

还有一个常被忽略的参数是frequency_penalty和presence_penalty。在处理重复性输出、长文本总结时,适当调高frequency_penalty可以降低无意义的重复句式。这类参数的调整没有银弹,必须结合测试集观察效果慢慢试。

3.4 模板版本管理与可回滚机制

前面说要把提示词当代码,那就必须配上版本管理。我自己的习惯是把所有模板放在prompts/目录下,用yaml或markdown文件存,文件名里带语义化版本号。每次改动,记录变更说明。线上服务加载的是固定版本,新版本先在测试环境跑回归,再切流量。

有一次我们改了分类模板的意图标签,把“物流催单”换成了“运输查询”。结果忘了同步下游路由表,导致上一版路由表找不到“运输查询”这个标签,直接走了默认分支。这个坑让我记住了一件事:模板和路由、解析逻辑、下游配置之间存在隐性契约,改一处必须检查上下游所有依赖项。

4. 常见问题与排查技巧实录

4.1 输出不稳定:JSON时而合法时而不合法

这是所有搞提示工程的人都会遇到的经典问题,在我调试模拟项目X时几乎天天见。模型输出JSON时,有时候会多一行注释,有时候会把键名加上引号,有时候干脆在JSON前后加一堆语气词“好的”“以下是我为您生成的结果”。

我的排查思路分三步走。

第一步,看提示词里是否给出了“只输出JSON”的硬性约束。没有的话先补上这一条:“请直接输出JSON对象,不要包含任何前言、解释或Markdown代码块标记。”

第二步,看输出格式定义是否精确到字段级别。如果你的提示词只写了“输出包含intent和entities字段”,模型就会自由发挥字段结构。把严格的JSON模板直接写进去,并要求“严格按照上述模板结构”。

第三步,加解析校验和修复机制。不要指望模型百分之百遵守约束。下游解析失败时,可以采用“修复式重试”——把模型刚才的输出连同一句“你的输出不符合要求,请仅输出修正后的合法JSON”重新发给模型,成功率很高。但要注意设置重试上限,最多两次,避免消耗太多token。

4.2 意图识别漂移:同一个问题,今天识别A明天识别B

模型在分类任务上的“漂移”问题,是生产环境中比较头疼的事。根因往往不是模型坏了,而是你的分类标签定义模糊,加上示例不够明确。

处理办法是:在每个分类标签下增加边界说明。比如“投诉维权”和“售后退换”看起来边界模糊,我在标签描述里会特意说明:“投诉维权特指用户表达情绪不满或要求升级处理的情况;售后退换特指用户要求退换货、退款、维修等具体操作。”

另外一个提升稳定性的利器是few-shot。给每个标签提供一到两个典型示例。示例不必很长,覆盖“典型带边界”的情况,就能极大改善分类效果。

4.3 模板越改越复杂,开始互相打架

当模板的数量超过二三十个,就会出现“提示词相互干扰”的问题。比如全局角色模板里写了“说话必须简洁”,某个场景模板里又写了“请给出详细步骤”,模型到底听谁的?

我在这类系统里统一了优先级规则:后端注入的模板优先级高于基础模板,具体任务指令优先于通用行为约束。所有模板在拼接时,按“全局角色 → 公共约束 → 任务描述 → 任务专属示例 → 动态变量”的层序排列,并且每一层之间用标记分隔,这样模型能区分指令层级。

还有一个小技巧:公共约束数量尽量控制在5条以内,超过5条时优先级靠后的几乎都会被模型无视。与其写“不要用表情符号、不要用感叹号、不要用口语化词汇”,不如只写一条“请使用正式严谨的书面语气”。一个抽象的高级规则,远胜过三条具体但相互重叠的禁令。

4.4 上下文太长,模型“忘掉”开头指令

这个问题经常出现在长对话场景。用户聊了二十轮,你把全部消息都塞进上下文,开始那段角色定义已经“淹没”在大量用户消息之后,模型行为开始变质。

解决思路有两层。第一层是上下文压缩,把历史消息压缩成语义摘要,保留最近几轮原文。第二层是把角色指令放到离当前问句最近的地方。部分模型对位置更靠后的内容注意力更强,所以我会在拼接时把最重要的指令放在用户最新消息之前。这个位置的调整往往比多写几行“你是一个客服”有效得多。

4.5 缺少观测数据:出了问题完全不知道是哪个环节错的

这一条放在最后,倒不是技术性最强,而是最容易被人忽略。没有观测就谈不上架构。在搭建提示工程系统时,我会把每一步的token消耗、延迟、模型输出原文、路由结果全部记录在日志系统里。每次业务方说“系统表现不对”,我第一件事不是猜,而是查日志。

我曾经为了排查一个“漏单”问题,花了一个下午看日志,最后发现是某个场景下领域知识检索的结果为空,模型在无兜底逻辑的情况下自行编造了答案。如果当时没有记录“检索结果为空”这个中间状态,这个问题根本无从定位。

5. 避坑心得:建灵活提示系统的三条戒律

这三条是我踩过足够多坑之后总结出来的,每次带新人我都会反复讲一遍。

第一,别在提示词里堆业务流程。业务流程是逻辑,应该由代码编排;提示词做判断和表达就够了。你让模型当一个“规则执行器”,它就只能偶尔做对、经常发挥,你却没有办法修它。

第二,别追求一次完美的提示词。我见过很多团队在写提示词上花几周时间反复“打磨”,这是浪费。正确路径是先搭一个“足够可用”的版本,配上测试集和观测,然后根据真实数据持续迭代。提示词工程不是写出来的,是一轮一轮调出来的。

第三,架构比词藻重要。说多少漂亮话不如让系统具备可拆解、可回滚、可观测的架构。面对一个复杂业务需求,你脑海中应该浮现的是模板设计、路由条件、变量槽位,而不是那句“请扮演一个专家”。

我们做提示工程,最容易犯的错误,就是把自己定位成一个“会问问题的人”。但真正落到生产环境,会发现光会问问题是远远不够的。你得会设计,会建模,会为模型搭建一个承接它的业务骨架。

现在每当我接手一个新的AI项目,我习惯性思考的已经不是“这句提示词怎么写”,而是“这个系统的输入从哪来、输出到哪去、哪些逻辑靠模型、哪些逻辑靠代码、效果怎么度量”。把这个思维转过来之后,提示工程的很多难题,其实都已经在动手之前解决掉一大半了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询