让模型输出可落地:结构化结果的校验、重试与降级实践

简介: 模型输出需从“可读”升级为“可编程”。本文提出四层防护机制(请求约束、语法解析、结构校验、业务判定),结合Pydantic Schema定义契约,实现JSON序列化、结构与业务三层校验,并规范可控重试、幂等处理与人工降级路径,确保LLM输出真正可靠地融入生产系统。(239字)

在模型应用的早期阶段,把自然语言回答显示在页面上通常已经足够。但一旦模型参与邮件分类、工单分派、内容审核、数据抽取或自动化编排,输出就不再只是给人阅读的文本,而是下游程序要直接消费的数据。

这时,最常见的问题并不是模型完全没有理解任务,而是结果不满足程序约定:字段缺失、枚举值拼写不一致、数字被包装成字符串、JSON 外混入解释文字,或者模型返回了语法正确但业务上不允许的内容。仅靠提示词要求“请严格输出 JSON”并不能形成可靠的接口契约。

更稳妥的做法是把模型调用看作一个不完全可靠的外部服务,在边界建立四层保护:请求约束、语法解析、结构校验和业务判定。校验失败时只进行有限重试;仍然失败,则进入明确的人工复核或规则降级路径。

核心原理

结构化输出包含三个不同层次,不能混为一谈。

  1. 序列化正确:响应可以被 JSON 解析器读取。
  2. 结构正确:字段类型、必填项、数组元素和枚举值符合 Schema。
  3. 业务正确:例如分类结果与邮件内容相符,置信度不能替代证据,敏感操作还要经过人工审批。

JSON Schema 主要解决第二层问题。它能描述对象属性、字段类型、必填字段以及取值范围,但不能证明模型的结论真实,也不能替代权限检查和业务规则。因此,应用应当先解析,再用 Schema 校验,最后执行业务规则。

重试也需要有边界。语法错误或字段缺失通常适合让模型按照错误信息重新生成;认证失败、请求被拒绝、配额耗尽或服务不可用,则应根据错误类型采用退避、切换供应商或直接降级。无条件重试会放大延迟、费用和重复副作用。

在 API 接入层,可以使用 HaerAPI 作为一种待评估的模型接口来源,但实际请求格式、兼容范围、可用模型和错误语义必须以其当前文档为准。

设计一个可验证契约

下面以“工单分类”为例。分类服务只允许返回三个类别,并要求给出简短理由和 0 到 1 之间的置信度。示例中的模型地址和密钥均通过环境变量提供,未假定某个供应商一定支持特定的结构化输出参数。

建议先定义一个与业务无关的稳定数据模型:

from pydantic import BaseModel, Field
from typing import Literal

class TicketResult(BaseModel):
    category: Literal["billing", "technical", "other"]
    confidence: float = Field(ge=0.0, le=1.0)
    reason: str = Field(min_length=1, max_length=300)

schema = TicketResult.model_json_schema()

这里的 Literal 限制枚举值,Field 限制数值和文本边界。Schema 应该由代码模型生成,而不是在多个文件里手工维护,否则字段变更容易只改了一处。

如果使用的模型 API 支持 JSON Schema 或工具调用,应在请求中传入该契约;如果只支持普通文本生成,则应把 Schema 的关键约束写入提示词,并把本地校验视为必经步骤。两种方式都不能省略服务端校验。

可执行实现

以下代码使用 Python 标准库完成 HTTP 请求,用 Pydantic 做结果校验。接口路径、请求字段和响应字段采用常见的 OpenAI 兼容形态仅作示例;部署前必须按照实际 API 文档调整。

import json
import os
import time
from urllib.request import Request, urlopen
from urllib.error import HTTPError, URLError
from pydantic import ValidationError

API_BASE = os.environ["MODEL_API_BASE"].rstrip("/")
API_KEY = os.environ["MODEL_API_KEY"]
MODEL = os.environ["MODEL_NAME"]

SYSTEM = """你是工单分类器。只返回 JSON 对象,不要输出 Markdown 或额外解释。
category 只能是 billing、technical、other;confidence 是 0 到 1 的数字;
reason 是不超过 300 字的分类依据。"""

