@agentica/vector-selector 0.44.0-dev.20260313-2 → 0.44.1

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.
@@ -1,116 +1,116 @@
1
- import type { AgenticaContext, AgenticaOperation } from "@agentica/core";
2
- import type { IConnection } from "@wrtnlabs/connector-hive-api";
3
- import type { IApplicationConnectorRetrieval } from "@wrtnlabs/connector-hive-api/lib/structures/connector/IApplicationConnectorRetrieval";
4
-
5
- import { functional, HttpError } from "@wrtnlabs/connector-hive-api";
6
-
7
- import type { IAgenticaVectorSelectorStrategy } from "..";
8
-
9
- import { getRetry, groupByArray } from "../utils";
10
-
11
- const retry = getRetry(3);
12
-
13
- const filterMap = new Map<string, IApplicationConnectorRetrieval.IFilter>();
14
- function searchTool(connection: IConnection<object | undefined>): IAgenticaVectorSelectorStrategy["searchTool"] {
15
- return async (ctx: AgenticaContext, query: string) => {
16
- const filter = filterMap.get(JSON.stringify(ctx.operations.array));
17
- return retry(async () =>
18
- functional.connector_retrievals.createRetrievalRequest(connection, {
19
- query,
20
- limit: 10,
21
- filter,
22
- }),
23
- );
24
- };
25
- }
26
-
27
- function embedOperation(connection: IConnection<object | undefined>) {
28
- return async (
29
- controllerName: string,
30
- opList: AgenticaOperation[],
31
- ) => {
32
- const application = await retry(async () =>
33
- functional.applications.create(connection, {
34
- name: controllerName,
35
- description: undefined,
36
- }),
37
- ).catch(async (e) => {
38
- if (!(e instanceof HttpError)) {
39
- throw e;
40
- }
41
- if (e.status !== 409) {
42
- throw e;
43
- }
44
-
45
- return retry(async () =>
46
- functional.applications.by_names.getByName(
47
- connection,
48
- controllerName,
49
- ),
50
- );
51
- });
52
-
53
- const version = await retry(async () =>
54
- functional.applications.by_ids.versions.create(
55
- connection,
56
- application.id,
57
- {},
58
- ),
59
- );
60
-
61
- // concurrency request count
62
- await groupByArray(opList, 10).reduce(async (accPromise, cur) => {
63
- await accPromise;
64
- await Promise.all(
65
- cur.map(async v =>
66
- retry(async () =>
67
- functional.application_versions.by_ids.connectors.create(
68
- connection,
69
- version.id,
70
- { name: v.name, description: v.function.description ?? "" },
71
- ),
72
- ),
73
- ),
74
- );
75
- return Promise.resolve();
76
- }, Promise.resolve());
77
-
78
- return { version, applicationId: application.id };
79
- };
80
- }
81
-
82
- function embedContext(connection: IConnection<object | undefined>): IAgenticaVectorSelectorStrategy["embedContext"] {
83
- return async (props: { ctx: AgenticaContext; setEmbedded: () => void }) => {
84
- const { ctx, setEmbedded } = props;
85
- const filter = await Promise.all(
86
- Array.from(ctx.operations.group.entries()).map(
87
- async ([key, value]: [
88
- string,
89
- Map<string, AgenticaOperation>,
90
- ]) => {
91
- const result = await embedOperation(connection)(
92
- key,
93
- Array.from(value.values()),
94
- );
95
-
96
- return {
97
- id: result.applicationId,
98
- version: result.version.version,
99
- type: "byId",
100
- } satisfies IApplicationConnectorRetrieval.IFilterApplicationById;
101
- },
102
- ),
103
- );
104
- filterMap.set(JSON.stringify(ctx.operations.array), {
105
- applications: filter,
106
- });
107
- setEmbedded();
108
- };
109
- }
110
-
111
- export function configurePostgresStrategy(connection: IConnection<object | undefined>): IAgenticaVectorSelectorStrategy {
112
- return {
113
- searchTool: searchTool(connection),
114
- embedContext: embedContext(connection),
115
- };
116
- }
1
+ import type { AgenticaContext, AgenticaOperation } from "@agentica/core";
2
+ import type { IConnection } from "@wrtnlabs/connector-hive-api";
3
+ import type { IApplicationConnectorRetrieval } from "@wrtnlabs/connector-hive-api/lib/structures/connector/IApplicationConnectorRetrieval";
4
+
5
+ import { functional, HttpError } from "@wrtnlabs/connector-hive-api";
6
+
7
+ import type { IAgenticaVectorSelectorStrategy } from "..";
8
+
9
+ import { getRetry, groupByArray } from "../utils";
10
+
11
+ const retry = getRetry(3);
12
+
13
+ const filterMap = new Map<string, IApplicationConnectorRetrieval.IFilter>();
14
+ function searchTool(connection: IConnection<object | undefined>): IAgenticaVectorSelectorStrategy["searchTool"] {
15
+ return async (ctx: AgenticaContext, query: string) => {
16
+ const filter = filterMap.get(JSON.stringify(ctx.operations.array));
17
+ return retry(async () =>
18
+ functional.connector_retrievals.createRetrievalRequest(connection, {
19
+ query,
20
+ limit: 10,
21
+ filter,
22
+ }),
23
+ );
24
+ };
25
+ }
26
+
27
+ function embedOperation(connection: IConnection<object | undefined>) {
28
+ return async (
29
+ controllerName: string,
30
+ opList: AgenticaOperation[],
31
+ ) => {
32
+ const application = await retry(async () =>
33
+ functional.applications.create(connection, {
34
+ name: controllerName,
35
+ description: undefined,
36
+ }),
37
+ ).catch(async (e) => {
38
+ if (!(e instanceof HttpError)) {
39
+ throw e;
40
+ }
41
+ if (e.status !== 409) {
42
+ throw e;
43
+ }
44
+
45
+ return retry(async () =>
46
+ functional.applications.by_names.getByName(
47
+ connection,
48
+ controllerName,
49
+ ),
50
+ );
51
+ });
52
+
53
+ const version = await retry(async () =>
54
+ functional.applications.by_ids.versions.create(
55
+ connection,
56
+ application.id,
57
+ {},
58
+ ),
59
+ );
60
+
61
+ // concurrency request count
62
+ await groupByArray(opList, 10).reduce(async (accPromise, cur) => {
63
+ await accPromise;
64
+ await Promise.all(
65
+ cur.map(async v =>
66
+ retry(async () =>
67
+ functional.application_versions.by_ids.connectors.create(
68
+ connection,
69
+ version.id,
70
+ { name: v.name, description: v.function.description ?? "" },
71
+ ),
72
+ ),
73
+ ),
74
+ );
75
+ return Promise.resolve();
76
+ }, Promise.resolve());
77
+
78
+ return { version, applicationId: application.id };
79
+ };
80
+ }
81
+
82
+ function embedContext(connection: IConnection<object | undefined>): IAgenticaVectorSelectorStrategy["embedContext"] {
83
+ return async (props: { ctx: AgenticaContext; setEmbedded: () => void }) => {
84
+ const { ctx, setEmbedded } = props;
85
+ const filter = await Promise.all(
86
+ Array.from(ctx.operations.group.entries()).map(
87
+ async ([key, value]: [
88
+ string,
89
+ Map<string, AgenticaOperation>,
90
+ ]) => {
91
+ const result = await embedOperation(connection)(
92
+ key,
93
+ Array.from(value.values()),
94
+ );
95
+
96
+ return {
97
+ id: result.applicationId,
98
+ version: result.version.version,
99
+ type: "byId",
100
+ } satisfies IApplicationConnectorRetrieval.IFilterApplicationById;
101
+ },
102
+ ),
103
+ );
104
+ filterMap.set(JSON.stringify(ctx.operations.array), {
105
+ applications: filter,
106
+ });
107
+ setEmbedded();
108
+ };
109
+ }
110
+
111
+ export function configurePostgresStrategy(connection: IConnection<object | undefined>): IAgenticaVectorSelectorStrategy {
112
+ return {
113
+ searchTool: searchTool(connection),
114
+ embedContext: embedContext(connection),
115
+ };
116
+ }
@@ -1,123 +1,123 @@
1
- import type { AgenticaContext, AgenticaOperation } from "@agentica/core";
2
- import type { Database } from "better-sqlite3";
3
- import type { Cohere } from "cohere-ai";
4
-
5
- import { CohereClientV2 } from "cohere-ai";
6
- import { load } from "sqlite-vec";
7
-
8
- import type { IAgenticaVectorSelectorStrategy } from "..";
9
-
10
- import { generateHashFromCtx, getRetry, groupByArray } from "../utils";
11
-
12
- export interface IAgenticaSqliteVectorSelectorStrategyProps {
13
- db: Database;
14
- cohereApiKey: string;
15
- }
16
-
17
- const retry = getRetry(3);
18
- const hashMemo = new Map<object, string>();
19
- export function configureSqliteStrategy(props: IAgenticaSqliteVectorSelectorStrategyProps): IAgenticaVectorSelectorStrategy {
20
- const { db, cohereApiKey } = props;
21
- load(db);
22
-
23
- const cohere = new CohereClientV2({
24
- token: cohereApiKey,
25
- });
26
-
27
- db.exec(`
28
- CREATE TABLE IF NOT EXISTS _agentica_vector_selector_embeddings (
29
- id INTEGER PRIMARY KEY AUTOINCREMENT,
30
- hash TEXT NOT NULL,
31
- name TEXT NOT NULL,
32
- description TEXT,
33
- vector BLOB NOT NULL
34
- )
35
- `);
36
-
37
- async function embed(text: string, inputType: Cohere.EmbedInputType) {
38
- const result = await retry(async () => cohere.embed({
39
- texts: [text],
40
- inputType,
41
- model: "embed-multilingual-light-v3.0",
42
- embeddingTypes: ["float"],
43
- }));
44
-
45
- if ((result.embeddings.float == null) || result.embeddings.float.length === 0) {
46
- throw new Error("no float embeddings returned");
47
- }
48
- const vector = result.embeddings.float[0]!;
49
- return vector;
50
- }
51
- // it's memoized to avoid generating the same hash for the same context
52
- // if you know react, it's like useMemo
53
- const getHash = (ctx: AgenticaContext) => {
54
- if (hashMemo.has(ctx)) {
55
- return hashMemo.get(ctx)!;
56
- }
57
- const hash = generateHashFromCtx(ctx);
58
- hashMemo.set(ctx, hash);
59
- return hash;
60
- };
61
-
62
- // embed each operation in the context.opersation.array
63
- async function embedOperation(props: {
64
- hash: string;
65
- operation: AgenticaOperation;
66
- }): Promise<void> {
67
- const name = props.operation.function.name;
68
-
69
- const embedding = await retry(async () => embed(props.operation.function.description ?? name, "search_document"));
70
-
71
- db
72
-
73
- .prepare("INSERT INTO _agentica_vector_selector_embeddings (hash, name, description, vector) VALUES (?, ?, ?, vec_f32(?))")
74
-
75
- .run(props.hash, name, props.operation.function.description, JSON.stringify(embedding));
76
- }
77
-
78
- async function embedContext(props: {
79
- ctx: AgenticaContext;
80
- setEmbedded: () => void;
81
- }): Promise<void> {
82
- const hash = getHash(props.ctx);
83
-
84
- const prepared = db.prepare(`SELECT name FROM _agentica_vector_selector_embeddings WHERE hash = ?`).all(hash);
85
- if (prepared.length > 0) {
86
- props.setEmbedded();
87
- return;
88
- }
89
-
90
- await groupByArray(props.ctx.operations.array, 10).reduce(async (accPromise, cur) => {
91
- await accPromise;
92
- await Promise.all(cur.map(async v => embedOperation({ hash, operation: v })));
93
- return Promise.resolve();
94
- }, Promise.resolve());
95
- props.setEmbedded();
96
- }
97
-
98
- async function searchTool(ctx: AgenticaContext, query: string): Promise<{
99
- name: string;
100
- description: string | undefined;
101
- }[]> {
102
- const hash = getHash(ctx);
103
- const vector = await embed(query, "search_query");
104
-
105
- const result = db.prepare(`
106
- SELECT name, description, vec_distance_L2(vector, ?) as distance
107
- FROM _agentica_vector_selector_embeddings
108
- WHERE hash = ?
109
- ORDER BY distance
110
- LIMIT 10
111
- `).all(JSON.stringify(vector), hash) as {
112
- name: string;
113
- description: string;
114
- distance: number;
115
- }[];
116
- return result;
117
- }
118
-
119
- return {
120
- searchTool,
121
- embedContext,
122
- };
123
- }
1
+ import type { AgenticaContext, AgenticaOperation } from "@agentica/core";
2
+ import type { Database } from "better-sqlite3";
3
+ import type { Cohere } from "cohere-ai";
4
+
5
+ import { CohereClientV2 } from "cohere-ai";
6
+ import { load } from "sqlite-vec";
7
+
8
+ import type { IAgenticaVectorSelectorStrategy } from "..";
9
+
10
+ import { generateHashFromCtx, getRetry, groupByArray } from "../utils";
11
+
12
+ export interface IAgenticaSqliteVectorSelectorStrategyProps {
13
+ db: Database;
14
+ cohereApiKey: string;
15
+ }
16
+
17
+ const retry = getRetry(3);
18
+ const hashMemo = new Map<object, string>();
19
+ export function configureSqliteStrategy(props: IAgenticaSqliteVectorSelectorStrategyProps): IAgenticaVectorSelectorStrategy {
20
+ const { db, cohereApiKey } = props;
21
+ load(db);
22
+
23
+ const cohere = new CohereClientV2({
24
+ token: cohereApiKey,
25
+ });
26
+
27
+ db.exec(`
28
+ CREATE TABLE IF NOT EXISTS _agentica_vector_selector_embeddings (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ hash TEXT NOT NULL,
31
+ name TEXT NOT NULL,
32
+ description TEXT,
33
+ vector BLOB NOT NULL
34
+ )
35
+ `);
36
+
37
+ async function embed(text: string, inputType: Cohere.EmbedInputType) {
38
+ const result = await retry(async () => cohere.embed({
39
+ texts: [text],
40
+ inputType,
41
+ model: "embed-multilingual-light-v3.0",
42
+ embeddingTypes: ["float"],
43
+ }));
44
+
45
+ if ((result.embeddings.float == null) || result.embeddings.float.length === 0) {
46
+ throw new Error("no float embeddings returned");
47
+ }
48
+ const vector = result.embeddings.float[0]!;
49
+ return vector;
50
+ }
51
+ // it's memoized to avoid generating the same hash for the same context
52
+ // if you know react, it's like useMemo
53
+ const getHash = (ctx: AgenticaContext) => {
54
+ if (hashMemo.has(ctx)) {
55
+ return hashMemo.get(ctx)!;
56
+ }
57
+ const hash = generateHashFromCtx(ctx);
58
+ hashMemo.set(ctx, hash);
59
+ return hash;
60
+ };
61
+
62
+ // embed each operation in the context.opersation.array
63
+ async function embedOperation(props: {
64
+ hash: string;
65
+ operation: AgenticaOperation;
66
+ }): Promise<void> {
67
+ const name = props.operation.function.name;
68
+
69
+ const embedding = await retry(async () => embed(props.operation.function.description ?? name, "search_document"));
70
+
71
+ db
72
+
73
+ .prepare("INSERT INTO _agentica_vector_selector_embeddings (hash, name, description, vector) VALUES (?, ?, ?, vec_f32(?))")
74
+
75
+ .run(props.hash, name, props.operation.function.description, JSON.stringify(embedding));
76
+ }
77
+
78
+ async function embedContext(props: {
79
+ ctx: AgenticaContext;
80
+ setEmbedded: () => void;
81
+ }): Promise<void> {
82
+ const hash = getHash(props.ctx);
83
+
84
+ const prepared = db.prepare(`SELECT name FROM _agentica_vector_selector_embeddings WHERE hash = ?`).all(hash);
85
+ if (prepared.length > 0) {
86
+ props.setEmbedded();
87
+ return;
88
+ }
89
+
90
+ await groupByArray(props.ctx.operations.array, 10).reduce(async (accPromise, cur) => {
91
+ await accPromise;
92
+ await Promise.all(cur.map(async v => embedOperation({ hash, operation: v })));
93
+ return Promise.resolve();
94
+ }, Promise.resolve());
95
+ props.setEmbedded();
96
+ }
97
+
98
+ async function searchTool(ctx: AgenticaContext, query: string): Promise<{
99
+ name: string;
100
+ description: string | undefined;
101
+ }[]> {
102
+ const hash = getHash(ctx);
103
+ const vector = await embed(query, "search_query");
104
+
105
+ const result = db.prepare(`
106
+ SELECT name, description, vec_distance_L2(vector, ?) as distance
107
+ FROM _agentica_vector_selector_embeddings
108
+ WHERE hash = ?
109
+ ORDER BY distance
110
+ LIMIT 10
111
+ `).all(JSON.stringify(vector), hash) as {
112
+ name: string;
113
+ description: string;
114
+ distance: number;
115
+ }[];
116
+ return result;
117
+ }
118
+
119
+ return {
120
+ searchTool,
121
+ embedContext,
122
+ };
123
+ }
package/src/tools.ts CHANGED
@@ -1,99 +1,99 @@
1
- import type { AgenticaContext } from "@agentica/core";
2
-
3
- export const Tools = {
4
- extract_query: {
5
- type: "function",
6
- function: {
7
- name: "extract_search_query",
8
- description: "extract search query from user message\n",
9
- parameters: {
10
- type: "object",
11
- properties: {
12
- query_list: {
13
- type: "array",
14
- items: {
15
- type: "object",
16
- properties: {
17
- reason: {
18
- type: "string",
19
- description: "The reason of the query selection.\n\nJust write the reason why you've determined to select this query.",
20
- },
21
- query: {
22
- type: "string",
23
- description: "the search query",
24
- },
25
- },
26
- required: ["reason", "query"],
27
- },
28
- },
29
- },
30
- required: ["query_list"],
31
- },
32
- },
33
- },
34
-
35
- select_functions: {
36
- type: "function",
37
- function: {
38
- name: "select_functions",
39
- description: `Select proper API functions to call.
40
-
41
- If you A.I. agent has found some proper API functions to call
42
- from the conversation with user, please select the API functions
43
- just by calling this function.
44
-
45
- When user wants to call a same function multiply, you A.I. agent must
46
- list up it multiply in the \`functions\` property. Otherwise the user has
47
- requested to call many different functions, you A.I. agent have to assign
48
- them all into the \`functions\` property.
49
-
50
- Also, if you A.I. agent can't specify a specific function to call due to lack
51
- of specificity or homogeneity of candidate functions, just assign all of them
52
- by in the \`functions\` property too. Instead, when you A.I. agent can specify
53
- a specific function to call, the others would be eliminated.
54
-
55
- @example
56
- \`\`\`json
57
- [
58
- {
59
- "reason": "The user wants to call the function multiply.",
60
- "function_name": "get_user_info"
61
- },
62
- {
63
- "reason": "The user wants to modify the user info.",
64
- "function_name": "modify_user_info"
65
- }
66
- ]
67
- \`\`\`
68
- `,
69
- parameters: {
70
- type: "object",
71
- properties: {
72
- function_list: {
73
- type: "array",
74
- items: {
75
- type: "object",
76
- properties: {
77
- reason: {
78
- type: "string",
79
- description: "The reason of the function selection.\n\nJust write the reason why you've determined to select this function.",
80
- },
81
- function_name: {
82
- type: "string",
83
- description: "Name of the target function to call.",
84
- },
85
- },
86
- required: ["reason", "function_name"],
87
- },
88
- },
89
- },
90
- required: ["function_list"],
91
- },
92
- },
93
- },
94
- } as const satisfies Record<
95
- string,
96
- NonNullable<
97
- Parameters<AgenticaContext["request"]>[1]["tools"]
98
- >[number]
99
- >;
1
+ import type { AgenticaContext } from "@agentica/core";
2
+
3
+ export const Tools = {
4
+ extract_query: {
5
+ type: "function",
6
+ function: {
7
+ name: "extract_search_query",
8
+ description: "extract search query from user message\n",
9
+ parameters: {
10
+ type: "object",
11
+ properties: {
12
+ query_list: {
13
+ type: "array",
14
+ items: {
15
+ type: "object",
16
+ properties: {
17
+ reason: {
18
+ type: "string",
19
+ description: "The reason of the query selection.\n\nJust write the reason why you've determined to select this query.",
20
+ },
21
+ query: {
22
+ type: "string",
23
+ description: "the search query",
24
+ },
25
+ },
26
+ required: ["reason", "query"],
27
+ },
28
+ },
29
+ },
30
+ required: ["query_list"],
31
+ },
32
+ },
33
+ },
34
+
35
+ select_functions: {
36
+ type: "function",
37
+ function: {
38
+ name: "select_functions",
39
+ description: `Select proper API functions to call.
40
+
41
+ If you A.I. agent has found some proper API functions to call
42
+ from the conversation with user, please select the API functions
43
+ just by calling this function.
44
+
45
+ When user wants to call a same function multiply, you A.I. agent must
46
+ list up it multiply in the \`functions\` property. Otherwise the user has
47
+ requested to call many different functions, you A.I. agent have to assign
48
+ them all into the \`functions\` property.
49
+
50
+ Also, if you A.I. agent can't specify a specific function to call due to lack
51
+ of specificity or homogeneity of candidate functions, just assign all of them
52
+ by in the \`functions\` property too. Instead, when you A.I. agent can specify
53
+ a specific function to call, the others would be eliminated.
54
+
55
+ @example
56
+ \`\`\`json
57
+ [
58
+ {
59
+ "reason": "The user wants to call the function multiply.",
60
+ "function_name": "get_user_info"
61
+ },
62
+ {
63
+ "reason": "The user wants to modify the user info.",
64
+ "function_name": "modify_user_info"
65
+ }
66
+ ]
67
+ \`\`\`
68
+ `,
69
+ parameters: {
70
+ type: "object",
71
+ properties: {
72
+ function_list: {
73
+ type: "array",
74
+ items: {
75
+ type: "object",
76
+ properties: {
77
+ reason: {
78
+ type: "string",
79
+ description: "The reason of the function selection.\n\nJust write the reason why you've determined to select this function.",
80
+ },
81
+ function_name: {
82
+ type: "string",
83
+ description: "Name of the target function to call.",
84
+ },
85
+ },
86
+ required: ["reason", "function_name"],
87
+ },
88
+ },
89
+ },
90
+ required: ["function_list"],
91
+ },
92
+ },
93
+ },
94
+ } as const satisfies Record<
95
+ string,
96
+ NonNullable<
97
+ Parameters<AgenticaContext["request"]>[1]["tools"]
98
+ >[number]
99
+ >;