人机交互协议:从许愿式提问到可复现工程流程的实践指南
1. 为什么需要一份“人机交互协议”大多数人跟大模型打交道的方式其实还停留在“许愿”阶段。打开对话框敲一句“帮我写个方案”然后盯着屏幕上吐出来的字心里默念“再聪明一点、再懂我一点”。结果不满意就换个说法再试一次来回折腾十几轮最后要么凑合用要么干脆放弃自己动手。这种交互模式的问题不在于模型不够强而在于双方没有建立起一套稳定的协作规则。我把它叫做“人机交互协议”是因为它本质上和网络通信里的协议是一回事。两台机器要可靠地交换数据得先约定好帧格式、校验方式、重传机制。人和大模型之间要高效地产出内容同样需要约定好输入的结构、期望的边界、纠错的路径。没有这套约定每次对话都是从零开始猜效率极低而且结果极不稳定。这份协议解决的核心问题是把“碰运气式提问”变成“可复现的工程流程”。它适合所有需要长期、高频使用大模型辅助工作的人——写代码的、做策划的、搞研究的、写文案的只要你每天跟模型打交道的次数超过五次这套东西就能帮你省下大量反复解释和返工的时间。我最初也是“许愿派”后来发现同一个任务换三种问法能得到三种质量完全不同的结果才开始认真琢磨这件事。V1.00 版本是我自己在笔记里记的几条零散规则用了一年多踩了不少坑迭代出了现在这套 V2.00。下面把它拆开讲清楚。2. 协议的第一层输入结构的标准化2.1 为什么“一句话需求”注定低效大模型的工作原理是根据上下文预测下一个 token。你给的上下文越模糊它需要“猜”的空间就越大。猜对了是运气猜错了是常态。很多人抱怨模型“不懂我”其实是你没给它懂你的机会。举个具体的例子。你说“帮我优化这段代码”模型面临的选择空间是巨大的优化性能优化可读性优化内存占用还是单纯把变量名改好看它不知道你的约束条件只能按训练数据里最常见的模式来猜。结果就是它可能给你改了一堆无关紧要的格式而你真正在意的性能瓶颈纹丝不动。标准化的输入结构就是把这个选择空间压缩到模型能准确命中的范围。我的做法是固定一个五段式模板每次提问都按这个结构来填。2.2 五段式输入模板的具体字段这套模板我用了大半年字段经过多次删减合并最终稳定在五个角色锚定一句话告诉模型它现在是谁。不是“你是一个AI助手”这种废话而是具体到领域和水平层级。比如“你是一个有十年经验的后端性能优化工程师”。任务陈述用动词开头说清楚要产出什么。是“写一段代码”还是“审查一段代码”还是“重构一段代码”动词不同模型的输出模式完全不同。约束条件这是最关键的一段。包括技术栈限制、长度限制、风格限制、必须包含或必须排除的内容。约束越具体返工越少。输入素材需要模型处理的原始内容。代码、文本、数据都放在这一段用明确的分隔符标出来。输出格式明确告诉模型你要什么形式的结果。是纯代码、是表格、是分点列表、还是带注释的段落。格式不指定模型就按它自己的偏好来大概率不是你想要的。这五段不需要每次都写全但角色锚定和约束条件这两段我建议永远不要省。它们对输出质量的影响最大。2.3 一个完整的输入示例光说结构太抽象直接看一个我实际用过的例子[角色] 你是一个资深 Python 后端工程师熟悉 FastAPI 和异步编程。 [任务] 审查以下代码找出潜在的并发安全问题。 [约束] 只关注并发和资源竞争问题不讨论代码风格。每个问题给出具体行号和修复建议。 [输入] def update_balance(user_id, amount): user db.get(user_id) user.balance amount db.save(user) [输出] 用表格列出问题描述 | 所在行 | 风险等级 | 修复方案这个输入丢进去模型输出的质量和我早期随便问一句“这段代码有问题吗”相比完全是两个档次。前者直接给出了竞态条件的分析后者大概率只会说“建议加锁”这种正确的废话。注意角色锚定不要写得太泛。“你是一个程序员”和“你是一个专注高并发场景的 Go 语言后端工程师”后者触发的知识区域明显更精准。这是我在大量对比测试中反复验证过的。3. 协议的第二层对话节奏的控制3.1 单轮对话的天然缺陷大模型的单轮输出有一个硬限制它必须在一次生成中完成所有推理。这意味着它没有“回头检查”的机会。对于复杂任务单轮输出几乎必然存在遗漏或逻辑跳跃。我早期做技术方案设计时习惯把整个需求一次性丢进去让模型输出完整方案。结果经常是开头很详细中间开始泛泛而谈结尾草草收场。这不是模型能力不够而是单轮生成的注意力分配问题——它把精力平摊到了所有部分导致每个部分都不够深入。解决办法是把复杂任务拆成多轮每轮只聚焦一个子问题。这就是协议的第二层用对话节奏控制输出深度。3.2 三轮递进法的操作细节我的做法是固定一个三轮节奏第一轮叫框架轮。只让模型输出大纲和关键决策点不展开细节。比如做技术方案第一轮只要它列出模块划分和技术选型建议每个点一两句话即可。这一轮的目的是确认方向对不对避免在错误的方向上深入。第二轮叫展开轮。针对框架轮里确认的每个模块逐个展开。这时候我会把框架轮里模型自己提出的关键点摘出来作为这一轮的输入约束。比如“你上一轮提到用消息队列解耦现在详细展开这个模块的设计包括队列选型、消息格式、失败重试策略”。第三轮叫审查轮。把前两轮的产出拼在一起让模型自己审查一遍找逻辑漏洞和前后矛盾的地方。这一轮特别有用因为模型在审查自己写的东西时往往能发现生成时没注意到的问题。这三轮下来产出的质量比单轮直接生成高出一大截。代价是多花了两轮对话的时间但省下了大量自己修改和补全的时间净收益是正的。3.3 什么时候该打断模型有一个反直觉的经验模型输出到一半发现方向不对应该立刻打断而不是等它写完再纠正。原因是模型在生成过程中会不断参考自己前面写的内容。如果前面已经跑偏了后面只会越跑越偏而且它会用后面的内容去“圆”前面的错误导致整个输出逻辑自洽但方向完全错误。这种输出比明显的错误更危险因为它看起来很有道理。打断的时机一般是看到第一个小标题或者第一段展开时。如果方向不对直接停止生成重新组织输入。不要心疼已经生成的那部分继续下去只会浪费更多时间。4. 协议的第三层输出质量的校验机制4.1 模型输出的三类典型问题用了这么久我把模型输出的问题归为三类第一类是事实性错误。模型自信地说了错误的信息尤其是涉及具体版本号、API 签名、配置参数的时候。这类问题最危险因为输出看起来很专业不仔细核对根本发现不了。第二类是逻辑跳跃。模型从 A 直接跳到 C中间缺了 B 的推理步骤。你读的时候会觉得“好像哪里不对”但又说不上来。这类问题在方案设计和论证类任务里特别常见。第三类是约束漂移。你明明说了“不要用某个库”模型写着写着还是用了。或者你要求“控制在 500 字以内”它给你输出了 800 字。这类问题不是模型能力问题是注意力衰减导致的。4.2 针对三类问题的校验清单针对这三类问题我固定了一套校验流程事实性校验凡是涉及具体数字、版本、API 名称、配置项的地方一律自己查一遍官方文档。不要偷这个懒。我吃过亏模型给的一个配置参数看起来完全合理实际跑起来直接报错查了文档才发现那个参数在目标版本里已经废弃了。逻辑校验把模型的输出当成别人写的东西来读重点看段落之间的衔接处。如果两个段落之间需要读者自己脑补一步推理才能连上那大概率就是逻辑跳跃。这时候直接追问“从 A 到 C 的推理过程是什么请补充中间步骤。”约束校验输出完成后对照自己写的约束条件逐条检查。我习惯把约束条件写在输入的最后然后在输出里用搜索功能逐个确认。比如约束里写了“必须包含错误处理”就在输出里搜“error”或“异常”看有没有对应的处理逻辑。4.3 让模型自己校验自己的技巧除了人工校验还有一个省力的办法让模型自己校验。具体做法是在输出完成后追加一轮对话请审查你刚才的输出检查以下三点 1. 是否有与事实不符的陈述特别是具体参数和版本号 2. 是否有逻辑跳跃即从 A 直接到 C 而缺少 B 的推理 3. 是否违反了我最初给出的约束条件 逐条列出你发现的问题不要客气。这个技巧的效果出乎意料地好。模型在“审查模式”下确实能发现自己生成时忽略的问题。我猜测是因为审查任务的注意力模式和生成任务不同生成时它在“向前推进”审查时它在“向后检查”两种模式看到的东西不一样。注意让模型自检时一定要明确说“不要客气”。不加这句话模型倾向于说“整体很好只有一些小问题”然后列出一堆无关痛痒的格式建议。加上这句话它才会认真找实质性问题。5. 协议在代码场景下的特殊约定5.1 代码任务的输入要带“上下文锚点”代码场景和文本场景有一个关键区别代码有严格的依赖关系。一个函数能不能改取决于谁在调用它、它依赖了什么、运行环境是什么。这些信息如果不给模型它只能瞎猜。我的做法是在输入里固定加一段“上下文锚点”包括语言和版本、框架和版本、关键依赖库、运行环境本地/容器/特定平台、以及这段代码在项目中的位置入口/中间层/工具函数。这些信息看起来琐碎但对输出质量的影响极大。举个例子同样是“写一个读取配置文件的函数”Python 3.8 和 Python 3.12 的写法不同用 pydantic 和不用 pydantic 的写法不同在容器里跑和在本机跑的路径处理也不同。不给这些锚点模型只能按最常见的模式来写大概率需要你手动改。5.2 代码输出的验收标准代码类输出我有一套固定的验收标准按优先级排序能跑通这是底线。把代码复制到本地补上必要的依赖实际运行一遍。不要只看逻辑对不对实际跑一遍经常能发现拼写错误、缩进问题、导入缺失。边界处理输入为空、输入超长、输入格式错误时代码的行为是什么。模型生成的代码经常只处理“正常路径”异常路径要么没写要么写得很敷衍。可读性变量命名是否清晰、函数是否过长、有没有必要的注释。这部分可以放宽要求因为可以自己改但如果模型生成的代码可读性太差改起来也费劲。性能有没有明显的性能问题比如循环里查数据库、重复计算、不必要的内存拷贝。这个需要根据具体场景判断不是所有代码都需要优化性能。5.3 代码场景下的常见坑代码场景有几个坑我踩过多次这里列出来坑一模型会“发明”不存在的 API。尤其是涉及第三方库的时候模型可能会编造一个看起来很像但实际不存在的函数名。防范办法是凡是模型提到的 API都去官方文档确认一遍。坑二模型会忽略版本差异。同一个库的不同版本API 可能完全不同。如果不在输入里指定版本模型会按它训练数据里最常见的版本来写。防范办法是在上下文锚点里明确写出版本号。坑三模型生成的测试用例覆盖不全。如果你让模型写测试它倾向于写“正常路径”的测试异常路径和边界条件的测试往往缺失。防范办法是明确要求“包含边界测试和异常测试”。6. 协议在文本场景下的特殊约定6.1 文本任务的风格锚定文本类任务最大的挑战是风格一致性。你让模型写一篇技术文档它可能写成营销文案的风格你让它写一篇轻松的介绍它可能写成学术论文。风格不对内容再好也得重写。我的做法是在输入里加一段“风格锚定”具体包括目标读者是谁、期望的语气正式/轻松/中性、参考风格如果有的话贴一段示例文本、以及必须避免的表达方式。风格锚定里最有用的是“参考风格”。贴一段你想要的风格的示例文本比任何形容词都管用。模型在模仿风格方面的能力很强给它一个具体的样本它能模仿得很像。6.2 长文本的分段生成策略让模型一次性生成几千字的长文本质量会明显下降。开头和结尾通常还行中间部分容易变得空洞、重复、逻辑松散。这是单轮生成的注意力限制导致的。我的策略是分段生成先让模型输出详细大纲确认后逐段生成。每段生成时把大纲里前后段落的要点也作为上下文传进去保证段落之间的衔接。具体操作是这样的第一轮输出大纲每个小节配一句话的内容概要。第二轮开始逐段生成生成第 N 段时输入里包含大纲全文、第 N-1 段的结尾、以及第 N 段的内容概要。这样模型知道前面写了什么、后面要写什么衔接会自然很多。6.3 文本输出的“人味”检查模型生成的文本有一个通病太“顺”了顺得不像人写的。具体表现是每段长度差不多、句式结构重复、过渡词使用过于规律、缺乏个人化的表达和语气词。我的检查方法是把生成的文本朗读一遍。如果读起来像在念说明书那就是“人味”不够。修改的方向是打乱段落长度、加入口语化的表达、在合适的地方插入个人经验或观点、删掉一些过于工整的过渡句。这一步没有捷径只能手动改。但好消息是模型生成的文本作为“初稿”是合格的你只需要在上面做“去模板化”的修改比从零开始写快得多。7. 协议的迭代与个人化调优7.1 记录每次交互的结果这套协议不是固定的它应该随着你的使用不断迭代。我的做法是维护一个简单的交互日志记录每次重要交互的输入结构、输出质量、以及遇到的问题。日志不需要很复杂我用的就是一个表格字段包括日期、任务类型、输入模板版本、输出质量评分1-5、主要问题、改进想法。每周花十分钟回顾一下看看有没有反复出现的问题然后针对性地调整协议。7.2 根据任务类型调整协议参数不同类型的任务协议参数应该不同。我目前总结出来的规律是任务类型角色锚定详细度约束条件数量推荐轮数校验重点代码生成高多2-3轮事实性、边界处理代码审查高中1-2轮逻辑完整性技术方案中中3轮逻辑跳跃文案写作低多2轮风格一致性数据分析高多2-3轮事实性、计算准确性知识问答低少1轮事实性这个表不是固定的每个人可以根据自己的使用习惯调整。核心思路是任务越复杂、约束越多需要的轮数越多任务越依赖事实准确性校验越要严格。7.3 什么时候该放弃协议直接问这套协议不是万能的。有些场景下直接问反而更好探索性提问你也不知道自己想要什么只是想看看模型能给出什么思路。这时候不需要约束让模型自由发挥从它的输出里找灵感。简单事实查询问一个具体的知识点不需要角色锚定和约束条件直接问就行。创意发散需要大量不同方向的点子时约束太多反而限制模型的发散能力。这时候可以故意放宽约束甚至故意给模糊的输入看模型能给出什么意外的东西。协议的目的是提高效率不是增加负担。当你发现按协议走反而更慢的时候就说明这个场景不适合用协议直接问就好。8. 我在实际使用中总结的几条硬经验第一条输入的质量决定输出的上限。你给模型的信息越具体、越结构化它的输出就越接近你的期望。不要指望用模糊的输入得到精确的输出这不现实。第二条模型说“不”的时候往往是对的。如果你要求模型做一件它明确表示做不到或不确定的事不要反复追问试图让它“松口”。它说做不到大概率是真的做不到或者做出来质量很差。这时候应该换思路而不是硬来。第三条保存好用的输入模板。我有一份“模板库”里面存了各种场景下验证有效的输入结构。每次遇到类似任务直接调模板改几个字段就行比从头写快得多。这个习惯帮我省了大量时间。第四条不要在一个对话里塞太多不相关的任务。模型的上下文是有限的前面聊的内容会影响后面的输出。如果一个对话里已经聊了代码突然切换到写文案模型可能会把代码对话里的语气和结构带到文案里。我的做法是不同任务开不同对话保持上下文的纯净。第五条定期回顾自己的交互日志。你会发现一些反复出现的问题比如“总是忘记指定输出格式”“总是低估约束条件的重要性”。发现这些模式后针对性地调整自己的输入习惯效率会有明显提升。这套协议从 V1.00 到 V2.00 用了一年多中间改了很多次。最大的体会是跟大模型协作本质上是在设计一套沟通规则而不是在“使用一个工具”。规则设计得好协作效率就高规则设计得差就变成互相折磨。希望这份协议能给你一些启发也欢迎你根据自己的使用场景做调整和补充。