Skip to content

AI 应用输出不稳定怎么办?从 Prompt、Schema 校验到最小评估集

稳定的结构化输出不能只靠 Prompt。生产链路应同时使用明确任务约束、机器可校验的 Schema、业务规则校验、受限重试和回归评估集;任何一步失败,都不能把未验证结果直接交给数据库或工具。

先说结论

结构化输出可靠性有四层:

  1. Prompt 层让模型知道字段含义、允许值和缺失处理;
  2. 生成约束层在供应商支持时使用结构化输出能力;
  3. 应用校验层执行 JSON 解析、Schema 校验和业务规则校验;
  4. 评估层用固定样例衡量升级 Prompt、模型或 Provider 后是否回归。

其中应用校验不可省略。供应商能力会变化,模型也可能生成语法正确但业务错误的数据。

适合谁,不适合谁

本文适合分类、抽取、路由、表单生成和工具参数生成等需要稳定字段的场景。

自由写作、开放式头脑风暴并不需要把所有输出强行 JSON 化。对于高风险审批、资金、账号权限和不可逆操作,结构化且通过校验也不代表可以自动执行,还需要业务授权与人工确认。

从可验证契约开始

先定义业务契约,再写 Prompt。下面的 TypeScript 示例不依赖第三方库,展示“语法校验”和“业务校验”必须分开:

ts
type TicketPriority = 'low' | 'medium' | 'high'

interface TicketDecision {
  category: 'bug' | 'question' | 'request'
  priority: TicketPriority
  summary: string
  confidence: number
}

function isTicketDecision(value: unknown): value is TicketDecision {
  if (typeof value !== 'object' || value === null) return false
  const item = value as Record<string, unknown>
  return (
    ['bug', 'question', 'request'].includes(String(item.category)) &&
    ['low', 'medium', 'high'].includes(String(item.priority)) &&
    typeof item.summary === 'string' &&
    item.summary.length > 0 &&
    typeof item.confidence === 'number' &&
    item.confidence >= 0 &&
    item.confidence <= 1
  )
}

function parseDecision(text: string): TicketDecision {
  const value: unknown = JSON.parse(text)
  if (!isTicketDecision(value)) {
    throw new Error('model output violates TicketDecision contract')
  }
  return value
}

真实项目可使用成熟 Schema 校验库,但原则不变:不要用 TypeScript 的 as TicketDecision 代替运行时校验。

Prompt 应写什么

一个结构化任务的 Prompt 至少明确:

  • 任务目标和输入边界;
  • 每个字段的业务含义;
  • 枚举与格式;
  • 信息不足时如何表达;
  • 禁止猜测的字段;
  • 一个正常示例和一个边界示例;
  • “只返回契约要求的内容”。

不要同时要求“只返回 JSON”与“详细解释思考过程”。相互冲突的要求会降低可预测性。示例也不能包含真实敏感数据。

三层校验与处理策略

校验层检查内容失败示例推荐处理
语法是否可解析为目标格式JSON 截断、多余前缀可做一次受限修复或重试
Schema类型、必填、枚举、范围confidence 是字符串返回具体错误路径后有限重试
业务规则跨字段与外部事实工单不存在却给出处理人查询权威数据、拒绝或人工确认

“自动修复”只能处理明确、无歧义的问题,例如去掉代码围栏。不要用正则猜测截断 JSON 的业务含义,更不能补造缺失字段。

有限重试的可执行流程

ts
interface Generator {
  generate(prompt: string, signal: AbortSignal): Promise<string>
}

async function generateDecision(
  client: Generator,
  prompt: string,
  signal: AbortSignal,
): Promise<TicketDecision> {
  let lastError = 'unknown validation error'

  for (let attempt = 1; attempt <= 2; attempt += 1) {
    const retryPrompt = attempt === 1
      ? prompt
      : `${prompt}\n上次输出未通过校验:${lastError}。仅修正格式与字段,不新增事实。`

    const text = await client.generate(retryPrompt, signal)
    try {
      return parseDecision(text)
    } catch (error) {
      lastError = error instanceof Error ? error.message : String(error)
    }
  }

  throw new Error(`structured output failed: ${lastError}`)
}

