约束明确的提示词

在提示词中写明范围、非目标、兼容性限制和验收命令,约束生成式改动。

难度 进阶 时长 标准深度约 17分钟
版本 Node 24
what

约束明确的提示词既定义预期结果,也划出生成式改动解决问题时必须遵守的边界。

trap

只描述功能会把相邻重构、依赖变更、兼容性选择和完成证据留给智能体猜测。

fix

写明修改范围、非目标、受保护行为、确切验收命令,以及遇到冲突或证据缺失时的停止条件。

是什么,为什么存在

约束明确的提示词是一份有边界的改动请求。它说明什么必须成立、哪里可以修改、哪些看似合理的结果被明确排除、哪些现有行为必须保留,以及哪些证据决定任务完成。它仍然使用自然语言,但关键选择足够明确,可以逐项审查。

只描述所需功能,相当于在很大的解空间里只指定一个点。「增加优惠券上限」可能让智能体修改验证逻辑、替换依赖、重命名公开函数、迁移存储数据、格式化相邻文件,甚至放宽阻碍其实现的测试。即使原意只允许改两个文件,每一步在局部看来都可能合理。

问题并不是智能体缺乏主动性。代码库里常有多种看似可行的模式、不完整的文档和彼此冲突的局部示例。约束没有写明时,模型只能从这些证据推断产品与维护决策,流畅的输出也就可能掩盖请求者从未授权的选择。

四类字段承担了大部分边界定义工作:

字段回答的问题具体形式
范围可以修改什么?具名文件、符号、目录、生成产物和文件数量预算
非目标排除哪些相邻结果?不升级依赖、不迁移模式、不大范围重命名、不做无关清理
兼容性哪些现有交互继续有效?公开签名、错误类型、序列化形状、运行时或 CLI 退出码
验收什么证据决定完成?确切命令、预期退出状态、聚焦案例和差异检查

范围首先是修改边界,而不是阅读边界。智能体可能需要检查允许修改范围之外的调用方、配置、测试或指令,才能理解改动。好的提示词会区分「可以检查」与「可以修改」,既让调查有效,又不会悄悄扩大补丁。

非目标是主动排除项,不是填充文字。它记录一项很有吸引力的相邻改动,避免这项改动被误当成当前任务。「不要替换验证库」在仓库同时存在旧辅助函数和新库时很有用;「不要做任何不必要的改动」只是把同一个判断再次交给智能体。

兼容性限制指出 API 契约(API contract) 中受保护的部分。它可以保护位置调用和关键字调用、JSON 字段、异常类、事件顺序或最低运行时版本。在提示词明确使用者及其观察结果之前,「不要引入破坏性变更」并没有说清禁止哪一种 破坏性变更(breaking change)

验收命令让完成条件可以复现。命令应来自仓库脚本或经过本地验证,并写明必要的工作目录以及成功标准。命令退出码是证据;智能体所说的「测试应该能通过」不是证据。

约束明确不等于篇幅很长。小型私有改动可能只需一个允许文件、一项受保护行为和一条测试命令。跨软件包改动、持久化数据、公开 API、身份验证、支付或迁移需要更明确的边界,因为一个看似合理的错误假设代价更高。

当智能体可以自主编辑、运行工具并连续执行多个步骤时,这类提示词尤其有用。行动循环越长,范围漂移的机会越多,早期假设也越容易影响后续改动。提示词为每一步提供稳定的参照点。

提示词不是授权系统。写下「不要读取秘密」不能撤销文件系统访问权限,写下「只能编辑 src/checkout/」也不能强制实现沙箱。安全边界应由权限、隔离、审查关卡和确定性验证落实;提示词约束用于传达预期工作。

工作原理

先从仓库证据出发,而不是凭记忆起草约束。找出活跃符号、调用方、失败行为、本地指令、软件包脚本、运行时目标和当前差异。这样才能把「保持兼容性」之类的通用偏好,转成与真实使用者有关的要求。

