import { ChatCompletionFunctions, ChatCompletionRequestMessageFunctionCall } from "openai"; import config from "./config"; type parameterMap = { string: string, number: number, }; type nameTypeMap = {[name: string]: keyof parameterMap} | Record; type OpenAIFunctionRequestData = { [name in keyof T]: T[name]; }; /** * Represents the function that can be ran by the OpenAI model */ export interface OpenAIFunction { name: string, description?: string, parameters: { type: "object", properties: T extends Record ? Record : { [name in T[string]]: { type: T[name], description?: string, } }, required?: Array, }, } export abstract class OpenAIFunction { getSettings(): ChatCompletionFunctions { return { name: this.name, description: this.description, parameters: this.parameters, }; } abstract execute(data: OpenAIFunctionRequestData): string; } /* * Manages functions for the OpenAI **/ export default class FunctionManager { store = new Map(); constructor() { this.store.set("getTime", new GetTime()); } public getFunctions(): ChatCompletionFunctions[] { const rvalue: ChatCompletionFunctions[] = []; for (const [, value] of this.store) { rvalue.push(value.getSettings()); } return rvalue; } public handleFunction(request: ChatCompletionRequestMessageFunctionCall) { try { const parsedArguments = JSON.parse(request.arguments ?? ""); return this.store.get(request.name ?? "")?.execute(parsedArguments); } catch (e) { console.error("Function arguments raw: " + request.arguments); throw new Error(`Failed to parse the function JSON arguments when running function [${request.name}]`, {cause: e}); } } } // buildins class GetTime extends OpenAIFunction> { name = "getTime"; description = "Gets current date and time with a timezone attached"; parameters = { type: "object" as const, properties: {} as Record, }; execute(): string { return `${Intl.DateTimeFormat().resolvedOptions().timeZone}): ${new Date().toLocaleString("en-US", config.calendarConfig)}`; } }