From 833fe2ce5ad9229eb4298a998916c79050ea20e1 Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 13:13:36 -0700 Subject: [PATCH 1/8] hooks on Graph:options --- src/graphai.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/graphai.ts b/src/graphai.ts index 03d6db690..7cbec3dfa 100644 --- a/src/graphai.ts +++ b/src/graphai.ts @@ -19,6 +19,7 @@ export class GraphAI { private readonly data: GraphData; private readonly loop?: LoopData; private readonly logs: Array = []; + private readonly hooks: Record {}>; public readonly callbackDictonary: AgentFunctionDictonary; public readonly taskManager: TaskManager; public readonly agentFilters: AgentFilterInfo[]; @@ -90,7 +91,7 @@ export class GraphAI { constructor( data: GraphData, callbackDictonary: AgentFunctionDictonary, - options: { agentFilters?: AgentFilterInfo[] | undefined; taskManager?: TaskManager | undefined } = { taskManager: undefined, agentFilters: [] }, + options: { agentFilters?: AgentFilterInfo[] | undefined; taskManager?: TaskManager | undefined, hooks?: Record {}> } = { taskManager: undefined, agentFilters: [] }, ) { if (!data.version && !options.taskManager) { console.log("------------ missing version number"); @@ -106,6 +107,7 @@ export class GraphAI { this.taskManager = options.taskManager ?? new TaskManager(data.concurrency ?? defaultConcurrency); this.agentFilters = options.agentFilters ?? []; this.loop = data.loop; + this.hooks = options.hooks ?? {}; this.verbose = data.verbose === true; this.onComplete = () => { console.error("-- SOMETHING IS WRONG: onComplete is called without run()"); From a57b7613db3891d027f3f4672e72e2a5954d2bdd Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 14:08:18 -0700 Subject: [PATCH 2/8] isHook --- src/type.ts | 1 + src/utils/utils.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/type.ts b/src/type.ts index 5010b0d5a..b000f4bc2 100644 --- a/src/type.ts +++ b/src/type.ts @@ -24,6 +24,7 @@ export type DataSource = { nodeId?: string; value?: any; propIds?: string[]; + isHook?: boolean; }; export type StaticNodeData = { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 3306154c5..5e34dfc99 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -25,6 +25,11 @@ export const parseNodeName = (inputNodeId: any, version: number): DataSource => return parseNodeName_02(inputNodeId); } if (typeof inputNodeId === "string") { + const regexHook = /^~(.*)$/; + const matchHook = inputNodeId.match(regexHook); + if (matchHook) { + return { value: matchHook[1], isHook: true }; + } const regex = /^:(.*)$/; const match = inputNodeId.match(regex); if (!match) { From dcf6f7e35216f14a4d7ec5e32f12b4035323aa56 Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 14:11:04 -0700 Subject: [PATCH 3/8] hooks --- src/graphai.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/graphai.ts b/src/graphai.ts index 7cbec3dfa..6342dd413 100644 --- a/src/graphai.ts +++ b/src/graphai.ts @@ -106,8 +106,8 @@ export class GraphAI { this.callbackDictonary = callbackDictonary; this.taskManager = options.taskManager ?? new TaskManager(data.concurrency ?? defaultConcurrency); this.agentFilters = options.agentFilters ?? []; - this.loop = data.loop; this.hooks = options.hooks ?? {}; + this.loop = data.loop; this.verbose = data.verbose === true; this.onComplete = () => { console.error("-- SOMETHING IS WRONG: onComplete is called without run()"); @@ -289,6 +289,9 @@ export class GraphAI { public resultsOf(sources: Array) { return sources.map((source) => { + if (source.isHook) { + return this.hooks[source.value]; + } const { result } = source.nodeId ? this.nodes[source.nodeId] : { result: undefined }; return getDataFromSource(result, source); }); From bea80faefbf15bd93ae38bfd9a1e2340a7d3d986 Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 14:34:05 -0700 Subject: [PATCH 4/8] test hooks --- tests/graphai/test_hooks.ts | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/graphai/test_hooks.ts diff --git a/tests/graphai/test_hooks.ts b/tests/graphai/test_hooks.ts new file mode 100644 index 000000000..b0dd12316 --- /dev/null +++ b/tests/graphai/test_hooks.ts @@ -0,0 +1,44 @@ +import { AgentFunction } from "@/graphai"; +import { graphDataTestRunner } from "~/utils/runner"; +import { sleep } from "@/utils/utils"; + +import test from "node:test"; +import assert from "node:assert"; + +const graphdata_hook = { + version: 0.3, + nodes: { + streamNode: { + agent: "streamAgent", + isResult: true, + }, + }, +}; + + +const streamAgent: AgentFunction<{ stream: (data:string)=> void }, string, any> = async ({ + params, +}) => { + const message = "May the force be with you"; + if (params.stream) { + message.split('').forEach(async (word: string) => { + await sleep(10); + params.stream(word); + }); + } + return message; +}; + +test("test dispatch", async () => { + const result = await graphDataTestRunner(__filename, graphdata_hook, {streamAgent}, () => {}, false); + console.log(result); + /* + assert.deepStrictEqual(result, { + node1: { node1: "output" }, + node2: { port1: { node2: "dispatch" } }, + node3: { node3: "output", node1: "output", node2: "dispatch" }, + node4: { node4: "output", node3: "output", node1: "output", node2: "dispatch" }, + node5: { node5: "output", node4: "output", node3: "output", node1: "output", node2: "dispatch" }, + }); + */ +}); From ca3fd161e9433b87303417c499b784a3a1fe55bc Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 14:45:15 -0700 Subject: [PATCH 5/8] compiles --- tests/graphai/test_hooks.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/graphai/test_hooks.ts b/tests/graphai/test_hooks.ts index b0dd12316..3cdc53be9 100644 --- a/tests/graphai/test_hooks.ts +++ b/tests/graphai/test_hooks.ts @@ -1,36 +1,45 @@ +import { GraphAI } from "@/graphai"; +import { defaultTestAgents } from "@/utils/test_agents"; import { AgentFunction } from "@/graphai"; -import { graphDataTestRunner } from "~/utils/runner"; import { sleep } from "@/utils/utils"; import test from "node:test"; -import assert from "node:assert"; +// import assert from "node:assert"; const graphdata_hook = { version: 0.3, nodes: { streamNode: { agent: "streamAgent", + params: { + stream: "~test_hook", + }, isResult: true, }, }, }; -const streamAgent: AgentFunction<{ stream: (data:string)=> void }, string, any> = async ({ +const streamAgent: AgentFunction<{ stream: (data:Record)=> void }, string, any> = async ({ params, }) => { const message = "May the force be with you"; if (params.stream) { message.split('').forEach(async (word: string) => { await sleep(10); - params.stream(word); + params.stream({word}); }); } return message; }; +const test_hook = (data: Record) => { + console.log(data.word); +} + test("test dispatch", async () => { - const result = await graphDataTestRunner(__filename, graphdata_hook, {streamAgent}, () => {}, false); + const graph = new GraphAI(graphdata_hook, { ...defaultTestAgents, streamAgent }, { hooks: { test_hook }}); + const result = await graph.run(false); console.log(result); /* assert.deepStrictEqual(result, { From 1ad6565ad0fab13a3f4778632ca0a1a56ecc3d67 Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 14:47:59 -0700 Subject: [PATCH 6/8] inputs --- tests/graphai/test_hooks.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/graphai/test_hooks.ts b/tests/graphai/test_hooks.ts index 3cdc53be9..c6b6d46e3 100644 --- a/tests/graphai/test_hooks.ts +++ b/tests/graphai/test_hooks.ts @@ -9,25 +9,29 @@ import test from "node:test"; const graphdata_hook = { version: 0.3, nodes: { + source: { + value: "May the force be with you" + }, streamNode: { agent: "streamAgent", params: { - stream: "~test_hook", + streamx: "~test_hook", }, isResult: true, + inputs: [":source"], }, }, }; -const streamAgent: AgentFunction<{ stream: (data:Record)=> void }, string, any> = async ({ - params, +const streamAgent: AgentFunction<{ stream: (data:Record)=> void }, string, string> = async ({ + params, inputs }) => { - const message = "May the force be with you"; + const [message] = inputs; if (params.stream) { message.split('').forEach(async (word: string) => { await sleep(10); - params.stream({word}); + params.stream({word}); }); } return message; @@ -37,7 +41,7 @@ const test_hook = (data: Record) => { console.log(data.word); } -test("test dispatch", async () => { +test("test hook", async () => { const graph = new GraphAI(graphdata_hook, { ...defaultTestAgents, streamAgent }, { hooks: { test_hook }}); const result = await graph.run(false); console.log(result); From 0f29baa9a79e0e7677808843fd16754dfcb78c93 Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 14:54:01 -0700 Subject: [PATCH 7/8] stream --- tests/graphai/test_hooks.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/graphai/test_hooks.ts b/tests/graphai/test_hooks.ts index c6b6d46e3..560f1d0df 100644 --- a/tests/graphai/test_hooks.ts +++ b/tests/graphai/test_hooks.ts @@ -10,12 +10,12 @@ const graphdata_hook = { version: 0.3, nodes: { source: { - value: "May the force be with you" + value: "May the force be with you." }, streamNode: { agent: "streamAgent", params: { - streamx: "~test_hook", + stream: "~test_hook", }, isResult: true, inputs: [":source"], @@ -24,14 +24,16 @@ const graphdata_hook = { }; -const streamAgent: AgentFunction<{ stream: (data:Record)=> void }, string, string> = async ({ +const streamAgent: AgentFunction<{ stream?: (data:Record)=> void }, string, string> = async ({ params, inputs }) => { const [message] = inputs; - if (params.stream) { - message.split('').forEach(async (word: string) => { + const {stream} = params; + if (stream) { + message.split(' ').forEach(async (word: string) => { await sleep(10); - params.stream({word}); + console.log(word); + //stream({word}); }); } return message; From 921e8a852253a83a0d25e505ffece0fdfe5fbbe2 Mon Sep 17 00:00:00 2001 From: snakajima Date: Sat, 11 May 2024 15:27:50 -0700 Subject: [PATCH 8/8] test_hook --- src/graphai.ts | 11 ++++++----- src/node.ts | 4 ++++ src/utils/utils.ts | 1 + tests/graphai/test_hooks.ts | 7 +++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/graphai.ts b/src/graphai.ts index 6342dd413..314c52e16 100644 --- a/src/graphai.ts +++ b/src/graphai.ts @@ -19,7 +19,7 @@ export class GraphAI { private readonly data: GraphData; private readonly loop?: LoopData; private readonly logs: Array = []; - private readonly hooks: Record {}>; + private readonly hooks: Record) => void>; public readonly callbackDictonary: AgentFunctionDictonary; public readonly taskManager: TaskManager; public readonly agentFilters: AgentFilterInfo[]; @@ -91,7 +91,7 @@ export class GraphAI { constructor( data: GraphData, callbackDictonary: AgentFunctionDictonary, - options: { agentFilters?: AgentFilterInfo[] | undefined; taskManager?: TaskManager | undefined, hooks?: Record {}> } = { taskManager: undefined, agentFilters: [] }, + options: { agentFilters?: AgentFilterInfo[] | undefined; taskManager?: TaskManager | undefined, hooks?: Record) => void> } = { taskManager: undefined, agentFilters: [] }, ) { if (!data.version && !options.taskManager) { console.log("------------ missing version number"); @@ -289,11 +289,12 @@ export class GraphAI { public resultsOf(sources: Array) { return sources.map((source) => { - if (source.isHook) { - return this.hooks[source.value]; - } const { result } = source.nodeId ? this.nodes[source.nodeId] : { result: undefined }; return getDataFromSource(result, source); }); } + + public getHook(hookId: string) { + return this.hooks[hookId]; + } } diff --git a/src/node.ts b/src/node.ts index a6bc45bac..ebf9c96fe 100644 --- a/src/node.ts +++ b/src/node.ts @@ -108,6 +108,10 @@ export class ComputedNode extends Node { assert(!this.anyInput, "Dynamic params are not supported with anyInput"); tmp[key] = dataSource; this.pendings.add(dataSource.nodeId); + } else if (dataSource.isHook) { + const hook = graph.getHook(dataSource.value); + assert(hook !== undefined, `Specified hook does not exist: ${dataSource.value}`); + this.params[key] = hook; } return tmp; }, {}); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 5e34dfc99..546797822 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -28,6 +28,7 @@ export const parseNodeName = (inputNodeId: any, version: number): DataSource => const regexHook = /^~(.*)$/; const matchHook = inputNodeId.match(regexHook); if (matchHook) { + console.log("****", inputNodeId, matchHook[1]); return { value: matchHook[1], isHook: true }; } const regex = /^:(.*)$/; diff --git a/tests/graphai/test_hooks.ts b/tests/graphai/test_hooks.ts index 560f1d0df..9b0a03f88 100644 --- a/tests/graphai/test_hooks.ts +++ b/tests/graphai/test_hooks.ts @@ -30,11 +30,10 @@ const streamAgent: AgentFunction<{ stream?: (data:Record)=> void }, const [message] = inputs; const {stream} = params; if (stream) { - message.split(' ').forEach(async (word: string) => { + for await (const word of message.split(' ')) { await sleep(10); - console.log(word); - //stream({word}); - }); + stream({word}); + }; } return message; };