@agentica/vector-selector 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/lib/embed.d.ts +0 -0
- package/lib/embed.js +2 -0
- package/lib/embed.js.map +1 -0
- package/lib/extract_query.d.ts +3 -0
- package/lib/extract_query.js +53 -0
- package/lib/extract_query.js.map +1 -0
- package/lib/index.d.ts +20 -0
- package/lib/index.js +52 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +312 -0
- package/lib/index.mjs.map +1 -0
- package/lib/select.d.ts +17 -0
- package/lib/select.js +197 -0
- package/lib/select.js.map +1 -0
- package/lib/strategy/index.d.ts +1 -0
- package/lib/strategy/index.js +18 -0
- package/lib/strategy/index.js.map +1 -0
- package/lib/strategy/postgres.strategy.d.ts +4 -0
- package/lib/strategy/postgres.strategy.js +87 -0
- package/lib/strategy/postgres.strategy.js.map +1 -0
- package/lib/tools.d.ts +62 -0
- package/lib/tools.js +95 -0
- package/lib/tools.js.map +1 -0
- package/lib/utils.d.ts +52 -0
- package/lib/utils.js +108 -0
- package/lib/utils.js.map +1 -0
- package/lib/utils.test.d.ts +1 -0
- package/package.json +76 -0
- package/src/embed.ts +0 -0
- package/src/extract_query.ts +47 -0
- package/src/index.ts +78 -0
- package/src/select.ts +217 -0
- package/src/strategy/index.ts +1 -0
- package/src/strategy/postgres.strategy.ts +117 -0
- package/src/tools.ts +99 -0
- package/src/utils.test.ts +185 -0
- package/src/utils.ts +105 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Wrtn Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Agentica, AI Function Calling Framework
|
|
2
|
+
|
|
3
|
+
<!-- https://github.com/user-attachments/assets/5326cc59-5129-470d-abcb-c3f458b5c488 -->
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
[](https://github.com/wrtnlabs/agentica/blob/master/LICENSE)
|
|
8
|
+
[](https://www.npmjs.com/package/@agentica/core)
|
|
9
|
+
[](https://www.npmjs.com/package/@agentica/core)
|
|
10
|
+
[](https://github.com/wrtnlabs/agentica/actions?query=workflow%3Abuild)
|
|
11
|
+
[](https://wrtnlabs.io/agentica/)
|
|
12
|
+
[](https://discord.gg/aMhRmzkqCx)
|
|
13
|
+
|
|
14
|
+
Agentic AI framework specialized in AI Function Calling.
|
|
15
|
+
|
|
16
|
+
Don't be afraid of AI agent development. Just list functions from three protocols below. This is everything you should do for AI agent development.
|
|
17
|
+
|
|
18
|
+
- TypeScript Class
|
|
19
|
+
- Swagger/OpenAPI Document
|
|
20
|
+
- MCP (Model Context Protocol) Server
|
|
21
|
+
|
|
22
|
+
Wanna make an e-commerce agent? Bring in e-commerce functions. Need a newspaper agent? Get API functions from the newspaper company. Just prepare any functions that you need, then it becomes an AI agent.
|
|
23
|
+
|
|
24
|
+
Are you a TypeScript developer? Then you're already an AI developer. Familiar with backend development? You're already well-versed in AI development. Anyone who can make functions can make AI agents.
|
|
25
|
+
|
|
26
|
+
<!-- eslint-skip -->
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { Agentica, assertHttpLlmApplication } from "@agentica/core";
|
|
30
|
+
import OpenAI from "openai";
|
|
31
|
+
import typia from "typia";
|
|
32
|
+
|
|
33
|
+
import { MobileFileSystem } from "./services/MobileFileSystem";
|
|
34
|
+
|
|
35
|
+
const agent = new Agentica({
|
|
36
|
+
vendor: {
|
|
37
|
+
api: new OpenAI({ apiKey: "********" }),
|
|
38
|
+
model: "gpt-4o-mini",
|
|
39
|
+
},
|
|
40
|
+
controllers: [
|
|
41
|
+
// functions from TypeScript class
|
|
42
|
+
{
|
|
43
|
+
protocol: "http",
|
|
44
|
+
application: typia.llm.application<MobileFileSystem, "chatgpt">(),
|
|
45
|
+
execute: new MobileFileSystem(),
|
|
46
|
+
},
|
|
47
|
+
// functions from Swagger/OpenAPI
|
|
48
|
+
{
|
|
49
|
+
protocol: "http",
|
|
50
|
+
application: assertHttpLlmApplication({
|
|
51
|
+
model: "chatgpt",
|
|
52
|
+
document: await fetch(
|
|
53
|
+
"https://shopping-be.wrtn.ai/editor/swagger.json",
|
|
54
|
+
).then(r => r.json()),
|
|
55
|
+
}),
|
|
56
|
+
connection: {
|
|
57
|
+
host: "https://shopping-be.wrtn.ai",
|
|
58
|
+
headers: { Authorization: "Bearer ********" },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
await agent.conversate("I wanna buy MacBook Pro");
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 📦 Setup
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
$ npx agentica start <directory>
|
|
70
|
+
|
|
71
|
+
----------------------------------------
|
|
72
|
+
Agentica Setup Wizard
|
|
73
|
+
----------------------------------------
|
|
74
|
+
? Package Manager (use arrow keys)
|
|
75
|
+
> npm
|
|
76
|
+
pnpm
|
|
77
|
+
yarn (berry is not supported)
|
|
78
|
+
? Project Type
|
|
79
|
+
NodeJS Agent Server
|
|
80
|
+
> NestJS Agent Server
|
|
81
|
+
React Client Application
|
|
82
|
+
Standalone Application
|
|
83
|
+
? Embedded Controllers (multi-selectable)
|
|
84
|
+
(none)
|
|
85
|
+
Google Calendar
|
|
86
|
+
Google News
|
|
87
|
+
> Github
|
|
88
|
+
Reddit
|
|
89
|
+
Slack
|
|
90
|
+
...
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The setup wizard helps you create a new project tailored to your needs.
|
|
94
|
+
|
|
95
|
+
For reference, when selecting a project type, any option other than "Standalone Application" will implement the [WebSocket Protocol](https://wrtnlabs.io/agentica/docs/websocket/) for client-server communication.
|
|
96
|
+
|
|
97
|
+
For comprehensive setup instructions, visit our [Getting Started](https://wrtnlabs.io/agentica/docs/) guide.
|
|
98
|
+
|
|
99
|
+
## 💻 Playground
|
|
100
|
+
|
|
101
|
+
Experience Agentica firsthand through our [interactive playground](https://wrtnlabs.io/agentica/playground) before installing.
|
|
102
|
+
|
|
103
|
+
Our demonstrations showcase the power and simplicity of Agentica's function calling capabilities across different integration methods.
|
|
104
|
+
|
|
105
|
+
- [TypeScript Class](https://wrtnlabs.io/agentica/playground/bbs)
|
|
106
|
+
- [Swagger/OpenAPI Document](https://wrtnlabs.io/agentica/playground/swagger)
|
|
107
|
+
- [Enterprise E-commerce Agent](https://wrtnlabs.io/agentica/playground/shopping)
|
|
108
|
+
|
|
109
|
+
<!--
|
|
110
|
+
@todo this section would be changed after making tutorial playground
|
|
111
|
+
-->
|
|
112
|
+
|
|
113
|
+
## 📚 Documentation Resources
|
|
114
|
+
|
|
115
|
+
Find comprehensive resources at our [official website](https://wrtnlabs.io/agentica).
|
|
116
|
+
|
|
117
|
+
- [Home](https://wrtnlabs.io/agentica)
|
|
118
|
+
- [Guide Documents](https://wrtnlabs.io/agentica/docs)
|
|
119
|
+
- [Tutorial](https://wrtnlabs.io/agentica/tutorial)
|
|
120
|
+
- [API Documents](https://wrtnlabs.io/agentica/api)
|
|
121
|
+
- [Youtube](https://www.youtube.com/@wrtnlabs)
|
|
122
|
+
- [Paper](https://wrtnlabs.io/agentica/paper)
|
|
123
|
+
|
|
124
|
+
## 🌟 Why Agentica?
|
|
125
|
+
|
|
126
|
+
```mermaid
|
|
127
|
+
flowchart
|
|
128
|
+
subgraph "JSON Schema Specification"
|
|
129
|
+
schemav4("JSON Schema v4 ~ v7") --upgrades--> emended[["OpenAPI v3.1 (emended)"]]
|
|
130
|
+
schema2910("JSON Schema 2019-03") --upgrades--> emended
|
|
131
|
+
schema2020("JSON Schema 2020-12") --emends--> emended
|
|
132
|
+
end
|
|
133
|
+
subgraph "Agentica"
|
|
134
|
+
emended --"Artificial Intelligence"--> fc{{"AI Function Calling"}}
|
|
135
|
+
fc --"OpenAI"--> chatgpt("ChatGPT")
|
|
136
|
+
fc --"Google"--> gemini("Gemini")
|
|
137
|
+
fc --"Anthropic"--> claude("Claude")
|
|
138
|
+
fc --"High-Flyer"--> deepseek("DeepSeek")
|
|
139
|
+
fc --"Meta"--> llama("Llama")
|
|
140
|
+
chatgpt --"3.1"--> custom(["Custom JSON Schema"])
|
|
141
|
+
gemini --"3.0"--> custom(["Custom JSON Schema"])
|
|
142
|
+
claude --"3.1"--> standard(["Standard JSON Schema"])
|
|
143
|
+
deepseek --"3.1"--> standard
|
|
144
|
+
llama --"3.1"--> standard
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Agentica enhances AI function calling by the following strategies:
|
|
149
|
+
|
|
150
|
+
- [**JSON schema conversion**](https://wrtnlabs.io/agentica/docs/core/vendor/#schema-specification): Automatically handles specification differences between LLM vendors, ensuring seamless integration regardless of your chosen AI model.
|
|
151
|
+
- [**Validation Feedback**](https://wrtnlabs.io/agentica/docs/concepts/function-calling#validation-feedback): Detects and corrects AI mistakes in argument composition, dramatically reducing errors and improving reliability.
|
|
152
|
+
- [**Selector Agent**](https://wrtnlabs.io/agentica/docs/concepts/function-calling#orchestration-strategy): Filtering candidate functions to minimize context usage, optimize performance, and reduce token consumption.
|
|
153
|
+
|
|
154
|
+
Thanks to these innovations, Agentica makes AI function calling easier, safer, and more accurate than before. Development becomes more intuitive since you only need to prepare functions relevant to your specific use case, and scaling your agent's capabilities is as simple as adding or removing functions.
|
|
155
|
+
|
|
156
|
+
In 2023, when OpenAI announced function calling, many predicted that function calling-driven AI development would become the mainstream. However, in reality, due to the difficulty and instability of function calling, the trend in AI development became agent workflow. Agent workflow, which is inflexible and must be created for specific purposes, has conquered the AI agent ecosystem.
|
|
157
|
+
By the way, as Agentica has resolved the difficulty and instability problems of function calling, the time has come to embrace function-driven AI development once again.
|
|
158
|
+
|
|
159
|
+
| Type | Workflow | Vanilla Function Calling | Agentica Function Calling |
|
|
160
|
+
| ----------- | ------------- | ------------------------ | ------------------------- |
|
|
161
|
+
| Purpose | ❌ Specific | 🟢 General | 🟢 General |
|
|
162
|
+
| Difficulty | ❌ Difficult | ❌ Difficult | 🟢 Easy |
|
|
163
|
+
| Stability | 🟢 Stable | ❌ Unstable | 🟢 Stable |
|
|
164
|
+
| Flexibility | ❌ Inflexible | 🟢 Flexible | 🟢 Flexible |
|
package/lib/embed.d.ts
ADDED
|
File without changes
|
package/lib/embed.js
ADDED
package/lib/embed.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed.js","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.extractQuery = extractQuery;
|
|
13
|
+
const core_1 = require("@agentica/core");
|
|
14
|
+
const tools_1 = require("./tools");
|
|
15
|
+
function extractQuery(ctx) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
const completionStream = yield ctx.request("select", {
|
|
19
|
+
messages: [
|
|
20
|
+
{
|
|
21
|
+
role: "system",
|
|
22
|
+
content: [
|
|
23
|
+
"You are a function searcher. You will extract search queries from the user's message, and the query results will be function names.",
|
|
24
|
+
"A query is a 2–3 sentence description of the action the user needs to perform.",
|
|
25
|
+
"Therefore, the extracted queries must be suitable for function search.",
|
|
26
|
+
"You need to identify the actions required to achieve what the user wants and extract queries that can be used to search for those actions.",
|
|
27
|
+
"Extract only one query per task.",
|
|
28
|
+
].join("\n"),
|
|
29
|
+
},
|
|
30
|
+
...ctx.histories
|
|
31
|
+
.map((core_1.factory.decodeHistory))
|
|
32
|
+
.flat(),
|
|
33
|
+
{
|
|
34
|
+
role: "user",
|
|
35
|
+
content: ctx.prompt.text,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
tool_choice: "required",
|
|
39
|
+
tools: [tools_1.Tools.extract_query],
|
|
40
|
+
});
|
|
41
|
+
const chunks = yield core_1.utils.StreamUtil.readAll(completionStream);
|
|
42
|
+
const completion = core_1.utils.ChatGptCompletionMessageUtil.merge(chunks);
|
|
43
|
+
const queries = (_c = (_b = (_a = completion.choices[0]) === null || _a === void 0 ? void 0 : _a.message.tool_calls) === null || _b === void 0 ? void 0 : _b.flatMap((v) => {
|
|
44
|
+
const arg = JSON.parse(v.function.arguments);
|
|
45
|
+
if (!Array.isArray(arg.query_list)) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return arg.query_list.map(v => v.query);
|
|
49
|
+
})) !== null && _c !== void 0 ? _c : [];
|
|
50
|
+
return queries;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=extract_query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract_query.js","sourceRoot":"","sources":["../src/extract_query.ts"],"names":[],"mappings":";;;;;;;;;;;AAQA,oCAsCC;AA1CD,yCAAgD;AAEhD,mCAAgC;AAEhC,SAAsB,YAAY,CAAuC,GAAiC;;;QACxG,MAAM,gBAAgB,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE;YACnD,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE;wBACP,qIAAqI;wBACrI,gFAAgF;wBAChF,wEAAwE;wBACxE,4IAA4I;wBAC5I,kCAAkC;qBACnC,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb;gBACD,GAAG,GAAG,CAAC,SAAS;qBACb,GAAG,CAAC,CAAA,cAAO,CAAC,aAA0B,CAAA,CAAC;qBACvC,IAAI,EAAE;gBACT;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI;iBACzB;aACF;YACD,WAAW,EAAE,UAAU;YAEvB,KAAK,EAAE,CAAC,aAAK,CAAC,aAAa,CAAC;SAC7B,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,YAAK,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,YAAK,CAAC,4BAA4B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAA,MAAA,MAAA,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,0CAAE,OAAO,CAAC,UAAU,0CAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAwE,CAAC;YACpH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC,CAAC,mCAAI,EAAE,CAAC;QAET,OAAO,OAAO,CAAC;IACjB,CAAC;CAAA"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgenticaContext, AgenticaHistory } from "@agentica/core";
|
|
2
|
+
import type { ILlmSchema } from "@samchon/openapi";
|
|
3
|
+
export interface IAgenticaVectorSelectorBootProps<SchemaModel extends ILlmSchema.Model> {
|
|
4
|
+
strategy: IAgenticaVectorSelectorStrategy<SchemaModel>;
|
|
5
|
+
}
|
|
6
|
+
export interface IAgenticaVectorSelectorStrategy<SchemaModel extends ILlmSchema.Model> {
|
|
7
|
+
searchTool: (ctx: AgenticaContext<SchemaModel>, query: string) => Promise<{
|
|
8
|
+
name: string;
|
|
9
|
+
description: string | undefined;
|
|
10
|
+
}[]>;
|
|
11
|
+
embedContext: (props: {
|
|
12
|
+
ctx: AgenticaContext<SchemaModel>;
|
|
13
|
+
setEmbedded: () => void;
|
|
14
|
+
}) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export declare function BootAgenticaVectorSelector<SchemaModel extends ILlmSchema.Model>(props: IAgenticaVectorSelectorBootProps<SchemaModel>): (ctx: AgenticaContext<SchemaModel>) => Promise<AgenticaHistory<SchemaModel>[]>;
|
|
17
|
+
export declare function useEmbeddedContext<SchemaModel extends ILlmSchema.Model>(): {
|
|
18
|
+
readonly isEmbedded: (ctx: AgenticaContext<SchemaModel>) => boolean;
|
|
19
|
+
readonly setEmbedded: (ctx: AgenticaContext<SchemaModel>) => void;
|
|
20
|
+
};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.BootAgenticaVectorSelector = BootAgenticaVectorSelector;
|
|
13
|
+
exports.useEmbeddedContext = useEmbeddedContext;
|
|
14
|
+
const extract_query_1 = require("./extract_query");
|
|
15
|
+
const select_1 = require("./select");
|
|
16
|
+
const utils_1 = require("./utils");
|
|
17
|
+
function BootAgenticaVectorSelector(props) {
|
|
18
|
+
const { isEmbedded, setEmbedded } = useEmbeddedContext();
|
|
19
|
+
const { searchTool, embedContext } = props.strategy;
|
|
20
|
+
const selectorExecute = (ctx) => __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
if (!isEmbedded(ctx)) {
|
|
22
|
+
yield embedContext({ ctx, setEmbedded: () => setEmbedded(ctx) });
|
|
23
|
+
}
|
|
24
|
+
const queries = yield (0, extract_query_1.extractQuery)(ctx);
|
|
25
|
+
const toolList = yield Promise.all(queries.map((query) => __awaiter(this, void 0, void 0, function* () { return searchTool(ctx, query); }))).then(res => res.flatMap(output => output.map(v => ({
|
|
26
|
+
name: v.name,
|
|
27
|
+
description: v.description,
|
|
28
|
+
}))).map((v) => {
|
|
29
|
+
const op = ctx.operations.flat.get(v.name);
|
|
30
|
+
if (op === undefined || op.protocol !== "http") {
|
|
31
|
+
return v;
|
|
32
|
+
}
|
|
33
|
+
return Object.assign(Object.assign({}, v), { method: op.function.method, path: op.function.path, tags: op.function.tags });
|
|
34
|
+
})).then(arr => (0, utils_1.uniqBy)(arr, v => v.name));
|
|
35
|
+
if (toolList.length === 0) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const prompts = yield (0, select_1.selectFunction)({ ctx, toolList });
|
|
39
|
+
return prompts;
|
|
40
|
+
});
|
|
41
|
+
return selectorExecute;
|
|
42
|
+
}
|
|
43
|
+
function useEmbeddedContext() {
|
|
44
|
+
const set = new Set();
|
|
45
|
+
return {
|
|
46
|
+
isEmbedded: (ctx) => set.has(JSON.stringify(ctx.operations.array)),
|
|
47
|
+
setEmbedded: (ctx) => {
|
|
48
|
+
set.add(JSON.stringify(ctx.operations.array));
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;AAuBA,gEA2CC;AAED,gDASC;AA1ED,mDAA+C;AAC/C,qCAA0C;AAC1C,mCAAiC;AAkBjC,SAAgB,0BAA0B,CAAuC,KAAoD;IACnI,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,kBAAkB,EAAe,CAAC;IACtE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC;IACpD,MAAM,eAAe,GAAG,CACtB,GAAiC,EACQ,EAAE;QAC3C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAA,4BAAY,EAAC,GAAG,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,OAAO,CAAC,GAAG,CAAC,CAAM,KAAK,EAAC,EAAE,gDAAC,OAAA,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA,GAAA,CAAC,CACnD,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACX,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CACnB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACf,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC,CACJ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gBAC/C,OAAO,CAAC,CAAC;YACX,CAAC;YAED,uCACK,CAAC,KACJ,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAC1B,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EACtB,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,IACtB;QACJ,CAAC,CAAC,CACH,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAA,cAAM,EAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAExC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAA,uBAAc,EAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAA,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,SAAgB,kBAAkB;IAChC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,OAAO;QACL,UAAU,EAAE,CAAC,GAAiC,EAAE,EAAE,CAChD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/C,WAAW,EAAE,CAAC,GAAiC,EAAE,EAAE;YACjD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC;KACO,CAAC;AACb,CAAC"}
|
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { factory, utils } from "@agentica/core";
|
|
2
|
+
|
|
3
|
+
import { AgenticaDefaultPrompt } from "@agentica/core/src/constants/AgenticaDefaultPrompt";
|
|
4
|
+
|
|
5
|
+
import { AgenticaSystemPrompt } from "@agentica/core/src/constants/AgenticaSystemPrompt";
|
|
6
|
+
|
|
7
|
+
const Tools = {
|
|
8
|
+
extract_query: {
|
|
9
|
+
type: "function",
|
|
10
|
+
function: {
|
|
11
|
+
name: "extract_search_query",
|
|
12
|
+
description: "extract search query from user message\n",
|
|
13
|
+
parameters: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
query_list: {
|
|
17
|
+
type: "array",
|
|
18
|
+
items: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
reason: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "The reason of the query selection.\n\nJust write the reason why you've determined to select this query."
|
|
24
|
+
},
|
|
25
|
+
query: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "the search query"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
required: [ "reason", "query" ]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
required: [ "query_list" ]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
select_functions: {
|
|
39
|
+
type: "function",
|
|
40
|
+
function: {
|
|
41
|
+
name: "select_functions",
|
|
42
|
+
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.\n\n@example\n\`\`\`json\n[\n {\n "reason": "The user wants to call the function multiply.",\n "function_name": "get_user_info"\n },\n {\n "reason": "The user wants to modify the user info.",\n "function_name": "modify_user_info"\n }\n]\n\`\`\`\n`,
|
|
43
|
+
parameters: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {
|
|
46
|
+
function_list: {
|
|
47
|
+
type: "array",
|
|
48
|
+
items: {
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: {
|
|
51
|
+
reason: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "The reason of the function selection.\n\nJust write the reason why you've determined to select this function."
|
|
54
|
+
},
|
|
55
|
+
function_name: {
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "Name of the target function to call."
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
required: [ "reason", "function_name" ]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
required: [ "function_list" ]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
async function extractQuery(ctx) {
|
|
71
|
+
const completionStream = await ctx.request("select", {
|
|
72
|
+
messages: [ {
|
|
73
|
+
role: "system",
|
|
74
|
+
content: [ "You are a function searcher. You will extract search queries from the user's message, and the query results will be function names.", "A query is a 2–3 sentence description of the action the user needs to perform.", "Therefore, the extracted queries must be suitable for function search.", "You need to identify the actions required to achieve what the user wants and extract queries that can be used to search for those actions.", "Extract only one query per task." ].join("\n")
|
|
75
|
+
}, ...ctx.histories.map(factory.decodeHistory).flat(), {
|
|
76
|
+
role: "user",
|
|
77
|
+
content: ctx.prompt.text
|
|
78
|
+
} ],
|
|
79
|
+
tool_choice: "required",
|
|
80
|
+
tools: [ Tools.extract_query ]
|
|
81
|
+
});
|
|
82
|
+
const chunks = await utils.StreamUtil.readAll(completionStream);
|
|
83
|
+
const completion = utils.ChatGptCompletionMessageUtil.merge(chunks);
|
|
84
|
+
const queries = completion.choices[0]?.message.tool_calls?.flatMap((v => {
|
|
85
|
+
const arg = JSON.parse(v.function.arguments);
|
|
86
|
+
if (!Array.isArray(arg.query_list)) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
return arg.query_list.map((v => v.query));
|
|
90
|
+
})) ?? [];
|
|
91
|
+
return queries;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function selectFunction(props) {
|
|
95
|
+
const {ctx, toolList, prevFailures = [], restRetry = 5} = props;
|
|
96
|
+
const selectCompletion = await ctx.request("select", {
|
|
97
|
+
messages: [ {
|
|
98
|
+
role: "system",
|
|
99
|
+
content: AgenticaDefaultPrompt.write(ctx.config)
|
|
100
|
+
}, {
|
|
101
|
+
role: "assistant",
|
|
102
|
+
tool_calls: [ {
|
|
103
|
+
type: "function",
|
|
104
|
+
id: "getApiFunctions",
|
|
105
|
+
function: {
|
|
106
|
+
name: "getApiFunctions",
|
|
107
|
+
arguments: JSON.stringify({})
|
|
108
|
+
}
|
|
109
|
+
} ]
|
|
110
|
+
}, {
|
|
111
|
+
role: "tool",
|
|
112
|
+
tool_call_id: "getApiFunctions",
|
|
113
|
+
content: JSON.stringify(toolList)
|
|
114
|
+
}, ...ctx.histories.flatMap(factory.decodeHistory), {
|
|
115
|
+
role: "user",
|
|
116
|
+
content: ctx.prompt.text
|
|
117
|
+
}, {
|
|
118
|
+
role: "system",
|
|
119
|
+
content: `${ctx.config?.systemPrompt?.select?.(ctx.histories) ?? AgenticaSystemPrompt.SELECT}\n \n \n When selecting functions, consider what the user can call from their perspective, and choose all the functions necessary to accomplish the task.\n Select them in a logical sequence, taking into account the relationships between each function.\n `
|
|
120
|
+
}, ...emendMessages(prevFailures) ],
|
|
121
|
+
tool_choice: {
|
|
122
|
+
type: "function",
|
|
123
|
+
function: {
|
|
124
|
+
name: "select_functions"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
parallel_tool_calls: false,
|
|
128
|
+
tools: [ Tools.select_functions ]
|
|
129
|
+
}).then((async v => utils.StreamUtil.readAll(v))).then(utils.ChatGptCompletionMessageUtil.merge);
|
|
130
|
+
const toolCalls = selectCompletion.choices.filter((v => v.message.tool_calls != null));
|
|
131
|
+
if (toolCalls.length === 0) {
|
|
132
|
+
return selectCompletion.choices.flatMap((v => {
|
|
133
|
+
if (v.message.content != null && v.message.content !== "") {
|
|
134
|
+
return [ factory.createTextHistory({
|
|
135
|
+
role: "assistant",
|
|
136
|
+
text: v.message.content
|
|
137
|
+
}) ];
|
|
138
|
+
}
|
|
139
|
+
return [];
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
const failures = toolCalls.reduce(((acc, cur) => {
|
|
143
|
+
cur.message.tool_calls?.forEach((tc => {
|
|
144
|
+
const errors = [];
|
|
145
|
+
const arg = JSON.parse(tc.function.arguments);
|
|
146
|
+
if (!Array.isArray(arg)) {
|
|
147
|
+
errors.push(JSON.stringify({
|
|
148
|
+
path: "$input",
|
|
149
|
+
expected: "array",
|
|
150
|
+
value: arg
|
|
151
|
+
}));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
arg.forEach(((v, idx) => {
|
|
155
|
+
if (v.reason == null || typeof v.reason !== "string") {
|
|
156
|
+
errors.push(JSON.stringify({
|
|
157
|
+
path: `$$input[${idx}].reason`,
|
|
158
|
+
expected: "string",
|
|
159
|
+
value: v.reason
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
if (v.function_name == null || typeof v.function_name !== "string") {
|
|
163
|
+
errors.push(JSON.stringify({
|
|
164
|
+
path: `$$input[${idx}].function_name`,
|
|
165
|
+
expected: "string",
|
|
166
|
+
value: v.function_name
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
}));
|
|
170
|
+
if (errors.length !== 0) {
|
|
171
|
+
acc.push({
|
|
172
|
+
id: tc.id,
|
|
173
|
+
name: tc.function.name,
|
|
174
|
+
validation: {
|
|
175
|
+
data: tc.function.arguments,
|
|
176
|
+
errors
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}));
|
|
181
|
+
return acc;
|
|
182
|
+
}), []);
|
|
183
|
+
if (failures.length !== 0) {
|
|
184
|
+
const feedback = [ ...prevFailures, ...failures ];
|
|
185
|
+
if (restRetry === 0) {
|
|
186
|
+
throw new Error(`Failed to select function after ${restRetry} retries\n${JSON.stringify(feedback)}`);
|
|
187
|
+
}
|
|
188
|
+
return selectFunction({
|
|
189
|
+
ctx,
|
|
190
|
+
toolList,
|
|
191
|
+
prevFailures: feedback,
|
|
192
|
+
restRetry: restRetry - 1
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
const prompts = [];
|
|
196
|
+
toolCalls.forEach((v => {
|
|
197
|
+
v.message.tool_calls.forEach((tc => {
|
|
198
|
+
const collection = {
|
|
199
|
+
type: "select",
|
|
200
|
+
id: tc.id,
|
|
201
|
+
selections: [],
|
|
202
|
+
toJSON: () => ({
|
|
203
|
+
type: "select",
|
|
204
|
+
id: tc.id,
|
|
205
|
+
selections: collection.selections.map((s => s.toJSON()))
|
|
206
|
+
})
|
|
207
|
+
};
|
|
208
|
+
const arg = JSON.parse(tc.function.arguments);
|
|
209
|
+
arg.function_list.forEach((v => {
|
|
210
|
+
const operation = ctx.operations.flat.get(v.function_name);
|
|
211
|
+
if (operation === undefined) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const selection = factory.createOperationSelection({
|
|
215
|
+
reason: v.reason,
|
|
216
|
+
operation
|
|
217
|
+
});
|
|
218
|
+
ctx.stack.push(selection);
|
|
219
|
+
ctx.dispatch(factory.createSelectEvent({
|
|
220
|
+
selection
|
|
221
|
+
})).catch((() => {}));
|
|
222
|
+
collection.selections.push(selection);
|
|
223
|
+
}));
|
|
224
|
+
prompts.push(collection);
|
|
225
|
+
}));
|
|
226
|
+
}));
|
|
227
|
+
return prompts;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function emendMessages(failures) {
|
|
231
|
+
return failures.flatMap((f => [ {
|
|
232
|
+
role: "assistant",
|
|
233
|
+
tool_calls: [ {
|
|
234
|
+
type: "function",
|
|
235
|
+
id: f.id,
|
|
236
|
+
function: {
|
|
237
|
+
name: f.name,
|
|
238
|
+
arguments: JSON.stringify(f.validation.data)
|
|
239
|
+
}
|
|
240
|
+
} ]
|
|
241
|
+
}, {
|
|
242
|
+
role: "tool",
|
|
243
|
+
content: JSON.stringify(f.validation.errors),
|
|
244
|
+
tool_call_id: f.id
|
|
245
|
+
}, {
|
|
246
|
+
role: "system",
|
|
247
|
+
content: [ "You A.I. assistant has composed wrong typed arguments.", "", "Correct it at the next function calling." ].join("\n")
|
|
248
|
+
} ]));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function uniqBy(array, selector) {
|
|
252
|
+
const seen = new Set;
|
|
253
|
+
return array.filter((item => {
|
|
254
|
+
const key = selector(item);
|
|
255
|
+
if (seen.has(key)) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
seen.add(key);
|
|
259
|
+
return true;
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function BootAgenticaVectorSelector(props) {
|
|
264
|
+
const {isEmbedded, setEmbedded} = useEmbeddedContext();
|
|
265
|
+
const {searchTool, embedContext} = props.strategy;
|
|
266
|
+
const selectorExecute = async ctx => {
|
|
267
|
+
if (!isEmbedded(ctx)) {
|
|
268
|
+
await embedContext({
|
|
269
|
+
ctx,
|
|
270
|
+
setEmbedded: () => setEmbedded(ctx)
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
const queries = await extractQuery(ctx);
|
|
274
|
+
const toolList = await Promise.all(queries.map((async query => searchTool(ctx, query)))).then((res => res.flatMap((output => output.map((v => ({
|
|
275
|
+
name: v.name,
|
|
276
|
+
description: v.description
|
|
277
|
+
}))))).map((v => {
|
|
278
|
+
const op = ctx.operations.flat.get(v.name);
|
|
279
|
+
if (op === undefined || op.protocol !== "http") {
|
|
280
|
+
return v;
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
...v,
|
|
284
|
+
method: op.function.method,
|
|
285
|
+
path: op.function.path,
|
|
286
|
+
tags: op.function.tags
|
|
287
|
+
};
|
|
288
|
+
})))).then((arr => uniqBy(arr, (v => v.name))));
|
|
289
|
+
if (toolList.length === 0) {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
const prompts = await selectFunction({
|
|
293
|
+
ctx,
|
|
294
|
+
toolList
|
|
295
|
+
});
|
|
296
|
+
return prompts;
|
|
297
|
+
};
|
|
298
|
+
return selectorExecute;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function useEmbeddedContext() {
|
|
302
|
+
const set = new Set;
|
|
303
|
+
return {
|
|
304
|
+
isEmbedded: ctx => set.has(JSON.stringify(ctx.operations.array)),
|
|
305
|
+
setEmbedded: ctx => {
|
|
306
|
+
set.add(JSON.stringify(ctx.operations.array));
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export { BootAgenticaVectorSelector, useEmbeddedContext };
|
|
312
|
+
//# sourceMappingURL=index.mjs.map
|