---
title: 提示与输出契约
url: https://doc.liz6.com/ai/02-context-and-interfaces/01-prompt-and-output-contracts
locale: zh
area: ai
tags:
- 大模型与 Agent
- 单次请求与证据
date: 2026-06-30
modified: 2026-09-10
description: 从一条模型请求开始建立工程契约：原文明确提供了什么，允许输出什么，哪些内容要继续确认？以订单表单预填为例，依次处理任务定义、缺失值、结构约束和业务验证。取得合法 JSON 之后，仍要证明字段有来源、状态允许使用。
---

# 提示与输出契约

从一条模型请求开始建立工程契约：原文明确提供了什么，允许输出什么，哪些内容要继续确认？以订单表单预填为例，依次处理任务定义、缺失值、结构约束和业务验证。取得合法 JSON 之后，仍要证明字段有来源、状态允许使用。

## 提示描述目标、输入和边界

“你是专家，请准确提取”没有定义准确的含义。一个可验证任务至少说明输入是什么、需要哪些字段、允许推断到什么程度、缺失或冲突如何处理、最终结果供谁使用。提示工程也需要先有成功标准，才能比较改动是否有效。[Prompt engineering overview](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/overview)

例如输入“想买 A1，数量稍后确认”，任务若只要求 sku 与 quantity，模型可能猜 1；明确规定未知数量为 null，并标记 needs_input，才让没有答案成为合法结果。

| 原始歧义 | 应明确的约定 |
|---|---|
| 数量没写，是否默认一件 | 不猜测，返回 null |
| 提到多个商品但字段只支持一个 | 标记歧义或改用数组，不随意选一个 |
| “下周”是哪段时间 | 指明参考日期与时区，或保留原文 |
| 来源中内容互相冲突 | 保留冲突与来源，不自选权威 |
| 输出会直接触发订单 | 提取只是候选，不自动授权执行 |

稳定规则可以放在相应的可信指令层，当前材料以来源清楚的数据提供。消息角色和内容块是接口结构，不应只把它们理解为随意拼接的文本。XML 标签、标题或分隔符有助于区分内容，但不是安全隔离；外部材料中的“忽略此前规则”仍应按数据处理。

一个教学提示可以这样组织：

```text
任务：从用户原文提取一个商品 SKU 和数量，供人工确认前的表单预填使用。
规则：只使用原文明确给出的信息；缺失字段为 null。
状态：两个字段都明确且无冲突时为 complete，否则为 needs_input。
范围：不要创建订单、查询个人资料或推断支付信息。
输出：遵守提供的 schema；不在结果前后添加说明。
用户原文：想买 A1，数量稍后确认。
```

提示中的“范围”说明模型应做什么，实际工具权限仍由执行端落实。把操作权限写成一句话，不能替代 [Agent 循环](/ai/03-agent-systems/01-agent-loop.md) 中的执行前核验。

## 用示例消除真实歧义

few-shot 示例用具体输入和输出说明约定。它适合解释 null、枚举、单位和冲突等抽象规则容易误读的地方；并非示例越多越好，也并非正例总能替代边界说明。

| 输入 | 期望核心结果 | 说明的规则 |
|---|---|---|
| 买 A1，共 3 件 | A1、3、complete | 正常提取 |
| 想买 A1，数量稍后确认 | A1、null、needs_input | 缺失不能猜 |
| A1 要 3 件，等等改成 2 件 | 需按明确的更正规则处理 | 时间顺序和改口语义 |
| 买 A1 或 B2，还未决定 | 不能随意选 SKU | 歧义需要表达 |

如果 schema 没有表达歧义的空间，示例再好也难以避免强行填值；先调整数据模型，再调整措辞。不要把开发集中的所有测试答案写进示例后，把同一批题的提升当作泛化能力。

需要多样方案时可以明确要求各方案在约束或取舍上不同；需要简短输出时直接规定篇幅与字段。temperature、effort 和篇幅要求各管不同问题，不能写成 `temperature=0 → effort=low` 的迁移公式。具体机制见 [Token 与采样](/ai/01-model-foundations/01-tokens-and-sampling.md) 与 [推理与 thinking](/ai/01-model-foundations/04-reasoning-and-verification.md)。

## 结构约束的作用范围

仅在 prompt 中要求 JSON，是让模型遵循文字约定；受约束解码则在生成时限制合法的输出延续，使完整的成功输出符合支持的 schema。客户端校验是生成之后的检查，可以补充服务不支持的约束，但不会倒过来改变已经生成的 token。

