graphai 0.4.8 → 0.5.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 CHANGED
@@ -190,12 +190,14 @@ nodes:
190
190
  inputs: [":source"] // == "sourceNode.query"
191
191
  database:
192
192
  agent: "nestedAgent"
193
- inputs: [":question", ":projectId"]
193
+ inputs:
194
+ prompt: ":question"
195
+ projectId: ":projectId"
194
196
  graph:
195
197
  nodes:
196
198
  schema: // retrieves the database schema for the apecified projectId
197
199
  agent: "schemaAgent"
198
- inputs: [":$1"]
200
+ inputs: [":projectId"]
199
201
  ... // issue query to the database and build an appropriate prompt with it.
200
202
  query: // send the generated prompt to the LLM
201
203
  agent: "llama3Agent"
@@ -296,7 +298,7 @@ nodes:
296
298
  value: [Steve Jobs, Elon Musk, Nikola Tesla]
297
299
  retriever:
298
300
  agent: "mapAgent"
299
- inputs: [":people"]
301
+ inputs: { rows: ":people" }
300
302
  graph:
301
303
  nodes:
302
304
  query:
@@ -304,7 +306,7 @@ nodes:
304
306
  params:
305
307
  manifest:
306
308
  prompt: Describe about the person in less than 100 words
307
- inputs: [":$0"]
309
+ inputs: [":row"]
308
310
  ```
309
311
 
310
312
  Here is the conceptual representation of this operation.
package/lib/graphai.d.ts CHANGED
@@ -25,6 +25,7 @@ export declare class GraphAI {
25
25
  constructor(data: GraphData, agentFunctionInfoDictionary: AgentFunctionInfoDictionary, options?: GraphOptions);
26
26
  getAgentFunctionInfo(agentId?: string): import("./type").AgentFunctionInfo | {
27
27
  agent: () => Promise<null>;
28
+ inputs: null;
28
29
  };
29
30
  asString(): string;
30
31
  results<T = DefaultResultData>(all: boolean): ResultDataDictionary<T>;
package/lib/graphai.js CHANGED
@@ -103,6 +103,7 @@ class GraphAI {
103
103
  agent: async () => {
104
104
  return null;
105
105
  },
106
+ inputs: null,
106
107
  };
107
108
  }
108
109
  // We are not supposed to hit this error because the validator will catch it.
package/lib/node.d.ts CHANGED
@@ -29,6 +29,7 @@ export declare class ComputedNode extends Node {
29
29
  transactionId: undefined | number;
30
30
  readonly anyInput: boolean;
31
31
  dataSources: Array<DataSource>;
32
+ inputNames?: Array<string>;
32
33
  pendings: Set<string>;
33
34
  private ifSource?;
34
35
  private unlessSource?;
package/lib/node.js CHANGED
@@ -40,23 +40,41 @@ class ComputedNode extends Node {
40
40
  this.params = data.params ?? {};
41
41
  this.console = data.console ?? {};
42
42
  this.filterParams = data.filterParams ?? {};
43
+ this.retryLimit = data.retry ?? graph.retryLimit ?? 0;
44
+ this.timeout = data.timeout;
45
+ this.isResult = data.isResult ?? false;
46
+ this.priority = data.priority ?? 0;
47
+ this.anyInput = data.anyInput ?? false;
48
+ if (!data.inputs) {
49
+ this.dataSources = [];
50
+ }
51
+ else if (Array.isArray(data.inputs)) {
52
+ this.dataSources = (data.inputs ?? []).map((input) => (0, utils_2.parseNodeName)(input, graph.version));
53
+ }
54
+ else {
55
+ const inputs = data.inputs;
56
+ const keys = Object.keys(inputs);
57
+ this.inputNames = keys;
58
+ this.dataSources = keys.map((key) => (0, utils_2.parseNodeName)(inputs[key], graph.version));
59
+ }
60
+ this.pendings = new Set(this.dataSources.filter((source) => source.nodeId).map((source) => source.nodeId));
43
61
  if (typeof data.agent === "string") {
44
62
  this.agentId = data.agent;
45
63
  }
46
64
  else {
47
65
  (0, utils_2.assert)(typeof data.agent === "function", "agent must be either string or function");
48
66
  const agent = data.agent;
49
- this.agentFunction = async ({ inputs }) => {
50
- return agent(...inputs);
51
- };
67
+ if (this.inputNames) {
68
+ this.agentFunction = async ({ namedInputs }) => {
69
+ return agent(namedInputs);
70
+ };
71
+ }
72
+ else {
73
+ this.agentFunction = async ({ inputs }) => {
74
+ return agent(...inputs);
75
+ };
76
+ }
52
77
  }
53
- this.retryLimit = data.retry ?? graph.retryLimit ?? 0;
54
- this.timeout = data.timeout;
55
- this.isResult = data.isResult ?? false;
56
- this.priority = data.priority ?? 0;
57
- this.anyInput = data.anyInput ?? false;
58
- this.dataSources = (data.inputs ?? []).map((input) => (0, utils_2.parseNodeName)(input, graph.version));
59
- this.pendings = new Set(this.dataSources.filter((source) => source.nodeId).map((source) => source.nodeId));
60
78
  if (typeof data.graph === "string") {
61
79
  const source = (0, utils_2.parseNodeName)(data.graph, graph.version);
62
80
  (0, utils_2.assert)(!!source.nodeId, `Invalid data source ${data.graph}`);
@@ -232,16 +250,26 @@ class ComputedNode extends Node {
232
250
  const context = {
233
251
  params: params,
234
252
  inputs: previousResults,
253
+ inputSchema: this.agentFunction ? undefined : this.graph.getAgentFunctionInfo(this.agentId)?.inputs,
254
+ namedInputs: {},
235
255
  debugInfo: {
236
256
  nodeId: this.nodeId,
237
257
  agentId: this.agentId,
238
258
  retry: this.retryCount,
239
259
  verbose: this.graph.verbose,
260
+ version: this.graph.version,
240
261
  },
241
262
  filterParams: this.filterParams,
242
263
  agentFilters: this.graph.agentFilters,
243
264
  log: localLog,
244
265
  };
266
+ if (this.inputNames) {
267
+ context.namedInputs = this.inputNames.reduce((tmp, name, index) => {
268
+ tmp[name] = previousResults[index];
269
+ return tmp;
270
+ }, {});
271
+ context.inputs = [];
272
+ }
245
273
  // NOTE: We use the existence of graph object in the agent-specific params to determine
246
274
  // if this is a nested agent or not.
247
275
  if (this.nestedGraph) {
@@ -257,7 +285,7 @@ class ComputedNode extends Node {
257
285
  context.agents = this.graph.agentFunctionInfoDictionary;
258
286
  }
259
287
  if (this.console.before) {
260
- console.log(this.console.before === true ? JSON.stringify(context.inputs, null, 2) : this.console.before);
288
+ console.log(this.console.before === true ? JSON.stringify(this.inputNames ? context.namedInputs : context.inputs, null, 2) : this.console.before);
261
289
  }
262
290
  const result = await this.agentFilterHandler(context, agentFunction);
263
291
  if (this.console.after) {
package/lib/type.d.ts CHANGED
@@ -30,7 +30,7 @@ export type AgentAnonymousFunction = (...params: any[]) => unknown;
30
30
  export type AgentFilterParams = Record<string, any>;
31
31
  export type ComputedNodeData = {
32
32
  agent: string | AgentAnonymousFunction;
33
- inputs?: Array<any>;
33
+ inputs?: Array<any> | Record<string, any>;
34
34
  anyInput?: boolean;
35
35
  params?: NodeDataParams;
36
36
  filterParams?: AgentFilterParams;
@@ -61,24 +61,27 @@ export type GraphOptions = {
61
61
  taskManager?: TaskManager | undefined;
62
62
  bypassAgentIds?: string[] | undefined;
63
63
  };
64
- export type AgentFunctionContext<ParamsType = DefaultParamsType, InputDataType = DefaultInputData> = {
64
+ export type AgentFunctionContext<ParamsType = DefaultParamsType, InputDataType = DefaultInputData, NamedInputDataType = DefaultInputData> = {
65
65
  params: NodeDataParams<ParamsType>;
66
66
  inputs: Array<InputDataType>;
67
+ inputSchema?: any;
68
+ namedInputs: NamedInputDataType;
67
69
  debugInfo: {
68
70
  verbose: boolean;
69
71
  nodeId: string;
70
72
  retry: number;
71
73
  agentId?: string;
74
+ version?: number;
72
75
  };
73
- graphData?: GraphData | string;
76
+ graphData?: GraphData;
74
77
  agents?: AgentFunctionInfoDictionary;
75
78
  taskManager?: TaskManager;
76
79
  filterParams: AgentFilterParams;
77
80
  agentFilters?: AgentFilterInfo[];
78
81
  log?: TransactionLog[];
79
82
  };
80
- export type AgentFunction<ParamsType = DefaultParamsType, ResultType = DefaultResultData, InputDataType = DefaultInputData> = (context: AgentFunctionContext<ParamsType, InputDataType>) => Promise<ResultData<ResultType>>;
81
- export type AgentFilterFunction<ParamsType = DefaultParamsType, ResultType = DefaultResultData, InputDataType = DefaultInputData> = (context: AgentFunctionContext<ParamsType, InputDataType>, agent: AgentFunction) => Promise<ResultData<ResultType>>;
83
+ export type AgentFunction<ParamsType = DefaultParamsType, ResultType = DefaultResultData, InputDataType = DefaultInputData, NamedInputDataType = DefaultInputData> = (context: AgentFunctionContext<ParamsType, InputDataType, NamedInputDataType>) => Promise<ResultData<ResultType>>;
84
+ export type AgentFilterFunction<ParamsType = DefaultParamsType, ResultType = DefaultResultData, InputDataType = DefaultInputData, NamedInputDataType = DefaultInputData> = (context: AgentFunctionContext<ParamsType, InputDataType, NamedInputDataType>, agent: AgentFunction) => Promise<ResultData<ResultType>>;
82
85
  export type AgentFilterInfo = {
83
86
  name: string;
84
87
  agent: AgentFilterFunction;
@@ -88,15 +91,16 @@ export type AgentFilterInfo = {
88
91
  };
89
92
  export type AgentFunctionInfo = {
90
93
  name: string;
91
- agent: AgentFunction<any, any, any>;
92
- mock: AgentFunction<any, any, any>;
94
+ agent: AgentFunction<any, any, any, any>;
95
+ mock: AgentFunction<any, any, any, any>;
96
+ inputs?: any;
97
+ output?: any;
93
98
  samples: {
94
99
  inputs: any;
95
100
  params: DefaultParamsType;
96
101
  result: any;
97
102
  graph?: GraphData;
98
103
  }[];
99
- skipTest?: boolean;
100
104
  description: string;
101
105
  category: string[];
102
106
  author: string;
@@ -12,17 +12,34 @@ const relationValidator = (data, staticNodeIds, computedNodeIds) => {
12
12
  const nodeData = data.nodes[computedNodeId];
13
13
  pendings[computedNodeId] = new Set();
14
14
  if ("inputs" in nodeData && nodeData && nodeData.inputs) {
15
- nodeData.inputs.forEach((inputNodeId) => {
16
- const sourceNodeId = (0, utils_1.parseNodeName)(inputNodeId, data.version ?? 0.02).nodeId;
17
- if (sourceNodeId) {
18
- if (!nodeIds.has(sourceNodeId)) {
19
- throw new common_1.ValidationError(`Inputs not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`);
15
+ if (Array.isArray(nodeData.inputs)) {
16
+ nodeData.inputs.forEach((inputNodeId) => {
17
+ const sourceNodeId = (0, utils_1.parseNodeName)(inputNodeId, data.version ?? 0.2).nodeId;
18
+ if (sourceNodeId) {
19
+ if (!nodeIds.has(sourceNodeId)) {
20
+ throw new common_1.ValidationError(`Inputs not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`);
21
+ }
22
+ waitlist[sourceNodeId] === undefined && (waitlist[sourceNodeId] = new Set());
23
+ pendings[computedNodeId].add(sourceNodeId);
24
+ waitlist[sourceNodeId].add(computedNodeId);
20
25
  }
21
- waitlist[sourceNodeId] === undefined && (waitlist[sourceNodeId] = new Set());
22
- pendings[computedNodeId].add(sourceNodeId);
23
- waitlist[sourceNodeId].add(computedNodeId);
24
- }
25
- });
26
+ });
27
+ }
28
+ else {
29
+ const keys = Object.keys(nodeData.inputs);
30
+ keys.forEach((key) => {
31
+ const inputNodeId = nodeData.inputs[key];
32
+ const sourceNodeId = (0, utils_1.parseNodeName)(inputNodeId, data.version ?? 0.3).nodeId;
33
+ if (sourceNodeId) {
34
+ if (!nodeIds.has(sourceNodeId)) {
35
+ throw new common_1.ValidationError(`Inputs not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`);
36
+ }
37
+ waitlist[sourceNodeId] === undefined && (waitlist[sourceNodeId] = new Set());
38
+ pendings[computedNodeId].add(sourceNodeId);
39
+ waitlist[sourceNodeId].add(computedNodeId);
40
+ }
41
+ });
42
+ }
26
43
  }
27
44
  });
28
45
  // TODO. validate update
@@ -30,7 +47,7 @@ const relationValidator = (data, staticNodeIds, computedNodeIds) => {
30
47
  const nodeData = data.nodes[staticNodeId];
31
48
  if ("value" in nodeData && nodeData.update) {
32
49
  const update = nodeData.update;
33
- const updateNodeId = (0, utils_1.parseNodeName)(update, data.version ?? 0.02).nodeId;
50
+ const updateNodeId = (0, utils_1.parseNodeName)(update, data.version ?? 0.2).nodeId;
34
51
  if (!updateNodeId) {
35
52
  throw new common_1.ValidationError("Update it a literal");
36
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphai",
3
- "version": "0.4.8",
3
+ "version": "0.5.1",
4
4
  "description": "Asynchronous data flow execution engine for agentic AI apps.",
5
5
  "main": "lib/index.js",
6
6
  "files": [