@agentica/core
Version:
Agentic AI Library specialized in LLM Function Calling
445 lines • 23 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.select = select;
const __typia_transform__validateReport = __importStar(require("typia/lib/internal/_validateReport.js"));
const typia_1 = __importDefault(require("typia"));
const AgenticaConstant_1 = require("../constants/AgenticaConstant");
const AgenticaDefaultPrompt_1 = require("../constants/AgenticaDefaultPrompt");
const AgenticaSystemPrompt_1 = require("../constants/AgenticaSystemPrompt");
const events_1 = require("../factory/events");
const histories_1 = require("../factory/histories");
const __retry_1 = require("../utils/__retry");
const AssistantMessageEmptyError_1 = require("../utils/AssistantMessageEmptyError");
const ChatGptCompletionStreamingUtil_1 = require("../utils/ChatGptCompletionStreamingUtil");
const JsonUtil_1 = require("../utils/JsonUtil");
const StreamUtil_1 = require("../utils/StreamUtil");
const selectFunctionFromContext_1 = require("./internal/selectFunctionFromContext");
const CONTAINER = {
config: {
reference: true,
strict: false,
separate: null,
validate: null
},
functions: [
{
name: "selectFunctions",
parameters: {
description: "Current Type: {@link __IChatFunctionReference.IProps}",
type: "object",
properties: {
functions: {
description: "List of target functions.",
type: "array",
items: {
$ref: "#/$defs/___IChatFunctionReference"
}
}
},
required: [
"functions"
],
additionalProperties: false,
$defs: {
___IChatFunctionReference: {
type: "object",
properties: {
reason: {
description: "The reason of the function selection.\n\nJust write the reason why you've determined to select this function.",
type: "string"
},
name: {
description: "Name of the target function to call.",
type: "string"
}
},
required: [
"reason",
"name"
]
}
}
},
description: "Select proper API functions to call.\n\nIf you A.I. agent has found some proper API functions to call\nfrom the conversation with user, please select the API functions\njust by calling this function.\n\nWhen user wants to call a same function multiply, you A.I. agent must\nlist up it multiply in the `functions` property. Otherwise the user has\nrequested to call many different functions, you A.I. agent have to assign\nthem all into the `functions` property.\n\nAlso, if you A.I. agent can't specify a specific function to call due to lack\nof specificity or homogeneity of candidate functions, just assign all of them\nby in the` functions` property` too. Instead, when you A.I. agent can specify\na specific function to call, the others would be eliminated.",
validate: (() => { const _io0 = input => Array.isArray(input.functions) && input.functions.every(elem => "object" === typeof elem && null !== elem && _io1(elem)); const _io1 = input => "string" === typeof input.reason && "string" === typeof input.name; const _vo0 = (input, _path, _exceptionable = true) => [(Array.isArray(input.functions) || _report(_exceptionable, {
path: _path + ".functions",
expected: "Array<___IChatFunctionReference>",
value: input.functions
})) && input.functions.map((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
path: _path + ".functions[" + _index2 + "]",
expected: "___IChatFunctionReference",
value: elem
})) && _vo1(elem, _path + ".functions[" + _index2 + "]", true && _exceptionable) || _report(_exceptionable, {
path: _path + ".functions[" + _index2 + "]",
expected: "___IChatFunctionReference",
value: elem
})).every(flag => flag) || _report(_exceptionable, {
path: _path + ".functions",
expected: "Array<___IChatFunctionReference>",
value: input.functions
})].every(flag => flag); const _vo1 = (input, _path, _exceptionable = true) => ["string" === typeof input.reason || _report(_exceptionable, {
path: _path + ".reason",
expected: "string",
value: input.reason
}), "string" === typeof input.name || _report(_exceptionable, {
path: _path + ".name",
expected: "string",
value: input.name
})].every(flag => flag); const __is = input => "object" === typeof input && null !== input && _io0(input); let errors; let _report; return input => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
path: _path + "",
expected: "__IChatFunctionReference.IProps",
value: input
})) && _vo0(input, _path + "", true) || _report(true, {
path: _path + "",
expected: "__IChatFunctionReference.IProps",
value: input
}))(input, "$input", true);
const success = 0 === errors.length;
return success ? {
success,
data: input
} : {
success,
errors,
data: input
};
}
return {
success: true,
data: input
};
}; })()
}
]
};
function select(ctx) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
if (ctx.operations.divided === undefined) {
return step(ctx, ctx.operations.array, 0);
}
const stacks = ctx.operations.divided.map(() => []);
const events = [];
yield Promise.all(ctx.operations.divided.map((operations, i) => __awaiter(this, void 0, void 0, function* () {
return step(Object.assign(Object.assign({}, ctx), { stack: stacks[i], dispatch: (e) => __awaiter(this, void 0, void 0, function* () {
events.push(e);
}) }), operations, 0);
})));
// ELITICISM
if (((_b = (_a = ctx.config) === null || _a === void 0 ? void 0 : _a.eliticism) !== null && _b !== void 0 ? _b : AgenticaConstant_1.AgenticaConstant.ELITICISM) === true
&& stacks.some(s => s.length !== 0)) {
return step(ctx, stacks
.flat()
.map(s => ctx.operations.group
.get(s.operation.controller.name)
.get(s.operation.function.name)), 0);
}
else {
const selected = events.filter(e => e.type === "select");
(selected.length !== 0 ? selected : events)
.forEach((e) => {
void ctx.dispatch(e).catch(() => { });
});
}
});
}
function step(ctx, operations, retry, failures) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c;
const _retryFn = (0, __retry_1.__get_retry)(1);
const retryFn = (fn) => __awaiter(this, void 0, void 0, function* () {
return _retryFn(fn).catch((e) => {
if (e instanceof AssistantMessageEmptyError_1.AssistantMessageEmptyError) {
return Symbol("emptyAssistantMessage");
}
throw e;
});
});
// ----
// EXECUTE CHATGPT API
// ----
const completion = yield retryFn((prevError) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g;
const stream = yield ctx.request("select", {
messages: [
// COMMON SYSTEM PROMPT
{
role: "system",
content: AgenticaDefaultPrompt_1.AgenticaDefaultPrompt.write(ctx.config),
},
// CANDIDATE FUNCTIONS
{
role: "assistant",
tool_calls: [
{
type: "function",
id: "getApiFunctions",
function: {
name: "getApiFunctions",
arguments: JSON.stringify({}),
},
},
],
},
{
role: "tool",
tool_call_id: "getApiFunctions",
content: JSON.stringify(operations.map(op => (Object.assign({ name: op.name, description: op.function.description }, (op.protocol === "http"
? {
method: op.function.method,
path: op.function.path,
tags: op.function.tags,
}
: {}))))),
},
// PREVIOUS HISTORIES
...ctx.histories.map(histories_1.decodeHistory).flat(),
// USER INPUT
{
role: "user",
content: ctx.prompt.contents.map(histories_1.decodeUserMessageContent),
},
// PREVIOUS ERROR
...(prevError instanceof AssistantMessageEmptyError_1.AssistantMessageEmptyWithReasoningError
? [
{
role: "assistant",
content: prevError.reasoning,
},
]
: []),
// SYSTEM PROMPT
{
role: "system",
content: (_d = (_c = (_b = (_a = ctx.config) === null || _a === void 0 ? void 0 : _a.systemPrompt) === null || _b === void 0 ? void 0 : _b.select) === null || _c === void 0 ? void 0 : _c.call(_b, ctx.histories)) !== null && _d !== void 0 ? _d : AgenticaSystemPrompt_1.AgenticaSystemPrompt.SELECT,
},
// TYPE CORRECTIONS
...emendMessages(failures !== null && failures !== void 0 ? failures : []),
],
// STACK FUNCTIONS
tools: [{
type: "function",
function: {
name: CONTAINER.functions[0].name,
description: CONTAINER.functions[0].description,
/**
* @TODO fix it
* The property and value have a type mismatch, but it works.
*/
parameters: CONTAINER.functions[0].parameters,
},
}],
tool_choice: retry === 0
? "auto"
: "required",
// parallel_tool_calls: false,
});
const completion = yield (0, ChatGptCompletionStreamingUtil_1.reduceStreamingWithDispatch)(stream, (props) => {
const event = (0, events_1.createAssistantMessageEvent)(props);
void ctx.dispatch(event).catch(() => { });
}, ctx.abortSignal);
const allAssistantMessagesEmpty = completion.choices.every(v => v.message.tool_calls == null && v.message.content === "");
if (allAssistantMessagesEmpty) {
const firstChoice = completion.choices.at(0);
if (((_e = firstChoice === null || firstChoice === void 0 ? void 0 : firstChoice.message) === null || _e === void 0 ? void 0 : _e.reasoning) != null) {
throw new AssistantMessageEmptyError_1.AssistantMessageEmptyWithReasoningError((_g = (_f = firstChoice === null || firstChoice === void 0 ? void 0 : firstChoice.message) === null || _f === void 0 ? void 0 : _f.reasoning) !== null && _g !== void 0 ? _g : "");
}
throw new AssistantMessageEmptyError_1.AssistantMessageEmptyError();
}
return completion;
}));
if (typeof completion === "symbol") {
const event = (0, events_1.createAssistantMessageEvent)({
stream: (0, StreamUtil_1.toAsyncGenerator)(""),
done: () => true,
get: () => "",
join: () => __awaiter(this, void 0, void 0, function* () {
return "";
}),
});
void ctx.dispatch(event).catch(() => { });
return;
}
// ----
// VALIDATION
// ----
if (retry++ < ((_b = (_a = ctx.config) === null || _a === void 0 ? void 0 : _a.retry) !== null && _b !== void 0 ? _b : AgenticaConstant_1.AgenticaConstant.RETRY)) {
const failures = [];
for (const choice of completion.choices) {
for (const tc of (_c = choice.message.tool_calls) !== null && _c !== void 0 ? _c : []) {
if (tc.type !== "function" || tc.function.name !== "selectFunctions") {
continue;
}
const input = JsonUtil_1.JsonUtil.parse(tc.function.arguments);
const validation = (() => { const _io0 = input => Array.isArray(input.functions) && input.functions.every(elem => "object" === typeof elem && null !== elem && _io1(elem)); const _io1 = input => "string" === typeof input.reason && "string" === typeof input.name; const _vo0 = (input, _path, _exceptionable = true) => [(Array.isArray(input.functions) || _report(_exceptionable, {
path: _path + ".functions",
expected: "Array<___IChatFunctionReference>",
value: input.functions
})) && input.functions.map((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
path: _path + ".functions[" + _index2 + "]",
expected: "___IChatFunctionReference",
value: elem
})) && _vo1(elem, _path + ".functions[" + _index2 + "]", true && _exceptionable) || _report(_exceptionable, {
path: _path + ".functions[" + _index2 + "]",
expected: "___IChatFunctionReference",
value: elem
})).every(flag => flag) || _report(_exceptionable, {
path: _path + ".functions",
expected: "Array<___IChatFunctionReference>",
value: input.functions
})].every(flag => flag); const _vo1 = (input, _path, _exceptionable = true) => ["string" === typeof input.reason || _report(_exceptionable, {
path: _path + ".reason",
expected: "string",
value: input.reason
}), "string" === typeof input.name || _report(_exceptionable, {
path: _path + ".name",
expected: "string",
value: input.name
})].every(flag => flag); const __is = input => "object" === typeof input && null !== input && _io0(input); let errors; let _report; return input => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
path: _path + "",
expected: "__IChatFunctionReference.IProps",
value: input
})) && _vo0(input, _path + "", true) || _report(true, {
path: _path + "",
expected: "__IChatFunctionReference.IProps",
value: input
}))(input, "$input", true);
const success = 0 === errors.length;
return success ? {
success,
data: input
} : {
success,
errors,
data: input
};
}
return {
success: true,
data: input
};
}; })()(input);
if (validation.success === false) {
failures.push({
id: tc.id,
name: tc.function.name,
validation,
});
}
}
}
if (failures.length > 0) {
return step(ctx, operations, retry, failures);
}
}
// ----
// PROCESS COMPLETION
// ----
for (const choice of completion.choices) {
// FUNCTION CALLING
if (choice.message.tool_calls != null) {
for (const tc of choice.message.tool_calls) {
if (tc.type !== "function") {
continue;
}
else if (tc.function.name !== "selectFunctions") {
continue;
}
const input = (() => { const _io0 = input => Array.isArray(input.functions) && input.functions.every(elem => "object" === typeof elem && null !== elem && _io1(elem)); const _io1 = input => "string" === typeof input.reason && "string" === typeof input.name; const __is = input => "object" === typeof input && null !== input && _io0(input); return input => { input = JSON.parse(input); return __is(input) ? input : null; }; })()(tc.function.arguments);
if (input === null) {
continue;
}
for (const reference of input.functions) {
(0, selectFunctionFromContext_1.selectFunctionFromContext)(ctx, reference);
}
}
}
}
});
}
function emendMessages(failures) {
return failures
.map(f => [
{
role: "assistant",
tool_calls: [
{
type: "function",
id: f.id,
function: {
name: f.name,
arguments: JSON.stringify(f.validation.data),
},
},
],
},
{
role: "tool",
content: JSON.stringify(f.validation.errors),
tool_call_id: f.id,
},
{
role: "system",
content: [
"You A.I. assistant has composed wrong typed arguments.",
"",
"Correct it at the next function calling.",
].join("\n"),
},
])
.flat();
}
//# sourceMappingURL=select.js.map