kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: improve custom schema support in @agentic/core
rodzic
f786ca9784
commit
4abde52146
|
@ -195,14 +195,8 @@ export function createAIChain<Result extends types.AIChainResult = string>({
|
||||||
} else if (Msg.isRefusal(message)) {
|
} else if (Msg.isRefusal(message)) {
|
||||||
throw new AbortError(`Model refusal: ${message.refusal}`)
|
throw new AbortError(`Model refusal: ${message.refusal}`)
|
||||||
} else if (Msg.isAssistant(message)) {
|
} else if (Msg.isAssistant(message)) {
|
||||||
if (schema && schema.validate) {
|
if (schema) {
|
||||||
const result = schema.validate(message.content)
|
return schema.parse(message.content)
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
return result.data
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(result.error)
|
|
||||||
} else {
|
} else {
|
||||||
return message.content as Result
|
return message.content as Result
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function createAIFunction<InputSchema extends z.ZodObject<any>, Output>(
|
||||||
name: string
|
name: string
|
||||||
/** Description of the function. */
|
/** Description of the function. */
|
||||||
description?: string
|
description?: string
|
||||||
/** Zod schema for the arguments string. */
|
/** Zod schema for the function parameters. */
|
||||||
inputSchema: InputSchema
|
inputSchema: InputSchema
|
||||||
/**
|
/**
|
||||||
* Whether or not to enable structured output generation based on the given
|
* Whether or not to enable structured output generation based on the given
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { z } from 'zod'
|
import type { z } from 'zod'
|
||||||
|
|
||||||
import type * as types from './types'
|
import type * as types from './types'
|
||||||
import { safeParseStructuredOutput } from './parse-structured-output'
|
import { parseStructuredOutput } from './parse-structured-output'
|
||||||
import { stringifyForModel } from './utils'
|
import { stringifyForModel } from './utils'
|
||||||
import { zodToJsonSchema } from './zod-to-json-schema'
|
import { zodToJsonSchema } from './zod-to-json-schema'
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import { zodToJsonSchema } from './zod-to-json-schema'
|
||||||
* Used to mark schemas so we can support both Zod and custom schemas.
|
* Used to mark schemas so we can support both Zod and custom schemas.
|
||||||
*/
|
*/
|
||||||
export const schemaSymbol = Symbol('agentic.schema')
|
export const schemaSymbol = Symbol('agentic.schema')
|
||||||
export const validatorSymbol = Symbol('agentic.validator')
|
|
||||||
|
|
||||||
export type Schema<TData = unknown> = {
|
export type Schema<TData = unknown> = {
|
||||||
/**
|
/**
|
||||||
|
@ -18,10 +17,18 @@ export type Schema<TData = unknown> = {
|
||||||
readonly jsonSchema: types.JSONSchema
|
readonly jsonSchema: types.JSONSchema
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional. Validates that the structure of a value matches this schema,
|
* Parses the value, validates that it matches this schema, and returns a
|
||||||
* and returns a typed version of the value if it does.
|
* typed version of the value if it does. Throw an error if the value does
|
||||||
|
* not match the schema.
|
||||||
*/
|
*/
|
||||||
readonly validate?: types.ValidatorFn<TData>
|
readonly parse: types.ParseFn<TData>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the value, validates that it matches this schema, and returns a
|
||||||
|
* typed version of the value if it does. Returns an error message if the
|
||||||
|
* value does not match the schema, and will never throw an error.
|
||||||
|
*/
|
||||||
|
readonly safeParse: types.SafeParseFn<TData>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to mark schemas so we can support both Zod and custom schemas.
|
* Used to mark schemas so we can support both Zod and custom schemas.
|
||||||
|
@ -41,7 +48,7 @@ export function isSchema(value: unknown): value is Schema {
|
||||||
schemaSymbol in value &&
|
schemaSymbol in value &&
|
||||||
value[schemaSymbol] === true &&
|
value[schemaSymbol] === true &&
|
||||||
'jsonSchema' in value &&
|
'jsonSchema' in value &&
|
||||||
'validate' in value
|
'parse' in value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,16 +78,28 @@ export function asSchema<TData>(
|
||||||
export function createSchema<TData = unknown>(
|
export function createSchema<TData = unknown>(
|
||||||
jsonSchema: types.JSONSchema,
|
jsonSchema: types.JSONSchema,
|
||||||
{
|
{
|
||||||
validate
|
parse = (value) => value as TData,
|
||||||
|
safeParse
|
||||||
}: {
|
}: {
|
||||||
validate?: types.ValidatorFn<TData>
|
parse?: types.ParseFn<TData>
|
||||||
|
safeParse?: types.SafeParseFn<TData>
|
||||||
} = {}
|
} = {}
|
||||||
): Schema<TData> {
|
): Schema<TData> {
|
||||||
|
safeParse ??= (value: unknown) => {
|
||||||
|
try {
|
||||||
|
const result = parse(value)
|
||||||
|
return { success: true, data: result }
|
||||||
|
} catch (err: any) {
|
||||||
|
return { success: false, error: err.message ?? String(err) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[schemaSymbol]: true,
|
[schemaSymbol]: true,
|
||||||
_type: undefined as TData,
|
_type: undefined as TData,
|
||||||
jsonSchema,
|
jsonSchema,
|
||||||
validate
|
parse,
|
||||||
|
safeParse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +108,8 @@ export function createSchemaFromZodSchema<TData>(
|
||||||
opts: { strict?: boolean } = {}
|
opts: { strict?: boolean } = {}
|
||||||
): Schema<TData> {
|
): Schema<TData> {
|
||||||
return createSchema(zodToJsonSchema(zodSchema, opts), {
|
return createSchema(zodToJsonSchema(zodSchema, opts), {
|
||||||
validate: (value) => {
|
parse: (value) => {
|
||||||
return safeParseStructuredOutput(value, zodSchema)
|
return parseStructuredOutput(value, zodSchema)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,4 +196,5 @@ export type SafeParseResult<TData> =
|
||||||
error: string
|
error: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ValidatorFn<TData> = (value: unknown) => SafeParseResult<TData>
|
export type ParseFn<TData> = (value: unknown) => TData
|
||||||
|
export type SafeParseFn<TData> = (value: unknown) => SafeParseResult<TData>
|
||||||
|
|
Ładowanie…
Reference in New Issue