graphai 0.1.1 → 0.1.2

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.
Files changed (38) hide show
  1. package/README.md +43 -33
  2. package/lib/experimental_agents/data_agents/data_object_merge_template_agent.d.ts +26 -0
  3. package/lib/experimental_agents/data_agents/data_object_merge_template_agent.js +25 -0
  4. package/lib/experimental_agents/data_agents/data_sum_template_agent.js +1 -1
  5. package/lib/experimental_agents/index.d.ts +1 -1
  6. package/lib/experimental_agents/index.js +1 -1
  7. package/lib/experimental_agents/matrix_agents/dot_product_agent.d.ts +4 -0
  8. package/lib/experimental_agents/{matrix_agent.js → matrix_agents/dot_product_agent.js} +1 -27
  9. package/lib/experimental_agents/matrix_agents/index.d.ts +2 -0
  10. package/lib/experimental_agents/matrix_agents/index.js +7 -0
  11. package/lib/experimental_agents/matrix_agents/sort_by_values_agent.d.ts +6 -0
  12. package/lib/experimental_agents/matrix_agents/sort_by_values_agent.js +29 -0
  13. package/lib/experimental_agents/nested_agent.d.ts +0 -1
  14. package/lib/experimental_agents/nested_agent.js +13 -3
  15. package/lib/experimental_agents/string_agents/string_splitter_agent.d.ts +32 -0
  16. package/lib/experimental_agents/string_agents/string_splitter_agent.js +40 -0
  17. package/lib/experimental_agents/string_agents/string_template_agent.d.ts +23 -0
  18. package/lib/experimental_agents/string_agents/string_template_agent.js +21 -0
  19. package/lib/experimental_agents/test_agents/copy2array_agent.d.ts +2 -0
  20. package/lib/experimental_agents/test_agents/copy2array_agent.js +9 -0
  21. package/lib/experimental_agents/test_agents/index.d.ts +1 -0
  22. package/lib/experimental_agents/test_agents/index.js +3 -1
  23. package/lib/graphai.js +1 -5
  24. package/lib/node.d.ts +1 -2
  25. package/lib/node.js +8 -17
  26. package/lib/transaction_log.js +1 -1
  27. package/lib/utils/test_agents.d.ts +2 -0
  28. package/lib/utils/test_agents.js +20 -0
  29. package/lib/utils/test_utils.d.ts +12 -0
  30. package/lib/utils/test_utils.js +34 -0
  31. package/package.json +8 -10
  32. package/lib/experimental_agents/matrix_agent.d.ts +0 -9
  33. package/lib/experimental_agents/test_agents/echo_fork_index_agent.d.ts +0 -2
  34. package/lib/experimental_agents/test_agents/echo_fork_index_agent.js +0 -7
  35. package/lib/log.d.ts +0 -22
  36. package/lib/log.js +0 -49
  37. package/lib/task.d.ts +0 -18
  38. package/lib/task.js +0 -63
package/README.md CHANGED
@@ -2,47 +2,57 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- GraphAI is an asynchronous data flow execution engine, which makes it easy to create AI applications that need to make asynchronous AI API calls multiple times with some dependencies among them, such as giving the answer from one LLM call to another LLM call as a prompt.
5
+ GraphAI is an asynchronous data flow execution engine, which makes it easy to build *agentic* applications, which perform the orchestration of mutiple "AI agents".
6
6
 