<svg viewBox="0 0 760 355" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="从生成到业务动作：每个检查解决不同问题" style="max-width:100%;height:auto" font-family="Source Han Sans CN,Microsoft YaHei,sans-serif">
<defs><marker id="output-validation-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="#64748b"></path></marker></defs>
<rect width="760" height="355" rx="12" fill="#f8fafc"></rect>


<g transform="translate(0 0)"><rect x="30" y="95" width="200" height="85" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="130.0" y="134.5" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">响应完整</text><text x="130.0" y="156.5" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">检查结束原因</text><line x1="230" y1="137" x2="275" y2="137" stroke="#64748b" stroke-width="1.8" marker-end="url(#output-validation-arrow)"></line><rect x="280" y="95" width="200" height="85" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="380.0" y="134.5" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">解析与 schema</text><text x="380.0" y="156.5" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">结构、字段、类型</text><line x1="480" y1="137" x2="525" y2="137" stroke="#64748b" stroke-width="1.8" marker-end="url(#output-validation-arrow)"></line><rect x="530" y="95" width="200" height="85" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="630.0" y="134.5" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">业务与证据</text><text x="630.0" y="156.5" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">范围、来源、权限</text><rect x="280" y="235" width="200" height="60" rx="8" fill="#e0e7ff" stroke="#c7d2fe"></rect><text x="380.0" y="262.0" font-size="15" fill="#1e293b" text-anchor="middle" font-weight="600">允许进入后续流程</text><text x="380.0" y="284.0" font-size="12" fill="#475569" text-anchor="middle" font-weight="400">仍遵守动作授权</text><line x1="630" y1="185" x2="630" y2="265" stroke="#64748b" stroke-width="1.8" marker-end="url(#output-validation-arrow)"></line><line x1="630" y1="265" x2="485" y2="265" stroke="#64748b" stroke-width="1.8" marker-end="url(#output-validation-arrow)"></line></g><text x="24" y="29" font-size="19" fill="#0f172a" text-anchor="start" font-weight="700"><tspan x="24" dy="0">从生成到业务动作：每个检查解决不同问题</tspan></text><text x="24" y="328" font-size="13" fill="#475569" text-anchor="start" font-weight="400"><tspan x="24" dy="0">合法 JSON 是必要的格式条件，不证明字段值真实，也不等于已获执行许可。</tspan></text>
</svg>

| 机制 | 约束对象 | 仍需应用检查 |
|---|---|---|
| JSON 格式要求或模式 | 可解析的 JSON 语法，能力依接口而异 | 字段、类型、语义 |
| schema 约束响应 | 最终输出的规定结构 | 完整响应、证据与业务条件 |
| 严格工具参数 | 工具选择及参数的允许结构 | 权限、资源状态、动作语义 |
| 客户端类型/业务验证 | 接收到的对象 | 后续执行时的状态变化 |

Claude 的 `output_config.format` 用于 JSON 响应，工具上的 `strict: true` 用于严格工具调用；两者可以组合，但可用 schema 子集和功能兼容范围需要按目标模型与 SDK 核对。[Structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)

### JSON Schema 本身的几个边界

