UNPKG

ai-utils.js

Version:

Build AI applications, chatbots, and agents with JavaScript and TypeScript.

113 lines (112 loc) 4.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createOpenAIChatFullDeltaIterableQueue = void 0; const secure_json_parse_1 = __importDefault(require("secure-json-parse")); const zod_1 = require("zod"); const AsyncQueue_js_1 = require("../../../model-function/generate-text/AsyncQueue.cjs"); const parseEventSourceReadableStream_js_1 = require("../../../model-function/generate-text/parseEventSourceReadableStream.cjs"); const chatResponseStreamEventSchema = zod_1.z.object({ choices: zod_1.z.array(zod_1.z.object({ delta: zod_1.z.object({ role: zod_1.z.enum(["assistant", "user"]).optional(), content: zod_1.z.string().nullable().optional(), function_call: zod_1.z .object({ name: zod_1.z.string().optional(), arguments: zod_1.z.string().optional(), }) .optional(), }), finish_reason: zod_1.z.enum(["stop", "length"]).nullable(), index: zod_1.z.number(), })), created: zod_1.z.number(), id: zod_1.z.string(), model: zod_1.z.string(), object: zod_1.z.string(), }); async function createOpenAIChatFullDeltaIterableQueue(stream) { const queue = new AsyncQueue_js_1.AsyncQueue(); const streamDelta = []; // process the stream asynchonously (no 'await' on purpose): (0, parseEventSourceReadableStream_js_1.parseEventSourceReadableStream)({ stream, callback: (event) => { if (event.type !== "event") { return; } const data = event.data; if (data === "[DONE]") { queue.close(); return; } try { const json = secure_json_parse_1.default.parse(data); const parseResult = chatResponseStreamEventSchema.safeParse(json); if (!parseResult.success) { queue.push({ type: "error", error: parseResult.error, }); queue.close(); return; } const event = parseResult.data; for (let i = 0; i < event.choices.length; i++) { const eventChoice = event.choices[i]; const delta = eventChoice.delta; if (streamDelta[i] == null) { streamDelta[i] = { role: undefined, content: "", isComplete: false, delta, }; } const choice = streamDelta[i]; choice.delta = delta; if (eventChoice.finish_reason != null) { choice.isComplete = true; } if (delta.content != undefined) { choice.content += delta.content; } if (delta.function_call != undefined) { if (choice.function_call == undefined) { choice.function_call = { name: "", arguments: "", }; } if (delta.function_call.name != undefined) { choice.function_call.name += delta.function_call.name; } if (delta.function_call.arguments != undefined) { choice.function_call.arguments += delta.function_call.arguments; } } if (delta.role != undefined) { choice.role = delta.role; } } // Since we're mutating the choices array in an async scenario, // we need to make a deep copy: const streamDeltaDeepCopy = JSON.parse(JSON.stringify(streamDelta)); queue.push({ type: "delta", fullDelta: streamDeltaDeepCopy, }); } catch (error) { queue.push({ type: "error", error }); queue.close(); return; } }, }); return queue; } exports.createOpenAIChatFullDeltaIterableQueue = createOpenAIChatFullDeltaIterableQueue;