7
- You just need to describe dependencies among those API calls in a single data flow graph, create a GraphAI object with that graph, and run it.
7
+ *Agentic* applications need to make asynchronous API calls (such as OpenAI's chat-completion API, database query, web search, and etc.) multiple times and manage data dependencies among them, such as giving the answer from one LLM call to another LLM call as a prompt -- which will become quite difficult to manage in a traditional programing style as the complexity of the application increases, because of the asynchronous nature of those APIs.
8
8
 
9
- Here is an example:
9
+ GraphAI allows developers to describe dependencies among those API calls in a single data flow graph (either in YAML or JSON), create a GraphAI instance with that graph, and let it run. The GraphAI engine will take care of all the complexity of concurrent asynchronous calls, data dependency management, error handling, retries and logging.
10
+
11
+ Here is an example graph, which uses the Wikipedia as the data source and perform an in-memory RAG.
10
12
 
11
13
  ```YAML
12
14
  nodes:
13
- taskA:
14
- agentId: sample
15
+ source: // Input data to this RAG application
16
+ value:
17
+ name: Sam Bankman-Fried
18
+ query: describe the final sentence by the court for Sam Bank-Fried
19
+ wikipedia: // Retrieve data from Wikipedia。
20
+ agentId: wikipediaAgent
21
+ inputs: [source.name]
22
+ chunks: // Break the text from Wikipedia into chunks(2048 character each with 512 overlap)
23
+ agentId: stringSplitterAgent
24
+ inputs: [wikipedia]
25
+ chunkEmbeddings: // Get embedding vector of each chunk
26
+ agentId: stringEmbeddingsAgent
27
+ inputs: [chunks]
28
+ topicEmbedding: // Get embedding vector of the question
29
+ agentId: stringEmbeddingsAgent
30
+ inputs: [source.query]
31
+ similarities: // Calculate the cosine similarity of each chunk
32
+ agentId: dotProductAgent
33
+ inputs: [chunkEmbeddings, topicEmbedding]
34
+ sortedChunks: // Sort chunks based on the similarity
35
+ agentId: sortByValuesAgent
36
+ inputs: [chunks, similarities]
37
+ referenceText: // Concatenate chunks up to the token limit (5000)
38
+ agentId: tokenBoundStringsAgent
39
+ inputs: [sortedChunks]
15
40
  params:
16
- // agent-specific parameters for taskA
17
- taskB:
18
- agentId: sample
41
+ limit: 5000
42
+ prompt: // Generate a prompt with that reference text
43
+ agentId: stringTemplateAgent
44
+ inputs: [source, referenceText]
19
45
  params:
20
- // agent-specific parameters for taskB
21
- taskC:
22
- agentId: sample
46
+ template: |-
47
+ Using the following document, ${0}
48
+ ${1}
49
+ query: // retrieves the answer from GPT3.5
50
+ agentId: slashGPTAgent
23
51
  params:
24
- // agent-specific parameters for taskC
25
- inputs: [taskA, taskB]
26
- ```
27
-
28
- ``` TypeScript
29
- const sampleAgentFunction = async (context: AgentFunctionContext) => {
30
- const {
31
- nodeId, // taskA, taskB or taskC
32
- params, // agent-specific parameters specified in the graph definition file
33
- inputs // inputs from previous nodes
34
- } = context;
35
- // Agent-specific code (such as calling OpenAI's chat.completions API)
36
- ...
37
- return result;
38
- }
39
-
40
- ...
41
- const file = fs.readFileSync(pathToYamlFile, "utf8");
42
- const graphData = YAML.parse(file);
43
- const graph = new GraphAI(graphData, { sample: sampleAgentFunction });
44
- const results = await graph.run();
45
- return results["taskC"];
52
+ manifest:
53
+ model: gpt-3.5-turbo
54
+ isResult: true // indicating this is the final result
55
+ inputs: [prompt]
46
56
  ```
47
57
 
48
58
  ## Background
@@ -1,2 +1,28 @@
1
1
  import { AgentFunction } from "../../graphai";
2
2
  export declare const dataObjectMergeTemplateAgent: AgentFunction;
3
+ declare const dataObjectMergeTemplateAgentInfo: {
4
+ name: string;
5
+ agent: AgentFunction;
6
+ mock: AgentFunction;
7
+ samples: {
8
+ inputs: ({
9
+ a: number;
10
+ b: number;
11
+ c?: undefined;
12
+ } | {
13
+ a: number;
14
+ b: number;
15
+ c: number;
16
+ })[];
17
+ params: {};
18
+ result: {
19
+ a: number;
20
+ b: number;
21
+ };
22
+ }[];
23
+ description: string;
24
+ author: string;
25
+ repository: string;
26
+ license: string;
27
+ };
28
+ export default dataObjectMergeTemplateAgentInfo;
@@ -11,3 +11,28 @@ const dataObjectMergeTemplateAgent = async ({ inputs }) => {
11
11
  }, {});
12
12
  };
13
13
  exports.dataObjectMergeTemplateAgent = dataObjectMergeTemplateAgent;
14
+ // for test and document
15
+ const sampleInputs = [
16
+ { a: 1, b: 1 },
17
+ { a: 2, b: 2 },
18
+ { a: 3, b: 0, c: 5 },
19
+ ];
20
+ const sampleParams = {};
21
+ const sampleResult = { a: 6, b: 3 };
22
+ const dataObjectMergeTemplateAgentInfo = {
23
+ name: "dataObjectMergeTemplateAgent",
24
+ agent: exports.dataObjectMergeTemplateAgent,
25
+ mock: exports.dataObjectMergeTemplateAgent,
26
+ samples: [
27
+ {
28
+ inputs: sampleInputs,
29
+ params: sampleParams,
30
+ result: sampleResult,
31
+ },
32
+ ],
33
+ description: "Merge object",
34
+ author: "Satoshi Nakajima",
35
+ repository: "https://github.com/receptron/graphai",
36
+ license: "MIT",
37
+ };
38
+ exports.default = dataObjectMergeTemplateAgentInfo;
@@ -24,7 +24,7 @@ const dataSumTemplateAgentInfo = {
24
24
  ],
25
25
  description: "Returns the sum of input values",
26
26
  author: "Satoshi Nakajima",
27
- repository: "https://github.com/snakajima/graphai",
27
+ repository: "https://github.com/receptron/graphai",
28
28
  license: "MIT",
29
29
  };
30
30
  exports.default = dataSumTemplateAgentInfo;
@@ -5,7 +5,7 @@ export * from "./data_agents";
5
5
  export * from "./nested_agent";
6
6
  export * from "./array_agents";
7
7
  export * from "./embedding_agent";
8
- export * from "./matrix_agent";
8
+ export * from "./matrix_agents";
9
9
  export * from "./token_agent";
10
10
  export * from "./test_agents";
11
11
  export * from "./map_agent";
