UNPKG

ai-utils.js

Version:

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

112 lines (111 loc) 3.85 kB
import { nanoid as createId } from "nanoid"; import { startDurationMeasurement } from "../../util/DurationMeasurement.js"; import { AbortError } from "../../util/api/AbortError.js"; import { runSafe } from "../../util/runSafe.js"; import { ModelCallEventSource } from "../ModelCallEventSource.js"; import { extractTextDeltas } from "./extractTextDeltas.js"; export async function streamText(model, prompt, options) { if (options?.settings != null) { model = model.withSettings(options.settings); options = { functionId: options.functionId, run: options.run, }; } const run = options?.run; const settings = model.settings; const eventSource = new ModelCallEventSource({ observers: [...(settings.observers ?? []), ...(run?.observers ?? [])], errorHandler: run?.errorHandler, }); const durationMeasurement = startDurationMeasurement(); const startMetadata = { callId: `call-${createId()}`, runId: run?.runId, sessionId: run?.sessionId, userId: run?.userId, functionId: options?.functionId, model: model.modelInformation, startEpochSeconds: durationMeasurement.startEpochSeconds, }; eventSource.notifyModelCallStarted({ type: "text-streaming-started", metadata: startMetadata, settings, prompt, }); const result = await runSafe(async () => extractTextDeltas({ deltaIterable: await model.generateDeltaStreamResponse(prompt, { functionId: options?.functionId, settings, run, }), extractDelta: (fullDelta) => model.extractTextDelta(fullDelta), onDone: (fullText, lastFullDelta) => { const finishMetadata = { ...startMetadata, durationInMs: durationMeasurement.durationInMs, }; eventSource.notifyModelCallFinished({ type: "text-streaming-finished", status: "success", metadata: finishMetadata, settings, prompt, response: lastFullDelta, generatedText: fullText, }); }, onError: (error) => { const finishMetadata = { ...startMetadata, durationInMs: durationMeasurement.durationInMs, }; eventSource.notifyModelCallFinished(error instanceof AbortError ? { type: "text-streaming-finished", status: "abort", metadata: finishMetadata, settings, prompt, } : { type: "text-streaming-finished", status: "failure", metadata: finishMetadata, settings, prompt, error, }); }, })); if (!result.ok) { const finishMetadata = { ...startMetadata, durationInMs: durationMeasurement.durationInMs, }; if (result.isAborted) { eventSource.notifyModelCallFinished({ type: "text-streaming-finished", status: "abort", metadata: finishMetadata, settings, prompt, }); throw new AbortError(); } eventSource.notifyModelCallFinished({ type: "text-streaming-finished", status: "failure", metadata: finishMetadata, settings, prompt, error: result.error, }); throw result.error; } return { textStream: result.output, metadata: startMetadata, }; }