@agentica/core
Version:
Agentic AI Library specialized in LLM Function Calling
302 lines • 11.4 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MicroAgentica = void 0;
const tstl_1 = require("tstl");
const AgenticaTokenUsage_1 = require("./context/AgenticaTokenUsage");
const AgenticaOperationComposer_1 = require("./context/internal/AgenticaOperationComposer");
const events_1 = require("./factory/events");
const orchestrate_1 = require("./orchestrate");
const transformHistory_1 = require("./transformers/transformHistory");
const __map_take_1 = require("./utils/__map_take");
const assertExecuteFailure_1 = require("./utils/assertExecuteFailure");
const request_1 = require("./utils/request");
/**
* Micro AI chatbot.
*
* `MicroAgentica` is a facade class for the micro AI chatbot agent
* which performs LLM (Large Language Model) function calling from the
* {@link conversate user's conversation} and manages the
* {@link getHistories prompt histories}.
*
* Different between `MicroAgentica` and {@link Agentica} is that
* `MicroAgentica` does not have function selecting filter. It directly
* list up every functions to the agent. Besides, {@link Agentica} has
* a function selecting mechanism to reduce the number of functions to
* be listed up to the agent.
*
* Therefore, if you have a lot of functions to call, you must not
* use this `MicroAgentica` class. Use this `MicroAgentica` class only
* when you have a few functions to call.
*
* - [Multi-agent orchestration of `@agentica`](https://wrtnlabs.io/agentica/docs/concepts/function-calling/#orchestration-strategy)
* - Internal agents of `MicroAgentica`
* - executor
* - describier
* - Internal agents of {@link Agentica}
* - initializer
* - **selector**
* - executor
* - describer
*
* @author Samchon
*/
class MicroAgentica {
/* -----------------------------------------------------------
CONSTRUCTOR
----------------------------------------------------------- */
/**
* Initializer Constructor.
*
* @param props Properties to construct the micro agent
*/
constructor(props) {
var _a;
this.props = props;
this.operations_ = AgenticaOperationComposer_1.AgenticaOperationComposer.compose({
controllers: props.controllers,
config: props.config,
});
this.histories_ = ((_a = props.histories) !== null && _a !== void 0 ? _a : []).map(input => (0, transformHistory_1.transformHistory)({
operations: this.operations_.group,
history: input,
}));
this.token_usage_ = this.props.tokenUsage !== undefined
? this.props.tokenUsage instanceof AgenticaTokenUsage_1.AgenticaTokenUsage
? this.props.tokenUsage
: new AgenticaTokenUsage_1.AgenticaTokenUsage(this.props.tokenUsage)
: AgenticaTokenUsage_1.AgenticaTokenUsage.zero();
this.listeners_ = new Map();
this.semaphore_ = props.vendor.semaphore != null
? typeof props.vendor.semaphore === "object"
? props.vendor.semaphore
: new tstl_1.Semaphore(props.vendor.semaphore)
: null;
}
/**
* @internal
*/
clone() {
var _a;
return new MicroAgentica(Object.assign(Object.assign({}, this.props), { histories: (_a = this.props.histories) === null || _a === void 0 ? void 0 : _a.slice() }));
}
/* -----------------------------------------------------------
ACCESSORS
----------------------------------------------------------- */
/**
* Conversate with the micro agent.
*
* User talks to the AI chatbot with the given content.
*
* When the user's conversation implies the AI chatbot to execute a
* function calling, the returned chat prompts will contain the
* function callinng information like {@link AgenticaExecuteHistory}
*
* @param content The content to talk
* @returns List of newly created histories
*/
conversate(content_1) {
return __awaiter(this, arguments, void 0, function* (content, options = {}) {
var _a, _b, _c;
const histories = [];
const dispatch = (event) => __awaiter(this, void 0, void 0, function* () {
try {
yield this.dispatch(event);
if ("toHistory" in event) {
if ("join" in event) {
histories.push(() => __awaiter(this, void 0, void 0, function* () {
yield event.join();
return event.toHistory();
}));
}
else {
histories.push(() => __awaiter(this, void 0, void 0, function* () { return event.toHistory(); }));
}
}
}
catch (_a) { }
});
const prompt = (0, events_1.createUserMessageEvent)({
contents: Array.isArray(content)
? content
: typeof content === "string"
? [{
type: "text",
text: content,
}]
: [content],
});
void dispatch(prompt).catch(() => { });
const ctx = this.getContext({
prompt,
dispatch,
usage: this.token_usage_,
abortSignal: options.abortSignal,
});
const executes = yield (0, orchestrate_1.call)(ctx, this.operations_.array);
// eslint-disable-next-line
if (executes.length && !!((_b = (_a = this.props.config) === null || _a === void 0 ? void 0 : _a.executor) === null || _b === void 0 ? void 0 : _b.describe)) {
const func = typeof this.props.config.executor.describe === "function"
? this.props.config.executor.describe
: orchestrate_1.describe;
yield func(ctx, executes);
}
const completed = yield Promise.all(histories.map((h) => __awaiter(this, void 0, void 0, function* () { return h(); })));
this.histories_.push(...completed);
// throw exception about failed execution
if (((_c = this.props.config) === null || _c === void 0 ? void 0 : _c.throw) !== false) {
for (const execute of executes) {
(0, assertExecuteFailure_1.assertExecuteFailure)(execute);
}
}
return completed;
});
}
/**
* Get configuration.
*/
getConfig() {
return this.props.config;
}
/**
* Get LLM vendor.
*/
getVendor() {
return this.props.vendor;
}
/**
* Get operations.
*
* Get list of operations, which has capsuled the pair of controller
* and function from the {@link getControllers controllers}.
*
* @returns List of operations
*/
getOperations() {
return this.operations_.array;
}
/**
* Get controllers.
*
* Get list of controllers, which are the collection of functions that
* the agent can execute.
*/
getControllers() {
return this.props.controllers;
}
/**
* Get the chatbot's histories.
*
* Get list of chat histories that the chatbot has been conversated.
*
* @returns List of chat histories
*/
getHistories() {
return this.histories_;
}
/**
* Get token usage of the AI chatbot.
*
* Entire token usage of the AI chatbot during the conversating
* with the user by {@link conversate} method callings.
*
* @returns Cost of the AI chatbot
*/
getTokenUsage() {
return this.token_usage_;
}
/**
* @internal
*/
getContext(props) {
const request = (0, request_1.getChatCompletionWithStreamingFunction)({
vendor: this.props.vendor,
config: this.props.config,
dispatch: props.dispatch,
abortSignal: props.abortSignal,
usage: this.token_usage_,
});
return {
operations: this.operations_,
config: this.props.config,
histories: this.histories_,
prompt: props.prompt,
dispatch: props.dispatch,
request: this.semaphore_ === null
? request
: (source, body) => __awaiter(this, void 0, void 0, function* () {
yield this.semaphore_.acquire();
try {
return yield request(source, body);
}
finally {
void this.semaphore_.release().catch(() => { });
}
}),
};
}
/* -----------------------------------------------------------
EVENT HANDLERS
----------------------------------------------------------- */
/**
* Add an event listener.
*
* Add an event listener to be called whenever the event is emitted.
*
* @param type Type of event
* @param listener Callback function to be called whenever the event is emitted
*/
on(type, listener) {
/**
* @TODO remove `as`
*/
(0, __map_take_1.__map_take)(this.listeners_, type, () => new Set()).add(listener);
return this;
}
/**
* Erase an event listener.
*
* Erase an event listener to stop calling the callback function.
*
* @param type Type of event
* @param listener Callback function to erase
*/
off(type, listener) {
const set = this.listeners_.get(type);
if (set !== undefined) {
/**
* @TODO remove `as`
*/
set.delete(listener);
if (set.size === 0) {
this.listeners_.delete(type);
}
}
return this;
}
dispatch(event) {
return __awaiter(this, void 0, void 0, function* () {
const set = this.listeners_.get(event.type);
if (set !== undefined) {
yield Promise.all(Array.from(set).map((listener) => __awaiter(this, void 0, void 0, function* () {
try {
yield listener(event);
}
catch (_a) {
/* empty */
}
})));
}
});
}
}
exports.MicroAgentica = MicroAgentica;
//# sourceMappingURL=MicroAgentica.js.map