breadboard-ai / breadboard

A library for prototyping generative AI applications.
Apache License 2.0
208 stars 31 forks source link

Infinite recursion bug #3562

Open surma opened 1 month ago

surma commented 1 month ago

When running the attached board, the page freezes. A quick glance at DevTools seems to indicate that Entry#findOrCreate is recursing infinitely.

Board JSON ``` { "title": "dumbai", "description": "A blank board. Use it as a starting point for your creations.", "version": "0.0.1", "nodes": [ { "id": "dumbai-0b37eb16", "type": "idb://board-server-local/dumbai.bgl.json", "metadata": { "visual": { "x": -124, "y": -135, "collapsed": "advanced" }, "logLevel": "debug" }, "configuration": { "base": [ { "role": "user", "parts": [ { "text": "http://litellm.surmcluster.10.0.0.2.nip.io" } ] } ], "model": [ { "role": "user", "parts": [ { "text": "llama3.2-1b-surmbook" } ] } ], "prompt": [ { "role": "user", "parts": [ { "text": "" } ] } ], "system": [ { "role": "user", "parts": [ { "text": "You are a bot that replies to user quests in l33t sp34k!" } ] } ] } }, { "id": "input-bea2b58e", "type": "input", "metadata": { "visual": { "x": -617, "y": -68, "collapsed": "collapsed" }, "title": "Input" }, "configuration": { "schema": { "properties": { "context": { "type": "array", "title": "Context", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ] }, "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" } }, "type": "object", "required": [] } } }, { "id": "output-b1d31c94", "type": "output", "metadata": { "visual": { "x": 609.5, "y": -52.74853515625, "collapsed": "collapsed" }, "title": "Output" }, "configuration": { "schema": { "properties": { "context": { "type": "array", "title": "Context", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ] }, "default": "null" } }, "type": "object", "required": [] } } } ], "edges": [ { "from": "input-bea2b58e", "to": "dumbai-0b37eb16", "out": "context", "in": "prompt" }, { "from": "dumbai-0b37eb16", "to": "output-b1d31c94", "out": "context", "in": "context" } ], "url": "idb://board-server-local/dumbai.bgl.json", "metadata": { "comments": [] }, "graphs": { "2f4cf71f-4890-4a20-b9c5-ed852e2dd311": { "title": "OpenAI request", "description": "A blank board. Use it as a starting point for your creations.", "version": "0.0.1", "nodes": [ { "type": "input", "id": "input", "configuration": { "schema": { "properties": { "model": { "type": "array", "title": "Model", "items": { "type": "object", "behavior": [ "llm-content" ] }, "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]", "description": "" } }, "type": "object", "required": [] } }, "metadata": { "visual": { "x": 0, "y": 187, "collapsed": "collapsed" }, "logLevel": "debug" } }, { "type": "output", "id": "output", "configuration": { "schema": { "properties": { "response": { "type": "array", "title": "Response", "items": { "type": "object", "behavior": [ "llm-content" ] }, "default": "[{\"parts\":[],\"role\":\"user\"}]", "description": "" } }, "type": "object", "required": [] } }, "metadata": { "visual": { "x": 1445, "y": 532, "collapsed": "collapsed" }, "logLevel": "debug" } }, { "id": "fetch-5952907d", "type": "fetch", "metadata": { "visual": { "x": 771, "y": 419, "collapsed": "collapsed" }, "title": "Fetch" } }, { "id": "urlTemplate-d45d8d90", "type": "urlTemplate", "metadata": { "visual": { "x": 339, "y": 0, "collapsed": "collapsed" }, "title": "URL Template", "logLevel": "debug" }, "configuration": { "template": "http://{{base}}/chat/completions" } }, { "id": "input-f28f6006", "type": "input", "metadata": { "visual": { "x": 0, "y": 351, "collapsed": "collapsed" }, "title": "Input", "logLevel": "debug" }, "configuration": { "schema": { "properties": { "system": { "type": "array", "title": "System Prompt", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ] }, "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]", "description": "" } }, "type": "object", "required": [] } } }, { "id": "input-6cb30c0b", "type": "input", "metadata": { "visual": { "x": 0, "y": 515, "collapsed": "collapsed" }, "title": "Input", "logLevel": "debug" }, "configuration": { "schema": { "properties": { "prompt": { "type": "array", "title": "Prompt", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ] }, "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]", "description": "" } }, "type": "object", "required": [] } } }, { "id": "input-6e85311d", "type": "input", "metadata": { "visual": { "x": 0, "y": 23, "collapsed": "collapsed" }, "title": "Input", "logLevel": "debug" }, "configuration": { "schema": { "properties": { "base": { "type": "array", "title": "Base URL", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ] }, "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"http://localhost:11434\"}]}]", "description": "" } }, "type": "object", "required": [] } } }, { "id": "runJavascript-08a7708c", "type": "runJavascript", "metadata": { "visual": { "x": 290, "y": 345, "collapsed": "collapsed" }, "title": "Run Javascript", "logLevel": "debug" }, "configuration": { "code": "function run({model, system, prompt}) {\n return {\n body: {\n model,\n messages: [\n {\n role: \"system\",\n content: system\n },\n {\n role: \"user\",\n content: prompt\n }\n ]\n }\n };\n}", "name": "run", "inputSchema": { "type": "object", "properties": { "model": { "type": "array", "title": "Model", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ], "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" }, "description": "", "default": "[{\"parts\":[{\"text\":\"gpt-4o-mini\"}],\"role\":\"user\"}]" }, "system": { "type": "array", "title": "System Prompt", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ], "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" }, "description": "", "default": "[{\"parts\":[],\"role\":\"user\"}]" }, "prompt": { "type": "array", "title": "User Prompt", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ], "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" }, "description": "", "default": "[{\"parts\":[],\"role\":\"user\"}]" } }, "required": [] }, "outputSchema": { "type": "object", "properties": { "body": { "type": "array", "title": "Chat Completion Request Body", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ], "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" }, "description": "", "default": "[{\"parts\":[],\"role\":\"user\"}]" } }, "required": [] } } }, { "id": "runJavascript-6d3318d5", "type": "runJavascript", "metadata": { "visual": { "x": 1061, "y": 428, "collapsed": "collapsed" }, "title": "Run Javascript", "logLevel": "debug" }, "configuration": { "inputSchema": { "type": "object", "properties": { "response": { "type": "array", "title": "Response", "items": { "type": "object", "examples": [], "behavior": [ "llm-content" ], "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" }, "description": "", "default": "[{\"parts\":[],\"role\":\"user\"}]" } }, "required": [] }, "code": "function run({response}) {\n return response.choices[0].message.content\n}", "name": "run" } } ], "edges": [ { "from": "input-6e85311d", "to": "urlTemplate-d45d8d90", "in": "base", "out": "base" }, { "from": "urlTemplate-d45d8d90", "to": "fetch-5952907d", "in": "url", "out": "url" }, { "from": "input", "to": "runJavascript-08a7708c", "in": "model", "out": "model" }, { "from": "input-f28f6006", "to": "runJavascript-08a7708c", "in": "system", "out": "system" }, { "from": "input-6cb30c0b", "to": "runJavascript-08a7708c", "in": "prompt", "out": "prompt" }, { "from": "runJavascript-08a7708c", "to": "fetch-5952907d", "in": "body", "out": "result" }, { "from": "fetch-5952907d", "to": "runJavascript-6d3318d5", "in": "response", "out": "response" }, { "from": "runJavascript-6d3318d5", "to": "output", "in": "context", "out": "result" } ], "metadata": { "comments": [] } } } } ```
dglazkov commented 1 month ago

