ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Prompt工程实战:从提示词优化到RAG与参数调优的完整指南

Prompt工程实战:从提示词优化到RAG与参数调优的完整指南 前段时间我在做一个内部文档问答的小工具初版效果很一般。模型能看懂文档但回答总是正确的废话——不引用原文、不区分文档里没有的信息甚至会在总结时自带偏见。后来我花了半天时间把每条提示词拆开重新设计只加了两句限定结果回答质量肉眼可见地提升。同事问我是不是换了模型其实模型没变变的只是我问问题的方式。这篇笔记是我学习大模型应用技术过程中关于Prompt工程实践的整理记录了我从把提示词当咒语到把提示词当系统工程的完整过程。内容既包含基础原理也有我实际项目中的写法、参数配置和踩坑记录适合刚接触大模型应用开发、准备自己做智能问答或工作流自动化的朋友参考。我会尽量把背后为什么这样设计的逻辑也讲清楚而不是只给一堆可以直接抄的模板。1. 为什么大模型时代的说话方式突然变得这么重要1.1 模型的理解和我们理解的理解不是一回事要理解Prompt工程为什么有存在的必要首先得看清一件事大模型的理解跟你我的理解不是一回事。人类读一句话靠的是语义、常识、语气以及对话背景而语言模型本质上在做的是给定前文预测下一个词的概率分布。它对世界的认知来自训练语料中的统计规律而不是真实的物理世界感知。所以你会发现同一个问题换个问法结果可以相差十万八千里。这就像跟一个博览群书但从没出过门的人聊天你说帮我把窗户打开他可能回复一篇开窗的好处的论文——因为他理解的帮助是提供信息而非物理行动。Prompt工程就是把我们想表达的目标翻译成模型最容易沿着正确方向续写下去的形式。1.2 Prompt是现阶段操控模型行为最直接的入口不夸张地说在模型能力固定的前提下Prompt就是你和模型之间唯一的方向盘。无论是API调用、网页对话框还是接入Dify这类低代码平台最终模型的输入入口就是一段文本以及可选的图片、音频等多模态内容。系统提示、用户消息、历史对话、工具调用结果……这些全都要汇集成模型上下文中的一段Prompt。我的经验是与其指望模型聪明到能猜出我的意图不如把意图显式写出来。你写的每一个字都是在为模型划定下一步续写的方向。1.3 网上的魔法咒语为什么时灵时不灵刚入门那阵子我也搜集过一堆万能提示词模板比如你是一位顶级专家请认真严谨地回答。实测下来不能说没用但稳定性很差。原因主要有三个模型版本在变上下文长度和前面内容在变任务的复杂度在变。所谓魔法咒语往往只是在一个特定场景下有效的一种措辞把它当成通用解很容易踩坑。真正可靠的Prompt是对任务本质有清晰拆解之后写成的工作指令而不是套话。2. Prompt工程的地基Token、上下文窗口与注意力机制2.1 Token模型按块阅读文本中文尤其要留意模型不是按字也不是按词去处理文本的而是先把文本切分成Token。Token是一个基础单位可能是英文单词的一部分可能是半个汉字也可能是标点。中文语料一个汉字约等于1到2个Token英文常见单词往往1个Token。之所以要关注这个概念是因为它跟成本、模型输出上限、上下文长度都直接相关。举例我用tiktoken统计过一段约800字的中文产品说明切出来大约1300到1500个Token。如果你在提示词里放了一大段背景资料又没预估Token消耗很可能在不知不觉中占满上下文窗口。建议在实际开发中用官方分词库跑一遍统计把Token用量作为提示词模板的一个元数据字段记录下来。2.2 上下文窗口是模型一次性思考的工作记忆上下文窗口决定了模型单次请求能看到的最大Token数量。它就像一个临时工作台——所有资料、任务、历史对话都堆在同一张桌子上。一旦超过上限系统只能做截断。不同模型对超长上下文的截断策略不一样有的从开头切有的从中间切有的按重要程度保留。实操层面的经验如果你有一个很长的资料库不要把全部内容塞进上下文宁可做检索后只放相关片段要在多轮对话里接住历史要么自己管理历史消息列表要么定期把旧对话压缩成摘要避免对话越长效果越差。2.3 位置与重复注意力机制带来的两个实用规律Transformer的注意力机制中模型会对上下文不同位置的内容采取不同关注权重。实践验证下来有两条规律比较可靠一是靠近提示词末尾的内容往往对最终输出影响更大因为解码是从最后一个位置往后生成的二是关键信息重复强调可以显著提高被注意到的概率。这就是为什么在Prompt末尾再次声明只依据以上资料回答不要使用训练数据中的常识往往比写在开头有效。但要注意这两种规律不是绝对的。信息密度过高、全是重复词反而会稀释重点。合理的做法是把核心指令放在提示词尾部用简洁的一句话再次强调而不是把整个Prompt复制两遍。2.4 别把模型当人连贯性与稳定性只是看起来的智能模型输出的流畅程度极具迷惑性。它能把一段回答写得像模像样但中间可能藏着事实错误、逻辑跳跃甚至自相矛盾。理解了这一点你就会明白Prompt工程中为什么强调约束性措辞和结构化验证——因为模型不会主动检查自己说的对不对所有检查规则都需要你写进指令或者在外层系统里做程序校验。这也是为什么Prompt工程被称为软件工程的一部分而不是聊天技巧。3. 我在项目中高频使用且实测有效的Prompt模式3.1 角色设定人设即规则给模型设定角色不是让它演戏而是借助角色背后训练数据中的语境帮助模型自动对齐语气、专业度和答复边界。比如做医疗问答时你是一位有20年临床经验的眼科医生回答需严谨、区分确定与不确定内容与单纯说你是医生输出风格和细节密度会差很多。我的写法是角色任务边界输出风格三段式例如你是一位企业IT运维专家。你的任务是根据下面的故障日志定位原因并提出排查步骤。回答用中文分点列出优先说明最可能的原因。这段提示词里角色解决知识倾向任务边界解决做什么输出风格解决怎么呈现。三层都写清楚模型才不容易跑偏。3.2 Few-shot示例一个示范胜过十句描述对于格式型任务比如信息抽取、分类打标、SQL生成给两三个示例通常比写一大段规则有效。语言模型都是续写性质的学习者示例相当于最直接的续写方向。但示例要选好不能只选极端正面例子要覆盖边界情况否则模型会过度模仿模板。我做过一个标题分类任务只给了一类正面示例结果模型把所有标题都分到那一类。后来加入易混淆的反例加正确分类后准确率明显回升。所以我的建议是示例组要有正例一两个、反例一两个、边界情况一两个这样的结构。3.3 思维链让模型先想后答面对推理、计算、方案设计类任务我想要模型先给出逐步推理过程再输出结论。操作上很简单在Prompt末尾加一句请先分步思考再给出最终结论或者更结构化1. 列出已知条件2. 逐步推导3. 给出结论并说明依据。这类指令的底层逻辑是模型把推理过程外显可以避免它直接跳到概率最大的那个结论。实测在数学题、故障分析、效果评估这类任务上提升明显。缺点是需要多消耗一些Token而且推理步骤本身也可能出错所以后面如果接程序判断最好把结构化结论单独解析出来。3.4 结构化输出一步拿回可解析的数据在真正的工程里我几乎不会让模型自然发挥一段文字然后靠人工去读。更可靠的做法是在Prompt里直接指定输出格式例如只输出JSON对象不要包含任何其他文字格式如下{原因分析: ..., 建议措施: [...]}。如果信息不足原因分析填信息不足。这样模型的输出可以直接被程序解析省去大量字符串清洗工作。如果你用的是Dify或者LangChain这类框架还能搭配输出解析器Output Parser把JSON自动转成结构体这比让模型自由发挥再硬解要稳得多。3.5 约束性措辞限定知识范围与输出边界做文档问答时最怕模型把训练期间学到的常识混进答案输出看起来有理有据但实际已经偏离文档。我常用的约束是只依据下方提供的资料片段回答如果资料中找不到答案请直接回复资料未提及。不要使用训练知识补充。这招在减少幻觉上非常有效。不过约束太多也会让模型束手束脚我的经验是负面指令控制在3条以内并且每条都具体——不要编造数据不要使用外部知识不要输出分析过程这种比请确保回答准确有用得多。4. 从单条Prompt到一套体系模板、上下文与RAG4.1 提示词模板化从手工调音到产品化项目一旦进入规模化提示词就应该像代码一样纳入版本管理。我会为每个功能维护一份模板文件里面用占位符表示动态内容例如system_prompt 你是一名{role}。 请根据以下{source_type}内容完成任务{task} 资料{context} 要求{constraints} 模板的好处有两个一是改动规则时只需改一处二是可以在上线前用同一批测试用例对比不同模板版本的效果。实操中我建议给每一版模板记录版本号、改动内容、测试集准确率、典型失败案例这比凭记忆调参可靠得多。4.2 多轮对话的上下文管理遗忘与误导都来自细节多轮对话场景每次请求都要把历史消息一起发给接口或由框架自动带上。问题在于历史越长模型越容易注意力漂移把几轮前的背景当成当前重点。我的做法是——维护一个关键信息显式化层每轮用户说完后先用一个轻量Prompt把本轮相关的关键点抽取出来拼接到下一轮Prompt顶部。这样即使中间穿插了很多闲话模型也不至于忘事。4.3 上下文压缩别让无限上下文养出坏习惯有些平台宣传超长上下文但把长历史全部喂给模型既费Token也会拉长推理时间、增加成本。当对话轮数很多时压缩是更好的选择。我常用的压缩策略是把历史里已经完成的任务结论汇成一小段摘要把待办和未答复问题单独保留原文。这样模型在后续回答中既不会丢失前置信息也不会被一大堆过程性内容干扰。4.4 接上RAG让Prompt带着资料回答做企业知识库问答时单靠Prompt死记资料不现实。主流做法是RAG先把文档切块并向量化根据用户问题检索出最相关的若干片段再把片段和问题组装进Prompt送给模型。这时候Prompt模板的设计非常关键。我会在模板中写明以下是资料片段{retrieved_chunks}。请基于其中信息回答问题。回答后可引用编号来源。让模型带着引用定位习惯去应答不仅提升可信度也方便用户回溯原始文档。这一套在本地大模型上同样适用——把Ollama部署的模型接进DifyRAG链路会由平台代管检索环节但Prompt模板还是得自己调。5. 与Prompt配合的采样参数和模型选型5.1 temperature与top_p把创造力的旋钮拧到合适位置除了文本指令生成参数也直接影响输出质量。temperature控制随机性接近0时模型几乎每次都选概率最高的token输出稳定调高则让低概率token也有机会被选风格更发散。top_p则是按累计概率截断候选词表类似只从累计概率达到90%的词语里选。两者经常一起出现但实践上通常只需要调一个。我的基准配置如下任务类型temperaturetop_p结构化抽取、分类、定标0.10.9代码生成、SQL生成0.20.9文案润色、创意标题0.70.95推理类任务0.30.9有一点要说明如果用了思维链类的逐步推理提示很多模型建议temperature在0.6左右保留一定探索性但这只是起点最终还是要拿自己的测试集量一量。5.2 max_tokens不给模型留自由发挥的过大空间max_tokens限制了输出最大长度。很多人只把它当上限保险但设置过大会让模型在简单任务上也凑字数设置过小又会导致回答被截断成残句。我的建议是根据任务预期答案长度把上限设定为正常答案长度的1.5倍即可并在Prompt里也写明长度约束双管齐下。5.3 不同模型对Prompt风格的敏感度差异模型之间的差异比很多人想象的大。商用模型通常对指令遵循度较高一句用中文回答就足够本地开源模型如Qwen系列、Llama系列以及Ollama部署的量化模型对措辞更敏感往往需要更完整、更显式的指令和示例。具体调参时同一套Prompt模板要针对目标模型做风格适配不能指望一次写好到处跑。5.4 本地部署与API调用一个容易被忽视的参数衔接问题本地部署还有一个细节很多本地推理框架对参数的默认值和上游API不完全一致。比如Ollama本地接口的默认temperature是0.8而某些云端API默认可能是0.7或1.0。把一段云端调试好的Prompt迁到本地模型时务必检查采样参数不要只复制文本否则你会得到一堆看起来活泼过头的回答。6. 实践中的踩坑记录与排查思路6.1 坑一负面指令堆太多模型反而草木皆兵我曾经在一版Prompt里写了一大串不要……不要……不要……结果模型开始回避几乎所有实质性回答频繁返回抱歉我无法提供建议。排查后发现问题不在于模型拒绝回答而在于负面指令过于密集把输出空间压缩到了极端保守的区域模型对正常问题的措辞也被传染了。解法是把负面指令精简成三条最关键的同时用正面表述指出应该怎么做。比如把不要编造信息改成如果信息不足请明确说资料中未提及。一个原则是正面指令确定行为方向负面指令只做边界保护。6.2 坑二输出带了多余文字JSON解析直接失败有一次对接财务摘要接口模型在JSON前加了一句好的根据你的要求结果如下程序直接解析失败。代码里做兼容处理是一种方案但更干净的做法是在Prompt里加只输出JSON不要输出任何解释性文字并且把输出长度约束同步加上。我还是建议不管Prompt怎么改解析端都要做一次兜底清洗——比如截取第一个左花括号到最后一个右花括号之间的内容再解析。字符串解析这层防御无论Prompt写得多好都值得保留因为你永远不知道模型下一次抽风是什么形式。6.3 坑三靠感觉调Prompt两周后发现改回去了由于Prompt效果存在明显的随机波动单看两三条例子很难判断哪个版本更优。我后来养成了一个习惯每版Prompt准备20条固定测试样本离线批量跑对结果做人工打分或程序校验。分数上升才替换模板分数不变或下降就回滚。这个方法虽然朴素却比这次看着不错靠谱得多。建议你把评估集也纳入版本管理。Prompt工程跟算法模型调参一样没有评估集就没有迭代基准改来改去都是原地打转。7. 给学习者的路线建议与延伸方向7.1 先建立实验记录再追求技巧如果你刚开始学Prompt工程我的建议是别急着背咒语。先把每个你准备投入生产的提示词当成实验对象记录版本、参数、样本和结果。这不仅是方法论也是一种效率投资——很多看似玄学的调优其实只是因为样本太少、变量没控制好。我自己的实验记录现在就是一张大表格改了什么词跑了多少用例涨了几分失败样例长什么样。7.2 三个延伸方向微调、Agent与多模态Prompt工程不是孤立的知识点它往下延伸是模型微调往外延伸是Agent与工具调用往宽延伸是多模态。微调改变的是模型行为本身Prompt则负责每次运行时任务的动态指挥。Agent场景下Prompt还可以作为行动指令让模型决定调用哪个工具。多模态大模型的Prompt新增了图像、音频输入原理不变但描述内容时要用视觉细节加任务意图的组合方式。7.3 一个日常练习习惯改写你手头的工作任务我现在每接手一个新的业务需求都会先写一版需求说明文档再把它改写成系统提示词角色、背景、输入、输出格式、边界条件、示例。这个习惯让我在真正写代码之前就把任务的语义契约想清楚了也减少了很多返工。如果你还没试过建议从今天手头的第一个任务开始把一句话需求扩写成一份提示词草案运行一下感受差别。这套实践最有意思的地方在于——你调的不只是模型还有自己对你到底想要什么结果的理解。想清楚任务本身Prompt往往就水到渠成了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进