UNPKG

@convo-lang/convo-lang

Version:
202 lines 8.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseOpenAiConvoConverter = void 0; const convo_lang_1 = require("@convo-lang/convo-lang"); const common_1 = require("@iyio/common"); const json5_1 = require("@iyio/json5"); /** * A conversation converter for OpenAI like APIs */ class BaseOpenAiConvoConverter { supportedInputTypes; supportedOutputTypes; userRoles; assistantRoles; systemRoles; functionRoles; chatModel; visionModel; models; hasVision; transformInput; transformOutput; constructor({ chatModel, visionModel, supportedInputTypes, supportedOutputTypes, userRoles, assistantRoles, systemRoles, functionRoles, models, hasVision, transformInput, transformOutput, }) { this.chatModel = chatModel; this.visionModel = visionModel; this.supportedInputTypes = supportedInputTypes ? [...supportedInputTypes] : []; Object.freeze(this.supportedInputTypes); this.supportedOutputTypes = supportedOutputTypes ? [...supportedOutputTypes] : []; Object.freeze(this.supportedOutputTypes); this.userRoles = userRoles ? [...userRoles] : ['user']; Object.freeze(this.userRoles); this.assistantRoles = assistantRoles ? [...assistantRoles] : ['assistant']; Object.freeze(this.assistantRoles); this.systemRoles = systemRoles ? [...systemRoles] : ['system']; Object.freeze(this.systemRoles); this.functionRoles = functionRoles ? [...functionRoles] : ['function']; Object.freeze(this.functionRoles); this.models = [...models]; Object.freeze(this.models); this.hasVision = hasVision; this.transformInput = transformInput; this.transformOutput = transformOutput; } convertOutputToConvo(output, outputType, input, inputType, flat) { if (this.transformOutput) { output = this.transformOutput(output); } const msg = output.choices[0]; if (!msg) { return []; } let params; let callError; ; const tool = msg.message.tool_calls?.find(t => t.function); const toolFn = tool?.function; let fnName = undefined; const toolId = (tool && toolFn) ? tool.id : undefined; if (toolFn) { try { fnName = toolFn.name; params = (0, json5_1.parseJson5)(toolFn.arguments ?? '{}'); } catch (ex) { callError = `Unable to parse arguments for ${toolFn.name} - ${(0, common_1.getErrorMessage)(ex)}\n${toolFn.arguments}`; } } if (fnName) { if (callError) { return [(0, convo_lang_1.createTextConvoCompletionMessage)({ flat, role: msg.message.role, content: callError, model: output.model, models: this.models, inputTokens: output.usage?.prompt_tokens, outputTokens: output.usage?.completion_tokens, })]; } return [(0, convo_lang_1.createFunctionCallConvoCompletionMessage)({ flat, callFn: fnName, callParams: params, toolId, model: output.model, models: this.models, inputTokens: output.usage?.prompt_tokens, outputTokens: output.usage?.completion_tokens, })]; } else { return [(0, convo_lang_1.createTextConvoCompletionMessage)({ flat, role: msg.message.role, content: msg.message.content, model: output.model, models: this.models, inputTokens: output.usage?.prompt_tokens, outputTokens: output.usage?.completion_tokens, })]; } } convertConvoToInput(flat, inputType) { const messages = (0, convo_lang_1.getNormalizedFlatMessageList)(flat); let visionCapable = flat.capabilities?.includes('vision'); const lastContentMessage = (0, convo_lang_1.getLastNonCalledConvoFlatMessage)(messages); const model = flat?.responseModel ?? (visionCapable ? this.visionModel : this.chatModel); if (!model) { throw new Error('Chat AI model not defined'); } const info = this.models.find(m => m.name === model); if (info && info.inputCapabilities?.includes('image') || this.hasVision?.(model)) { visionCapable = true; } const oMsgs = []; const oFns = []; for (const m of messages) { if (m.fn) { oFns.push({ type: "function", function: (0, common_1.deleteUndefined)({ name: m.fn.name, description: m.fn.description, parameters: (m._fnParams ?? (m.fnParams ? ((0, common_1.zodTypeToJsonScheme)(m.fnParams) ?? {}) : {})) }) }); } else if (m.content !== undefined) { let content; const vc = (visionCapable || m.vision) && m.vision !== false && m.role !== 'system'; if (vc) { const items = (0, common_1.parseMarkdownImages)(m.content ?? '', { requireImgProtocol: true }); if (items.length === 1 && (typeof items[0]?.text === 'string')) { content = items[0]?.text ?? ''; } else { content = items.map(i => i.image ? { type: 'image_url', image_url: { url: i.image.url } } : { type: 'text', text: i.text ?? '' }); } } else { content = m.content ?? ''; } oMsgs.push((0, common_1.deleteUndefined)((0, common_1.asType)({ role: this.isKnownRole(m.role) ? m.role : 'user', content }))); } else if (m.called) { const toolId = m.tags?.['toolId'] ?? m.called.name; oMsgs.push({ role: 'assistant', content: null, tool_calls: [{ id: toolId, type: 'function', function: { name: m.called.name, arguments: JSON.stringify(m.calledParams), } }] }); oMsgs.push({ role: 'tool', tool_call_id: toolId, content: m.calledReturn === undefined ? 'function-called' : JSON.stringify(m.calledReturn), }); } } const jsonMode = lastContentMessage?.responseFormat === 'json'; const cParams = { model, response_format: jsonMode ? { type: 'json_object' } : undefined, stream: false, messages: oMsgs, tools: oFns?.length ? oFns : undefined, user: flat?.userId, tool_choice: flat.toolChoice ? ((typeof flat.toolChoice === 'string') ? flat.toolChoice : { type: "function", "function": flat.toolChoice }) : undefined }; if (this.transformInput) { return this.transformInput(cParams); } else { return cParams; } } isKnownRole(role) { return (this.userRoles.includes(role) || this.assistantRoles.includes(role) || this.systemRoles.includes(role) || this.functionRoles.includes(role)); } } exports.BaseOpenAiConvoConverter = BaseOpenAiConvoConverter; //# sourceMappingURL=BaseOpenAiConvoConverter.js.map