chatgpt-api/src/fns.ts

107 wiersze
2.5 KiB
TypeScript
Czysty Zwykły widok Historia

2024-06-02 02:11:07 +00:00
import type { z } from 'zod'
2024-05-21 13:52:06 +00:00
import type * as types from './types.js'
2024-05-24 23:55:26 +00:00
import { AIFunctionSet } from './ai-function-set.js'
2024-06-02 23:13:24 +00:00
import { createAIFunction } from './create-ai-function.js'
2024-05-24 23:55:26 +00:00
import { assert } from './utils.js'
2024-05-21 13:52:06 +00:00
2024-06-03 00:12:22 +00:00
export interface PrivateAIFunctionMetadata {
2024-06-02 02:04:13 +00:00
name: string
2024-06-02 07:30:50 +00:00
description: string
2024-06-02 02:04:13 +00:00
inputSchema: z.AnyZodObject
methodName: string
}
// Polyfill for `Symbol.metadata`
// https://github.com/microsoft/TypeScript/issues/53461
declare global {
interface SymbolConstructor {
readonly metadata: unique symbol
}
}
;(Symbol as any).metadata ??= Symbol.for('Symbol.metadata')
const _metadata = Object.create(null)
if (typeof Symbol === 'function' && Symbol.metadata) {
Object.defineProperty(globalThis, Symbol.metadata, {
enumerable: true,
configurable: true,
writable: true,
value: _metadata
})
}
export abstract class AIFunctionsProvider {
2024-05-24 23:55:26 +00:00
private _functions?: AIFunctionSet
2024-05-21 13:52:06 +00:00
2024-05-24 23:55:26 +00:00
get functions(): AIFunctionSet {
2024-05-21 13:52:06 +00:00
if (!this._functions) {
2024-05-22 08:11:36 +00:00
const metadata = this.constructor[Symbol.metadata]
2024-06-02 00:34:25 +00:00
assert(metadata)
2024-06-03 00:12:22 +00:00
const invocables =
(metadata?.invocables as PrivateAIFunctionMetadata[]) ?? []
2024-06-02 02:04:13 +00:00
// console.log({ metadata, invocables })
2024-05-22 08:11:36 +00:00
2024-05-24 23:55:26 +00:00
const aiFunctions = invocables.map((invocable) => {
2024-06-02 23:13:24 +00:00
const impl = (this as any)[invocable.methodName]
2024-05-24 23:55:26 +00:00
assert(impl)
return createAIFunction(invocable, impl)
})
2024-05-22 08:11:36 +00:00
2024-05-24 23:55:26 +00:00
this._functions = new AIFunctionSet(aiFunctions)
2024-05-21 13:52:06 +00:00
}
return this._functions
}
}
2024-05-22 08:11:36 +00:00
export function aiFunction<
2024-06-03 08:46:05 +00:00
This extends AIFunctionsProvider,
2024-05-24 23:55:26 +00:00
InputSchema extends z.SomeZodObject,
OptionalArgs extends Array<undefined>,
Return extends types.MaybePromise<any>
2024-05-22 08:11:36 +00:00
>({
2024-05-21 13:52:06 +00:00
name,
description,
inputSchema
}: {
name?: string
2024-06-02 07:30:50 +00:00
description: string
2024-05-24 23:55:26 +00:00
inputSchema: InputSchema
2024-05-21 13:52:06 +00:00
}) {
2024-05-22 08:11:36 +00:00
return (
2024-05-24 23:55:26 +00:00
_targetMethod: (
this: This,
input: z.infer<InputSchema>,
...optionalArgs: OptionalArgs
) => Return,
2024-05-22 08:11:36 +00:00
context: ClassMethodDecoratorContext<
This,
2024-05-24 23:55:26 +00:00
(
this: This,
input: z.infer<InputSchema>,
...optionalArgs: OptionalArgs
) => Return
2024-05-23 23:19:38 +00:00
>
2024-05-22 08:11:36 +00:00
) => {
const methodName = String(context.name)
if (!context.metadata.invocables) {
context.metadata.invocables = []
}
2024-06-03 00:12:22 +00:00
;(context.metadata.invocables as PrivateAIFunctionMetadata[]).push({
2024-05-22 08:11:36 +00:00
name: name ?? methodName,
2024-05-21 13:52:06 +00:00
description,
2024-05-22 08:11:36 +00:00
inputSchema,
2024-05-24 23:55:26 +00:00
methodName
2024-05-21 13:52:06 +00:00
})
2024-06-02 23:13:24 +00:00
context.addInitializer(function () {
;(this as any)[methodName] = (this as any)[methodName].bind(this)
})
2024-05-22 08:11:36 +00:00
}
2024-05-21 13:52:06 +00:00
}