515 lines
28 KiB
JavaScript
515 lines
28 KiB
JavaScript
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
||
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
||
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
||
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
||
|
};
|
||
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
||
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
||
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||
|
};
|
||
|
var _AbstractChatCompletionRunner_instances, _AbstractChatCompletionRunner_connectedPromise, _AbstractChatCompletionRunner_resolveConnectedPromise, _AbstractChatCompletionRunner_rejectConnectedPromise, _AbstractChatCompletionRunner_endPromise, _AbstractChatCompletionRunner_resolveEndPromise, _AbstractChatCompletionRunner_rejectEndPromise, _AbstractChatCompletionRunner_listeners, _AbstractChatCompletionRunner_ended, _AbstractChatCompletionRunner_errored, _AbstractChatCompletionRunner_aborted, _AbstractChatCompletionRunner_catchingPromiseCreated, _AbstractChatCompletionRunner_getFinalContent, _AbstractChatCompletionRunner_getFinalMessage, _AbstractChatCompletionRunner_getFinalFunctionCall, _AbstractChatCompletionRunner_getFinalFunctionCallResult, _AbstractChatCompletionRunner_calculateTotalUsage, _AbstractChatCompletionRunner_handleError, _AbstractChatCompletionRunner_validateParams, _AbstractChatCompletionRunner_stringifyFunctionCallResult;
|
||
|
import { APIUserAbortError, OpenAIError } from 'openai/error';
|
||
|
import { isRunnableFunctionWithParse, } from "./RunnableFunction.mjs";
|
||
|
import { isAssistantMessage, isFunctionMessage, isToolMessage } from "./chatCompletionUtils.mjs";
|
||
|
const DEFAULT_MAX_CHAT_COMPLETIONS = 10;
|
||
|
export class AbstractChatCompletionRunner {
|
||
|
constructor() {
|
||
|
_AbstractChatCompletionRunner_instances.add(this);
|
||
|
this.controller = new AbortController();
|
||
|
_AbstractChatCompletionRunner_connectedPromise.set(this, void 0);
|
||
|
_AbstractChatCompletionRunner_resolveConnectedPromise.set(this, () => { });
|
||
|
_AbstractChatCompletionRunner_rejectConnectedPromise.set(this, () => { });
|
||
|
_AbstractChatCompletionRunner_endPromise.set(this, void 0);
|
||
|
_AbstractChatCompletionRunner_resolveEndPromise.set(this, () => { });
|
||
|
_AbstractChatCompletionRunner_rejectEndPromise.set(this, () => { });
|
||
|
_AbstractChatCompletionRunner_listeners.set(this, {});
|
||
|
this._chatCompletions = [];
|
||
|
this.messages = [];
|
||
|
_AbstractChatCompletionRunner_ended.set(this, false);
|
||
|
_AbstractChatCompletionRunner_errored.set(this, false);
|
||
|
_AbstractChatCompletionRunner_aborted.set(this, false);
|
||
|
_AbstractChatCompletionRunner_catchingPromiseCreated.set(this, false);
|
||
|
_AbstractChatCompletionRunner_handleError.set(this, (error) => {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_errored, true, "f");
|
||
|
if (error instanceof Error && error.name === 'AbortError') {
|
||
|
error = new APIUserAbortError();
|
||
|
}
|
||
|
if (error instanceof APIUserAbortError) {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_aborted, true, "f");
|
||
|
return this._emit('abort', error);
|
||
|
}
|
||
|
if (error instanceof OpenAIError) {
|
||
|
return this._emit('error', error);
|
||
|
}
|
||
|
if (error instanceof Error) {
|
||
|
const openAIError = new OpenAIError(error.message);
|
||
|
// @ts-ignore
|
||
|
openAIError.cause = error;
|
||
|
return this._emit('error', openAIError);
|
||
|
}
|
||
|
return this._emit('error', new OpenAIError(String(error)));
|
||
|
});
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_connectedPromise, new Promise((resolve, reject) => {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_resolveConnectedPromise, resolve, "f");
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_rejectConnectedPromise, reject, "f");
|
||
|
}), "f");
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_endPromise, new Promise((resolve, reject) => {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_resolveEndPromise, resolve, "f");
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_rejectEndPromise, reject, "f");
|
||
|
}), "f");
|
||
|
// Don't let these promises cause unhandled rejection errors.
|
||
|
// we will manually cause an unhandled rejection error later
|
||
|
// if the user hasn't registered any error listener or called
|
||
|
// any promise-returning method.
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_connectedPromise, "f").catch(() => { });
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_endPromise, "f").catch(() => { });
|
||
|
}
|
||
|
_run(executor) {
|
||
|
// Unfortunately if we call `executor()` immediately we get runtime errors about
|
||
|
// references to `this` before the `super()` constructor call returns.
|
||
|
setTimeout(() => {
|
||
|
executor().then(() => {
|
||
|
this._emitFinal();
|
||
|
this._emit('end');
|
||
|
}, __classPrivateFieldGet(this, _AbstractChatCompletionRunner_handleError, "f"));
|
||
|
}, 0);
|
||
|
}
|
||
|
_addChatCompletion(chatCompletion) {
|
||
|
this._chatCompletions.push(chatCompletion);
|
||
|
this._emit('chatCompletion', chatCompletion);
|
||
|
const message = chatCompletion.choices[0]?.message;
|
||
|
if (message)
|
||
|
this._addMessage(message);
|
||
|
return chatCompletion;
|
||
|
}
|
||
|
_addMessage(message, emit = true) {
|
||
|
if (!('content' in message))
|
||
|
message.content = null;
|
||
|
this.messages.push(message);
|
||
|
if (emit) {
|
||
|
this._emit('message', message);
|
||
|
if ((isFunctionMessage(message) || isToolMessage(message)) && message.content) {
|
||
|
// Note, this assumes that {role: 'tool', content: …} is always the result of a call of tool of type=function.
|
||
|
this._emit('functionCallResult', message.content);
|
||
|
}
|
||
|
else if (isAssistantMessage(message) && message.function_call) {
|
||
|
this._emit('functionCall', message.function_call);
|
||
|
}
|
||
|
else if (isAssistantMessage(message) && message.tool_calls) {
|
||
|
for (const tool_call of message.tool_calls) {
|
||
|
if (tool_call.type === 'function') {
|
||
|
this._emit('functionCall', tool_call.function);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
_connected() {
|
||
|
if (this.ended)
|
||
|
return;
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_resolveConnectedPromise, "f").call(this);
|
||
|
this._emit('connect');
|
||
|
}
|
||
|
get ended() {
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_ended, "f");
|
||
|
}
|
||
|
get errored() {
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_errored, "f");
|
||
|
}
|
||
|
get aborted() {
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_aborted, "f");
|
||
|
}
|
||
|
abort() {
|
||
|
this.controller.abort();
|
||
|
}
|
||
|
/**
|
||
|
* Adds the listener function to the end of the listeners array for the event.
|
||
|
* No checks are made to see if the listener has already been added. Multiple calls passing
|
||
|
* the same combination of event and listener will result in the listener being added, and
|
||
|
* called, multiple times.
|
||
|
* @returns this ChatCompletionStream, so that calls can be chained
|
||
|
*/
|
||
|
on(event, listener) {
|
||
|
const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] || (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] = []);
|
||
|
listeners.push({ listener });
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Removes the specified listener from the listener array for the event.
|
||
|
* off() will remove, at most, one instance of a listener from the listener array. If any single
|
||
|
* listener has been added multiple times to the listener array for the specified event, then
|
||
|
* off() must be called multiple times to remove each instance.
|
||
|
* @returns this ChatCompletionStream, so that calls can be chained
|
||
|
*/
|
||
|
off(event, listener) {
|
||
|
const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event];
|
||
|
if (!listeners)
|
||
|
return this;
|
||
|
const index = listeners.findIndex((l) => l.listener === listener);
|
||
|
if (index >= 0)
|
||
|
listeners.splice(index, 1);
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* Adds a one-time listener function for the event. The next time the event is triggered,
|
||
|
* this listener is removed and then invoked.
|
||
|
* @returns this ChatCompletionStream, so that calls can be chained
|
||
|
*/
|
||
|
once(event, listener) {
|
||
|
const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] || (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] = []);
|
||
|
listeners.push({ listener, once: true });
|
||
|
return this;
|
||
|
}
|
||
|
/**
|
||
|
* This is similar to `.once()`, but returns a Promise that resolves the next time
|
||
|
* the event is triggered, instead of calling a listener callback.
|
||
|
* @returns a Promise that resolves the next time given event is triggered,
|
||
|
* or rejects if an error is emitted. (If you request the 'error' event,
|
||
|
* returns a promise that resolves with the error).
|
||
|
*
|
||
|
* Example:
|
||
|
*
|
||
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
||
|
*/
|
||
|
emitted(event) {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, true, "f");
|
||
|
if (event !== 'error')
|
||
|
this.once('error', reject);
|
||
|
this.once(event, resolve);
|
||
|
});
|
||
|
}
|
||
|
async done() {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, true, "f");
|
||
|
await __classPrivateFieldGet(this, _AbstractChatCompletionRunner_endPromise, "f");
|
||
|
}
|
||
|
/**
|
||
|
* @returns a promise that resolves with the final ChatCompletion, or rejects
|
||
|
* if an error occurred or the stream ended prematurely without producing a ChatCompletion.
|
||
|
*/
|
||
|
async finalChatCompletion() {
|
||
|
await this.done();
|
||
|
const completion = this._chatCompletions[this._chatCompletions.length - 1];
|
||
|
if (!completion)
|
||
|
throw new OpenAIError('stream ended without producing a ChatCompletion');
|
||
|
return completion;
|
||
|
}
|
||
|
/**
|
||
|
* @returns a promise that resolves with the content of the final ChatCompletionMessage, or rejects
|
||
|
* if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
|
||
|
*/
|
||
|
async finalContent() {
|
||
|
await this.done();
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this);
|
||
|
}
|
||
|
/**
|
||
|
* @returns a promise that resolves with the the final assistant ChatCompletionMessage response,
|
||
|
* or rejects if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
|
||
|
*/
|
||
|
async finalMessage() {
|
||
|
await this.done();
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this);
|
||
|
}
|
||
|
/**
|
||
|
* @returns a promise that resolves with the content of the final FunctionCall, or rejects
|
||
|
* if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
|
||
|
*/
|
||
|
async finalFunctionCall() {
|
||
|
await this.done();
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCall).call(this);
|
||
|
}
|
||
|
async finalFunctionCallResult() {
|
||
|
await this.done();
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCallResult).call(this);
|
||
|
}
|
||
|
async totalUsage() {
|
||
|
await this.done();
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this);
|
||
|
}
|
||
|
allChatCompletions() {
|
||
|
return [...this._chatCompletions];
|
||
|
}
|
||
|
_emit(event, ...args) {
|
||
|
// make sure we don't emit any events after end
|
||
|
if (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_ended, "f")) {
|
||
|
return;
|
||
|
}
|
||
|
if (event === 'end') {
|
||
|
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_ended, true, "f");
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_resolveEndPromise, "f").call(this);
|
||
|
}
|
||
|
const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event];
|
||
|
if (listeners) {
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] = listeners.filter((l) => !l.once);
|
||
|
listeners.forEach(({ listener }) => listener(...args));
|
||
|
}
|
||
|
if (event === 'abort') {
|
||
|
const error = args[0];
|
||
|
if (!__classPrivateFieldGet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, "f") && !listeners?.length) {
|
||
|
Promise.reject(error);
|
||
|
}
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectConnectedPromise, "f").call(this, error);
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectEndPromise, "f").call(this, error);
|
||
|
this._emit('end');
|
||
|
return;
|
||
|
}
|
||
|
if (event === 'error') {
|
||
|
// NOTE: _emit('error', error) should only be called from #handleError().
|
||
|
const error = args[0];
|
||
|
if (!__classPrivateFieldGet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, "f") && !listeners?.length) {
|
||
|
// Trigger an unhandled rejection if the user hasn't registered any error handlers.
|
||
|
// If you are seeing stack traces here, make sure to handle errors via either:
|
||
|
// - runner.on('error', () => ...)
|
||
|
// - await runner.done()
|
||
|
// - await runner.finalChatCompletion()
|
||
|
// - etc.
|
||
|
Promise.reject(error);
|
||
|
}
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectConnectedPromise, "f").call(this, error);
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectEndPromise, "f").call(this, error);
|
||
|
this._emit('end');
|
||
|
}
|
||
|
}
|
||
|
_emitFinal() {
|
||
|
const completion = this._chatCompletions[this._chatCompletions.length - 1];
|
||
|
if (completion)
|
||
|
this._emit('finalChatCompletion', completion);
|
||
|
const finalMessage = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this);
|
||
|
if (finalMessage)
|
||
|
this._emit('finalMessage', finalMessage);
|
||
|
const finalContent = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this);
|
||
|
if (finalContent)
|
||
|
this._emit('finalContent', finalContent);
|
||
|
const finalFunctionCall = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCall).call(this);
|
||
|
if (finalFunctionCall)
|
||
|
this._emit('finalFunctionCall', finalFunctionCall);
|
||
|
const finalFunctionCallResult = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCallResult).call(this);
|
||
|
if (finalFunctionCallResult != null)
|
||
|
this._emit('finalFunctionCallResult', finalFunctionCallResult);
|
||
|
if (this._chatCompletions.some((c) => c.usage)) {
|
||
|
this._emit('totalUsage', __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this));
|
||
|
}
|
||
|
}
|
||
|
async _createChatCompletion(completions, params, options) {
|
||
|
const signal = options?.signal;
|
||
|
if (signal) {
|
||
|
if (signal.aborted)
|
||
|
this.controller.abort();
|
||
|
signal.addEventListener('abort', () => this.controller.abort());
|
||
|
}
|
||
|
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_validateParams).call(this, params);
|
||
|
const chatCompletion = await completions.create({ ...params, stream: false }, { ...options, signal: this.controller.signal });
|
||
|
this._connected();
|
||
|
return this._addChatCompletion(chatCompletion);
|
||
|
}
|
||
|
async _runChatCompletion(completions, params, options) {
|
||
|
for (const message of params.messages) {
|
||
|
this._addMessage(message, false);
|
||
|
}
|
||
|
return await this._createChatCompletion(completions, params, options);
|
||
|
}
|
||
|
async _runFunctions(completions, params, options) {
|
||
|
const role = 'function';
|
||
|
const { function_call = 'auto', stream, ...restParams } = params;
|
||
|
const singleFunctionToCall = typeof function_call !== 'string' && function_call?.name;
|
||
|
const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {};
|
||
|
const functionsByName = {};
|
||
|
for (const f of params.functions) {
|
||
|
functionsByName[f.name || f.function.name] = f;
|
||
|
}
|
||
|
const functions = params.functions.map((f) => ({
|
||
|
name: f.name || f.function.name,
|
||
|
parameters: f.parameters,
|
||
|
description: f.description,
|
||
|
}));
|
||
|
for (const message of params.messages) {
|
||
|
this._addMessage(message, false);
|
||
|
}
|
||
|
for (let i = 0; i < maxChatCompletions; ++i) {
|
||
|
const chatCompletion = await this._createChatCompletion(completions, {
|
||
|
...restParams,
|
||
|
function_call,
|
||
|
functions,
|
||
|
messages: [...this.messages],
|
||
|
}, options);
|
||
|
const message = chatCompletion.choices[0]?.message;
|
||
|
if (!message) {
|
||
|
throw new OpenAIError(`missing message in ChatCompletion response`);
|
||
|
}
|
||
|
if (!message.function_call)
|
||
|
return;
|
||
|
const { name, arguments: args } = message.function_call;
|
||
|
const fn = functionsByName[name];
|
||
|
if (!fn) {
|
||
|
const content = `Invalid function_call: ${JSON.stringify(name)}. Available options are: ${functions
|
||
|
.map((f) => JSON.stringify(f.name))
|
||
|
.join(', ')}. Please try again`;
|
||
|
this._addMessage({ role, name, content });
|
||
|
continue;
|
||
|
}
|
||
|
else if (singleFunctionToCall && singleFunctionToCall !== name) {
|
||
|
const content = `Invalid function_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`;
|
||
|
this._addMessage({ role, name, content });
|
||
|
continue;
|
||
|
}
|
||
|
let parsed;
|
||
|
try {
|
||
|
parsed = isRunnableFunctionWithParse(fn) ? await fn.parse(args) : args;
|
||
|
}
|
||
|
catch (error) {
|
||
|
this._addMessage({
|
||
|
role,
|
||
|
name,
|
||
|
content: error instanceof Error ? error.message : String(error),
|
||
|
});
|
||
|
continue;
|
||
|
}
|
||
|
// @ts-expect-error it can't rule out `never` type.
|
||
|
const rawContent = await fn.function(parsed, this);
|
||
|
const content = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(this, rawContent);
|
||
|
this._addMessage({ role, name, content });
|
||
|
if (singleFunctionToCall)
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
async _runTools(completions, params, options) {
|
||
|
const role = 'tool';
|
||
|
const { tool_choice = 'auto', stream, ...restParams } = params;
|
||
|
const singleFunctionToCall = typeof tool_choice !== 'string' && tool_choice?.function?.name;
|
||
|
const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {};
|
||
|
const functionsByName = {};
|
||
|
for (const f of params.tools) {
|
||
|
if (f.type === 'function') {
|
||
|
functionsByName[f.function.name || f.function.function.name] = f.function;
|
||
|
}
|
||
|
}
|
||
|
const tools = 'tools' in params ?
|
||
|
params.tools.map((t) => t.type === 'function' ?
|
||
|
{
|
||
|
type: 'function',
|
||
|
function: {
|
||
|
name: t.function.name || t.function.function.name,
|
||
|
parameters: t.function.parameters,
|
||
|
description: t.function.description,
|
||
|
},
|
||
|
}
|
||
|
: t)
|
||
|
: undefined;
|
||
|
for (const message of params.messages) {
|
||
|
this._addMessage(message, false);
|
||
|
}
|
||
|
for (let i = 0; i < maxChatCompletions; ++i) {
|
||
|
const chatCompletion = await this._createChatCompletion(completions, {
|
||
|
...restParams,
|
||
|
tool_choice,
|
||
|
tools,
|
||
|
messages: [...this.messages],
|
||
|
}, options);
|
||
|
const message = chatCompletion.choices[0]?.message;
|
||
|
if (!message) {
|
||
|
throw new OpenAIError(`missing message in ChatCompletion response`);
|
||
|
}
|
||
|
if (!message.tool_calls) {
|
||
|
return;
|
||
|
}
|
||
|
for (const tool_call of message.tool_calls) {
|
||
|
if (tool_call.type !== 'function')
|
||
|
continue;
|
||
|
const tool_call_id = tool_call.id;
|
||
|
const { name, arguments: args } = tool_call.function;
|
||
|
const fn = functionsByName[name];
|
||
|
if (!fn) {
|
||
|
const content = `Invalid tool_call: ${JSON.stringify(name)}. Available options are: ${tools
|
||
|
.map((f) => JSON.stringify(f.function.name))
|
||
|
.join(', ')}. Please try again`;
|
||
|
this._addMessage({ role, tool_call_id, content });
|
||
|
continue;
|
||
|
}
|
||
|
else if (singleFunctionToCall && singleFunctionToCall !== name) {
|
||
|
const content = `Invalid tool_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`;
|
||
|
this._addMessage({ role, tool_call_id, content });
|
||
|
continue;
|
||
|
}
|
||
|
let parsed;
|
||
|
try {
|
||
|
parsed = isRunnableFunctionWithParse(fn) ? await fn.parse(args) : args;
|
||
|
}
|
||
|
catch (error) {
|
||
|
const content = error instanceof Error ? error.message : String(error);
|
||
|
this._addMessage({ role, tool_call_id, content });
|
||
|
continue;
|
||
|
}
|
||
|
// @ts-expect-error it can't rule out `never` type.
|
||
|
const rawContent = await fn.function(parsed, this);
|
||
|
const content = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(this, rawContent);
|
||
|
this._addMessage({ role, tool_call_id, content });
|
||
|
if (singleFunctionToCall) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
_AbstractChatCompletionRunner_connectedPromise = new WeakMap(), _AbstractChatCompletionRunner_resolveConnectedPromise = new WeakMap(), _AbstractChatCompletionRunner_rejectConnectedPromise = new WeakMap(), _AbstractChatCompletionRunner_endPromise = new WeakMap(), _AbstractChatCompletionRunner_resolveEndPromise = new WeakMap(), _AbstractChatCompletionRunner_rejectEndPromise = new WeakMap(), _AbstractChatCompletionRunner_listeners = new WeakMap(), _AbstractChatCompletionRunner_ended = new WeakMap(), _AbstractChatCompletionRunner_errored = new WeakMap(), _AbstractChatCompletionRunner_aborted = new WeakMap(), _AbstractChatCompletionRunner_catchingPromiseCreated = new WeakMap(), _AbstractChatCompletionRunner_handleError = new WeakMap(), _AbstractChatCompletionRunner_instances = new WeakSet(), _AbstractChatCompletionRunner_getFinalContent = function _AbstractChatCompletionRunner_getFinalContent() {
|
||
|
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this).content ?? null;
|
||
|
}, _AbstractChatCompletionRunner_getFinalMessage = function _AbstractChatCompletionRunner_getFinalMessage() {
|
||
|
let i = this.messages.length;
|
||
|
while (i-- > 0) {
|
||
|
const message = this.messages[i];
|
||
|
if (isAssistantMessage(message)) {
|
||
|
return { ...message, content: message.content ?? null };
|
||
|
}
|
||
|
}
|
||
|
throw new OpenAIError('stream ended without producing a ChatCompletionMessage with role=assistant');
|
||
|
}, _AbstractChatCompletionRunner_getFinalFunctionCall = function _AbstractChatCompletionRunner_getFinalFunctionCall() {
|
||
|
for (let i = this.messages.length - 1; i >= 0; i--) {
|
||
|
const message = this.messages[i];
|
||
|
if (isAssistantMessage(message) && message?.function_call) {
|
||
|
return message.function_call;
|
||
|
}
|
||
|
if (isAssistantMessage(message) && message?.tool_calls?.length) {
|
||
|
return message.tool_calls.at(-1)?.function;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}, _AbstractChatCompletionRunner_getFinalFunctionCallResult = function _AbstractChatCompletionRunner_getFinalFunctionCallResult() {
|
||
|
for (let i = this.messages.length - 1; i >= 0; i--) {
|
||
|
const message = this.messages[i];
|
||
|
if (isFunctionMessage(message) && message.content != null) {
|
||
|
return message.content;
|
||
|
}
|
||
|
if (isToolMessage(message) &&
|
||
|
message.content != null &&
|
||
|
this.messages.some((x) => x.role === 'assistant' &&
|
||
|
x.tool_calls?.some((y) => y.type === 'function' && y.id === message.tool_call_id))) {
|
||
|
return message.content;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}, _AbstractChatCompletionRunner_calculateTotalUsage = function _AbstractChatCompletionRunner_calculateTotalUsage() {
|
||
|
const total = {
|
||
|
completion_tokens: 0,
|
||
|
prompt_tokens: 0,
|
||
|
total_tokens: 0,
|
||
|
};
|
||
|
for (const { usage } of this._chatCompletions) {
|
||
|
if (usage) {
|
||
|
total.completion_tokens += usage.completion_tokens;
|
||
|
total.prompt_tokens += usage.prompt_tokens;
|
||
|
total.total_tokens += usage.total_tokens;
|
||
|
}
|
||
|
}
|
||
|
return total;
|
||
|
}, _AbstractChatCompletionRunner_validateParams = function _AbstractChatCompletionRunner_validateParams(params) {
|
||
|
if (params.n != null && params.n > 1) {
|
||
|
throw new OpenAIError('ChatCompletion convenience helpers only support n=1 at this time. To use n>1, please use chat.completions.create() directly.');
|
||
|
}
|
||
|
}, _AbstractChatCompletionRunner_stringifyFunctionCallResult = function _AbstractChatCompletionRunner_stringifyFunctionCallResult(rawContent) {
|
||
|
return (typeof rawContent === 'string' ? rawContent
|
||
|
: rawContent === undefined ? 'undefined'
|
||
|
: JSON.stringify(rawContent));
|
||
|
};
|
||
|
//# sourceMappingURL=AbstractChatCompletionRunner.mjs.map
|