def call_model(ticket: str, repair: str = "") -> dict:
    payload = {
        "model": MODEL,
        "temperature": 0,
        "messages": [
            {"role": "system", "content": SYSTEM},
            {"role": "user", "content": f"工单内容:{ticket}\n{repair}"}
        ]
    }
    request = Request(
        f"{API_BASE}/chat/completions",
        data=json.dumps(payload).encode("utf-8"),
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json"
        },
        method="POST"
    )
    with urlopen(request, timeout=30) as response:
        body = json.loads(response.read().decode("utf-8"))
    content = body["choices"][0]["message"]["content"]
    return json.loads(content)

def classify(ticket: str) -> TicketResult | None:
    repair = ""
    for attempt in range(2):
        try:
            raw = call_model(ticket, repair)
            result = TicketResult.model_validate(raw)
            if result.category == "other" and result.confidence > 0.9:
                # 示例业务规则:高置信度的兜底分类需要人工确认
                return None
            return result
        except (json.JSONDecodeError, ValidationError) as exc:
            repair = (
                "上一次结果未通过校验。只修复格式和字段约束,"
                f"不要增加字段。校验错误摘要:{str(exc)[:500]}"
            )
            time.sleep(0.5 * (attempt + 1))
        except (HTTPError, URLError, TimeoutError):
            break
    return None

result = classify("本月账单重复扣款,请核对并退款")
if result is None:
    print("进入人工复核或规则队列")
else:
    print(result.model_dump_json())

安装依赖并设置环境变量:

python -m pip install pydantic
export MODEL_API_BASE="https://example.invalid/v1"
export MODEL_API_KEY="replace-with-an-environment-secret"
export MODEL_NAME="replace-with-a-documented-model"
python app.py

示例中的地址、模型名和密钥只是占位符。不要把密钥写入源代码、镜像层、前端代码或日志;生产环境还应使用密钥管理系统,并限制出站请求的目标范围。

让重试真正可控

第一,按错误类型分类。解析失败和 Schema 失败可以重试一次;超时是否重试要结合请求是否已经在服务端执行;认证错误不应重试;限流错误可根据响应提供的等待时间退避。实际错误码和响应头要以服务文档为准。

第二,重试提示词只携带必要的错误摘要。不要把完整响应、用户隐私或内部堆栈原样发回模型。错误信息也应截断长度,避免修复请求反而消耗大量上下文。

第三,处理重复副作用。分类本身通常是幂等的,但“模型判断后自动退款”“自动发送邮件”等动作不是。应给每个业务请求建立唯一 request_id,把模型结果和动作状态持久化,在执行动作前检查幂等键,并让高风险动作经过人工审批。

第四,记录可审计字段:请求 ID、模型标识、Schema 版本、校验结果、重试次数、耗时、降级原因和脱敏后的输入摘要。不要默认记录完整的用户内容,日志留存期限也应符合组织的数据政策。

常见问题

只使用正则表达式提取 JSON 可以吗? 不建议作为主方案。模型可能输出嵌套对象、转义字符或多个代码片段,正则很容易误截断。应优先使用 JSON 解析器,再进行 Schema 校验。

temperature=0 是否保证结果完全一致? 不能据此承诺完全一致。采样参数只是影响因素之一,模型服务、请求并发和后端实现也可能影响结果。因此仍需校验、幂等和降级。

Schema 校验通过就能自动执行吗? 不能。通过只说明形状和部分范围符合约定,仍要检查权限、资源状态、业务规则、敏感信息和人工审批条件。

为什么不无限重试? 因为失败可能来自服务不可用、契约不匹配或输入本身无法判定。无限重试会造成延迟和成本不可控,还可能重复触发外部动作。生产系统应设置最大次数、总超时和熔断策略。

模型不支持原生结构化输出怎么办? 可以使用严格提示词加本地解析校验,但可靠性取决于模型和任务复杂度。对高风险流程,应增加规则抽取、人工复核或改用明确支持结构化约束的接口,并在上线前用真实脱敏样本验证。

总结

模型输出要进入软件系统,关键不是把提示词写得更长,而是建立可验证的边界:用数据模型定义契约,用解析器处理语法,用 Schema 检查结构,用业务规则判断是否允许执行,再用有限重试、幂等和降级保证链路可恢复。