可以按以下顺序起草:

  1. 写明一个可观察结果,以及需要该结果的用户或调用方。
  2. 指定有充分依据的最小修改面,并说明哪些生成文件不能直接编辑。
  3. 排除当前仓库中合理但本次不需要的相邻工作。
  4. 分开列出受保护的兼容性维度与有意改变的行为。
  5. 给出确切验收命令,以及有判别力的正向和负向案例。
  6. 定义智能体必须停止并报告的条件,避免它自行猜测或扩大范围。

这个顺序很重要,因为后面的约束会限定目标。「显式页大小为零时返回零」是行为要求。「保留现有单参数导出」保护兼容性,而「不要修改调用方」收窄实现范围。这些条款不能安全地相互替代。

限定修改面

文件范围是最容易在差异中检查的边界。手术式改动可以指定确切文件;允许新增测试或生成快照时,可以指定目录与文件类型。如果任务最多允许修改三个文件,就应写明这项改动预算,让第四个文件触发讨论,而不是悄悄扩张。

只列路径可能过于僵硬。提示词允许 src/checkout/discount.mjs 却遗漏配套测试文件,就无法提供证明。更合适的做法是给出一组很小的必需文件,再补充条件规则,例如「可以在 test/checkout/ 下增加一个测试夹具;修改清单、锁文件、模式或公开类型前必须先报告」。

还要说明语义边界。「定价策略留在 discount.mjs 中;不要把网络调用移入该文件」保护了一条仅靠路径列表无法表达的 架构边界(architecture boundary) 。改动即使都落在允许目录中,仍可能反转依赖方向,或者把策略与 I/O 混在一起。

阅读范围通常应该比修改范围更宽。可以要求智能体搜索所有调用点并检查软件包指令,同时把修改限定在具名范围内。如果调查证明修复还需要另一个所有者或迁移,停止条件就应要求它先提交证据,再讨论是否扩张。

写出有效的非目标

非目标应当与任务相邻、很有诱惑力,并且可以在最终差异中检查。常见例子包括升级软件包、修改数据库模式、重命名无关符号、引入框架、重新格式化未触碰的代码,或顺手修复附近的第二个缺陷。每一项都阻止一种真实的范围蔓延。

不要试图预言所有不想要的行为。上百条禁令难以协调,也容易被跳读。只选择仓库证据提示的少数排除项,然后增加一条通用停止规则,处理必须越过允许边界的改动。

负面措辞需要指出正面归属。「不要编辑生成文件」还应说明哪个源文件拥有它们,以及哪条生成命令可以更新它们。「不要改 API」还应给出确切导出符号和受保护的观察结果。否则智能体只知道不能往哪里走,却不知道合法改动应该落在哪里。

按维度规定兼容性

向后兼容性(backward compatibility) 总是相对于一组以前有效的交互而言。应当明确这组交互。对于 JavaScript 函数,它可能包括依赖参数个数的反射、参数省略时的默认行为、是否接受零、抛出的错误类、返回对象字段和异步时序。

不同兼容性维度可能指向不同要求:

维度约束示例证据
源码保持 parsePageSize(value) 可用一个参数调用现有调用方测试与调用点搜索
行为省略输入仍返回 25;显式 0 仍返回 0具名边界案例
数据不增加、删除或重命名存储的 JSON 字段夹具往返与模式差异
运行时使用 Node 24 可用的 API;不增加 polyfill声明的工具链与干净安装
运维保留自动化依赖的退出码和 stderr 格式CLI 集成测试

把有意的不兼容与受保护行为分开。如果无效字符串以前会被强制转成数字,现在必须失败,就要明确写出这项变化。提示词不能既要求严格拒绝,又要求与依赖强制转换的调用方保持完全行为兼容。

存在未知使用者时,不可能提出普遍兼容保证。应要求搜索调用点、盘点公开表面或编写特征测试,再把承诺限定在实际找到的证据上。如果证据不完整,就要求智能体标出不确定性,而不是宣称「没有回归」。

让验收可执行

验收命令应该可以直接复制、从具名目录运行,并能因目标缺陷而失败。应写 node test/checkout/discount.test.mjs,而不是「运行相关测试」。只有当仓库的类型、检查、构建或格式化命令适用于当前改动面时,才把它们加入验收。

命令与行为标准互为补充。宽泛测试套件可能通过,却没有检查新的零值边界;聚焦测试也可能遗漏类型或打包故障。用文字写出有判别力的案例,再写明执行这些案例的命令。

还要为禁止的改动提供负向验收证据。git diff --check 可以发现空白错误,已修改文件检查可以发现范围漂移,清单差异可以发现意外依赖。这些检查无法证明语义正确,却能补上行为测试常见的缺口。

还要定义命令无法运行时的处理方式。智能体应报告确切命令、退出状态和阻碍;不能用「看起来正确」代替,也不能悄悄省略检查。如果基线已有无关失败,应要求证据把它与当前补丁造成的回归区分开。

先运行便宜且聚焦的检查,再运行昂贵且宽泛的检查。这样可以缩短反馈时间,又不会削弱最终关卡。提示词仍应明确:所有具名命令都通过才算完成,而不是任意一项早期检查通过即可。

编辑前解决冲突

所有约束组成同一个集合,因此矛盾必须一起处理。严格的双文件范围可能与重新生成锁文件的要求冲突。保留错误类也可能与采用另一个公开包装器错误不同的库冲突。只有所有细节都能同时成立时,更多细节才真正有帮助。

为智能体写出优先级与升级规则:先遵守仓库指令和安全边界;显式任务约束限定所需行为;两项要求无法同时满足时,提交最小冲突集合和一两个有证据支持的选项,然后停止。不要让智能体自行选择看起来更重要的条款。

要求在假设进入代码前把它们显式列出。简短的编辑前摘要可以列出计划修改的文件、受保护行为、预期命令和未决问题。对于直接的任务,这可以是一份紧凑清单,不必变成形式化计划。

可复用的提示词结构

以下字段只是起点,不是强制表单:

  • 任务: 一个可观察行为变化、目标符号和受影响的调用方。
  • 证据: 当前行为、失败示例、相关源码位置和仓库指令。
  • 范围: 允许的文件或目录、文件预算、生成文件策略和允许的阅读范围。
  • 非目标: 明确排除的相邻重构、迁移、依赖变化或产品行为。
  • 兼容性: 受保护的签名、失败、数据形状、运行时版本和使用者。
  • 验收: 确切命令、关键案例、差异检查和预期成功条件。
  • 停止条件: 冲突、权限缺失、证据不可用,或必须在范围外写入。

各字段应使用仓库自己的语言。如果软件包把边界称为适配器,就沿用这个词并给出文件名。如果测试脚本是 pnpm test:checkout,就准确复制;凭空编造通用的 npm test 会削弱原本精确的请求。

示例

下面的示例把提示词条款转成能够拒绝诱人但未获授权补丁的检查。这些脚本只是仓库关卡的小型模型,并不意味着仅靠文字就能强制智能体遵守约束。所有输出都在本地使用 Node 24 实际生成。

拒绝扩大修改范围

假设任务是调整结账折扣。提示词允许修改两个具名根目录下的实现与测试文件,把补丁上限设为三个文件,并把软件包元数据标为受保护文件。它的非目标排除了文档清理和依赖变更。

scope_guard.mjs
const contract = {
  allowedRoots: ["src/checkout/", "test/checkout/"],
  protectedFiles: new Set(["package.json", "pnpm-lock.yaml"]),
  maxChangedFiles: 3,
};

function assessChange(paths) {
  const violations = [];
  if (paths.length > contract.maxChangedFiles) {
    violations.push(`file budget exceeded: ${paths.length}`);
  }
  for (const path of paths) {
    if (contract.protectedFiles.has(path)) {
      violations.push(`protected file: ${path}`);
    } else if (!contract.allowedRoots.some((root) => path.startsWith(root))) {
      violations.push(`outside scope: ${path}`);
    }
  }
  return violations;
}

