@agentica/core
Version:
Agentic AI Library specialized in LLM Function Calling
409 lines • 20.8 kB
JavaScript
"use strict";
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 ChatGptCompletionMessageUtil_1 = require("../utils/ChatGptCompletionMessageUtil");
const StreamUtil_1 = require("../utils/StreamUtil");
const selectFunctionFromContext_1 = require("./internal/selectFunctionFromContext");
const CONTAINER = {
model: "chatgpt",
options: {
reference: true,
strict: false,
separate: null
},
functions: [
{
name: "selectFunctions",
parameters: {
description: " Properties of the function\n\n------------------------------\n\nCurrent 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) => {
events.push(e);
return 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(ctx.dispatch);
}
});
}
function step(ctx, operations, retry, failures) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g;
// ----
// EXECUTE CHATGPT API
// ----
const completionStream = 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),
},
// 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 chunks = yield StreamUtil_1.StreamUtil.readAll(completionStream);
const completion = ChatGptCompletionMessageUtil_1.ChatGptCompletionMessageUtil.merge(chunks);
// ----
// VALIDATION
// ----
if (retry++ < ((_f = (_e = ctx.config) === null || _e === void 0 ? void 0 : _e.retry) !== null && _f !== void 0 ? _f : AgenticaConstant_1.AgenticaConstant.RETRY)) {
const failures = [];
for (const choice of completion.choices) {
for (const tc of (_g = choice.message.tool_calls) !== null && _g !== void 0 ? _g : []) {
if (tc.function.name !== "selectFunctions") {
continue;
}
const input = JSON.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);
}
}
}
// ASSISTANT MESSAGE
if (choice.message.role === "assistant"
&& choice.message.content != null
&& choice.message.content.length !== 0) {
const event = (0, events_1.createAssistantMessageEvent)({
stream: (0, StreamUtil_1.toAsyncGenerator)(choice.message.content),
join: () => __awaiter(this, void 0, void 0, function* () { return Promise.resolve(choice.message.content); }),
done: () => true,
get: () => choice.message.content,
});
ctx.dispatch(event);
}
}
});
}
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