`properties` 描述字段，不表示这些字段必须出现；必填由 `required` 声明。`additionalProperties: false` 拒绝未定义字段，也不会自动把已定义字段变成必填。null 是一个值，与字段不存在不同。[JSON Schema object](https://json-schema.org/understanding-json-schema/reference/object)

比如希望 quantity 字段总出现、但未知时为 null，就同时需要 required 和可空类型。把它只定义为 integer 并设为 required，会让“原文没有数量”无法得到符合预期的表达。

供应商的结构化输出可能只支持 JSON Schema 子集。某些 SDK 会将完整 schema 转成服务支持的简化形式，再在客户端按原始约束验证；这与直接发送不支持字段的原始 JSON 请求不同。不能把“SDK 能接受”解释成“服务端生成时强制了全部约束”。[SDK schema 转换说明](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)

### 合法 JSON 到可用结果，还差几关？

把 quantity 从 3 改成 5，JSON 与类型仍可通过，原文支持却失败；保持 3 而降低库存，失败又发生在业务层。图中显示每个独立判据，帮助确定应该修提示、数据模型、证据核对还是执行前条件。

**合法 JSON 到可用结果，还差几关？**

语法、schema、原文支持和业务条件是不同检查；前一层通过不会替后面作保证。


## 为非成功路径设计输出

结构化输出的保证要限定在接口支持且响应完整的路径。截断、拒绝、传输错误和取消需要独立处理，不能一律取第一个 text 块然后写进数据库。

| 情况 | 应用处理 |
|---|---|
| 正常完成 | 解析、schema 校验，再做业务核验 |
| 输出截断 | 标记未完成，保留原因；不执行半截参数 |
| 信息缺失 | 接受 schema 中的未知状态，按任务继续读取或询问 |
| 原文冲突 | 返回可定位的冲突，不自动编造一致结论 |
| 模型拒绝 | 按接口读取拒绝状态，不能伪造成正常业务数据 |
| 网络断流或超时 | 区分生成未完成与外部操作结果未知 |

客户端可以有限重试或要求修正具体字段，但每次重试都要有上限并记入成本。如果失败源于缺失信息，重复同一输入不会凭空补出事实；若此前已经执行了工具副作用，不能因为解析失败就重放整个任务。

为结构化报告保留来源，可以在自己的 schema 中携带文档 ID、证据位置和版本，再由应用验证。供应商内建 citations 是否能与某种结构输出同时使用属于具体功能兼容问题，不等于“JSON 与可追溯性不能共存”。检索证据的完整性见 [RAG](/ai/02-context-and-interfaces/03-retrieval-and-evidence.md)。

## 一个完整的本地校验例子

以下 schema 用于应用侧完整校验，不承诺目标服务能原样支持其中所有关键字。例子依赖 Python 的 `jsonschema` 包，校验正常结果、缺失结果、额外字段、错误类型和跨字段矛盾；它不调用模型，也不创建订单。

```python
from jsonschema import Draft202012Validator, ValidationError

schema = {
    "type": "object",
    "properties": {
        "sku": {"type": ["string", "null"], "minLength": 1},
        "quantity": {"type": ["integer", "null"], "minimum": 1},
        "status": {"type": "string", "enum": ["complete", "needs_input"]},
    },
    "required": ["sku", "quantity", "status"],
    "additionalProperties": False,
}
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(schema)

def check(data):
    validator.validate(data)
    fields_present = data["sku"] is not None and data["quantity"] is not None
    if (data["status"] == "complete") != fields_present:
        raise ValueError("状态与字段完整性不一致")
    return data

assert check({"sku": "A1", "quantity": 3, "status": "complete"})["quantity"] == 3
assert check({"sku": "A1", "quantity": None,
              "status": "needs_input"})["quantity"] is None
bad = [
    {"sku": "A1", "quantity": True, "status": "complete"},
    {"sku": "A1", "quantity": 0, "status": "complete"},
    {"sku": "A1", "quantity": None, "status": "complete"},
    {"sku": "A1", "status": "needs_input"},
    {"sku": "A1", "quantity": 3, "status": "complete", "extra": 1},
]
for item in bad:
    try:
        check(item)
    except (ValidationError, ValueError):
        pass
    else:
        raise AssertionError(f"错误结果被接受：{item}")
print("正常/缺失结果通过，5 类无效结果被拒绝")
```

这个简化数据模型只表达缺失，不表达多商品或冲突。如果真实任务需要这些状态，应增加相应字段和规则，而不能继续沿用 `fields_present` 作为完整性判据。例子也没有验证 SKU 是否存在、数量是否来自原文、库存是否足够；这些属于来源与业务校验。

执行动作时还要再次核验实时状态。例如提取时库存充足，提交时已经售罄，schema 不可能解决这个竞争。参数校验、业务约束与事务处理必须在对应系统里完成。

## 把提示与 schema 一起做版本管理

记录提示、schema、模型、SDK 和验证逻辑的版本。字段由可空改为必填、枚举增加新值、数组取代单对象，都可能改变下游行为；不仅要看模型输出，还要验证旧消费者如何处理新版结果。

评估集应覆盖正常输入、缺失、冲突、噪声、长输入、恶意材料和截断。分别统计结构有效率、字段准确率、未知处理是否正确，以及真正的任务成功率。若 JSON 全部合法但事实错了，继续加结构限制未必有效，应回到证据、提示与模型能力定位问题。

保留有意义的少量示例和清楚的约定，删掉相互冲突的重复要求；每次改动都用 [评估与可观测](/ai/04-evaluation-and-production/01-evaluation-and-observability.md) 中的任务级比较验证。

继续阅读：[上下文工程](/ai/02-context-and-interfaces/02-context-engineering)。