const proposals = [
  ["focused", ["src/checkout/discount.mjs", "test/checkout/discount.test.mjs"]],
  ["expanded", ["src/checkout/discount.mjs", "README.md", "package.json"]],
];

for (const [name, paths] of proposals) {
  const violations = assessChange(paths);
  console.log(`${name}: ${violations.length === 0 ? "PASS" : `FAIL (${violations.join("; ")})`}`);
}
focused: PASS
expanded: FAIL (outside scope: README.md; protected file: package.json)

聚焦方案满足路径规则。扩张方案也只有三个文件,但其中两个违反了更具体的边界。因此,文件数量预算不能替代允许列表或受保护文件规则。

提示词仍应允许调查这些根目录以外的内容。为了找到测试命令而读取 package.json,与修改它是两回事。如果实现确实需要一个依赖,正确结果是提交范围外发现,而不是暗中编辑清单。

保护兼容性边界

接下来要修改 parsePageSize,让无效值明确失败。提示词保留单参数调用,让 undefined 继续映射到 25,让显式 0 继续有效,把上限设为 100,并要求保留现有 RangeError 消息。这些条款可以阻止生成的 value || 25 捷径改变零值语义。

compatibility_matrix.mjs
function parsePageSize(value) {
  if (value === undefined) return 25;
  if (!Number.isSafeInteger(value) || value < 0 || value > 100) {
    throw new RangeError("pageSize must be an integer from 0 to 100");
  }
  return value;
}

const cases = [
  ["missing", undefined],
  ["zero", 0],
  ["maximum", 100],
  ["too large", 101],
];

for (const [name, value] of cases) {
  try {
    console.log(`${name}: ${parsePageSize(value)}`);
  } catch (error) {
    console.log(`${name}: ${error.name}: ${error.message}`);
  }
}
missing: 25
zero: 0
maximum: 100
too large: RangeError: pageSize must be an integer from 0 to 100

这些案例区分了省略参数与显式假值,并在上限边界放置示例。它们也让错误通道和消息可观察。「保持旧行为」无法说明请求者究竟保护其中哪些交互。

验收条款可以指定 node compatibility_matrix.mjs 并要求退出状态为零,而打印的各行仍是有用的审查证据。如果真实仓库已有聚焦测试命令,提示词应调用那条命令,而不是另建一套平行的临时工具。

拒绝不完整的验收证据

最后一个示例建立完成关卡模型。提示词要求聚焦行为检查、针对修改面的代码检查,以及差异卫生检查。只有证据包含全部命令且退出码都为零时,智能体才能报告完成。

acceptance_evidence.mjs
const requiredCommands = [
  "node test/checkout/discount.test.mjs",
  "pnpm eslint src/checkout test/checkout",
  "git diff --check",
];

function releaseDecision(results) {
  const evidence = new Map(results.map((result) => [result.command, result.exitCode]));
  let ready = true;

  for (const command of requiredCommands) {
    const exitCode = evidence.get(command);
    const state = exitCode === undefined ? "MISSING" : exitCode === 0 ? "PASS" : `FAIL exit=${exitCode}`;
    console.log(`${state}: ${command}`);
    if (exitCode !== 0) ready = false;
  }

  console.log(`decision: ${ready ? "READY" : "NOT READY"}`);
}

releaseDecision([
  { command: "node test/checkout/discount.test.mjs", exitCode: 0 },
  { command: "pnpm eslint src/checkout test/checkout", exitCode: 1 },
]);
PASS: node test/checkout/discount.test.mjs
FAIL exit=1: pnpm eslint src/checkout test/checkout
MISSING: git diff --check
decision: NOT READY