Fun! This board attempts to refer to itself, and that's why the weirdness happens.

dglazkov commented 1 month ago

it has three nodes:

We should probably not allow that 😆

dglazkov commented 1 month ago

seems like the right fix is to detect recursion in loader and bail with an error?

surma commented 1 month ago

I was trying to reference a subboard. I did that by opening the subboard, copying the URL using the tool bar icon and pasting it into the main board. Is that not the way? I could find the subboard in the components menu.

But yes, would be good to detect that ever being created, but also to detect at load.

surma commented 1 month ago

It's curious because the editor shows the correct inputs/outputs of the subboard... so it is clearly referencing the subboard. Not sure where I went wrong now 🤔

dglazkov commented 1 month ago

I did that by opening the subboard, copying the URL using the tool bar icon and pasting it into the main board

OOOH that's another bug! The URL it gave you was the main board URL!

dglazkov commented 1 month ago

The current working way of doing this is to use the invoke component, and then selecting the sub-board from the dropdown.

surma commented 1 month ago

Wait so I can paste other boards but I cannot paste a sub board? I think @paullewis is right that the name "subboard" is a misnomer. At least for me it causes associations that don't seem to hold

dglazkov commented 1 month ago

yeah, the whole "paste URL of the board as a component" hasn't propagated to sub-boards yet. Emergent software engineering 😆

dglazkov commented 1 month ago

Two bugs: