UNPKG

@hashbrownai/openai

Version:
207 lines 9.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.text = text; const tslib_1 = require("tslib"); const core_1 = require("@hashbrownai/core"); const openai_1 = require("openai"); function text(options) { return tslib_1.__asyncGenerator(this, arguments, function* text_1() { var _a, e_1, _b, _c; var _d, _e; const { apiKey, baseURL, request, transformRequestOptions, loadThread, saveThread, } = options; const { model, tools, responseFormat, toolChoice, system } = request; const threadId = request.threadId; let loadedThread = []; let effectiveThreadId = threadId; const openai = new openai_1.default({ apiKey, baseURL: baseURL, }); // Thread loading (both load-thread op and generate op with threadId) const shouldLoadThread = Boolean(request.threadId); const shouldHydrateThreadOnTheClient = Boolean(request.operation === 'load-thread'); if (shouldLoadThread) { yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-start' })); if (!loadThread) { yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-failure', error: 'Thread loading is not available for this transport.', })); return yield tslib_1.__await(void 0); } const loadFn = loadThread; try { loadedThread = yield tslib_1.__await(loadFn(request.threadId)); if (shouldHydrateThreadOnTheClient) { yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-success', thread: loadedThread, })); } else { yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-success', })); } } catch (error) { const { message, stack } = normalizeError(error); yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-load-failure', error: message, stacktrace: stack, })); return yield tslib_1.__await(void 0); } } if (request.operation === 'load-thread') { return yield tslib_1.__await(void 0); } const mergedMessages = request.threadId && shouldLoadThread ? (0, core_1.mergeMessagesForThread)(loadedThread, (_d = request.messages) !== null && _d !== void 0 ? _d : []) : ((_e = request.messages) !== null && _e !== void 0 ? _e : []); let assistantMessage = null; try { const baseOptions = { stream: true, model: model, messages: [ { role: 'system', content: system, }, ...mergedMessages.map((message) => { if (message.role === 'user') { return { role: message.role, content: message.content, }; } if (message.role === 'assistant') { return { role: message.role, content: message.content && typeof message.content !== 'string' ? JSON.stringify(message.content) : message.content, tool_calls: message.toolCalls && message.toolCalls.length > 0 ? message.toolCalls.map((toolCall) => (Object.assign(Object.assign({}, toolCall), { type: 'function', function: Object.assign(Object.assign({}, toolCall.function), { arguments: JSON.stringify(toolCall.function.arguments) }) }))) : undefined, }; } if (message.role === 'tool') { return { role: message.role, content: JSON.stringify(message.content), tool_call_id: message.toolCallId, }; } throw new Error(`Invalid message role`); }), ], tools: tools && tools.length > 0 ? tools.map((tool) => ({ type: 'function', function: { name: tool.name, description: tool.description, parameters: tool.parameters, strict: true, }, })) : undefined, tool_choice: toolChoice, response_format: responseFormat ? { type: 'json_schema', json_schema: { strict: true, name: 'schema', description: '', schema: responseFormat, }, } : undefined, }; const resolvedOptions = transformRequestOptions ? yield tslib_1.__await(transformRequestOptions(baseOptions)) : baseOptions; const stream = openai.chat.completions.stream(resolvedOptions); yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'generation-start' })); try { for (var _f = true, stream_1 = tslib_1.__asyncValues(stream), stream_1_1; stream_1_1 = yield tslib_1.__await(stream_1.next()), _a = stream_1_1.done, !_a; _f = true) { _c = stream_1_1.value; _f = false; const chunk = _c; const chunkMessage = { choices: chunk.choices.map((choice) => ({ index: choice.index, delta: { content: choice.delta.content, role: choice.delta.role, toolCalls: choice.delta.tool_calls, }, finishReason: choice.finish_reason, })), }; const frame = { type: 'generation-chunk', chunk: chunkMessage, }; assistantMessage = (0, core_1.updateAssistantMessage)(assistantMessage, chunkMessage); yield yield tslib_1.__await((0, core_1.encodeFrame)(frame)); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_f && !_a && (_b = stream_1.return)) yield tslib_1.__await(_b.call(stream_1)); } finally { if (e_1) throw e_1.error; } } yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'generation-finish' })); } catch (error) { const { message, stack } = normalizeError(error); const frame = { type: 'generation-error', error: message, stacktrace: stack, }; yield yield tslib_1.__await((0, core_1.encodeFrame)(frame)); return yield tslib_1.__await(void 0); } if (saveThread) { const threadToSave = (0, core_1.mergeMessagesForThread)(mergedMessages, [ ...(assistantMessage ? [assistantMessage] : []), ]); yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-save-start' })); try { const savedThreadId = yield tslib_1.__await(saveThread(threadToSave, effectiveThreadId)); if (effectiveThreadId && savedThreadId !== effectiveThreadId) { throw new Error('Save returned a different threadId than the existing thread'); } effectiveThreadId = savedThreadId; yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-save-success', threadId: savedThreadId, })); } catch (error) { const { message, stack } = normalizeError(error); yield yield tslib_1.__await((0, core_1.encodeFrame)({ type: 'thread-save-failure', error: message, stacktrace: stack, })); return yield tslib_1.__await(void 0); } } }); } function normalizeError(error) { if (error instanceof Error) { return { message: error.message, stack: error.stack }; } return { message: String(error) }; } //# sourceMappingURL=text.fn.js.map