聚焦测试通过不能抵消代码检查失败,省略差异检查也不等于通过。有效的智能体响应应包含真实失败与缺失证据,然后修复范围内的原因;如果解决问题需要越界,就应停止。

确切命令字符串还可以防止替换证据。pnpm eslint src/checkout test/checkout 与编辑器显示的「没有可见警告」并不是等价检查。如果命令本身已经过期,修改验收契约需要显式决策,不能悄悄替换。

陷阱

添加无法同时满足的约束

修复方法: 编辑前先检查可满足性。把每项必需结果与它涉及的文件和命令配对。如果两个条款冲突,就提交最小冲突集合,并请所有者放宽或拆分其中一项要求。

把非目标写成模糊克制

修复方法: 写明两三个与仓库有关的诱惑项:不升级软件包、不迁移模式、不重命名 src/checkout/ 以外的内容,也不清理既有检查问题。对照最终文件列表和差异逐项验证。

让范围僵硬或无限

修复方法: 先给出狭窄的默认范围,再定义条件扩张。写明允许增加哪些测试或生成文件、哪些文件受保护,以及智能体必须在增加其他路径前报告哪些证据。

把兼容性当成口号

修复方法: 用小型兼容性矩阵列出受保护的使用者与维度。在每个重要行旁放置示例或特征测试,并明确哪些行为允许有意改变。

过度限制实现方式

修复方法: 先约束可观察行为与架构边界。只有内部形式能够保护所有权、依赖方向、安全、性能或稳定约定时才规定它,并在提示词中写明理由。

把具名命令当成已执行证据

修复方法: 要求完成报告写出命令、必要的工作目录、退出码和简短真实输出。命令缺失或受阻时,结果仍未完成;遇到基线失败,还要用聚焦比较说明补丁是否改变了它。

深入 约束交集与证据闭环

约束交集与证据闭环

提示词中的约束以交集方式生效。候选补丁既要实现所需行为,也要留在修改范围内,保留每项受保护交互,避开非目标,并产出必需证据。满足其中四项不能抵消第五项缺失。

这个模型会改变审查问题。不要只问「功能是否有效」,还要问是否存在满足完整集合的补丁,以及提交的补丁是否属于这个集合。第一个问题能发现矛盾提示词,第二个问题能发现范围漂移和验证不完整。

行为与范围是独立维度

行为正确的补丁仍可能越界。例如,替换项目验证库也许能完美实现新规则,却会引入当前任务排除的清单变化和迁移工作。反过来,两行范围内补丁也可能遵守差异预算,却返回错误的错误类型。

应分别跟踪两个维度:

审查结果满足行为满足范围决策
预期补丁继续检查兼容性与验证
范围漂移停止或取得扩张批准
修复不完整在边界内修改
无关改动丢弃并回到证据

因此,仅看行数是很弱的防线。一行公开签名改动可能比二十行聚焦测试更具破坏性。文件和行数预算是有用的触发器,但补丁是否属于任务,仍由语义所有权和可观察行为决定。

非目标不同于负向测试

非目标限制项目结果,例如「不要迁移现有记录」。负向验收案例限制行为,例如「国家代码缺失时抛出 TypeError,并且不写入任何内容」。两者都使用否定措辞,但约束的对象不同。

混淆两者会留下缺口。除非测试观察差异,否则它无法证明没有无关文件被重新格式化;允许差异列表也无法证明无效输入不会修改存储。项目排除项需要改动级检查,行为排除项需要运行时观察。

有些非目标是临时排序决策。「本补丁不要移除旧端点」会保护分阶段迁移,即使以后计划移除。应在当前验收标准之外记录未来所有者或后续事项,避免智能体提前实现第二阶段。

兼容性需要受保护集合

兼容性审查从列举使用者开始。静态调用点揭示直接源码依赖,模式、夹具、快照、集成测试和自动化脚本揭示数据与运维依赖。运行时反射、插件或外部客户端可能仍未知,应作为不确定性报告。

