
我第一次接触大模型接口时脑子里冒出来的就是 The Lamp and the Genie 这个画面。你擦亮神灯灯神出现说“主人你的愿望是什么”你只要说出来它就能做到。大模型 API 被封装好之后确实很像这盏灯输入一句自然语言输出一段看起来像答案的内容。但现实很快把我拉了回来——同一个模型有人能用它稳定地产出项目文档、数据清洗脚本、测试用例有人连让它输出一段符合格式要求的 JSON 都要反复重试。差别不在灯的材质而在使用者递出去的那句愿望。今天我们把这件事拆开看灯是接口精灵是模型你擦灯时说的话就是提示词Prompt。很多时候问题不是模型不够强而是我们还在用“许愿”的方式和接口交流。1. 同一个模型为什么有人用得像神灯有人用得像摸奖1.1 模型本身不是工程请求结构才是先把一个很容易被忽略的区分说清楚模型是一种能力应用是一次成功调用。能力是静态参数调用是动态过程。同样是开车同一个引擎有人开得平稳有人频繁起步熄火。模型也一样。你向大模型发一个请求本质上不是“问它一个问题”而是“让它在你的约束下执行一个任务”。这个任务能不能完成取决于你如何描述任务边界、输入资料、输出格式和验收标准。很多朋友会拿模型直接聊业务问题比如“帮我分析一下这个销售数据”然后把一长段文本直接贴进去。模型确实会响应但响应质量很容易飘。原因很简单模型不是数据库也不了解你的默认背景。它只能根据你提供的上下文、指令风格和概率分布生成下一个 token。如果你的指令没有把“分析”定义清楚它就只能按训练语料里最常见的模式写一段泛泛而谈的总结。这个差别平时可能不明显。一旦换到严肃场景比如让模型批量生成结构化字段、抽取实体、改写文案同一个模型输出质量可能一个天上一个地下。根源不在于模型版本而在于你有没有把任务边界封住。1.2 一句话塞太多需求是大多数问题的起点我见过很多刚接触大模型的开发者第一版 prompt 通常长这样“请帮我根据下面这个项目写一份详细的技术方案包括架构设计、数据库表结构、接口说明、部署步骤还要注意安全性和性能优化最好给出代码示例。”这句话从人类角度看非常正常但从模型的角度看它是一个多目标任务而且目标之间没有优先级输出长度没有约束验收标准也不明确。模型面对这种请求时大概率会拆解成一个“看起来合理的平均结果”每个部分都写一点但每个部分都不深。更麻烦的是你想让它先做方案、再写接口它可能把顺序打乱你想让它给代码它可能给的是伪代码你想让它注意安全性它可能只在最后加一句“需要加强安全”。这类问题不是模型不够聪明而是指令没有把“任务分解”和“交付物格式”交代清楚。1.3 你可以把 Prompt 理解成“使用说明书”跟大模型协作和跟一个能力很强但完全不了解你业务的新同事协作很像。新同事背景知识扎实但如果你只说“把这事处理一下”他大概率会按自己的想法来。你需要交代背景、目标、输入、输出、约束、示例和验收标准。Prompt 就是这份使用说明书。它不是文字游戏也不是玄学而是你把需求翻译成模型执行语言的过程。所以“The Lamp and the Genie”这个隐喻的真正含义不是“模型是魔法”而是“魔法产生于你对灯的语言的理解”。模型确实强大但精灵不会读心它只会回应愿望的表面语义。2. 灯的结构拆解一次大模型请求的四个关键要素2.1 System 消息给精灵设定身份和边界在实际的大模型接口中一个请求往往不是只有一句“question”。常见结构会包含 system、messages 等字段。System 消息是用来设定整体行为边界的地方相当于你在召唤精灵前先念规则“你是一个资深数据分析师只能使用中文回答只能基于我提供的输入数据不编造事实。”很多初学者会忽略 system 的力量。他们把所有指令全塞到用户消息里导致指令和输入数据混在一起模型更难分辨哪些是任务、哪些是材料。更合理的方式是System 里写角色和规则比如“你是一个严谨的软件架构师”“不要使用 Markdown”“不确定时输出 null”。User 里写给模型的具体任务和输入材料。Assistant 消息可以放历史回答或 few-shot 示例。这样分层的意义在于让模型在“进入任务前”先完成人设和约束的设定而不是在具体请求里临时切换。2.2 User 消息把愿望说清楚而不是写一段小作文User 消息是真正的人类请求。这里最需要克制。有人会觉得 prompt 越长越代表“有丰富上下文”于是把一大段背景、多个任务、输出要求、禁止事项都堆在一起。实际上模型的注意力是有限资源信息密度比长度更重要。一个有效的 User 消息通常包含四块任务我要你做什么。输入给你什么材料。约束有哪些限制比如不能编造、必须引用原文。输出格式返回什么结构例如 JSON、Markdown、表格。如果有多个子任务可以拆成编号列表让模型按顺序处理。如果你希望它只做一件事就别在 prompt 里同时给它三件事。否则它会在三者之间找平衡而不是完成你真正需要的那一个。2.3 输出格式先在 Prompt 里定好不要事后解析实战中最大的坑之一是让模型“自由发挥”之后再希望它输出 JSON。你可能遇到过模型返回了 Markdown 代码块里面套着 JSON但代码块前后有说明文字或者 JSON 键名不符合预期或者字符串内的引号被转义错。关键是把输出格式变成约束而不是期待。下面是一个常见写法的简化示例prompt 请从下面的商品评论中抽取以下字段 - sentiment: 正面 / 负面 / 中性 - category: 商品类型 - summary: 不超过15个字的总结 只输出 JSON不要包含 Markdown 代码块。 不要输出其他文字。 评论 {comment} 这里最关键的是最后三行约束“只输出 JSON”“不要包含 Markdown 代码块”“不要输出其他文字”。这比在代码里写“请把 JSON 解析出来”要可靠得多。但就算这样上线前仍然要写解析兜底逻辑。因为模型是概率输出不是强约束解析器。2.4 参数温度、长度和随机性不是越大越好接口里的 temperature、max_tokens、top_p 等参数也是灯的开关。很多人不理解这些参数意味着什么随手设成 0.9 或 1.0然后抱怨输出反复无常。经验上参数作用建议取值temperature控制随机性越低越稳定抽取、分类用 0.1~0.3创意写作用 0.7~0.9max_tokens限制输出长度要比正常需要的长度多留一点否则结果会被截断top_p核采样概率控制候选词范围一般不用和 temperature 同时大调需要记住的是对抽取、分类、结构化输出尽量用低 temperature让输出更稳定。对头脑风暴、文案创意可以适当调高但要知道这会牺牲一致性。如果同时调整 top_p 和 temperature可能会互相干扰。通常建议先固定一个再调另一个。注意不要一上来就把 temperature 调到 0.9然后抱怨输出不稳定。先明确这个任务到底是偏稳定还是偏创意。3. 从模糊愿望到可执行指令提示词设计的五步法3.1 第一步先写任务骨架而不是一段连贯文案当我们要设计一个真正可复用的 prompt 时不要一上来就写一整段话。先把任务拆成骨架角色谁来做。背景为什么做。任务具体做什么。输入提供什么。输出格式和长度。约束不能做什么。验收怎么判断合格。这个骨架看起来很基础但很多人并不真的执行。他们的 prompt 是“帮我写一个 Python 函数把 CSV 文件读取后做数据清洗”却没有告诉模型字段缺失怎么办、日期格式是什么、输出是否需要保留原始列、异常数据是否要记录。结果模型给出一个理想化的、能跑的代码但一接到真实数据就崩因为它不知道缺失值策略所以风险全留在后面。3.2 第二步把模糊词替换成可测试条件“详细”“准确”“合理”这类词人类能懂但模型无法把它变成验收条件。你需要把“准确”换成“只能基于给定文本不能自行补充信息”。“详细”换成“每个步骤不少于 3 个操作说明并列出涉及的命令”。“合理”换成“输出结果满足以下三个条件……”。可测试条件意味着你可以写一段脚本去校验输出。比如检查输出是否包含指定字段JSON 是否能被解析长度是否超过阈值。如果一个约束没法被校验模型大概率不会认真对待。3.3 第三步加入 Few-shot 示例但别让示例喧宾夺主Few-shot 是指在 prompt 中给出一两组输入输出对让模型照着样式做。这比单纯描述格式更直观特别适合分类、抽取、风格改写。示例的价值在于它是一种约束的具象化。但这里也有一个常见误判示例越长越细效果就一定越好不一定。如果示例和真实输入相差太远模型会模仿示例的表面格式而不是理解规则。示例应该覆盖边界情况而不是重复普通情况。比如一个情感分类任务与其给三个“正面”示例不如给一个正面、一个负面、一个中性再给一个带有营销话术的“假正面”样本。这样模型才知道边界在哪里。3.4 第四步先跑通一条样本再讨论规模化设计好 prompt 之后别立刻批量调用。先用 5 到 10 条有代表性的样本做小规模验证。这既是为了看输出质量也是为了看成本、延迟和稳定性。我在实践中的做法是准备一个 test.csv包含不同场景的输入。写一个脚本循环调用把 prompt 和输出都记录到日志里。人工或写规则检查前 20 条输出。遇到不满足条件的先改 prompt不要调参数。当 20 条都通过之后再扩大到 100 条、1000 条。这个流程看起来慢但它能避免你批量产出大量无用结果之后才发现问题。成本上查一次 prompt 的代价远低于清洗一批坏数据。3.5 第五步把每一次失败变成下次迭代的输入Prompt 不是一次写成的它需要版本管理。哪怕只是加了一个示例也可能改变输出分布的倾向。所以最好的习惯是每次修改都记录输入是什么。期望是什么。实际输出是什么。为什么失败。改了什么。效果如何。一段时间后你会形成一份属于自己的 prompt 经验库。这里要特别提醒不要一遇到输出不满意就立刻往 prompt 里加限制词。过多“不要”“禁止”会引入冲突反而让模型混淆。更稳妥的做法是把希望它做什么写清楚而不是把所有不希望发生的都列一遍。4. 当精灵开始胡说幻觉、不可重复和边界控制4.1 模型不是数据库也不是搜索引擎即使是能力很强的大模型也会出现“一本正经地胡说八道”。这不是它态度不好而是生成机制决定的模型在做 token 概率预测而不是查询事实。如果一个问题在训练语料里不常见或者上下文里的信息不足以支撑推理模型就会用最像样的方式补全。这种补全有时候是对的有时候是错的但语气往往同样自信。理解这个机制很重要它意味着两件事不要把事实类问题完全交给模型。让模型回答事实类问题时必须给它可靠的知识来源比如资料片段、数据库结果或工具返回。4.2 不可重复Temperature 低也不代表每次输出完全一样你可能会发现同一个 prompt 多次调用结果有细微差别。这是因为模型采样过程本身带有随机性。temperature0 也只是尽量取最高概率但某些实现里仍可能受随机种子影响。所以如果你的应用需要可重复输出比如自动化测试或审核不能幻想 prompt 一致就结果一致。工程上更推荐的做法是对输出做幂等处理比如只取第一个 JSON 对象。对关键场景做重试策略比如解析失败后换 temperature 重新生成一次。在业务上允许同一个输入偶尔出现表达不同、含义相同的输出。如果业务不能接受需要加校验和归一化逻辑。4.3 边界控制什么不该交给模型决定使用大模型前先画一条线哪些环节模型可以参与哪些环节不能。可以文本改写、抽取结构化字段、生成初稿、代码补全、总结、分类。 不应该对健康、法律、金融等高风险场景做最终判断不经过人工复核直接执行关键操作。这里的边界不是否定模型能力而是承认概率模型的不确定性。你可以在 prompt 里加“如果你不确定请回答不确定”但模型并不总是可靠地遵守。真正的边界控制要靠代码逻辑凡是不能接受错误结果的输出都要有人工确认或规则校验。4.4 输出异常时的排查链路如果遇到模型输出质量下降或报错建议按这个顺序排查先看现象是报错、空输出、格式不对、内容错误还是速度慢。再看输入字符串是否被截断编码是否正确字段是否拼接错上下文是否缺失。再看提示词角色是否清楚任务是否单一输出格式有没有约束示例有没有歧义。再看参数temperature 是否过高max_tokens 是否限制得太小是否用了不兼容的参数。最后看工具边界版本是否太老API 是否限流当前模型是否适合这个任务是不是任务本身超出了模型能力。这个链路不要跳步也不要一上来就怀疑“模型太差了”。多数问题其实出在第 2 步和第 3 步。如果校验失败了先别急着重试。看失败类型是 JSON 格式错误还是字段值不符合规则。不同的失败原因处理方式完全不同。5. 从一次召唤到流水线把 Prompt 变成可维护的工程模块5.1 用模板管理 Prompt而不是散落在代码里Prompt 一旦进入业务就不要直接写在调用函数里。它应该像配置一样被管理。常见做法是维护一个模板文件用变量占位符填充输入。比如你是一个客服工单分类助手。 请根据下面的工单内容判断问题类型并输出 JSON。 工单内容{{ticket_content}} 输出格式{category: 硬件/软件/账户/其他, confidence: 0-1}然后在代码里读取模板把变量替换成实际数据。这样做的好处是产品和运营同学可以独立调整 prompt不需要动代码。甚至可以在后台配置不同版本的 prompt做 A/B 对比。5.2 输出校验和重试大模型接口不是纯函数我之前说过模型是概率输出所以任何依赖模型输出的流程都要有一个输出校验层。这个校验层至少要做三件事格式校验能否解析成 JSON、字段是否存在、枚举值是否合法。内容校验关键字段是否为空是否出现“我不知道”之类的结果。业务校验是否符合某个业务规则比如金额不能为负数日期不能早于创建时间。校验失败后可以重试一次但不要无限循环。重试时可以改成更保守的参数或者提示模型“你刚才的输出格式不符合要求请重新输出”。加一轮对话式的修正往往比直接改 prompt 更有效。下面是一个简化伪代码流程def call_with_validation(prompt, validator, max_retry2): for i in range(max_retry 1): output call_model(prompt) if validator(output): return output raise ValueError(模型输出多次校验失败)5.3 成本和延迟批量任务别用一个循环硬扛当任务量从几条变成几万条时单纯写一个 for 循环会踩很多坑接口限流、超时、并发冲突、成本失控。工程上需要分批处理、设置并发数上限、加超时和退避重试并且估算 token 消耗。token 消耗不仅和输出长度有关也和 prompt 长度有关。如果你每次请求都附带大段背景资料这些 token 会计费也会增加延迟。所以 prompt 不是越长越好要按性价比取舍。可以把不必要的历史记录、重复描述去掉只保留模型完成任务必需的信息。5.4 评估集和回归让 Prompt 像代码一样可以被测试Prompt 是软件的一部分所以它应该有测试。你可以维护一个评估集包含 50 到 100 条典型输入以及每条输入对应的“期望行为”。这里的期望行为不一定是完整答案可以是一组检查规则。每次修改 prompt 后跑一遍评估集看通过率是否下降。这样你的优化才不是拍脑袋。这可能是最容易被忽略的一环。很多人会花很多时间调 prompt却没有任何客观标准。结果就是改了一个示例某个 case 变好了另一些 case 变差了自己根本不知道。有了评估集你至少能看到回归风险也能在版本升级或更换模型时快速判断新模型是否适合当前场景。6. 回到灯与精灵真正的壁垒不是魔法而是理解接口的人“The Lamp and the Genie”这个隐喻到这里可以收束了。灯里的精灵确实强大但强大的能力只有在清晰、可验证的召唤方式下才会变成可靠的生产力。模型本身是灯API 是灯口而 prompt、参数、数据流和校验逻辑是你擦灯的手指和念出的愿望。你愿意投入多少去理解这个接口决定了你能从模型身上“召唤”出多少稳定的价值。6.1 把模型当协作者而不是许愿机我现在越来越觉得Prompt Engineering 不是短期技巧而是人与大模型协作的基本功。传统接口调用输入输出规范是明确的偏差是可预见的。大模型则是“宽进严出”你给它模糊的输入它就还你模糊的输出你给它清晰的约束和足够的上下文它才能接近你的预期。所以一个成熟的开发者会在写 prompt 之前先问自己三个问题我到底想让模型完成一个什么任务这个任务的成功标准是什么如果模型输出不符合标准我的兜底方案是什么这三个问题想清楚哪怕 prompt 写得不华丽效果也不会太差。6.2 下一步先从一个最小可验证任务开始如果你现在正准备用大模型做一个小工具我的建议很简单不要急着写一个很长很全的 prompt。先找一个最小的任务把输入、输出、约束和示例写清楚跑通 10 条样本再逐步加复杂度。等你把这条链路跑稳了再回头理解“灯与精灵”的隐喻。那时你会意识到真正的魔法不在模型里而在你把需求翻译成接口约束的过程里。模型很可能还会继续变强但一个能清晰定义任务、设计约束、验证输出的人永远不会被工具替代。