graphai 0.2.8 → 0.3.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.
- package/README.md +27 -26
- package/lib/experimental_agent_filters/stream.d.ts +2 -0
- package/lib/experimental_agent_filters/stream.js +13 -0
- package/lib/experimental_agents/llm_agents/groq_agent.d.ts +10 -9
- package/lib/experimental_agents/llm_agents/groq_agent.js +1 -1
- package/lib/experimental_agents/llm_agents/openai_agent.d.ts +57 -0
- package/lib/experimental_agents/llm_agents/openai_agent.js +86 -0
- package/lib/experimental_agents/llm_agents/slashgpt_agent.js +6 -2
- package/lib/experimental_agents/matrix_agents/dot_product_agent.d.ts +4 -4
- package/lib/experimental_agents/matrix_agents/dot_product_agent.js +4 -4
- package/lib/experimental_agents/test_agents/stream_mock_agent.js +6 -6
- package/lib/graphai.d.ts +1 -1
- package/lib/graphai.js +11 -7
- package/lib/node.d.ts +2 -1
- package/lib/node.js +12 -10
- package/lib/type.d.ts +5 -1
- package/lib/utils/test_agents.js +2 -0
- package/lib/utils/utils.d.ts +1 -1
- package/lib/utils/utils.js +19 -1
- package/lib/validators/agent_validator.js +1 -1
- package/lib/validators/common.js +1 -1
- package/lib/validators/nodeValidator.js +2 -2
- package/lib/validators/relation_validator.js +2 -2
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -22,30 +22,30 @@ nodes:
|
|
|
22
22
|
query: describe the final sentence by the court for Sam Bank-Fried
|
|
23
23
|
wikipedia: // Retrieve data from Wikipedia
|
|
24
24
|
agent: wikipediaAgent
|
|
25
|
-
inputs: [source.name]
|
|
25
|
+
inputs: [:source.name]
|
|
26
26
|
chunks: // Break the text from Wikipedia into chunks (2048 character each with 512 overlap)
|
|
27
27
|
agent: stringSplitterAgent
|
|
28
|
-
inputs: [wikipedia]
|
|
28
|
+
inputs: [:wikipedia]
|
|
29
29
|
chunkEmbeddings: // Get embedding vector of each chunk
|
|
30
30
|
agent: stringEmbeddingsAgent
|
|
31
|
-
inputs: [chunks]
|
|
31
|
+
inputs: [:chunks]
|
|
32
32
|
topicEmbedding: // Get embedding vector of the question
|
|
33
33
|
agent: stringEmbeddingsAgent
|
|
34
|
-
inputs: [source.query]
|
|
34
|
+
inputs: [:source.query]
|
|
35
35
|
similarities: // Calculate the cosine similarity of each chunk
|
|
36
36
|
agent: dotProductAgent
|
|
37
|
-
inputs: [chunkEmbeddings, topicEmbedding]
|
|
37
|
+
inputs: [:chunkEmbeddings, :topicEmbedding]
|
|
38
38
|
sortedChunks: // Sort chunks based on their similarities
|
|
39
39
|
agent: sortByValuesAgent
|
|
40
|
-
inputs: [chunks, similarities]
|
|
40
|
+
inputs: [:chunks, :similarities]
|
|
41
41
|
referenceText: // Concatenate chunks up to the token limit (5000)
|
|
42
42
|
agent: tokenBoundStringsAgent
|
|
43
|
-
inputs: [sortedChunks]
|
|
43
|
+
inputs: [:sortedChunks]
|
|
44
44
|
params:
|
|
45
45
|
limit: 5000
|
|
46
46
|
prompt: // Generate a prompt with that reference text
|
|
47
47
|
agent: stringTemplateAgent
|
|
48
|
-
inputs: [source, referenceText]
|
|
48
|
+
inputs: [:source, :referenceText]
|
|
49
49
|
params:
|
|
50
50
|
template: |-
|
|
51
51
|
Using the following document, ${0}
|
|
@@ -56,7 +56,7 @@ nodes:
|
|
|
56
56
|
manifest:
|
|
57
57
|
model: gpt-3.5-turbo
|
|
58
58
|
isResult: true // indicating this is the final result
|
|
59
|
-
inputs: [prompt]
|
|
59
|
+
inputs: [:prompt]
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
```mermaid
|
|
@@ -96,10 +96,11 @@ A DFG consists of a collection of [nodes](#node), which contains a series of nes
|
|
|
96
96
|
|
|
97
97
|
### Data Source
|
|
98
98
|
|
|
99
|
-
Connections between nodes will be established by references from one node to another, using either its "inputs" or "
|
|
99
|
+
Connections between nodes will be established by references from one node to another, using either its "inputs", "update", "if" or "while" property. The values of those properties are *data sources*. A *data souce* is specified by either the ":" + nodeId (e.g., ":node1"), or ":" + nodeId + propertyId (e.g., ":node1.item"), index (e.g., ":node1.$0", ":node2.$last") or combinations (e.g., ":node1.messages.$0.content").
|
|
100
100
|
|
|
101
101
|
### DFG Structure
|
|
102
102
|
|
|
103
|
+
- *version*: GraphAI version, *required*. The latest version is 0.3.
|
|
103
104
|
- *nodes*: A list of node. Required.
|
|
104
105
|
- *concurrency*: An optional property, which specifies the maximum number of concurrent operations (agent functions to be executed at the same time). The default is 8.
|
|
105
106
|
- *loop*: An optional property, which specifies if the graph needs to be executed multiple times (iterations). See the [Loop section below](#loop) for details.
|
|
@@ -134,7 +135,7 @@ Here is an examnple (from [weather chat](https://github.com/receptron/graphai/bl
|
|
|
134
135
|
messagesWithUserInput: {
|
|
135
136
|
// Appends the user's input to the messages.
|
|
136
137
|
agent: (messages: Array<any>, content: string) => [...messages, { role: "user", content }],
|
|
137
|
-
inputs: ["messages", "userInput"],
|
|
138
|
+
inputs: [":messages", ":userInput"],
|
|
138
139
|
if: "checkInput",
|
|
139
140
|
},
|
|
140
141
|
```
|
|
@@ -183,23 +184,23 @@ nodes:
|
|
|
183
184
|
value: "Find out which materials we need to purchase this week for Joe Smith's residential house project."
|
|
184
185
|
projectId: // identifies the projectId from the question
|
|
185
186
|
agent: "identifierAgent"
|
|
186
|
-
inputs: ["source"] // == "sourceNode.query"
|
|
187
|
+
inputs: [":source"] // == "sourceNode.query"
|
|
187
188
|
database:
|
|
188
189
|
agent: "nestedAgent"
|
|
189
|
-
inputs: ["question", "projectId"]
|
|
190
|
+
inputs: [":question", ":projectId"]
|
|
190
191
|
graph:
|
|
191
192
|
nodes:
|
|
192
193
|
schema: // retrieves the database schema for the apecified projectId
|
|
193
194
|
agent: "schemaAgent"
|
|
194
|
-
inputs: ["
|
|
195
|
+
inputs: [":$1"]
|
|
195
196
|
... // issue query to the database and build an appropriate prompt with it.
|
|
196
197
|
query: // send the generated prompt to the LLM
|
|
197
198
|
agent: "llama3Agent"
|
|
198
|
-
inputs: ["prompt"]
|
|
199
|
+
inputs: [":prompt"]
|
|
199
200
|
isResult: true
|
|
200
201
|
response: // Deliver the answer
|
|
201
202
|
agent: "deliveryAgent"
|
|
202
|
-
inputs: [database.query.$last.content]
|
|
203
|
+
inputs: [:database.query.$last.content]
|
|
203
204
|
```
|
|
204
205
|
|
|
205
206
|
The databaseQuery node (which is associated "nestedAgent") takes the data from "question" node abd "projectId" node, and make them available to inner nodes (nodes of the child graph) via phantom node, "$0" and "$1". After the completion of the child graph, the data from "query" node (which has "isResult" property) becomes available as a property of the output of "database" node.
|
|
@@ -239,14 +240,14 @@ The "update" property of two static nodes ("people" and "result"), updates those
|
|
|
239
240
|
|
|
240
241
|
```
|
|
241
242
|
loop:
|
|
242
|
-
while: people
|
|
243
|
+
while: :people
|
|
243
244
|
nodes:
|
|
244
245
|
people:
|
|
245
246
|
value: [Steve Jobs, Elon Musk, Nikola Tesla]
|
|
246
|
-
update: retriever.array
|
|
247
|
+
update: :retriever.array
|
|
247
248
|
result:
|
|
248
249
|
value: []
|
|
249
|
-
update: reducer
|
|
250
|
+
update: :reducer
|
|
250
251
|
isResult: true
|
|
251
252
|
retriever:
|
|
252
253
|
agent: shift
|
|
@@ -256,10 +257,10 @@ nodes:
|
|
|
256
257
|
params:
|
|
257
258
|
manifest:
|
|
258
259
|
prompt: Describe about the person in less than 100 words
|
|
259
|
-
inputs: [retriever.item]
|
|
260
|
+
inputs: [:retriever.item]
|
|
260
261
|
reducer:
|
|
261
262
|
agent: push
|
|
262
|
-
inputs: [result, query.content]
|
|
263
|
+
inputs: [:result, :query.content]
|
|
263
264
|
```
|
|
264
265
|
|
|
265
266
|
```mermaid
|
|
@@ -292,7 +293,7 @@ nodes:
|
|
|
292
293
|
value: [Steve Jobs, Elon Musk, Nikola Tesla]
|
|
293
294
|
retriever:
|
|
294
295
|
agent: "mapAgent"
|
|
295
|
-
inputs: ["people"]
|
|
296
|
+
inputs: [":people"]
|
|
296
297
|
graph:
|
|
297
298
|
nodes:
|
|
298
299
|
query:
|
|
@@ -300,7 +301,7 @@ nodes:
|
|
|
300
301
|
params:
|
|
301
302
|
manifest:
|
|
302
303
|
prompt: Describe about the person in less than 100 words
|
|
303
|
-
inputs: ["
|
|
304
|
+
inputs: [":$0"]
|
|
304
305
|
```
|
|
305
306
|
|
|
306
307
|
Here is the conceptual representation of this operation.
|
|
@@ -324,8 +325,8 @@ A sample code, [weather chat](https://github.com/receptron/graphai/blob/main/sam
|
|
|
324
325
|
tool_calls: {
|
|
325
326
|
// This node is activated if the LLM requests a tool call.
|
|
326
327
|
agent: "nestedAgent",
|
|
327
|
-
inputs: ["groq.choices.$0.message.tool_calls", "messagesWithFirstRes"],
|
|
328
|
-
if: "groq.choices.$0.message.tool_calls",
|
|
328
|
+
inputs: [":groq.choices.$0.message.tool_calls", ":messagesWithFirstRes"],
|
|
329
|
+
if: ":groq.choices.$0.message.tool_calls",
|
|
329
330
|
graph: {
|
|
330
331
|
// This graph is nested only for the readability.
|
|
331
332
|
```
|
|
@@ -341,7 +342,7 @@ The [weather chat](https://github.com/receptron/graphai/blob/main/samples/sample
|
|
|
341
342
|
// Receives messages from either case.
|
|
342
343
|
agent: "copyAgent",
|
|
343
344
|
anyInput: true,
|
|
344
|
-
inputs: ["no_tool_calls", "tool_calls.messagesWithSecondRes"],
|
|
345
|
+
inputs: [":no_tool_calls", ":tool_calls.messagesWithSecondRes"],
|
|
345
346
|
},
|
|
346
347
|
```
|
|
347
348
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.streamAgentFilterGenerator = void 0;
|
|
4
|
+
const streamAgentFilterGenerator = (callback) => {
|
|
5
|
+
const streamAgentFilter = async (context, next) => {
|
|
6
|
+
context.filterParams.streamTokenCallback = (data) => {
|
|
7
|
+
callback(context, data);
|
|
8
|
+
};
|
|
9
|
+
return next(context);
|
|
10
|
+
};
|
|
11
|
+
return streamAgentFilter;
|
|
12
|
+
};
|
|
13
|
+
exports.streamAgentFilterGenerator = streamAgentFilterGenerator;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { AgentFunction } from "../../graphai";
|
|
2
|
+
import { Groq } from "groq-sdk";
|
|
2
3
|
export declare const groqAgent: AgentFunction<{
|
|
3
4
|
model: string;
|
|
4
5
|
query?: string;
|
|
5
6
|
system?: string;
|
|
6
7
|
verbose?: boolean;
|
|
7
|
-
tools?: Record<string,
|
|
8
|
+
tools?: Record<string, Groq.Chat.CompletionCreateParams.Tool>;
|
|
8
9
|
temperature?: number;
|
|
9
10
|
max_tokens?: number;
|
|
10
|
-
tool_choice?: string | Record<string,
|
|
11
|
-
},
|
|
11
|
+
tool_choice?: string | Record<string, Groq.Chat.CompletionCreateParams.ToolChoice>;
|
|
12
|
+
}, Groq.Chat.ChatCompletion, string | Array<Groq.Chat.CompletionCreateParams.Message>>;
|
|
12
13
|
declare const groqAgentInfo: {
|
|
13
14
|
name: string;
|
|
14
15
|
agent: AgentFunction<{
|
|
@@ -16,21 +17,21 @@ declare const groqAgentInfo: {
|
|
|
16
17
|
query?: string | undefined;
|
|
17
18
|
system?: string | undefined;
|
|
18
19
|
verbose?: boolean | undefined;
|
|
19
|
-
tools?: Record<string,
|
|
20
|
+
tools?: Record<string, Groq.Chat.Completions.CompletionCreateParams.Tool> | undefined;
|
|
20
21
|
temperature?: number | undefined;
|
|
21
22
|
max_tokens?: number | undefined;
|
|
22
|
-
tool_choice?: string | Record<string,
|
|
23
|
-
},
|
|
23
|
+
tool_choice?: string | Record<string, Groq.Chat.Completions.CompletionCreateParams.ToolChoice> | undefined;
|
|
24
|
+
}, Groq.Chat.Completions.ChatCompletion, string | Groq.Chat.Completions.CompletionCreateParams.Message[]>;
|
|
24
25
|
mock: AgentFunction<{
|
|
25
26
|
model: string;
|
|
26
27
|
query?: string | undefined;
|
|
27
28
|
system?: string | undefined;
|
|
28
29
|
verbose?: boolean | undefined;
|
|
29
|
-
tools?: Record<string,
|
|
30
|
+
tools?: Record<string, Groq.Chat.Completions.CompletionCreateParams.Tool> | undefined;
|
|
30
31
|
temperature?: number | undefined;
|
|
31
32
|
max_tokens?: number | undefined;
|
|
32
|
-
tool_choice?: string | Record<string,
|
|
33
|
-
},
|
|
33
|
+
tool_choice?: string | Record<string, Groq.Chat.Completions.CompletionCreateParams.ToolChoice> | undefined;
|
|
34
|
+
}, Groq.Chat.Completions.ChatCompletion, string | Groq.Chat.Completions.CompletionCreateParams.Message[]>;
|
|
34
35
|
samples: never[];
|
|
35
36
|
description: string;
|
|
36
37
|
category: string[];
|
|
@@ -28,7 +28,7 @@ const groqAgent = async ({ params, inputs }) => {
|
|
|
28
28
|
const [input_query, previous_messages] = inputs;
|
|
29
29
|
// Notice that we ignore params.system if previous_message exists.
|
|
30
30
|
const messages = previous_messages && Array.isArray(previous_messages) ? previous_messages : system ? [{ role: "system", content: system }] : [];
|
|
31
|
-
const content = (query ? [query] : []).concat(input_query ? [input_query] : []).join("\n");
|
|
31
|
+
const content = (query ? [query] : []).concat(input_query && typeof input_query === "string" ? [input_query] : []).join("\n");
|
|
32
32
|
if (content) {
|
|
33
33
|
messages.push({
|
|
34
34
|
role: "user",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { AgentFunction } from "../../graphai";
|
|
2
|
+
export declare const openAIAgent: AgentFunction<{
|
|
3
|
+
model?: string;
|
|
4
|
+
query?: string;
|
|
5
|
+
system?: string;
|
|
6
|
+
verbose?: boolean;
|
|
7
|
+
temperature?: number;
|
|
8
|
+
}, Record<string, any> | string, string | Array<any>>;
|
|
9
|
+
export declare const openAIMockAgent: AgentFunction<{
|
|
10
|
+
model?: string;
|
|
11
|
+
query?: string;
|
|
12
|
+
system?: string;
|
|
13
|
+
verbose?: boolean;
|
|
14
|
+
temperature?: number;
|
|
15
|
+
}, Record<string, any> | string, string | Array<any>>;
|
|
16
|
+
declare const openaiAgentInfo: {
|
|
17
|
+
name: string;
|
|
18
|
+
agent: AgentFunction<{
|
|
19
|
+
model?: string | undefined;
|
|
20
|
+
query?: string | undefined;
|
|
21
|
+
system?: string | undefined;
|
|
22
|
+
verbose?: boolean | undefined;
|
|
23
|
+
temperature?: number | undefined;
|
|
24
|
+
}, string | Record<string, any>, string | any[]>;
|
|
25
|
+
mock: AgentFunction<{
|
|
26
|
+
model?: string | undefined;
|
|
27
|
+
query?: string | undefined;
|
|
28
|
+
system?: string | undefined;
|
|
29
|
+
verbose?: boolean | undefined;
|
|
30
|
+
temperature?: number | undefined;
|
|
31
|
+
}, string | Record<string, any>, string | any[]>;
|
|
32
|
+
samples: {
|
|
33
|
+
inputs: string[];
|
|
34
|
+
params: {};
|
|
35
|
+
result: {
|
|
36
|
+
object: string;
|
|
37
|
+
id: string;
|
|
38
|
+
choices: {
|
|
39
|
+
message: {
|
|
40
|
+
role: string;
|
|
41
|
+
content: string;
|
|
42
|
+
};
|
|
43
|
+
finish_reason: string;
|
|
44
|
+
index: number;
|
|
45
|
+
logprobs: null;
|
|
46
|
+
}[];
|
|
47
|
+
created: number;
|
|
48
|
+
model: string;
|
|
49
|
+
};
|
|
50
|
+
}[];
|
|
51
|
+
description: string;
|
|
52
|
+
category: string[];
|
|
53
|
+
author: string;
|
|
54
|
+
repository: string;
|
|
55
|
+
license: string;
|
|
56
|
+
};
|
|
57
|
+
export default openaiAgentInfo;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.openAIMockAgent = exports.openAIAgent = void 0;
|
|
7
|
+
const openai_1 = __importDefault(require("openai"));
|
|
8
|
+
const utils_1 = require("../../utils/utils");
|
|
9
|
+
const openAIAgent = async ({ filterParams, params, inputs }) => {
|
|
10
|
+
const { verbose, query, system, temperature } = params;
|
|
11
|
+
const [input_query, previous_messages] = inputs;
|
|
12
|
+
// Notice that we ignore params.system if previous_message exists.
|
|
13
|
+
const messages = previous_messages && Array.isArray(previous_messages) ? previous_messages : system ? [{ role: "system", content: system }] : [];
|
|
14
|
+
const content = (query ? [query] : []).concat(input_query ? [input_query] : []).join("\n");
|
|
15
|
+
if (content) {
|
|
16
|
+
messages.push({
|
|
17
|
+
role: "user",
|
|
18
|
+
content,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (verbose) {
|
|
22
|
+
console.log(messages);
|
|
23
|
+
}
|
|
24
|
+
const openai = new openai_1.default();
|
|
25
|
+
const chatStream = await openai.beta.chat.completions.stream({
|
|
26
|
+
model: params.model || "gpt-3.5-turbo",
|
|
27
|
+
messages,
|
|
28
|
+
temperature: temperature ?? 0.7,
|
|
29
|
+
stream: true,
|
|
30
|
+
});
|
|
31
|
+
for await (const message of chatStream) {
|
|
32
|
+
const token = message.choices[0].delta.content;
|
|
33
|
+
if (filterParams && filterParams.streamTokenCallback && token) {
|
|
34
|
+
filterParams.streamTokenCallback(token);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const chatCompletion = await chatStream.finalChatCompletion();
|
|
38
|
+
return chatCompletion;
|
|
39
|
+
};
|
|
40
|
+
exports.openAIAgent = openAIAgent;
|
|
41
|
+
const input_sample = "this is response result";
|
|
42
|
+
const result_sample = {
|
|
43
|
+
object: "chat.completion",
|
|
44
|
+
id: "chatcmpl-9N7HxXYbwjmdbdiQE94MHoVluQhyt",
|
|
45
|
+
choices: [
|
|
46
|
+
{
|
|
47
|
+
message: {
|
|
48
|
+
role: "assistant",
|
|
49
|
+
content: input_sample,
|
|
50
|
+
},
|
|
51
|
+
finish_reason: "stop",
|
|
52
|
+
index: 0,
|
|
53
|
+
logprobs: null,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
created: 1715296589,
|
|
57
|
+
model: "gpt-3.5-turbo-0125",
|
|
58
|
+
};
|
|
59
|
+
const openAIMockAgent = async ({ filterParams }) => {
|
|
60
|
+
for await (const token of input_sample.split("")) {
|
|
61
|
+
if (filterParams && filterParams.streamTokenCallback && token) {
|
|
62
|
+
await (0, utils_1.sleep)(100);
|
|
63
|
+
filterParams.streamTokenCallback(token);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result_sample;
|
|
67
|
+
};
|
|
68
|
+
exports.openAIMockAgent = openAIMockAgent;
|
|
69
|
+
const openaiAgentInfo = {
|
|
70
|
+
name: "openAIAgent",
|
|
71
|
+
agent: exports.openAIAgent,
|
|
72
|
+
mock: exports.openAIMockAgent,
|
|
73
|
+
samples: [
|
|
74
|
+
{
|
|
75
|
+
inputs: [input_sample],
|
|
76
|
+
params: {},
|
|
77
|
+
result: result_sample,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
description: "Openai Agent",
|
|
81
|
+
category: ["llm"],
|
|
82
|
+
author: "Receptron team",
|
|
83
|
+
repository: "https://github.com/receptron/graphai",
|
|
84
|
+
license: "MIT",
|
|
85
|
+
};
|
|
86
|
+
exports.default = openaiAgentInfo;
|
|
@@ -7,7 +7,7 @@ exports.slashGPTAgent = void 0;
|
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const slashgpt_1 = require("slashgpt");
|
|
9
9
|
const config = new slashgpt_1.ChatConfig(path_1.default.resolve(__dirname));
|
|
10
|
-
const slashGPTAgent = async ({ params, inputs, debugInfo: { verbose, nodeId } }) => {
|
|
10
|
+
const slashGPTAgent = async ({ params, inputs, debugInfo: { verbose, nodeId }, filterParams }) => {
|
|
11
11
|
if (verbose) {
|
|
12
12
|
console.log("executing", nodeId, params);
|
|
13
13
|
}
|
|
@@ -15,7 +15,11 @@ const slashGPTAgent = async ({ params, inputs, debugInfo: { verbose, nodeId } })
|
|
|
15
15
|
const query = params?.query ? [params.query] : [];
|
|
16
16
|
const contents = query.concat(inputs);
|
|
17
17
|
session.append_user_question(contents.join("\n"));
|
|
18
|
-
await session.call_loop(() => { })
|
|
18
|
+
await session.call_loop(() => { }, (token) => {
|
|
19
|
+
if (filterParams && filterParams.streamTokenCallback && token) {
|
|
20
|
+
filterParams.streamTokenCallback(token);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
19
23
|
return session.history.messages();
|
|
20
24
|
};
|
|
21
25
|
exports.slashGPTAgent = slashGPTAgent;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { AgentFunction } from "../../graphai";
|
|
2
|
-
export declare const dotProductAgent: AgentFunction<Record<never, never>, Array<number>, Array<Array<number
|
|
2
|
+
export declare const dotProductAgent: AgentFunction<Record<never, never>, Array<number>, Array<Array<number>> | Array<number>>;
|
|
3
3
|
declare const dotProductAgentInfo: {
|
|
4
4
|
name: string;
|
|
5
|
-
agent: AgentFunction<Record<never, never>, number[], number[][]>;
|
|
6
|
-
mock: AgentFunction<Record<never, never>, number[], number[][]>;
|
|
5
|
+
agent: AgentFunction<Record<never, never>, number[], number[] | number[][]>;
|
|
6
|
+
mock: AgentFunction<Record<never, never>, number[], number[] | number[][]>;
|
|
7
7
|
samples: {
|
|
8
|
-
inputs: number[][][];
|
|
8
|
+
inputs: (number[] | number[][])[];
|
|
9
9
|
params: {};
|
|
10
10
|
result: number[];
|
|
11
11
|
}[];
|
|
@@ -5,14 +5,14 @@ exports.dotProductAgent = void 0;
|
|
|
5
5
|
// typically used to calculate cosine similarity of embedding vectors.
|
|
6
6
|
// Inputs:
|
|
7
7
|
// inputs[0]: Two dimentional array of numbers.
|
|
8
|
-
// inputs[1]:
|
|
8
|
+
// inputs[1]: One dimentional array of numbers.
|
|
9
9
|
// Outputs:
|
|
10
10
|
// { contents: Array<number> } // array of docProduct of each vector (A[]) and vector B
|
|
11
11
|
const dotProductAgent = async ({ inputs }) => {
|
|
12
12
|
const embeddings = inputs[0];
|
|
13
|
-
const reference = inputs[1]
|
|
13
|
+
const reference = inputs[1];
|
|
14
14
|
if (embeddings[0].length != reference.length) {
|
|
15
|
-
throw new Error(
|
|
15
|
+
throw new Error(`dotProduct: Length of vectors do not match. ${embeddings[0].length}, ${reference.length}`);
|
|
16
16
|
}
|
|
17
17
|
const contents = embeddings.map((embedding) => {
|
|
18
18
|
return embedding.reduce((dotProduct, value, index) => {
|
|
@@ -34,7 +34,7 @@ const dotProductAgentInfo = {
|
|
|
34
34
|
[3, 4],
|
|
35
35
|
[5, 6],
|
|
36
36
|
],
|
|
37
|
-
[
|
|
37
|
+
[3, 2],
|
|
38
38
|
],
|
|
39
39
|
params: {},
|
|
40
40
|
result: [7, 17, 27],
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.streamMockAgent = void 0;
|
|
4
4
|
const utils_1 = require("../../utils/utils");
|
|
5
|
-
const streamMockAgent = async ({ params }) => {
|
|
6
|
-
const message = params.message;
|
|
5
|
+
const streamMockAgent = async ({ params, filterParams }) => {
|
|
6
|
+
const message = params.message || "";
|
|
7
7
|
for await (const token of message.split("")) {
|
|
8
|
-
if (
|
|
9
|
-
|
|
8
|
+
if (filterParams.streamTokenCallback) {
|
|
9
|
+
filterParams.streamTokenCallback(token);
|
|
10
10
|
}
|
|
11
11
|
await (0, utils_1.sleep)(params.sleep || 100);
|
|
12
12
|
}
|
|
@@ -19,9 +19,9 @@ const streamMockAgentInfo = {
|
|
|
19
19
|
agent: exports.streamMockAgent,
|
|
20
20
|
mock: exports.streamMockAgent,
|
|
21
21
|
samples: [],
|
|
22
|
-
description: "
|
|
22
|
+
description: "Stream mock agent",
|
|
23
23
|
category: [],
|
|
24
|
-
author: "
|
|
24
|
+
author: "Isamu Arimoto",
|
|
25
25
|
repository: "https://github.com/receptron/graphai",
|
|
26
26
|
license: "MIT",
|
|
27
27
|
};
|
package/lib/graphai.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { ComputedNode, StaticNode } from "./node";
|
|
|
5
5
|
import { TaskManager } from "./task_manager";
|
|
6
6
|
type GraphNodes = Record<string, ComputedNode | StaticNode>;
|
|
7
7
|
export declare class GraphAI {
|
|
8
|
-
|
|
8
|
+
readonly version: number;
|
|
9
9
|
private readonly graphId;
|
|
10
10
|
private readonly data;
|
|
11
11
|
private readonly loop?;
|
package/lib/graphai.js
CHANGED
|
@@ -6,6 +6,7 @@ const utils_1 = require("./utils/utils");
|
|
|
6
6
|
const validator_1 = require("./validator");
|
|
7
7
|
const task_manager_1 = require("./task_manager");
|
|
8
8
|
const defaultConcurrency = 8;
|
|
9
|
+
const latestVersion = 0.3;
|
|
9
10
|
class GraphAI {
|
|
10
11
|
// This method is called when either the GraphAI obect was created,
|
|
11
12
|
// or we are about to start n-th iteration (n>2).
|
|
@@ -39,8 +40,7 @@ class GraphAI {
|
|
|
39
40
|
});
|
|
40
41
|
return nodes;
|
|
41
42
|
}
|
|
42
|
-
getValueFromResults(
|
|
43
|
-
const source = (0, utils_1.parseNodeName)(key);
|
|
43
|
+
getValueFromResults(source, results) {
|
|
44
44
|
return (0, utils_1.getDataFromSource)(source.nodeId ? results[source.nodeId] : undefined, source);
|
|
45
45
|
}
|
|
46
46
|
// for static
|
|
@@ -58,7 +58,7 @@ class GraphAI {
|
|
|
58
58
|
const update = node?.update;
|
|
59
59
|
if (update && previousResults) {
|
|
60
60
|
const result = this.getValueFromResults(update, previousResults);
|
|
61
|
-
this.injectValue(nodeId, result, update);
|
|
61
|
+
this.injectValue(nodeId, result, update.nodeId);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
});
|
|
@@ -67,10 +67,13 @@ class GraphAI {
|
|
|
67
67
|
this.logs = [];
|
|
68
68
|
this.onLogCallback = (__log, __isUpdate) => { };
|
|
69
69
|
this.repeatCount = 0;
|
|
70
|
-
if (!data.version) {
|
|
71
|
-
console.log("------------
|
|
70
|
+
if (!data.version && !options.taskManager) {
|
|
71
|
+
console.log("------------ missing version number");
|
|
72
|
+
}
|
|
73
|
+
this.version = data.version ?? latestVersion;
|
|
74
|
+
if (this.version < latestVersion) {
|
|
75
|
+
console.log(`------------ upgrade to ${latestVersion}!`);
|
|
72
76
|
}
|
|
73
|
-
this.version = data.version ?? 0.2;
|
|
74
77
|
this.retryLimit = data.retry; // optional
|
|
75
78
|
this.graphId = URL.createObjectURL(new Blob()).slice(-36);
|
|
76
79
|
this.data = data;
|
|
@@ -195,7 +198,8 @@ class GraphAI {
|
|
|
195
198
|
this.initializeNodes(results);
|
|
196
199
|
// Notice that we need to check the while condition *after* calling initializeNodes.
|
|
197
200
|
if (loop.while) {
|
|
198
|
-
const
|
|
201
|
+
const source = (0, utils_1.parseNodeName)(loop.while, this.version);
|
|
202
|
+
const value = this.getValueFromResults(source, this.results(true));
|
|
199
203
|
// NOTE: We treat an empty array as false.
|
|
200
204
|
if (Array.isArray(value) ? value.length === 0 : !value) {
|
|
201
205
|
return false; // while condition is not met
|
package/lib/node.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class ComputedNode extends Node {
|
|
|
16
16
|
readonly graphId: string;
|
|
17
17
|
readonly isResult: boolean;
|
|
18
18
|
readonly params: NodeDataParams;
|
|
19
|
+
private readonly filterParams;
|
|
19
20
|
private readonly dynamicParams;
|
|
20
21
|
readonly nestedGraph?: GraphData;
|
|
21
22
|
readonly retryLimit: number;
|
|
@@ -49,7 +50,7 @@ export declare class ComputedNode extends Node {
|
|
|
49
50
|
}
|
|
50
51
|
export declare class StaticNode extends Node {
|
|
51
52
|
value?: ResultData;
|
|
52
|
-
readonly update?:
|
|
53
|
+
readonly update?: DataSource;
|
|
53
54
|
readonly isResult: boolean;
|
|
54
55
|
readonly isStaticNode = true;
|
|
55
56
|
readonly isComputedNode = false;
|
package/lib/node.js
CHANGED
|
@@ -38,6 +38,7 @@ class ComputedNode extends Node {
|
|
|
38
38
|
this.isComputedNode = true;
|
|
39
39
|
this.graphId = graphId;
|
|
40
40
|
this.params = data.params ?? {};
|
|
41
|
+
this.filterParams = data.filterParams ?? {};
|
|
41
42
|
this.nestedGraph = data.graph;
|
|
42
43
|
if (typeof data.agent === "string") {
|
|
43
44
|
this.agentId = data.agent;
|
|
@@ -54,21 +55,18 @@ class ComputedNode extends Node {
|
|
|
54
55
|
this.isResult = data.isResult ?? false;
|
|
55
56
|
this.priority = data.priority ?? 0;
|
|
56
57
|
this.anyInput = data.anyInput ?? false;
|
|
57
|
-
this.dataSources = (data.inputs ?? []).map((input) => (0, utils_2.parseNodeName)(input));
|
|
58
|
+
this.dataSources = (data.inputs ?? []).map((input) => (0, utils_2.parseNodeName)(input, graph.version));
|
|
58
59
|
this.pendings = new Set(this.dataSources.filter((source) => source.nodeId).map((source) => source.nodeId));
|
|
59
60
|
if (data.if) {
|
|
60
|
-
this.ifSource = (0, utils_2.parseNodeName)(data.if);
|
|
61
|
+
this.ifSource = (0, utils_2.parseNodeName)(data.if, graph.version);
|
|
61
62
|
(0, utils_2.assert)(!!this.ifSource.nodeId, `Invalid data source ${data.if}`);
|
|
62
63
|
this.pendings.add(this.ifSource.nodeId);
|
|
63
64
|
}
|
|
64
|
-
const regex = /^\$\{([^{}]+)\}$/;
|
|
65
65
|
this.dynamicParams = Object.keys(this.params).reduce((tmp, key) => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const dataSource = (0, utils_2.parseNodeName)(match[1]);
|
|
66
|
+
const dataSource = (0, utils_2.parseNodeName)(this.params[key], graph.version < 0.3 ? 0.3 : graph.version);
|
|
67
|
+
if (dataSource.nodeId) {
|
|
68
|
+
(0, utils_2.assert)(!this.anyInput, "Dynamic params are not supported with anyInput");
|
|
70
69
|
tmp[key] = dataSource;
|
|
71
|
-
(0, utils_2.assert)(!!dataSource.nodeId, `Invalid data source ${key}:${value}`);
|
|
72
70
|
this.pendings.add(dataSource.nodeId);
|
|
73
71
|
}
|
|
74
72
|
return tmp;
|
|
@@ -175,6 +173,9 @@ class ComputedNode extends Node {
|
|
|
175
173
|
const agentFilter = this.graph.agentFilters[index++];
|
|
176
174
|
if (agentFilter) {
|
|
177
175
|
if (this.shouldApplyAgentFilter(agentFilter)) {
|
|
176
|
+
if (agentFilter.filterParams) {
|
|
177
|
+
context.filterParams = { ...agentFilter.filterParams, ...context.filterParams };
|
|
178
|
+
}
|
|
178
179
|
return agentFilter.agent(context, next);
|
|
179
180
|
}
|
|
180
181
|
return next(context);
|
|
@@ -212,10 +213,11 @@ class ComputedNode extends Node {
|
|
|
212
213
|
inputs: previousResults,
|
|
213
214
|
debugInfo: {
|
|
214
215
|
nodeId: this.nodeId,
|
|
216
|
+
agentId: this.agentId,
|
|
215
217
|
retry: this.retryCount,
|
|
216
218
|
verbose: this.graph.verbose,
|
|
217
219
|
},
|
|
218
|
-
filterParams:
|
|
220
|
+
filterParams: this.filterParams,
|
|
219
221
|
log: localLog,
|
|
220
222
|
};
|
|
221
223
|
// NOTE: We use the existence of graph object in the agent-specific params to determine
|
|
@@ -282,7 +284,7 @@ class StaticNode extends Node {
|
|
|
282
284
|
this.isStaticNode = true;
|
|
283
285
|
this.isComputedNode = false;
|
|
284
286
|
this.value = data.value;
|
|
285
|
-
this.update = data.update;
|
|
287
|
+
this.update = data.update ? (0, utils_2.parseNodeName)(data.update, graph.version) : undefined;
|
|
286
288
|
this.isResult = data.isResult ?? false;
|
|
287
289
|
}
|
|
288
290
|
injectValue(value, injectFrom) {
|
package/lib/type.d.ts
CHANGED
|
@@ -27,11 +27,13 @@ export type StaticNodeData = {
|
|
|
27
27
|
isResult?: boolean;
|
|
28
28
|
};
|
|
29
29
|
export type AgentNamelessFunction = (...param: any[]) => unknown;
|
|
30
|
+
export type AgentFilterParams = Record<string, any>;
|
|
30
31
|
export type ComputedNodeData = {
|
|
31
32
|
agent: string | AgentNamelessFunction;
|
|
32
33
|
inputs?: Array<any>;
|
|
33
34
|
anyInput?: boolean;
|
|
34
35
|
params?: NodeDataParams;
|
|
36
|
+
filterParams?: AgentFilterParams;
|
|
35
37
|
retry?: number;
|
|
36
38
|
timeout?: number;
|
|
37
39
|
if?: string;
|
|
@@ -59,11 +61,12 @@ export type AgentFunctionContext<ParamsType = DefaultParamsType, InputDataType =
|
|
|
59
61
|
verbose: boolean;
|
|
60
62
|
nodeId: string;
|
|
61
63
|
retry: number;
|
|
64
|
+
agentId?: string;
|
|
62
65
|
};
|
|
63
66
|
graphData?: GraphData | string;
|
|
64
67
|
agents?: AgentFunctionDictonary;
|
|
65
68
|
taskManager?: TaskManager;
|
|
66
|
-
filterParams:
|
|
69
|
+
filterParams: AgentFilterParams;
|
|
67
70
|
log?: TransactionLog[];
|
|
68
71
|
};
|
|
69
72
|
export type AgentFunction<ParamsType = DefaultParamsType, ResultType = DefaultResultData, InputDataType = DefaultInputData> = (context: AgentFunctionContext<ParamsType, InputDataType>) => Promise<ResultData<ResultType>>;
|
|
@@ -73,6 +76,7 @@ export type AgentFilterInfo = {
|
|
|
73
76
|
agent: AgentFilterFunction;
|
|
74
77
|
agentIds?: string[];
|
|
75
78
|
nodeIds?: string[];
|
|
79
|
+
filterParams?: AgentFilterParams;
|
|
76
80
|
};
|
|
77
81
|
export type AgentFunctionDictonary = Record<string, AgentFunction<any, any, any>>;
|
|
78
82
|
export type AgentFunctionInfo = {
|
package/lib/utils/test_agents.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.defaultTestAgents = void 0;
|
|
4
4
|
const experimental_agents_1 = require("../experimental_agents");
|
|
5
|
+
const openai_agent_1 = require("../experimental_agents/llm_agents/openai_agent");
|
|
5
6
|
exports.defaultTestAgents = {
|
|
6
7
|
bypassAgent: experimental_agents_1.bypassAgent,
|
|
7
8
|
echoAgent: experimental_agents_1.echoAgent,
|
|
@@ -19,4 +20,5 @@ exports.defaultTestAgents = {
|
|
|
19
20
|
popAgent: experimental_agents_1.popAgent,
|
|
20
21
|
shiftAgent: experimental_agents_1.shiftAgent,
|
|
21
22
|
streamMockAgent: experimental_agents_1.streamMockAgent,
|
|
23
|
+
openAIMockAgent: openai_agent_1.openAIMockAgent,
|
|
22
24
|
};
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataSource, ResultData } from "../type";
|
|
2
2
|
export declare const sleep: (milliseconds: number) => Promise<unknown>;
|
|
3
|
-
export declare const parseNodeName: (inputNodeId: any) => DataSource;
|
|
3
|
+
export declare const parseNodeName: (inputNodeId: any, version: number) => DataSource;
|
|
4
4
|
export declare function assert(condition: boolean, message: string, isWarn?: boolean): asserts condition;
|
|
5
5
|
export declare const isObject: (x: unknown) => boolean;
|
|
6
6
|
export declare const getDataFromSource: (result: ResultData | undefined, source: DataSource) => ResultData | undefined;
|
package/lib/utils/utils.js
CHANGED
|
@@ -5,7 +5,7 @@ const sleep = async (milliseconds) => {
|
|
|
5
5
|
return await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
6
6
|
};
|
|
7
7
|
exports.sleep = sleep;
|
|
8
|
-
const
|
|
8
|
+
const parseNodeName_02 = (inputNodeId) => {
|
|
9
9
|
if (typeof inputNodeId === "string") {
|
|
10
10
|
const regex = /^"(.*)"$/;
|
|
11
11
|
const match = inputNodeId.match(regex);
|
|
@@ -20,6 +20,24 @@ const parseNodeName = (inputNodeId) => {
|
|
|
20
20
|
}
|
|
21
21
|
return { value: inputNodeId }; // non-string literal
|
|
22
22
|
};
|
|
23
|
+
const parseNodeName = (inputNodeId, version) => {
|
|
24
|
+
if (version === 0.2) {
|
|
25
|
+
return parseNodeName_02(inputNodeId);
|
|
26
|
+
}
|
|
27
|
+
if (typeof inputNodeId === "string") {
|
|
28
|
+
const regex = /^:(.*)$/;
|
|
29
|
+
const match = inputNodeId.match(regex);
|
|
30
|
+
if (!match) {
|
|
31
|
+
return { value: inputNodeId }; // string literal
|
|
32
|
+
}
|
|
33
|
+
const parts = match[1].split(".");
|
|
34
|
+
if (parts.length == 1) {
|
|
35
|
+
return { nodeId: parts[0] };
|
|
36
|
+
}
|
|
37
|
+
return { nodeId: parts[0], propIds: parts.slice(1) };
|
|
38
|
+
}
|
|
39
|
+
return { value: inputNodeId }; // non-string literal
|
|
40
|
+
};
|
|
23
41
|
exports.parseNodeName = parseNodeName;
|
|
24
42
|
function assert(condition, message, isWarn = false) {
|
|
25
43
|
if (!condition) {
|
|
@@ -4,7 +4,7 @@ exports.agentValidator = void 0;
|
|
|
4
4
|
const agentValidator = (graphAgentIds, agentIds) => {
|
|
5
5
|
graphAgentIds.forEach((agentId) => {
|
|
6
6
|
if (!agentIds.has(agentId)) {
|
|
7
|
-
throw new Error("Invalid
|
|
7
|
+
throw new Error("Invalid Agent : " + agentId + " is not in callbackDictonary.");
|
|
8
8
|
}
|
|
9
9
|
});
|
|
10
10
|
return true;
|
package/lib/validators/common.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.staticNodeAttributeKeys = exports.computedNodeAttributeKeys = exports.graphDataAttributeKeys = void 0;
|
|
4
4
|
exports.graphDataAttributeKeys = ["nodes", "concurrency", "agentId", "loop", "verbose", "version"];
|
|
5
|
-
exports.computedNodeAttributeKeys = ["inputs", "anyInput", "params", "retry", "timeout", "agent", "graph", "isResult", "priority", "if"];
|
|
5
|
+
exports.computedNodeAttributeKeys = ["inputs", "anyInput", "params", "retry", "timeout", "agent", "graph", "isResult", "priority", "if", "filterParams"];
|
|
6
6
|
exports.staticNodeAttributeKeys = ["value", "update", "isResult"];
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.nodeValidator = void 0;
|
|
4
4
|
const nodeValidator = (nodeData) => {
|
|
5
5
|
if (nodeData.agent && nodeData.value) {
|
|
6
|
-
throw new Error("Cannot set both
|
|
6
|
+
throw new Error("Cannot set both agent and value");
|
|
7
7
|
}
|
|
8
8
|
if (!("agent" in nodeData) && !("value" in nodeData)) {
|
|
9
|
-
throw new Error("Either
|
|
9
|
+
throw new Error("Either agent or value is required");
|
|
10
10
|
}
|
|
11
11
|
return true;
|
|
12
12
|
};
|
|
@@ -12,7 +12,7 @@ const relationValidator = (data, staticNodeIds, computedNodeIds) => {
|
|
|
12
12
|
pendings[computedNodeId] = new Set();
|
|
13
13
|
if ("inputs" in nodeData && nodeData && nodeData.inputs) {
|
|
14
14
|
nodeData.inputs.forEach((inputNodeId) => {
|
|
15
|
-
const sourceNodeId = (0, utils_1.parseNodeName)(inputNodeId).nodeId;
|
|
15
|
+
const sourceNodeId = (0, utils_1.parseNodeName)(inputNodeId, data.version ?? 0.02).nodeId;
|
|
16
16
|
if (sourceNodeId) {
|
|
17
17
|
if (!nodeIds.has(sourceNodeId)) {
|
|
18
18
|
throw new Error(`Inputs not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`);
|
|
@@ -29,7 +29,7 @@ const relationValidator = (data, staticNodeIds, computedNodeIds) => {
|
|
|
29
29
|
const nodeData = data.nodes[staticNodeId];
|
|
30
30
|
if ("value" in nodeData && nodeData.update) {
|
|
31
31
|
const update = nodeData.update;
|
|
32
|
-
const updateNodeId = (0, utils_1.parseNodeName)(update).nodeId;
|
|
32
|
+
const updateNodeId = (0, utils_1.parseNodeName)(update, data.version ?? 0.02).nodeId;
|
|
33
33
|
if (!updateNodeId) {
|
|
34
34
|
throw new Error("Update it a literal");
|
|
35
35
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Asynchronous data flow execution engine for agentic AI apps.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -28,12 +28,14 @@
|
|
|
28
28
|
"homepage": "https://github.com/receptron/graphai#readme",
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@inquirer/prompts": "^5.0.0",
|
|
31
|
+
"@types/cors": "^2.8.17",
|
|
31
32
|
"@types/express": "^4.17.21",
|
|
32
33
|
"@types/node": "^20.8.7",
|
|
33
34
|
"@types/xml2js": "^0.4.14",
|
|
34
35
|
"@typescript-eslint/eslint-plugin": "^6.8.0",
|
|
35
36
|
"@typescript-eslint/parser": "^6.8.0",
|
|
36
37
|
"arxiv-api-ts": "^1.0.3",
|
|
38
|
+
"cors": "^2.8.5",
|
|
37
39
|
"deepmerge": "^4.3.1",
|
|
38
40
|
"dotenv": "^16.4.5",
|
|
39
41
|
"eslint": "^7.32.0 || ^8.2.0",
|
|
@@ -42,7 +44,7 @@
|
|
|
42
44
|
"groq-sdk": "^0.3.3",
|
|
43
45
|
"openai": "^4.12.4",
|
|
44
46
|
"prettier": "^3.0.3",
|
|
45
|
-
"slashgpt": "^0.0.
|
|
47
|
+
"slashgpt": "^0.0.9",
|
|
46
48
|
"tiktoken": "^1.0.14",
|
|
47
49
|
"ts-node": "^10.9.1",
|
|
48
50
|
"tsc-alias": "^1.8.8",
|