response-format.js
1.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* responseFormat(structured output)归一纯函数 —— 自 base.js 提取的职责单一模块。
*
* 契约:入站 responseFormat 只有两种归一形态,入口一次判别、内部信任:
* { type:'json_object' } —— 要求返回合法 JSON,无 schema 约束。
* { type:'json_schema', schema, name? } —— 按 schema 约束的结构化输出。
* 各 provider 只声明「支持哪种归一 type → 怎么落地」的分派表(responseFormatHandlers),
* 不再各写 if-else;不支持的 type 由 base 统一 badRequest。
*/
import { LLMError } from './errors.js'
/**
* 把入站 responseFormat 归一为两种单一形态之一。
* 归一规则(MECE):显式 json_object → json_object;否则凡带 schema(或显式 json_schema)→ json_schema;
* 其余无法表达的形态在此一次性 badRequest(杜绝静默忽略)。
* @param {{ type?:string, name?:string, schema?:object }} rf 已非空的入站 responseFormat。
* @param {string} provider
* @returns {{ type:'json_object' } | { type:'json_schema', schema:object, name?:string }}
*/
export function normalizeResponseFormat(rf, provider) {
if (rf.type === 'json_object') return { type: 'json_object' }
if (rf.type === 'json_schema' || rf.schema != null) {
if (rf.schema == null) {
throw new LLMError({
provider,
reason: 'badRequest',
retryable: false,
message: `[${provider}] responseFormat json_schema requires a 'schema'`,
})
}
/** @type {{ type:'json_schema', schema:object, name?:string }} */
const out = { type: 'json_schema', schema: rf.schema }
if (rf.name != null) out.name = rf.name
return out
}
throw new LLMError({
provider,
reason: 'badRequest',
retryable: false,
message: `[${provider}] unrecognized responseFormat (expected json_object or json_schema)`,
})
}