old-agentic
Travis Fischer 2025-03-14 20:58:35 +08:00
rodzic 89d5e21beb
commit e59356c85a
2 zmienionych plików z 44 dodań i 15 usunięć

Wyświetl plik

@ -22,7 +22,7 @@ async function main() {
const res = await openai.responses.create({ const res = await openai.responses.create({
model: 'gpt-4o-mini', model: 'gpt-4o-mini',
temperature: 0, temperature: 0,
tools: weather.functions.specs, tools: weather.functions.responsesToolSpecs,
tool_choice: 'required', tool_choice: 'required',
input: messages input: messages
}) })
@ -34,9 +34,7 @@ async function main() {
const fn = weather.functions.get('get_current_weather')! const fn = weather.functions.get('get_current_weather')!
assert(fn) assert(fn)
const toolResult = await fn(message.arguments)
const toolParams = message.arguments
const toolResult = await fn(toolParams)
messages.push(message) messages.push(message)
messages.push({ messages.push({

Wyświetl plik

@ -2,6 +2,10 @@ import type * as types from './types.ts'
import { AIFunctionsProvider } from './fns' import { AIFunctionsProvider } from './fns'
import { isAIFunction } from './utils' import { isAIFunction } from './utils'
export type AIFunctionSetOptions = {
transformNameKeysFn?: (name: string) => string
}
/** /**
* A set of AI functions intended to make it easier to work with large sets of * A set of AI functions intended to make it easier to work with large sets of
* AI functions across different clients. * AI functions across different clients.
@ -14,8 +18,14 @@ import { isAIFunction } from './utils'
*/ */
export class AIFunctionSet implements Iterable<types.AIFunction> { export class AIFunctionSet implements Iterable<types.AIFunction> {
protected readonly _map: Map<string, types.AIFunction> protected readonly _map: Map<string, types.AIFunction>
protected readonly _transformNameKeysFn: (name: string) => string
constructor(
aiFunctionLikeObjects?: types.AIFunctionLike[],
{ transformNameKeysFn = transformName }: AIFunctionSetOptions = {}
) {
this._transformNameKeysFn = transformNameKeysFn
constructor(aiFunctionLikeObjects?: types.AIFunctionLike[]) {
// TODO: these `instanceof` checks seem to be failing on some platforms, // TODO: these `instanceof` checks seem to be failing on some platforms,
// so for now we're using an uglier, but more reliable approach to parsing // so for now we're using an uglier, but more reliable approach to parsing
// the AIFunctionLike objects. // the AIFunctionLike objects.
@ -64,7 +74,9 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
} }
this._map = new Map( this._map = new Map(
fns ? fns.map((fn) => [transformName(fn.spec.name), fn]) : null fns
? fns.map((fn) => [this._transformNameKeysFn(fn.spec.name), fn])
: null
) )
} }
@ -73,21 +85,21 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
} }
add(fn: types.AIFunction): this { add(fn: types.AIFunction): this {
this._map.set(transformName(fn.spec.name), fn) this._map.set(this._transformNameKeysFn(fn.spec.name), fn)
return this return this
} }
get(name: string): types.AIFunction | undefined { get(name: string): types.AIFunction | undefined {
return this._map.get(transformName(name)) return this._map.get(this._transformNameKeysFn(name))
} }
set(name: string, fn: types.AIFunction): this { set(name: string, fn: types.AIFunction): this {
this._map.set(transformName(name), fn) this._map.set(this._transformNameKeysFn(name), fn)
return this return this
} }
has(name: string): boolean { has(name: string): boolean {
return this._map.has(transformName(name)) return this._map.has(this._transformNameKeysFn(name))
} }
clear(): void { clear(): void {
@ -95,23 +107,23 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
} }
delete(name: string): boolean { delete(name: string): boolean {
return this._map.delete(transformName(name)) return this._map.delete(this._transformNameKeysFn(name))
} }
pick(...keys: string[]): AIFunctionSet { pick(...keys: string[]): AIFunctionSet {
const keysToIncludeSet = new Set(keys.map(transformName)) const keysToIncludeSet = new Set(keys.map(this._transformNameKeysFn))
return new AIFunctionSet( return new AIFunctionSet(
Array.from(this).filter((fn) => Array.from(this).filter((fn) =>
keysToIncludeSet.has(transformName(fn.spec.name)) keysToIncludeSet.has(this._transformNameKeysFn(fn.spec.name))
) )
) )
} }
omit(...keys: string[]): AIFunctionSet { omit(...keys: string[]): AIFunctionSet {
const keysToExcludeSet = new Set(keys.map(transformName)) const keysToExcludeSet = new Set(keys.map(this._transformNameKeysFn))
return new AIFunctionSet( return new AIFunctionSet(
Array.from(this).filter( Array.from(this).filter(
(fn) => !keysToExcludeSet.has(transformName(fn.spec.name)) (fn) => !keysToExcludeSet.has(this._transformNameKeysFn(fn.spec.name))
) )
) )
} }
@ -120,10 +132,18 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
return [...this.entries].map(fn) return [...this.entries].map(fn)
} }
/**
* Returns the functions in this set as an array compatible with OpenAI's
* chat completions `functions`.
*/
get specs(): types.AIFunctionSpec[] { get specs(): types.AIFunctionSpec[] {
return this.map((fn) => fn.spec) return this.map((fn) => fn.spec)
} }
/**
* Returns the functions in this set as an array compatible with OpenAI's
* chat completions `tools`.
*/
get toolSpecs(): types.AIToolSpec[] { get toolSpecs(): types.AIToolSpec[] {
return this.map((fn) => ({ return this.map((fn) => ({
type: 'function' as const, type: 'function' as const,
@ -131,6 +151,17 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
})) }))
} }
/**
* Returns the tools in this set compatible with OpenAI's `responses` API.
*
* Note that this is currently the same type as `AIFunctionSet.specs`, but
* they are separate APIs which may diverge over time, so if you're using the
* OpenAI `responses` API, you should reference this property.
*/
get responsesToolSpecs(): types.AIFunctionSpec[] {
return this.specs
}
get entries(): IterableIterator<types.AIFunction> { get entries(): IterableIterator<types.AIFunction> {
return this._map.values() return this._map.values()
} }