@@ -21,7 +21,7 @@ __exportStar(require("./data_agents"), exports);
21
21
  __exportStar(require("./nested_agent"), exports);
22
22
  __exportStar(require("./array_agents"), exports);
23
23
  __exportStar(require("./embedding_agent"), exports);
24
- __exportStar(require("./matrix_agent"), exports);
24
+ __exportStar(require("./matrix_agents"), exports);
25
25
  __exportStar(require("./token_agent"), exports);
26
26
  __exportStar(require("./test_agents"), exports);
27
27
  __exportStar(require("./map_agent"), exports);
@@ -0,0 +1,4 @@
1
+ import { AgentFunction } from "../../graphai";
2
+ export declare const dotProductAgent: AgentFunction<Record<string, any>, {
3
+ contents: Array<number>;
4
+ }, Array<Array<number>>>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sortByValuesAgent = exports.dotProductAgent = void 0;
3
+ exports.dotProductAgent = void 0;
4
4
  // This agent calculates the dot product of an array of vectors (A[]) and a vector (B),
5
5
  // typically used to calculate cosine similarity of embedding vectors.
6
6
  // Inputs:
@@ -22,29 +22,3 @@ const dotProductAgent = async ({ inputs }) => {
22
22
  return { contents };
23
23
  };
24
24
  exports.dotProductAgent = dotProductAgent;
25
- // This agent returned a sorted array of one array (A) based on another array (B).
26
- // The default sorting order is "decendant".
27
- //
28
- // Parameters:
29
- // acendant: Specifies if the sorting order should be acendant. The default is "false" (decendant).
30
- // Inputs:
31
- // inputs[0]: Array<any>; // array to be sorted
32
- // inputs[1]: Array<number>; // array of numbers for sorting
33
- //
34
- const sortByValuesAgent = async ({ params, inputs }) => {
35
- const direction = params?.assendant ?? false ? -1 : 1;
36
- const sources = inputs[0];
37
- const values = inputs[1];
38
- const joined = sources.map((item, index) => {
39
- return { item, value: values[index] };
40
- });
41
- const contents = joined
42
- .sort((a, b) => {
43
- return (b.value - a.value) * direction;
44
- })
45
- .map((a) => {
46
- return a.item;
47
- });
48
- return { contents };
49
- };
50
- exports.sortByValuesAgent = sortByValuesAgent;
@@ -0,0 +1,2 @@
1
+ export { dotProductAgent } from "../../experimental_agents/matrix_agents/dot_product_agent";
2
+ export { sortByValuesAgent } from "../../experimental_agents/matrix_agents/sort_by_values_agent";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortByValuesAgent = exports.dotProductAgent = void 0;
4
+ var dot_product_agent_1 = require("../../experimental_agents/matrix_agents/dot_product_agent");
5
+ Object.defineProperty(exports, "dotProductAgent", { enumerable: true, get: function () { return dot_product_agent_1.dotProductAgent; } });
6
+ var sort_by_values_agent_1 = require("../../experimental_agents/matrix_agents/sort_by_values_agent");
7
+ Object.defineProperty(exports, "sortByValuesAgent", { enumerable: true, get: function () { return sort_by_values_agent_1.sortByValuesAgent; } });
@@ -0,0 +1,6 @@
1
+ import { AgentFunction } from "../../graphai";
2
+ export declare const sortByValuesAgent: AgentFunction<{
3
+ assendant?: boolean;
4
+ }, {
5
+ contents: Array<any>;
6
+ }, Array<any>>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortByValuesAgent = void 0;
4
+ // This agent returned a sorted array of one array (A) based on another array (B).
5
+ // The default sorting order is "decendant".
6
+ //
7
+ // Parameters:
8
+ // acendant: Specifies if the sorting order should be acendant. The default is "false" (decendant).
9
+ // Inputs:
10
+ // inputs[0]: Array<any>; // array to be sorted
11
+ // inputs[1]: Array<number>; // array of numbers for sorting
12
+ //
13
+ const sortByValuesAgent = async ({ params, inputs }) => {
14
+ const direction = params?.assendant ?? false ? -1 : 1;
15
+ const sources = inputs[0];
16
+ const values = inputs[1];
17
+ const joined = sources.map((item, index) => {
18
+ return { item, value: values[index] };
19
+ });
20
+ const contents = joined
21
+ .sort((a, b) => {
22
+ return (b.value - a.value) * direction;
23
+ })
24
+ .map((a) => {
25
+ return a.item;
26
+ });
27
+ return { contents };
28
+ };
29
+ exports.sortByValuesAgent = sortByValuesAgent;
@@ -1,6 +1,5 @@
1
1
  import { GraphData, AgentFunction } from "../graphai";
2
2
  export declare const nestedAgent: AgentFunction<{
3
3
  graph: GraphData;
4
- resultFrom: string;
5
4
  injectionTo?: Array<string>;
6
5
  }>;
