ai-utils.js
Version:
Build AI applications, chatbots, and agents with JavaScript and TypeScript.
57 lines (56 loc) • 2.21 kB
JavaScript
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";
export async function executeCall({ model, options, getStartEvent, getAbortEvent, getFailureEvent, getSuccessEvent, generateResponse, extractOutputValue, }) {
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(getStartEvent(startMetadata, settings));
const result = await runSafe(() => generateResponse({
functionId: options?.functionId,
settings,
run,
}));
const finishMetadata = {
...startMetadata,
durationInMs: durationMeasurement.durationInMs,
};
if (!result.ok) {
if (result.isAborted) {
eventSource.notifyModelCallFinished(getAbortEvent(finishMetadata, settings));
throw new AbortError();
}
eventSource.notifyModelCallFinished(getFailureEvent(finishMetadata, settings, result.error));
throw result.error;
}
const response = result.output;
const output = extractOutputValue(response);
eventSource.notifyModelCallFinished(getSuccessEvent(finishMetadata, settings, response, output));
return {
output,
response,
metadata: finishMetadata,
};
}