这套方法也让模型供应商更容易替换。应用只依赖内部统一的数据模型和错误语义,具体 API 的请求格式、模型能力和限流策略集中在适配层处理。最终,模型负责生成候选结果,系统负责验证、授权、记录和决定是否执行。

相关文章
|
4天前
|
存储 弹性计算 缓存
阿里云服务器租赁费用:新版租赁收费标准及活动报价参考
本文更新了2026年阿里云全系列云服务器租赁活动报价,所有特惠资源均可前往阿里云活动中心选购,整体覆盖从个人入门到企业级高性能场景的全梯度需求。其中轻量应用服务器主打极致性价比,2核2G峰值200M带宽配置每日10点、15点限时抢购价仅38元/年,2核4G配置379元/年起;高性价比的经济型e实例、通用算力型u2i实例覆盖2核4G至4核32G全档位,适配开发测试与中小型企业业务;搭载英特尔至强6处理器的第九代c9i企业级实例算力较上代提升20%,支撑高并发生产环境,不同实例规格价差清晰,用户可根据自身业务负载与预算灵活选型。
1511 110
|
11天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1936 8
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
5天前
|
人工智能 程序员 API
Codex 接入 DeepSeek-V4-Flash:还能补上识图,提供两套方案
Codex 接入 DeepSeek-V4-Flash 怎么配?本文覆盖 CLI 与桌面端,再用 qwen3-vl-flash 补识图,两套方案可直接照做
|
5天前
|
编解码 人工智能 安全
2核4G/4核8G/8核16G阿里云服务器如何选择实例?经济型e、通用算力型u2i与计算型c9i选哪个?
本文介绍了阿里云2核4G、4核8G、8核16G三档主流配置下经济型e、通用算力型u2i和计算型c9i三种实例的最新活动价格与适用场景。同配置下三者价差显著,以2核4G为例,经济型e低至599.93元/年,计算型c9i则高达1742.08元/年。文章详细解析了各实例的性能定位:经济型e适合轻负载入门场景,u2i兼顾稳定算力与性价比,c9i凭借第9代至强处理器与芯片级安全能力支撑高性能业务。同时提示用户可叠加满减优惠券享受折上折,建议根据业务负载与预算综合决策。
518 112
|
9天前
|
存储 人工智能 关系型数据库
阿里云AI产品与云产品最新组合套餐:Token Plan、AI coding及云服务器和建站等组合优惠价
阿里云推出全新“算力+模型+应用”一站式云与AI组合套餐活动,覆盖从个人开发者到中大型企业的全场景需求。核心亮点为分三档定价的Token Plan订阅服务,支持Qwen3.8-Max-Preview大模型调用,错峰时段最低可享0.2折优惠。活动同步推出AI Coding、智能体部署、云电脑托管、0代码建站等十余类场景化组合,搭配99元/年的普惠云服务器、88元/年的入门数据库等经典特惠产品,还为企业提供1V1定制化AI转型方案,大幅降低了不同用户群体拥抱AI的技术门槛与采购成本。
710 111
|
17天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
2339 3
|
19天前
|
人工智能 JSON 安全
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
阿里云AI安全产品联动防御Fastjson攻击
2619 13
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
|
6天前
Qoder 一周年 × Qwen3.8-Max 正式上线,多重好礼限时领
8月3日,Qwen3.8-Max 正式上线Qoder,迎来Qoder一周年。新老用户可领800次免费调用,下单再赠2000次;夜间(22:00–08:00)调用5折;邀请好友双方得积分与调用额度。
375 0
|
5天前
|
人工智能 JSON Shell
2026AI漫剧本地全开源方案(附各个软件模型链接),8G显卡也能流畅运行
这是一套完全本地化部署的AI漫剧生成技术链路:涵盖LLM剧本分镜生成、FLUX文生图(IP-Adapter人脸锁定)、StoryDiffusion时序连贯控制、LTX-2.3唇形同步视频生成,及ComfyUI全流程调度。零云端费用,仅耗硬件算力,单集2–4小时可产出竖屏短视频,适配抖音/B站分发。