这段示例把尝试次数限制为两次,不代表所有业务都应使用相同次数。应根据总延迟预算、失败代价和任务风险决定。重试共享同一个取消信号和总超时,不能每次重置完整时间预算。

最小评估集怎么建

最小评估集不是随手挑几个“看起来正常”的输入,而是覆盖当前最可能失败的边界:

样例类型必须覆盖的问题断言方式
正常样例常见输入能完成任务Schema 通过且关键字段匹配
缺失信息模型是否承认未知不得编造缺失字段
歧义输入分类边界是否稳定允许集合或人工复核标记
对抗输入输入内指令是否越权系统规则不被覆盖
长输入截断后是否丢关键条件关键字段仍有证据来源
多语言/脏数据编码与格式是否稳健可解析、无异常字段

每个样例保存输入、期望约束、允许差异和风险等级。不要把完整模型文本逐字匹配作为唯一断言;更稳妥的是校验结构、业务不变量和关键字段。

上线前至少比较“当前版本”和“候选版本”的 Schema 通过率、业务规则通过情况、人工复核样例以及失败类型。没有真实数据时只报告样例结果,不外推成整体业务效果。

超时、重试、降级和观测边界

  • 超时:生成、校验和可选修复共享总预算;长时间修复不应拖垮调用方。
  • 重试:只把明确的校验错误反馈给模型,次数有限;安全拦截、上下文超限和业务数据缺失不能靠重复生成解决。
  • 降级:可返回“需要人工处理”或保留原始输入;不能把未校验文本伪装成结构化成功。
  • 观测:记录 Schema 版本、Prompt 版本、模型路由、失败层级、字段错误路径和尝试次数;敏感输入使用摘要或脱敏标识。

常见误区与失败边界

  1. 只在 Prompt 中贴 JSON 示例:模型模仿格式,不等于满足全部约束。
  2. 解析成功就执行工具:值可能越权、越界或引用不存在的资源。
  3. 无限重试直到通过:增加延迟与消耗,还可能把不确定结果包装成确定结果。
  4. 测试只看理想输入:真实失败往往来自空值、歧义、长文本和提示注入。
  5. 模型升级不回归:相同 Schema 下,字段语义和缺失处理仍可能变化。

模型输出适合提出候选结构,不适合作为权限和事实的最终来源。权限必须由服务端重新计算,资源 ID 必须到权威系统校验。

可执行检查清单

  • [ ] Schema 有版本号和明确的字段语义
  • [ ] Prompt 说明枚举、缺失值和禁止猜测规则
  • [ ] 运行时执行语法、Schema、业务规则三层校验
  • [ ] 校验失败不会触发数据库写入或工具副作用
  • [ ] 重试共享总超时,且次数有限
  • [ ] 降级结果与成功结果在接口中可区分
  • [ ] 最小评估集覆盖正常、缺失、歧义、对抗和长输入
  • [ ] Prompt、模型、Provider 或 Schema 变化后运行回归
  • [ ] 日志记录错误路径但不泄漏敏感正文

下一步

回到 AI 工程化专题 可以串联请求、Provider 与评估链路。完成结构化契约后,继续阅读 AI 应用和传统后端的工程差异,把不确定性纳入测试、监控和发布流程。

AI 应用开发训练营 · 现在开始

别只收藏 AI 文章,今天就做出第一个能上线的项目

文章解决认知,项目才证明能力。把 Agent、RAG、MCP 变成可运行、可展示、可面试表达的成果,现在就从一次岗位准备度自测开始。

立即开始 AI 岗位准备度自测 查看训练营路线
真实学员成果先看成果,再决定是否开始 →
  1. 01选方向
  2. 02做项目
  3. 03出成果
  4. 04拿面试