UNPKG

zod-to-openai-tool

Version:

Easily create tools from zod schemas to use with OpenAI Assistants and Chat Completions

133 lines 3.67 kB
// src/index.ts import { z } from "zod"; import { zodToJsonSchema } from "zod-to-json-schema"; function tool() { const data = { schema: z.object({}), func: () => { }, description: void 0 }; return { input(s) { data.schema = s; return this; }, run(f) { data.func = f; return this; }, describe(d) { data.description = d; return this; }, /** @internal */ get _data() { return data; }, /** @internal */ get _parameters() { const { $schema, ...parameters } = zodToJsonSchema(data.schema); return parameters; } }; } var t = { input(s) { return tool().input(s); }, run(...args) { return tool().run(...args); }, describe(d) { return tool().describe(d); }, codeInterpreter: { type: "code_interpreter" }, fileSearch: { type: "file_search" } }; function createTools(tools, onError) { function _processActions(data) { const results = Promise.all( data.map(async ({ function: { arguments: args, name }, id }, i) => { const tool2 = tools[name]; let output; try { const input = await tool2._data.schema.parseAsync(JSON.parse(args)); output = await tool2._data.func(input); } catch (error) { error = onError?.(error) ?? error; if (error instanceof Error) { error = error.message; } output = { error }; } return { id, output: JSON.stringify(output) }; }) ); return results; } return { tools: Object.entries(tools).map( ([name, tool2]) => { const parameters = tool2._parameters; return { type: "function", function: { name, description: tool2._data.description, parameters } }; } ), /** * Process the actions from the chat completion. * @param data The tool calls generated from the chat completion. (`message.tool_calls`) * @returns The message which should be sent with the messages to generate the result based on the tool calls */ async processChatActions(data = []) { return (await _processActions(data)).map( ({ id, output }) => ({ tool_call_id: id, role: "tool", content: output }) ); }, /** * Process the actions from the assistant run. * @param data The tool calls generated from the assistant run. (`run.required_action.submit_tool_outputs.tool_calls`) * @returns The tool outputs which should be sent to `runs.submitToolOutputs()` to continue the run. */ async processAssistantActions(data = []) { return (await _processActions(data)).map( ({ id, output }) => ({ tool_call_id: id, output }) ); } }; } function combineTools(...tools) { const customTools = tools.filter( (t2) => "tools" in t2 ); const combinedCustomTools = { tools: customTools.flatMap((t2) => t2.tools), async processChatActions(data = []) { return (await Promise.all(customTools.map((t2) => t2.processChatActions(data)))).flat(); }, async processAssistantActions(data = []) { return (await Promise.all(customTools.map((t2) => t2.processAssistantActions(data)))).flat(); } }; const builtInTools = tools.filter((t2) => "type" in t2); return { tools: [...combinedCustomTools.tools, ...builtInTools], processChatActions: combinedCustomTools.processChatActions, processAssistantActions: combinedCustomTools.processAssistantActions }; } export { combineTools, createTools, t }; //# sourceMappingURL=index.js.map