@@ -9,15 +9,25 @@ const nestedAgent = async ({ params, inputs, agents, log, taskManager, graphData
9
9
  (0, utils_1.assert)(status.concurrency > status.running, `nestedAgent: Concurrency is too low: ${status.concurrency}`);
10
10
  }
11
11
  (0, utils_1.assert)(graphData !== undefined, "nestedAgent: graphData is required");
12
+ const injectionTo = params.injectionTo ??
13
+ inputs.map((__input, index) => {
14
+ return `$${index}`;
15
+ });
16
+ injectionTo.forEach((nodeId) => {
17
+ if (graphData.nodes[nodeId] === undefined) {
18
+ // If the input node does not exist, automatically create a static node
19
+ graphData.nodes[nodeId] = { value: {} };
20
+ }
21
+ });
12
22
  const graphAI = new graphai_1.GraphAI(graphData, agents || {}, taskManager);
13
23
  try {
14
24
  // Inject inputs to specified source nodes
15
- (params.injectionTo ?? []).forEach((injectToNodeId, index) => {
25
+ injectionTo.forEach((injectToNodeId, index) => {
16
26
  graphAI.injectValue(injectToNodeId, inputs[index]);
17
27
  });
18
- const results = await graphAI.run(true);
28
+ const results = await graphAI.run(false);
19
29
  log?.push(...graphAI.transactionLogs());
20
- return results[params.resultFrom];
30
+ return results;
21
31
  }
22
32
  catch (error) {
23
33
  log?.push(...graphAI.transactionLogs());
@@ -5,3 +5,35 @@ export declare const stringSplitterAgent: AgentFunction<{
5
5
  }, {
6
6
  contents: Array<string>;
7
7
  }, string>;
8
+ declare const stringSplitterAgentInfo: {
9
+ name: string;
10
+ agent: AgentFunction<{
11
+ chunkSize?: number | undefined;
12
+ overlap?: number | undefined;
13
+ }, {
14
+ contents: Array<string>;
15
+ }, string>;
16
+ mock: AgentFunction<{
17
+ chunkSize?: number | undefined;
18
+ overlap?: number | undefined;
19
+ }, {
20
+ contents: Array<string>;
21
+ }, string>;
22
+ samples: {
23
+ inputs: string[];
24
+ params: {
25
+ chunkSize: number;
26
+ };
27
+ result: {
28
+ contents: string[];
29
+ count: number;
30
+ chunkSize: number;
31
+ overlap: number;
32
+ };
33
+ }[];
34
+ description: string;
35
+ author: string;
36
+ repository: string;
37
+ license: string;
38
+ };
39
+ export default stringSplitterAgentInfo;
@@ -22,3 +22,43 @@ const stringSplitterAgent = async ({ params, inputs }) => {
22
22
  return { contents, count, chunkSize, overlap };
23
23
  };
24
24
  exports.stringSplitterAgent = stringSplitterAgent;
25
+ // for test and document
26
+ const sampleInput = [
27
+ "Here's to the crazy ones, the misfits, the rebels, the troublemakers, the round pegs in the square holes ... the ones who see things differently -- they're not fond of rules, and they have no respect for the status quo. ... You can quote them, disagree with them, glorify or vilify them, but the only thing you can't do is ignore them because they change things. ... They push the human race forward, and while some may see them as the crazy ones, we see genius, because the people who are crazy enough to think that they can change the world, are the ones who do.",
28
+ ];
29
+ const sampleParams = { chunkSize: 64 };
30
+ const sampleResult = {
31
+ contents: [
32
+ "Here's to the crazy ones, the misfits, the rebels, the troublema",
33
+ "roublemakers, the round pegs in the square holes ... the ones wh",
34
+ " ones who see things differently -- they're not fond of rules, a",
35
+ "rules, and they have no respect for the status quo. ... You can ",
36
+ "You can quote them, disagree with them, glorify or vilify them, ",
37
+ "y them, but the only thing you can't do is ignore them because t",
38
+ "ecause they change things. ... They push the human race forward,",
39
+ "forward, and while some may see them as the crazy ones, we see g",
40
+ "we see genius, because the people who are crazy enough to think ",
41
+ "o think that they can change the world, are the ones who do.",
42
+ " do.",
43
+ ],
44
+ count: 11,
45
+ chunkSize: 64,
46
+ overlap: 8,
47
+ };
48
+ const stringSplitterAgentInfo = {
49
+ name: "stringSplitterAgent",
50
+ agent: exports.stringSplitterAgent,
51
+ mock: exports.stringSplitterAgent,
52
+ samples: [
53
+ {
54
+ inputs: sampleInput,
55
+ params: sampleParams,
56
+ result: sampleResult,
57
+ },
58
+ ],
59
+ description: "This agent strip one long string into chunks using following parameters",
60
+ author: "Satoshi Nakajima",
61
+ repository: "https://github.com/receptron/graphai",
62
+ license: "MIT",
63
+ };
64
+ exports.default = stringSplitterAgentInfo;
@@ -2,3 +2,26 @@ import { AgentFunction } from "../../graphai";
2
2
  export declare const stringTemplateAgent: AgentFunction<{
3
3
  template: string;
4
4
  }, Record<string, any> | string, string>;
5
+ declare const stringTemplateAgentInfo: {
6
+ name: string;
7
+ agent: AgentFunction<{
8
+ template: string;
9
+ }, string | Record<string, any>, string>;
10
+ mock: AgentFunction<{
11
+ template: string;
12
+ }, string | Record<string, any>, string>;
13
+ samples: {
14
+ inputs: string[];
15
+ params: {
16
+ template: string;
17
+ };
18
+ result: {
19
+ content: string;
20
+ };
21
+ }[];
22
+ description: string;
23
+ author: string;
24
+ repository: string;
25
+ license: string;
26
+ };
27
+ export default stringTemplateAgentInfo;
@@ -10,3 +10,24 @@ const stringTemplateAgent = async ({ params, inputs }) => {
10
10
  return { content };
11
11
  };
12
12
  exports.stringTemplateAgent = stringTemplateAgent;
13
+ const sampleInput = ["hello", "test"];
14
+ const sampleParams = { template: "${0}: ${1}" };
15
+ const sampleResult = { content: "hello: test" };
16
+ // for test and document
17
+ const stringTemplateAgentInfo = {
18
+ name: "stringTemplateAgent",
19
+ agent: exports.stringTemplateAgent,
20
+ mock: exports.stringTemplateAgent,
21
+ samples: [
22
+ {
23
+ inputs: sampleInput,
24
+ params: sampleParams,
25
+ result: sampleResult,
26
+ },
27
+ ],
28
+ description: "Template agent",
29
+ author: "Satoshi Nakajima",
30
+ repository: "https://github.com/receptron/graphai",
31
+ license: "MIT",
32
+ };
33
+ exports.default = stringTemplateAgentInfo;
@@ -0,0 +1,2 @@
1
+ import { AgentFunction } from "../../graphai";
2
+ export declare const copy2ArrayAgent: AgentFunction;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copy2ArrayAgent = void 0;
4
+ const copy2ArrayAgent = async ({ inputs }) => {
5
+ return new Array(10).fill(undefined).map(() => {
6
+ return inputs[0];
7
+ });
8
+ };
9
+ exports.copy2ArrayAgent = copy2ArrayAgent;
@@ -3,3 +3,4 @@ export { echoAgent } from "../../experimental_agents/test_agents/echo_agent";
3
3
  export { copyMessageAgent } from "../../experimental_agents/test_agents/copy_message_agent";
4
4
  export { mergeNodeIdAgent } from "../../experimental_agents/test_agents/merge_node_id_agent";
5
5
  export { countingAgent } from "../../experimental_agents/test_agents/counting_agent";
6
+ export { copy2ArrayAgent } from "../../experimental_agents/test_agents/copy2array_agent";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.countingAgent = exports.mergeNodeIdAgent = exports.copyMessageAgent = exports.echoAgent = exports.bypassAgent = void 0;
3
+ exports.copy2ArrayAgent = exports.countingAgent = exports.mergeNodeIdAgent = exports.copyMessageAgent = exports.echoAgent = exports.bypassAgent = void 0;
4
4
  var bypass_agent_1 = require("../../experimental_agents/test_agents/bypass_agent");
5
5
  Object.defineProperty(exports, "bypassAgent", { enumerable: true, get: function () { return bypass_agent_1.bypassAgent; } });
6
6
  var echo_agent_1 = require("../../experimental_agents/test_agents/echo_agent");
@@ -11,3 +11,5 @@ var merge_node_id_agent_1 = require("../../experimental_agents/test_agents/merge
11
11
  Object.defineProperty(exports, "mergeNodeIdAgent", { enumerable: true, get: function () { return merge_node_id_agent_1.mergeNodeIdAgent; } });
12
12
  var counting_agent_1 = require("../../experimental_agents/test_agents/counting_agent");
13
13
  Object.defineProperty(exports, "countingAgent", { enumerable: true, get: function () { return counting_agent_1.countingAgent; } });
14
+ var copy2array_agent_1 = require("../../experimental_agents/test_agents/copy2array_agent");
15
+ Object.defineProperty(exports, "copy2ArrayAgent", { enumerable: true, get: function () { return copy2array_agent_1.copy2ArrayAgent; } });
package/lib/graphai.js CHANGED
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.GraphAI = void 0;
7
4
  const type_1 = require("./type");
@@ -9,7 +6,6 @@ const node_1 = require("./node");
9
6
  const utils_1 = require("./utils/utils");
10
7
  const validator_1 = require("./validator");
11
8
  const task_manager_1 = require("./task_manager");
12
- const crypto_1 = __importDefault(require("crypto"));
13
9
  const defaultConcurrency = 8;
14
10
  class GraphAI {
15
11
  // This method is called when either the GraphAI obect was created,
@@ -73,7 +69,7 @@ class GraphAI {
73
69
  this.logs = [];
74
70
  this.onLogCallback = (__log, __isUpdate) => { };
75
71
  this.repeatCount = 0;
76
- this.graphId = crypto_1.default.randomUUID();
72
+ this.graphId = URL.createObjectURL(new Blob()).slice(-36);
77
73
  this.data = data;
78
74
  this.callbackDictonary = callbackDictonary;
79
75
  this.taskManager = taskManager ?? new task_manager_1.TaskManager(data.concurrency ?? defaultConcurrency);
package/lib/node.d.ts CHANGED
@@ -23,9 +23,8 @@ export declare class ComputedNode extends Node {
23
23
  readonly timeout?: number;
24
24
  error?: Error;
25
25
  transactionId: undefined | number;
26
- sources: Record<string, DataSource>;
27
26
  readonly anyInput: boolean;
28
- inputs: Array<string>;
27
+ dataSources: Array<DataSource>;
29
28
  pendings: Set<string>;
30
29
  readonly isStaticNode = false;
31
30
  readonly isComputedNode = true;
package/lib/node.js CHANGED
@@ -33,7 +33,6 @@ class ComputedNode extends Node {
33
33
  constructor(graphId, nodeId, data, graph) {
34
34
  super(nodeId, graph);
35
35
  this.retryCount = 0;
36
- this.sources = {}; // data sources.
37
36
  this.isStaticNode = false;
38
37
  this.isComputedNode = true;
39
38
  this.graphId = graphId;
@@ -44,13 +43,8 @@ class ComputedNode extends Node {
44
43
  this.timeout = data.timeout;
45
44
  this.isResult = data.isResult ?? false;
46
45
  this.anyInput = data.anyInput ?? false;
47
- this.sources = (data.inputs ?? []).reduce((tmp, input) => {
48
- const source = (0, utils_1.parseNodeName)(input);
49
- tmp[source.nodeId] = source;
50
- return tmp;
51
- }, {});
52
- this.inputs = Object.keys(this.sources);
53
- this.pendings = new Set(this.inputs);
46
+ this.dataSources = (data.inputs ?? []).map(utils_1.parseNodeName);
47
+ this.pendings = new Set(this.dataSources.map((source) => source.nodeId));
54
48
  this.log.initForComputedNode(this);
55
49
  }
56
50
  isReadyNode() {
@@ -58,8 +52,7 @@ class ComputedNode extends Node {
58
52
  // Count the number of data actually available.
59
53
  // We care it only when this.anyInput is true.
60
54
  // Notice that this logic enables dynamic data-flows.
61
- const counter = this.inputs.reduce((count, nodeId) => {
62
- const source = this.sources[nodeId];
55
+ const counter = this.dataSources.reduce((count, source) => {
63
56
  const [result] = this.graph.resultsOf([source], this.anyInput);
64
57
  return result === undefined ? count : count + 1;
65
58
  }, 0);
@@ -90,8 +83,10 @@ class ComputedNode extends Node {
90
83
  // which this node needs data from.
91
84
  removePending(nodeId) {
92
85
  if (this.anyInput) {
93
- const [result] = this.graph.resultsOf([this.sources[nodeId]], this.anyInput);
94
- if (result) {
86
+ const results = this.graph.resultsOf(this.dataSources, this.anyInput).filter((result) => {
87
+ return result !== undefined;
88
+ });
89
+ if (results.length > 0) {
95
90
  this.pendings.clear();
96
91
  }
97
92
  }
@@ -116,11 +111,7 @@ class ComputedNode extends Node {
116
111
  // then it removes itself from the "running node" list of the graph.
117
112
  // Notice that setting the result of this node may make other nodes ready to run.
118
113
  async execute() {
119
- const previousResults = this.graph
120
- .resultsOf(this.inputs.map((input) => {
121
- return this.sources[input];
122
- }), this.anyInput)
123
- .filter((result) => {
114
+ const previousResults = this.graph.resultsOf(this.dataSources, this.anyInput).filter((result) => {
124
115
  // Remove undefined if anyInput flag is set.
125
116
  return !this.anyInput || result !== undefined;
126
117
  });
@@ -40,7 +40,7 @@ class TransactionLog {
40
40
  this.state = node.state;
41
41
  this.retryCount = node.retryCount > 0 ? node.retryCount : undefined;
42
42
  this.startTime = transactionId;
43
- this.inputs = node.inputs;
43
+ this.inputs = node.dataSources.map((source) => source.nodeId);
44
44
  this.inputsData = inputs.length > 0 ? inputs : undefined;
45
45
  graph.setLoopLog(this);
46
46
  graph.appendLog(this);
@@ -0,0 +1,2 @@
1
+ import { AgentFunctionDictonary } from "../graphai";
2
+ export declare const defaultTestAgents: AgentFunctionDictonary;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultTestAgents = void 0;
4
+ const experimental_agents_1 = require("../experimental_agents");
5
+ exports.defaultTestAgents = {
6
+ bypassAgent: experimental_agents_1.bypassAgent,
7
+ echoAgent: experimental_agents_1.echoAgent,
8
+ copyMessageAgent: experimental_agents_1.copyMessageAgent,
9
+ mergeNodeIdAgent: experimental_agents_1.mergeNodeIdAgent,
10
+ sleeperAgent: experimental_agents_1.sleeperAgent,
11
+ sleeperAgentDebug: experimental_agents_1.sleeperAgentDebug,
12
+ stringTemplateAgent: experimental_agents_1.stringTemplateAgent,
13
+ nestedAgent: experimental_agents_1.nestedAgent,
14
+ mapAgent: experimental_agents_1.mapAgent,
15
+ totalAgent: experimental_agents_1.totalAgent,
16
+ countingAgent: experimental_agents_1.countingAgent,
17
+ copy2ArrayAgent: experimental_agents_1.copy2ArrayAgent,
18
+ pushAgent: experimental_agents_1.pushAgent,
19
+ popAgent: experimental_agents_1.popAgent,
20
+ };
@@ -0,0 +1,12 @@
1
+ import { AgentFunctionInfo } from "../type";
2
+ export declare const defaultTestContext: {
3
+ debugInfo: {
4
+ nodeId: string;
5
+ retry: number;
6
+ verbose: boolean;
7
+ };
8
+ params: {};
9
+ agents: {};
10
+ log: never[];
11
+ };
12
+ export declare const agentTestRunner: (agentInfo: AgentFunctionInfo) => Promise<void>;
@@ -0,0 +1,34 @@
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.agentTestRunner = exports.defaultTestContext = void 0;
7
+ const node_assert_1 = __importDefault(require("node:assert"));
8
+ const node_test_1 = __importDefault(require("node:test"));
9
+ exports.defaultTestContext = {
10
+ debugInfo: {
11
+ nodeId: "test",
12
+ retry: 0,
13
+ verbose: true,
14
+ },
15
+ params: {},
16
+ agents: {},
17
+ log: [],
18
+ };
19
+ // for agent
20
+ const agentTestRunner = async (agentInfo) => {
21
+ (0, node_test_1.default)(`test ${agentInfo.name}`, async () => {
22
+ const { agent, samples } = agentInfo;
23
+ for await (const sample of samples) {
24
+ const { params, inputs, result } = sample;
25
+ const actual = await agent({
26
+ ...exports.defaultTestContext,
27
+ params,
28
+ inputs,
29
+ });
30
+ node_assert_1.default.deepStrictEqual(result, actual);
31
+ }
32
+ });
33
+ };
34
+ exports.agentTestRunner = agentTestRunner;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "graphai",
3
- "version": "0.1.1",
4
- "description": "Asynchronous data flow execution engine to make it simple to build LLM apps.",
3
+ "version": "0.1.2",
4
+ "description": "Asynchronous data flow execution engine for agentic AI apps.",
5
5
  "main": "lib/index.js",
6
6
  "files": [
7
7
  "./lib"
@@ -17,14 +17,14 @@
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": "git+https://github.com/snakajima/graphai"
20
+ "url": "git+https://github.com/receptron/graphai"
21
21
  },
22
- "author": "Satoshi Nakajima",
22
+ "author": "Satoshi Nakajima, Isamu Arimoto",
23
23
  "license": "MIT",
24
24
  "bugs": {
25
- "url": "https://github.com/snakajima/graphai/issues"
25
+ "url": "https://github.com/receptron/graphai/issues"
26
26
  },
27
- "homepage": "https://github.com/snakajima/graphai#readme",
27
+ "homepage": "https://github.com/receptron/graphai#readme",
28
28
  "devDependencies": {
29
29
  "@inquirer/prompts": "^5.0.0",
30
30
  "@types/express": "^4.17.21",
@@ -45,10 +45,8 @@
45
45
  "tsc-alias": "^1.8.8",
46
46
  "tsconfig-paths": "^4.2.0",
47
47
  "typescript": "^5.2.2",
48
- "wikipedia": "^2.1.2"
49
- },
50
- "dependencies": {
51
- "yaml": "^2.3.3"
48
+ "wikipedia": "^2.1.2",
49
+ "yaml": "^2.4.1"
52
50
  },
53
51
  "types": "./lib/index.d.ts",
54
52
  "directories": {
@@ -1,9 +0,0 @@
1
- import { AgentFunction } from "../graphai";
2
- export declare const dotProductAgent: AgentFunction<Record<string, any>, {
3
- contents: Array<number>;
4
- }, Array<Array<number>>>;
5
- export declare const sortByValuesAgent: AgentFunction<{
6
- assendant?: boolean;
7
- }, {
8
- contents: Array<any>;
9
- }, Array<any>>;
@@ -1,2 +0,0 @@
1
- import { AgentFunction } from "../../graphai";
2
- export declare const echoForkIndexAgent: AgentFunction;
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.echoForkIndexAgent = void 0;
4
- const echoForkIndexAgent = async ({ debugInfo: { forkIndex } }) => {
5
- return { forkIndex };
6
- };
7
- exports.echoForkIndexAgent = echoForkIndexAgent;
package/lib/log.d.ts DELETED
@@ -1,22 +0,0 @@
1
- import { ResultData, NodeDataParams, NodeState } from "./type";
2
- import type { GraphAI } from "./graphai";
3
- import type { ComputedNode, StaticNode } from "./node";
4
- export declare class TransactionLog {
5
- nodeId: string;
6
- state: NodeState;
7
- startTime?: number;
8
- endTime?: number;
9
- retryCount?: number;
10
- agentId?: string;
11
- params?: NodeDataParams;
12
- inputs?: Array<ResultData>;
13
- errorMessage?: string;
14
- result?: ResultData;
15
- log?: TransactionLog[];
16
- constructor(nodeId: string);
17
- initForComputedNode(node: ComputedNode): void;
18
- onInjected(node: StaticNode, graph: GraphAI): void;
19
- onComplete(node: ComputedNode, graph: GraphAI, localLog: TransactionLog[]): void;
20
- beforeExecute(node: ComputedNode, graph: GraphAI, transactionId: number, inputs: ResultData[]): void;
21
- onError(node: ComputedNode, graph: GraphAI, errorMessage: string): void;
22
- }
package/lib/log.js DELETED
@@ -1,49 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TransactionLog = void 0;
4
- const type_1 = require("./type");
5
- class TransactionLog {
6
- constructor(nodeId) {
7
- this.nodeId = nodeId;
8
- this.state = type_1.NodeState.Waiting;
9
- }
10
- initForComputedNode(node) {
11
- this.agentId = node.agentId;
12
- this.params = node.params;
13
- }
14
- onInjected(node, graph) {
15
- const isUpdating = "endTime" in this;
16
- this.result = node.value;
17
- this.state = node.state;
18
- this.endTime = Date.now();
19
- if (isUpdating) {
20
- graph.updateLog(this);
21
- }
22
- else {
23
- graph.appendLog(this);
24
- }
25
- }
26
- onComplete(node, graph, localLog) {
27
- this.result = node.result;
28
- this.state = node.state;
29
- this.endTime = Date.now();
30
- if (localLog.length > 0) {
31
- this.log = localLog;
32
- }
33
- graph.updateLog(this);
34
- }
35
- beforeExecute(node, graph, transactionId, inputs) {
36
- this.state = node.state;
37
- this.retryCount = node.retryCount > 0 ? node.retryCount : undefined;
38
- this.startTime = transactionId;
39
- this.inputs = inputs.length > 0 ? inputs : undefined;
40
- graph.appendLog(this);
41
- }
42
- onError(node, graph, errorMessage) {
43
- this.state = node.state;
44
- this.errorMessage = errorMessage;
45
- this.endTime = Date.now();
46
- graph.updateLog(this);
47
- }
48
- }
49
- exports.TransactionLog = TransactionLog;
package/lib/task.d.ts DELETED
@@ -1,18 +0,0 @@
1
- import { ComputedNode } from "./node";
2
- export declare class TaskManager {
3
- private concurrency;
4
- private taskQueue;
5
- private runningNodes;
6
- constructor(concurrency: number);
7
- private dequeueTaskIfPossible;
8
- addTask(node: ComputedNode, callback: (node: ComputedNode) => void): void;
9
- onComplete(node: ComputedNode): void;
10
- prepareForNesting(): void;
11
- getStatus(verbose?: boolean): {
12
- runningNodes?: string[] | undefined;
13
- queuedNodes?: string[] | undefined;
14
- concurrency: number;
15
- queue: number;
16
- running: number;
17
- };
18
- }
package/lib/task.js DELETED
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TaskManager = void 0;
4
- const utils_1 = require("./utils/utils");
5
- // TaskManage object controls the concurrency of ComputedNode execution.
6
- //
7
- // NOTE: A TaskManager instance will be shared between parent graph and its children
8
- // when nested agents are involved.
9
- class TaskManager {
10
- constructor(concurrency) {
11
- this.taskQueue = [];
12
- this.runningNodes = new Set();
13
- this.concurrency = concurrency;
14
- }
15
- // This internal method dequeus a task from the task queue
16
- // and call the associated callback method, if the number of
17
- // running task is lower than the spcified limit.
18
- dequeueTaskIfPossible() {
19
- if (this.runningNodes.size < this.concurrency) {
20
- const task = this.taskQueue.shift();
21
- if (task) {
22
- this.runningNodes.add(task.node);
23
- task.callback(task.node);
24
- }
25
- }
26
- }
27
- // Node will call this method to put itself in the execution queue.
28
- // We call the associated callback function when it is dequeued.
29
- addTask(node, callback) {
30
- this.taskQueue.push({ node, callback });
31
- this.dequeueTaskIfPossible();
32
- }
33
- // Node MUST call this method once the execution of agent function is completed
34
- // either successfully or not.
35
- onComplete(node) {
36
- (0, utils_1.assert)(this.runningNodes.has(node), `TaskManager.onComplete node(${node.nodeId}) is not in list`);
37
- this.runningNodes.delete(node);
38
- this.dequeueTaskIfPossible();
39
- }
40
- // Node will call this method before it hands the task manager from the graph
41
- // to a nested agent. We need to make it sure that there is enough room to run
42
- // computed nodes inside the nested graph to avoid a deadlock.
43
- prepareForNesting() {
44
- if (this.runningNodes.size === this.concurrency) {
45
- this.concurrency++;
46
- console.warn("WARNING: increasing concurrenty to", this.concurrency);
47
- }
48
- }
49
- getStatus(verbose = false) {
50
- return {
51
- concurrency: this.concurrency,
52
- queue: this.taskQueue.length,
53
- running: this.runningNodes.size,
54
- ...(verbose
55
- ? {
56
- runningNodes: Array.from(this.runningNodes).map((node) => node.nodeId),
57
- queuedNodes: this.taskQueue.map((task) => task.node.nodeId),
58
- }
59
- : {}),
60
- };
61
- }
62
- }
63
- exports.TaskManager = TaskManager;