第 1.4.3 节:把结构化输出接入校验、重试和人工复核流程
结构化输出不能只停留在口头约定,还需要落实为字段、校验和失败处理。完成本节后,你应该能够把结构化输出落成字段表、校验规则、错误处理和验收样例。
实现步骤或决策流程
Prompt(提示词)的组成
这个图提醒我们:用户输入只是 Prompt(提示词)的一部分。工程化 Prompt 还需要角色、边界、资料和输出契约。
系统角色、任务说明、上下文资料、输出格式、边界规则和示例共同组成最终 Prompt;最终 Prompt 产生模型输出,再进入结构化校验。这里的重点不是把各部分堆在一起,而是让每一项都能被后续校验和回归样例验证。
客服工作台输出契约如何落地
客服工作台里,结构化输出最好从“下一步动作”反推字段,而不是从模型想返回什么开始。
| 下一步动作 | 系统必须知道什么 | 输出字段重点 | 失败兜底 |
|---|---|---|---|
| 直接回答 | 是否有资料依据、风险是否低 | intent(意图)、risk_level(风险等级)、evidence_source(依据来源) | 无依据时不回答或转知识库检索。 |
| 追问信息 | 缺什么字段、为什么缺 | missing_fields(缺失字段)、reply(回复草稿) | 只追问必要字段,避免反复问。 |
| 查知识库 | 检索什么主题、需要哪些引用 | intent(意图)、search_query(检索问题)、evidence_source(依据来源) | 检索不到时拒答或转人工。 |
| 准备工具调用 | 调什么工具、字段是否齐全 | next_action(下一步动作)、missing_fields(缺失字段)、risk_level(风险等级) | 缺字段时不能调用工具。 |
| 创建工单或转人工 | 风险原因、摘要、用户确认状态 | risk_level(风险等级)、need_human(是否需要人工)、reply(回复草稿) | 高风险必须人工接手。 |
这套落地方式会让第 1.5 章的第一个 Agent(智能体)有稳定输入,也让第 1.6 章的工具调用不会变成“模型想调什么就调什么”。
一个坏 Prompt(提示词)
| 内容 | 问题 |
|---|---|
| 你是客服,帮我判断用户想干什么,然后回复用户。 | 任务、边界、字段、风险和下一步动作都不清楚。 |
这个 Prompt 的问题是:
- 任务不清楚。
- 输出格式不清楚。
- 意图分类不清楚。
- 不知道哪些情况要转人工。
- 不知道能不能承诺退款。
它也许能在演示里给出一个看似合理的回答,但无法稳定进入业务系统。
一个更好的 Prompt(提示词)结构
| 模块 | 应写清的内容 |
|---|---|
| 角色 | 你是售后客服意图识别助手。 |
| 任务 | 根据用户输入判断售后意图、风险等级、是否需要人工处理,并生成一句客服回复草稿。 |
| 边界 | 不承诺退款结果,不编造订单状态,投诉和威胁曝光必须转人工,缺少订单号时要求补充订单号。 |
| 输出 | 返回 intent(意图)、risk_level(风险等级)、need_human(是否需要人工)、next_action(下一步动作)、reply(回复草稿)等稳定字段。 |
这仍然只是示意,但已经从“让模型随便回答”变成“让模型按业务规则输出”。
用数据校验表达输出契约
Pydantic(数据校验库)或 JSON Schema(结构定义格式)都可以表达输出契约。本书不讲它们的语法,只讲字段应该如何设计、校验和验收。
客服意图识别输出契约
| 环节 | 需要明确的内容 | 验收方式 |
|---|---|---|
| 请求进入 | 用户问题、身份、业务对象和会话编号 | 能复现同一次请求 |
| 智能体处理 | 角色、提示词、工具、资料范围和停止条件 | 典型任务能稳定走完 |
| 工具调用 | 工具名称、权限、输入字段和失败处理 | 高风险工具需人工确认 |
| 结果返回 | 答案、依据、风险、下一步动作和拒答原因 | 前端和业务人员能理解 |
| 运行记录 | 追踪编号、耗时、模型调用、工具结果和人工确认 | 问题能追溯和复盘 |
这个模型表达了系统期望的输出结构。真实项目里还可以加入置信度、引用来源、工具建议和错误原因。
| 字段 | 含义 | 推荐取值 | 为什么需要 |
|---|---|---|---|
| intent(意图) | 用户当前问题类型 | product_question、order_status、refund_request、complaint、unknown | 决定后续走知识库、工具、工单还是人工。 |
| risk_level(风险等级) | 当前请求风险 | low、medium、high | 决定是否允许自动处理。 |
| need_human(是否需要人工) | 是否必须转人工 | true 或 false | 投诉、资金和合规场景不能全自动。 |
| missing_fields(缺失字段) | 还需要用户补什么 | order_id、product_name、contact_info | 防止 Agent 在信息不全时乱调工具。 |
| next_action(下一步动作) | 系统建议做什么 | answer、ask_followup、search_knowledge、call_tool、create_ticket、handoff | 连接第 1.5 章和第 1.6 章。 |
| reply(回复草稿) | 给用户看的回复 | 安抚、说明、追问或引导 | 前端可以直接展示或给人工修改。 |
| evidence_source(依据来源) | 回答依据 | 知识库片段、工具结果、无依据 | 防止无来源回答。 |
| error_reason(错误原因) | 输出异常时说明 | parse_failed、missing_required_field、unsafe_action | 便于兜底和复盘。 |
输出校验流程
不要默认模型输出一定符合要求。结构化输出必须经过解析和校验。
读图重点:解析和字段校验是两道独立门禁;失败可以有限重试,但绝不能绕过校验直接驱动工具或高风险动作。
模型原始输出先判断能否解析:不能时进入重试或降级;能解析后再判断字段是否有效,无效同样进入重试或降级,只有有效结果才能进入业务流程。
推荐技术流:从 Prompt(提示词)到可验收输出
| 步骤 | 做什么 | 为什么 |
|---|---|---|
| 1 | 定义业务任务 | 先确认是意图识别、答案生成、工具结果总结还是质检复盘。 |
| 2 | 列出用户输入样例 | 覆盖普通咨询、退款、投诉、缺信息、恶意输入和超范围问题。 |
| 3 | 设计输出字段 | 让后端和前端知道如何读取模型结果。 |
| 4 | 明确枚举值 | 防止模型随意创造字段值。 |
| 5 | 写清边界规则 | 例如不能承诺退款、不能编造订单、投诉必须转人工。 |
| 6 | 设计校验流程 | 解析失败、字段缺失和枚举错误都不能进入业务动作。 |
| 7 | 设计失败兜底 | 重试、降级、转人工或要求用户补充信息。 |
| 8 | 建立回归样例 | 每次修改 Prompt 后用同一批样例检查。 |
| 9 | 记录 Prompt 版本 | 方便追踪一次线上问题由哪个版本引起。 |
| 10 | 把结果接入第 1.5 章最小 Agent | 让输出字段真正驱动流程,而不是停在文档里。 |
Prompt(提示词)调试方法
1. 建立测试样例
先准备一组代表性输入:
- 普通咨询。
- 售后退款。
- 投诉。
- 信息不足。
- 恶意输入。
- 超出业务范围。
2. 固定期望输出
对每个样例写清楚预期字段。例如投诉类问题,risk_level 应为 high,need_human 应为 true。
3. 每次修改 Prompt(提示词)后回归
Prompt 一旦进入商业项目,就应该像代码一样管理版本。不能随手改完上线。
4. 记录失败案例
失败案例是 Prompt 优化最重要的资料。不要只保留成功样例。
版本与资料来源
具体结构化输出参数和 SDK(软件开发工具包)写法以后续实现章节及官方文档为准。
主要资料入口:
- OpenAI(模型服务商) Text Generation(文本生成)指南:https://developers.openai.com/api/docs/guides/text
- OpenAI(模型服务商) Function Calling(函数调用)指南:https://developers.openai.com/api/docs/guides/function-calling
- Pydantic(数据校验库)文档:https://docs.pydantic.dev/
过时风险:结构化输出、工具调用和 SDK(软件开发工具包)参数可能随模型和接口升级调整。发布前需要核对官方文档。