TypeScript 服务端实现审批流时 Structured Outputs 该怎么封装

TypeScript 服务端实现审批流时 Structured Outputs 该怎么封装

作者:Joshua Lee发布时间:2026-06-05 13:17阅读时长:21 分钟阅读次数:3
常见问答
Q
在 TypeScript 服务端里接入 Structured Outputs,怎样设计封装层才方便在审批流场景复用?

我想在审批流服务里统一接入 Structured Outputs,但不同节点的字段结构、校验规则和返回结果都不一样。如果直接散落在各个接口里,后期维护会很麻烦。应该怎样封装,才能兼顾通用性、可读性和扩展性?

A

把 Structured Outputs 抽成“schema + 解析 + 业务映射”三层

在审批流场景里,建议把 Structured Outputs 封装成一个独立能力层,而不是直接写在业务代码中。可以按“schema 定义层、调用解析层、业务映射层”来拆分。

schema 定义层负责描述每个审批节点需要的结构,比如申请单信息、审批意见、风险标记等;调用解析层负责把模型输出约束到指定结构,并统一处理解析失败、字段缺失、类型不符等情况;业务映射层负责把标准化结果转换成审批流里的节点动作、状态变更或工单字段。

这样做的好处是,不同审批节点只需要替换 schema 配置,不必重复写解析逻辑。你还可以把常见能力抽成通用函数,比如 schema 注册、结果校验、异常包装、日志埋点等。对于复杂审批流,建议再加一层“节点适配器”,让每个节点只关心自己的输入输出,而不是直接依赖模型响应细节。

Q
审批流里如果要让模型返回固定字段,TypeScript 侧怎么做类型安全校验?

审批流接口经常要求模型输出固定字段,比如审批结论、原因、风险等级、补充说明等。由于是服务端调用,我希望 TypeScript 能在编译期和运行时都尽量减少错误。Structured Outputs 这部分应该怎么和类型系统结合?

A

用 Zod 或类似 Schema 同步约束编译期与运行时

在 TypeScript 服务端里,最稳妥的方式是让 schema 同时承担“类型来源”和“运行时校验”两种职责。常见做法是使用 Zod、Valibot 这类库来定义结构,再从 schema 推导 TypeScript 类型。

审批流里可以把每个节点的输出结构抽成独立 schema,例如“通过/驳回/转人工”三类结果分别定义不同字段。模型返回后,不要直接信任原始字符串,而是先经过 schema parse,再进入业务逻辑。这样能把类型错误、字段遗漏、枚举值不合法等问题尽量拦在服务层。

如果你的审批流存在多种节点模板,可以用泛型封装一个统一函数,让调用方传入 schema 和 prompt 配置,函数内部负责调用模型、校验结构、返回强类型结果。这样既能保持代码整洁,也能避免每个审批节点单独写一套校验逻辑。

Q
当 Structured Outputs 在审批流中返回不完整或不合法数据时,服务端应如何兜底处理?

审批流对稳定性要求很高,模型偶尔会返回缺字段、格式不对、枚举不匹配的结果。如果直接报错,可能会卡住整个审批链路。遇到这种情况,服务端应该怎么设计兜底策略,既保证流程不中断,又不影响审批结果的可靠性?

A

把失败结果标准化,交给重试、降级和人工介入

审批流场景下,Structured Outputs 的失败处理不能只靠简单抛异常,而要设计成标准化的兜底链路。建议把所有解析失败统一包装成一种业务错误对象,明确记录失败原因、原始响应、节点编号和重试次数。

对于轻微问题,比如字段缺失或格式偏差,可以做一次受控重试,并在重试时附带更明确的结构约束。对于持续失败的情况,可以切换到降级路径,例如使用规则引擎给出保守结论,或把任务转入人工复核队列。这样可以避免因为模型输出不合规而阻塞整个审批流。

还可以增加结果置信标记,把模型输出是否可直接执行、是否需要人工确认写进统一结果结构。审批流引擎只消费标准化后的状态,不直接依赖模型原始文本,这样系统会更稳,也更容易排查问题。

Q
在多节点审批流中,Structured Outputs 应该按单个节点封装,还是做成统一管道?

我的审批流里有多个节点,每个节点的目标不同,有的负责抽取信息,有的负责判断风险,有的负责生成审批意见。Structured Outputs 到底应该在每个节点单独封装,还是做成一个统一的处理管道,哪种更适合长期维护?

A

节点差异大时适合分层封装,公共能力集中到管道

如果审批流节点之间差异较大,更推荐采用“节点级封装 + 公共管道”的混合方案。也就是,每个节点维护自己的输出 schema、提示词和业务规则,而调用模型、结构校验、错误处理、日志记录等通用能力放在统一管道里。

这样做能避免把所有审批节点强行塞进一个大而全的封装中。因为抽取类节点、判断类节点、生成类节点的结构要求往往不一样,统一抽象过度会降低可维护性。节点级封装能让每个模块清晰表达自己的目标,公共管道则负责标准化执行流程。

如果某些节点模板高度相似,比如都输出“结论 + 理由 + 风险项”,你可以再抽出一个更上层的通用节点工厂,减少重复代码。整体思路是让“变化部分靠近节点,稳定部分集中管理”,这样审批流扩展起来会更顺手。

* 文章含AI生成内容