当多个输入类别和兼容性规则重叠时, 决策表(decision table) 很有帮助。各行可以覆盖省略值、零值、最大值、畸形值和旧形式;各列可以记录旧结果、预期结果、是否允许变化及证据命令。这样,有意变化与意外回归就能明显区分。

没有外部契约时,不要承诺超出已观察集合的兼容性。如果库是公开的,语义化版本可以传达预期影响,但版本号不会自动发现使用者,也不能证明其行为。提示词仍需写明公开表面与迁移边界。

验收命令用证据闭合声明

每项验收声明都应指向一个证据生成器。行为声明指向使用独立预期值的聚焦测试,类型与构建声明指向实际工具调用,范围声明指向已修改文件列表和差异,依赖声明指向清单与锁文件检查。

这种映射可以在实现前记录:

声明证据生成器失败时的行动
显式零值继续有效具名边界测试修改实现
保留公开错误类兼容性测试修改实现或批准破坏性变更
依赖未改变清单与锁文件差异移除改动或请求扩张
补丁通过仓库检查确切测试、检查和构建命令报告退出码并在范围内修复

证据必须足够独立,才能抓住可能发生的错误。生成测试若使用实现公式计算预期值,可能与同一个缺陷保持一致。契约要求时,应使用字面结果、相邻边界、已知夹具或外部模式。

命令列表还要保持新鲜。软件包脚本会移动,参数会改变,从另一个目录复制的命令也可能没有检查任何文件。把命令放入提示词前,应在当前仓库验证;即使进程成功退出,「没有找到测试」仍应视为证据失败。

停止条件保留决策权

停止条件定义自主执行的终点。有效触发项包括必须在范围外写入、要求互相矛盾、缺少产品决策、凭据不可用、迁移不安全,或具名验收命令无法执行。智能体应报告阻碍和最小的、有证据支持的选项。

如果继续执行意味着自行发明权限,那么停止并不等于失败。它保留了请求者对范围和兼容性决策的所有权。好的阻碍报告会指出确切条款、仓库事实、受影响文件或使用者,以及继续所需的决策。

不要为每个小不确定性都设置停止规则。提示词可以授权边界内的可逆实现选择,只把会改变产品行为、公开兼容性、安全状态、数据、成本或修改范围的选择留待升级。这样既能发挥智能体作用,也不会把沉默当成同意。

提示词约束与强制层

提示词约束引导模型决策,确定性关卡检查结果,权限限制能力。三层可以相互加强,却不能互相替代。模型可能误解文字,差异检查可能遗漏运行时语义,沙箱配置不当也可能阻止原本允许的构建。

使用提示词表达意图与停止条件。使用测试、模式、代码检查、构建和差异策略,让重要属性可以被证伪。使用凭据、文件系统边界、网络策略和批准关卡,确保模型即使忽略指令也不能产生未授权影响。

高风险工作应显式连接这些层。提示词可以写「不要执行迁移」,工具环境可以拒绝生产凭据,验收关卡可以检查迁移文件。这种冗余有价值,因为每一层处理的失败模式不同。

审查提示词本身

把提示词交出去之前,应像审查小型工程产物一样审查它。确认每项约束都有所有者,每项兼容性声明都有使用者,每条验收命令真实存在,每个非目标都可检查。删除不会改变任何决策的装饰性限制。

然后用两个候选方案测试提示词:一个明显过宽,一个足够狭窄且正确。文字应能以具名原因拒绝前者,并且无需隐藏知识就能允许后者。如果两个方案看起来都有效,缺失的区别就应补进行为、兼容性、范围或证据。

约束明确的提示词仍可以修改。调查可能发现请求者原本不知道的调用方、生成产物或仓库规则。修订必须显式进行:记录证据,修改受影响条款,再重新运行由该条款导出的检查。

延伸阅读

检查点

4个问题 · 1 道输出预测题 · 1 道找错题

复制为 Markdown 面试题库 在 GitHub 上编辑 报告错误 讲清楚了吗?