graphai 0.3.0 → 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.
@@ -0,0 +1,2 @@
1
+ import { AgentFilterFunction, AgentFunctionContext } from "../type";
2
+ export declare const streamAgentFilterGenerator: <T>(callback: (context: AgentFunctionContext, data: T) => void) => AgentFilterFunction;
@@ -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;
@@ -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]: Two dimentional array of numbers (but the array size is 1 for the first dimention)
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][0];
13
+ const reference = inputs[1];
14
14
  if (embeddings[0].length != reference.length) {
15
- throw new Error("dotProduct: Length of vectors do not match.");
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
- [[3, 2]],
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 (params.streamCallback) {
9
- params.streamCallback(token);
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: "Sstream mock agent",
22
+ description: "Stream mock agent",
23
23
  category: [],
24
- author: "xSatoshi Nakajima",
24
+ author: "Isamu Arimoto",
25
25
  repository: "https://github.com/receptron/graphai",
26
26
  license: "MIT",
27
27
  };
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(key, results) {
43
- const source = (0, utils_1.parseNodeName)(key, this.version);
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,12 +67,12 @@ class GraphAI {
67
67
  this.logs = [];
68
68
  this.onLogCallback = (__log, __isUpdate) => { };
69
69
  this.repeatCount = 0;
70
- if (!data.version) {
71
- console.log("------------ no version");
70
+ if (!data.version && !options.taskManager) {
71
+ console.log("------------ missing version number");
72
72
  }
73
- this.version = data.version ?? 0.2;
74
- if (this.version < 0.3) {
75
- console.log("------------ upgrade to 0.3!");
73
+ this.version = data.version ?? latestVersion;
74
+ if (this.version < latestVersion) {
75
+ console.log(`------------ upgrade to ${latestVersion}!`);
76
76
  }
77
77
  this.retryLimit = data.retry; // optional
78
78
  this.graphId = URL.createObjectURL(new Blob()).slice(-36);
@@ -198,7 +198,8 @@ class GraphAI {
198
198
  this.initializeNodes(results);
199
199
  // Notice that we need to check the while condition *after* calling initializeNodes.
200
200
  if (loop.while) {
201
- const value = this.getValueFromResults(loop.while, this.results(true));
201
+ const source = (0, utils_1.parseNodeName)(loop.while, this.version);
202
+ const value = this.getValueFromResults(source, this.results(true));
202
203
  // NOTE: We treat an empty array as false.
203
204
  if (Array.isArray(value) ? value.length === 0 : !value) {
204
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?: string;
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;
@@ -64,6 +65,7 @@ class ComputedNode extends Node {
64
65
  this.dynamicParams = Object.keys(this.params).reduce((tmp, key) => {
65
66
  const dataSource = (0, utils_2.parseNodeName)(this.params[key], graph.version < 0.3 ? 0.3 : graph.version);
66
67
  if (dataSource.nodeId) {
68
+ (0, utils_2.assert)(!this.anyInput, "Dynamic params are not supported with anyInput");
67
69
  tmp[key] = dataSource;
68
70
  this.pendings.add(dataSource.nodeId);
69
71
  }
@@ -171,6 +173,9 @@ class ComputedNode extends Node {
171
173
  const agentFilter = this.graph.agentFilters[index++];
172
174
  if (agentFilter) {
173
175
  if (this.shouldApplyAgentFilter(agentFilter)) {
176
+ if (agentFilter.filterParams) {
177
+ context.filterParams = { ...agentFilter.filterParams, ...context.filterParams };
178
+ }
174
179
  return agentFilter.agent(context, next);
175
180
  }
176
181
  return next(context);
@@ -208,10 +213,11 @@ class ComputedNode extends Node {
208
213
  inputs: previousResults,
209
214
  debugInfo: {
210
215
  nodeId: this.nodeId,
216
+ agentId: this.agentId,
211
217
  retry: this.retryCount,
212
218
  verbose: this.graph.verbose,
213
219
  },
214
- filterParams: {},
220
+ filterParams: this.filterParams,
215
221
  log: localLog,
216
222
  };
217
223
  // NOTE: We use the existence of graph object in the agent-specific params to determine
@@ -278,7 +284,7 @@ class StaticNode extends Node {
278
284
  this.isStaticNode = true;
279
285
  this.isComputedNode = false;
280
286
  this.value = data.value;
281
- this.update = data.update;
287
+ this.update = data.update ? (0, utils_2.parseNodeName)(data.update, graph.version) : undefined;
282
288
  this.isResult = data.isResult ?? false;
283
289
  }
284
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: Record<string, any>;
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 = {
@@ -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
  };
@@ -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 AgentId : " + agentId + " is not in callbackDictonary.");
7
+ throw new Error("Invalid Agent : " + agentId + " is not in callbackDictonary.");
8
8
  }
9
9
  });
10
10
  return true;
@@ -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 agentId and value");
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 agentId or value is required");
9
+ throw new Error("Either agent or value is required");
10
10
  }
11
11
  return true;
12
12
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphai",
3
- "version": "0.3.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.8",
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",