kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add extractObject
rodzic
deedf06081
commit
73878c602b
|
@ -1,20 +1,25 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
import 'dotenv/config'
|
import 'dotenv/config'
|
||||||
|
|
||||||
import { createAIChain, Msg } from '@agentic/stdlib'
|
import { extractObject, Msg } from '@agentic/stdlib'
|
||||||
import { ChatModel } from '@dexaai/dexter'
|
import { ChatModel } from '@dexaai/dexter'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const chatModel = new ChatModel({
|
const chatModel = new ChatModel({
|
||||||
params: { model: 'gpt-4o', temperature: 0 },
|
params: { model: 'gpt-4o-mini', temperature: 0 },
|
||||||
debug: true
|
debug: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const chain = createAIChain({
|
const result = await extractObject({
|
||||||
chatFn: chatModel.run.bind(chatModel),
|
chatFn: chatModel.run.bind(chatModel),
|
||||||
params: {
|
params: {
|
||||||
messages: [Msg.system('Extract a JSON user object from the given text.')]
|
messages: [
|
||||||
|
Msg.system('Extract a JSON user object from the given text.'),
|
||||||
|
Msg.user(
|
||||||
|
'Bob Vance is 42 years old and lives in Brooklyn, NY. He is a software engineer.'
|
||||||
|
)
|
||||||
|
]
|
||||||
},
|
},
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
|
@ -23,9 +28,6 @@ async function main() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const result = await chain(
|
|
||||||
'Bob Vance is 42 years old and lives in Brooklyn, NY. He is a software engineer.'
|
|
||||||
)
|
|
||||||
console.log(result)
|
console.log(result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import type { SetOptional } from 'type-fest'
|
import type { SetOptional } from 'type-fest'
|
||||||
import type { ZodType } from 'zod'
|
|
||||||
import pMap from 'p-map'
|
import pMap from 'p-map'
|
||||||
|
|
||||||
import type * as types from './types.js'
|
import type * as types from './types.js'
|
||||||
|
@ -33,18 +32,7 @@ export function createAIChain<Result extends types.AIChainResult = string>({
|
||||||
maxRetries = 2,
|
maxRetries = 2,
|
||||||
toolCallConcurrency = 8,
|
toolCallConcurrency = 8,
|
||||||
injectSchemaIntoSystemMessage = true
|
injectSchemaIntoSystemMessage = true
|
||||||
}: {
|
}: types.AIChainParams<Result>): types.AIChain<Result> {
|
||||||
chatFn: types.ChatFn
|
|
||||||
params?: types.Simplify<
|
|
||||||
Partial<Omit<types.ChatParams, 'tools' | 'functions'>>
|
|
||||||
>
|
|
||||||
tools?: types.AIFunctionLike[]
|
|
||||||
schema?: ZodType<Result> | types.Schema<Result>
|
|
||||||
maxCalls?: number
|
|
||||||
maxRetries?: number
|
|
||||||
toolCallConcurrency?: number
|
|
||||||
injectSchemaIntoSystemMessage?: boolean
|
|
||||||
}): types.AIChain<Result> {
|
|
||||||
const functionSet = new AIFunctionSet(tools)
|
const functionSet = new AIFunctionSet(tools)
|
||||||
const defaultParams: Partial<types.ChatParams> | undefined =
|
const defaultParams: Partial<types.ChatParams> | undefined =
|
||||||
rawSchema && !functionSet.size
|
rawSchema && !functionSet.size
|
||||||
|
@ -67,7 +55,7 @@ export function createAIChain<Result extends types.AIChainResult = string>({
|
||||||
...chatParams,
|
...chatParams,
|
||||||
messages: [
|
messages: [
|
||||||
...(params?.messages ?? []),
|
...(params?.messages ?? []),
|
||||||
...(chatParams.messages ?? [])
|
...(chatParams?.messages ?? [])
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { zodToJsonSchema } from './zod-to-json-schema.js'
|
||||||
* The `spec` property of the returned function is the spec for adding the
|
* The `spec` property of the returned function is the spec for adding the
|
||||||
* function to the OpenAI API `functions` property.
|
* function to the OpenAI API `functions` property.
|
||||||
*/
|
*/
|
||||||
export function createAIFunction<InputSchema extends z.ZodObject<any>, Return>(
|
export function createAIFunction<InputSchema extends z.ZodObject<any>, Output>(
|
||||||
spec: {
|
spec: {
|
||||||
/** Name of the function. */
|
/** Name of the function. */
|
||||||
name: string
|
name: string
|
||||||
|
@ -24,8 +24,8 @@ export function createAIFunction<InputSchema extends z.ZodObject<any>, Return>(
|
||||||
inputSchema: InputSchema
|
inputSchema: InputSchema
|
||||||
},
|
},
|
||||||
/** Implementation of the function to call with the parsed arguments. */
|
/** Implementation of the function to call with the parsed arguments. */
|
||||||
implementation: (params: z.infer<InputSchema>) => types.MaybePromise<Return>
|
implementation: (params: z.infer<InputSchema>) => types.MaybePromise<Output>
|
||||||
): types.AIFunction<InputSchema, Return> {
|
): types.AIFunction<InputSchema, Output> {
|
||||||
assert(spec.name, 'createAIFunction missing required "spec.name"')
|
assert(spec.name, 'createAIFunction missing required "spec.name"')
|
||||||
assert(
|
assert(
|
||||||
spec.inputSchema,
|
spec.inputSchema,
|
||||||
|
@ -52,7 +52,7 @@ export function createAIFunction<InputSchema extends z.ZodObject<any>, Return>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the implementation function with the parsed arguments.
|
// Call the implementation function with the parsed arguments.
|
||||||
const aiFunction: types.AIFunction<InputSchema, Return> = (
|
const aiFunction: types.AIFunction<InputSchema, Output> = (
|
||||||
input: string | types.Msg
|
input: string | types.Msg
|
||||||
) => {
|
) => {
|
||||||
const parsedInput = parseInput(input)
|
const parsedInput = parseInput(input)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import type * as types from './types.js'
|
||||||
|
import { createAIChain } from './create-ai-chain.js'
|
||||||
|
|
||||||
|
export function extractObject<Result extends types.AIChainResult = string>(
|
||||||
|
args: types.ExtractObjectParams<Result>
|
||||||
|
): Promise<Result> {
|
||||||
|
const chain = createAIChain(args)
|
||||||
|
return chain()
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ export * from './ai-function-set.js'
|
||||||
export * from './create-ai-chain.js'
|
export * from './create-ai-chain.js'
|
||||||
export * from './create-ai-function.js'
|
export * from './create-ai-function.js'
|
||||||
export * from './errors.js'
|
export * from './errors.js'
|
||||||
|
export * from './extract-object.js'
|
||||||
export * from './fns.js'
|
export * from './fns.js'
|
||||||
export * from './message.js'
|
export * from './message.js'
|
||||||
export * from './parse-structured-output.js'
|
export * from './parse-structured-output.js'
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import type { Jsonifiable, SetOptional, Simplify } from 'type-fest'
|
import type { Jsonifiable, SetOptional, SetRequired, Simplify } from 'type-fest'
|
||||||
import type { z } from 'zod'
|
import type { z } from 'zod'
|
||||||
|
|
||||||
import type { AIFunctionSet } from './ai-function-set.js'
|
import type { AIFunctionSet } from './ai-function-set.js'
|
||||||
import type { AIFunctionsProvider } from './fns.js'
|
import type { AIFunctionsProvider } from './fns.js'
|
||||||
import type { Msg } from './message.js'
|
import type { Msg } from './message.js'
|
||||||
|
import type { Schema } from './schema.js'
|
||||||
|
|
||||||
export type { Msg } from './message.js'
|
export type { Msg } from './message.js'
|
||||||
export type { Schema } from './schema.js'
|
export type { Schema } from './schema.js'
|
||||||
|
@ -65,14 +66,14 @@ export type AIFunctionLike = AIFunctionsProvider | AIFunction | AIFunctionSet
|
||||||
*/
|
*/
|
||||||
export interface AIFunction<
|
export interface AIFunction<
|
||||||
InputSchema extends z.ZodObject<any> = z.ZodObject<any>,
|
InputSchema extends z.ZodObject<any> = z.ZodObject<any>,
|
||||||
Return = any
|
Output = any
|
||||||
> {
|
> {
|
||||||
/**
|
/**
|
||||||
* Invokes the underlying AI function `impl` but first validates the input
|
* Invokes the underlying AI function `impl` but first validates the input
|
||||||
* against this function's `inputSchema`. This method is callable and is
|
* against this function's `inputSchema`. This method is callable and is
|
||||||
* meant to be passed the raw LLM JSON string or an OpenAI-compatible Message.
|
* meant to be passed the raw LLM JSON string or an OpenAI-compatible Message.
|
||||||
*/
|
*/
|
||||||
(input: string | Msg): MaybePromise<Return>
|
(input: string | Msg): MaybePromise<Output>
|
||||||
|
|
||||||
/** The Zod schema for the input object. */
|
/** The Zod schema for the input object. */
|
||||||
inputSchema: InputSchema
|
inputSchema: InputSchema
|
||||||
|
@ -87,7 +88,7 @@ export interface AIFunction<
|
||||||
* The underlying function implementation without any arg parsing or validation.
|
* The underlying function implementation without any arg parsing or validation.
|
||||||
*/
|
*/
|
||||||
// TODO: this `any` shouldn't be necessary, but it is for `createAIFunction` results to be assignable to `AIFunctionLike`
|
// TODO: this `any` shouldn't be necessary, but it is for `createAIFunction` results to be assignable to `AIFunctionLike`
|
||||||
impl: (params: z.infer<InputSchema> | any) => MaybePromise<Return>
|
impl: (params: z.infer<InputSchema> | any) => MaybePromise<Output>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChatParams {
|
export interface ChatParams {
|
||||||
|
@ -124,7 +125,7 @@ export type ChatFn = (
|
||||||
export type AIChainResult = string | Record<string, any>
|
export type AIChainResult = string | Record<string, any>
|
||||||
|
|
||||||
export type AIChain<Result extends AIChainResult = string> = (
|
export type AIChain<Result extends AIChainResult = string> = (
|
||||||
params:
|
params?:
|
||||||
| string
|
| string
|
||||||
| Simplify<SetOptional<Omit<ChatParams, 'tools' | 'functions'>, 'model'>>
|
| Simplify<SetOptional<Omit<ChatParams, 'tools' | 'functions'>, 'model'>>
|
||||||
) => Promise<Result>
|
) => Promise<Result>
|
||||||
|
@ -140,3 +141,24 @@ export type SafeParseResult<TData> =
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ValidatorFn<TData> = (value: unknown) => SafeParseResult<TData>
|
export type ValidatorFn<TData> = (value: unknown) => SafeParseResult<TData>
|
||||||
|
|
||||||
|
export type AIChainParams<Result extends AIChainResult = string> = {
|
||||||
|
chatFn: ChatFn
|
||||||
|
params?: Simplify<Partial<Omit<ChatParams, 'tools' | 'functions'>>>
|
||||||
|
tools?: AIFunctionLike[]
|
||||||
|
schema?: z.ZodType<Result> | Schema<Result>
|
||||||
|
maxCalls?: number
|
||||||
|
maxRetries?: number
|
||||||
|
toolCallConcurrency?: number
|
||||||
|
injectSchemaIntoSystemMessage?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExtractObjectParams<Result extends AIChainResult = string> =
|
||||||
|
Simplify<
|
||||||
|
SetRequired<
|
||||||
|
Omit<AIChainParams<Result>, 'tools' | 'toolCallConcurrency' | 'params'>,
|
||||||
|
'schema'
|
||||||
|
> & {
|
||||||
|
params: SetRequired<Partial<ChatParams>, 'messages'>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
|
Ładowanie…
Reference in New Issue