架构与工程深潜 · 2026-10-25

拒绝正则路由与脆弱修补:基于 Zod 单一事实源(SSOT)的 AI Agent 工具契约与自愈设计

在构建复杂的企业级 AI 音乐与多媒体创作系统时,许多工程师最常踩的一个坑,就是试图通过“提示词祈祷 + 正则表达式”去解析大模型的输出。一旦大模型多返回了一个转义字符、遗漏了某个嵌套字段或者返回了非法枚举值,下游业务流程就会直接崩溃抛出 500。在 苏诺之音(官方网站:https://www.suno.cn

进入苏诺之音官网 →
苏诺之音 AI MV 分镜编排与结构化参数列表

在构建复杂的企业级 AI 音乐与多媒体创作系统时,许多工程师最常踩的一个坑,就是试图通过“提示词祈祷 + 正则表达式”去解析大模型的输出。一旦大模型多返回了一个转义字符、遗漏了某个嵌套字段或者返回了非法枚举值,下游业务流程就会直接崩溃抛出 500。在 苏诺之音(官方网站:https://www.suno.cn/ ) 的智能创作系统与 AI MV 2.0 导演工作台 中,我们坚决废除了脆弱的文本正则解析,全面建立了以 Zod Schema 作为单一事实源(Single Source of Truth, SSOT) 的强类型工具契约与闭环自愈验证体系。

一、 为什么传统的“正则提取 + 宽松字典”必死无疑?

在 苏诺之音 的创作场景下,Agent 需要调用的工具绝非简单的“获取当前天气”,而是包含大量多模态强约束参数的重型工具:

  • 例如在分镜规划阶段,Agent 需要输出每个镜头的起始与结束时间戳(精确到毫秒)、运镜方式、角色锚点、光影风格标签、是否启用主唱口型同步以及预估的积分报价:
苏诺之音 AI MV 分镜编排与结构化参数列表
苏诺之音 AI MV 分镜编排与结构化参数列表

如果使用传统的非结构化方案,系统会面临以下三大致命漏洞:

  • 类型漂移与契约脱节:前端 TypeScript 接口、后端数据库表结构、Python 算法推理参数与 LLM Function Calling 的入参定义各写一套,任何一个字段重命名都会导致隐蔽的运行时白屏;
  • 非法枚举与越界数值无法在网关层拦截:模型可能幻觉出一个不存在的景别(如 cameraShot: "super_ultra_far")或者合成了总时长大于音频总长度的分镜切片;
  • 缺乏自动纠错闭环:发生校验错误后,直接把异常抛给前端用户,导致用户面对冰冷的“系统内部错误”手足无措。

二、 Zod 作为单一事实源(SSOT)的契约设计

在苏诺之音的技术底座中,同一份 Zod Schema 贯穿了“LLM 工具入参定义 → 运行时网关静态拦截 → TypeScript 类型推导 → 前端表单联动”全生命周期:

苏诺之音四层 Agent 架构中的 Zod 契约枢纽
苏诺之音四层 Agent 架构中的 Zod 契约枢纽

以下为苏诺之音 MV 分镜规划工具的核心 Schema 定义示例:

import { z } from 'zod';

// 严格受控的景别与运镜枚举契约
export const CameraShotTypeSchema = z.enum([
  'EXTREME_WIDE', // 大远景
  'WIDE_SHOT',    // 全景
  'MEDIUM_SHOT',  // 中景
  'CLOSE_UP',     // 特写
  'EXTREME_CLOSE' // 大特写
]);

export const CameraMovementSchema = z.enum([
  'STATIC',       // 静止固定机位
  'PAN_SLOW',     // 慢速平摇
  'PUSH_IN',      // 缓慢推镜
  'PULL_OUT',     // 缓慢拉出
  'ORBIT_360',    // 环绕运镜
]);

// 单个分镜切片的强校验契约
export const ShotPlanItemSchema = z.object({
  shotIndex: z.number().int().min(1).max(50),
  startSec: z.number().nonnegative(),
  endSec: z.number().positive(),
  lyricSnippet: z.string().default(''),
  visualDescription: z.string().min(10, '画面描述不得少于10个字').max(300),
  shotType: CameraShotTypeSchema,
  cameraMovement: CameraMovementSchema,
  characterIds: z.array(z.string()).default([]),
  enableLipSync: z.boolean().default(false),
}).refine(data => data.endSec > data.startSec, {
  message: '分镜结束时间必须严格大于开始时间',
  path: ['endSec'],
});

// 从 Zod Schema 自动推导权威 TypeScript 类型,杜绝任何手动重复定义
export type ShotPlanItem = z.infer<typeof ShotPlanItemSchema>;

三、 基于反射循环(Reflection Loop)的工具入参自愈机制

即使在 System Prompt 中提供了详尽的 Schema 说明,当面对极端复杂的业务指令时,模型仍有约 1%~2% 的概率输出格式轻微瑕疵的参数。

苏诺之音没有在网关层粗暴地直接抛出 500 报错,而是实现了一套双步闭环自愈中间件(Self-Healing Middleware):

  • 第一步:确定性格式修复(Deterministic Sanitizer)
  • 自动清除包裹在 JSON 外部的多余 Markdown 语法标记(如 `json );
  • 对单数字串(如 "12")做安全的数值类型强转;
  • 对未闭合的末尾括号做轻量级安全截断。
  • 第二步:Zod 结构化错误回传与模型单轮自愈(Feedback Reflection)
  • 若第一步修复后依然无法通过 schema.safeParse,中间件会提取 Zod 的详细错误路径(error.issues),格式化为紧凑的修正引导信息回传给模型:
  • 核心反馈模板如下:

Tool call "planMvStoryboards" failed schema validation: Path: shots[3].endSec -> 分镜结束时间必须严格大于开始时间 (received startSec: 15.2, endSec: 14.8) Please rectify only the invalid fields and re-emit the tool call.

  • 模型在接收到高指向性的 Zod 报错后,能够在 1 秒内以极高成功率(>99.6%)输出正确修正的参数,实现对用户的完全静默自愈。
进入苏诺之音(www.suno.cn),立即开始创作 →