[ { "id": "c7c51d373990a1fa", "type": "comment", "z": "a38a9db5ce759685", "name": "node-red-ai-toolkit", "info": "", "x": 110, "y": 40, "wires": [] }, { "id": "f27a059d7c76c412", "type": "comment", "z": "a38a9db5ce759685", "name": "Configuration", "info": "", "x": 90, "y": 240, "wires": [] }, { "id": "d83adc2f187a5ab9", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "configure", "info": "describe your reusable flow here", "scope": "global", "x": 80, "y": 300, "wires": [ [ "52418588691ed3c2" ] ] }, { "id": "6af725c9630f5ef9", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 400, "y": 280, "wires": [] }, { "id": "52418588691ed3c2", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": ";(async function () {\n node.status({ fill:'yellow', shape:'ring', text:'configuring' })\n const { configureGlobally } = global.get('AI-Toolkit-commonCode')\n\n await configureGlobally(msg)\n node.status({ fill:'green', shape:'dot', text:'configured' })\n\n node.send(msg)\n node.done()\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 240, "y": 300, "wires": [ [ "6af725c9630f5ef9" ], [ "8fcb24e7b94eb2c0" ] ] }, { "id": "8fcb24e7b94eb2c0", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 390, "y": 320, "wires": [] }, { "id": "20d770dbee6b3fc6", "type": "comment", "z": "a38a9db5ce759685", "name": "Model List", "info": "", "x": 740, "y": 100, "wires": [] }, { "id": "d4dfef4c8826163f", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "list_models", "info": "describe your reusable flow here", "scope": "global", "x": 750, "y": 160, "wires": [ [ "3acff27d8da4ea50" ] ] }, { "id": "f28f593c71780f3b", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1080, "y": 140, "wires": [] }, { "id": "3acff27d8da4ea50", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const { availableModels } = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n try {\n msg.payload = await availableModels()\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.send([null,msg])\n node.done()\n }\n})()\n\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 920, "y": 160, "wires": [ [ "f28f593c71780f3b" ], [ "66cbdc84cfa7a35c" ] ] }, { "id": "66cbdc84cfa7a35c", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1070, "y": 180, "wires": [] }, { "id": "5e925a9ae4836a65", "type": "comment", "z": "a38a9db5ce759685", "name": "Text Completion", "info": "", "x": 760, "y": 260, "wires": [] }, { "id": "5b9643f8ab152fe5", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "complete_text", "info": "describe your reusable flow here", "scope": "global", "x": 750, "y": 320, "wires": [ [ "5d3c8db44f01bd5e" ] ] }, { "id": "8477e25db44665bb", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1080, "y": 300, "wires": [] }, { "id": "5d3c8db44f01bd5e", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, CompletionOfText\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await CompletionOfText(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 920, "y": 320, "wires": [ [ "8477e25db44665bb" ], [ "9dd918f5bfeb8d86" ] ] }, { "id": "9dd918f5bfeb8d86", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1070, "y": 340, "wires": [] }, { "id": "57829b6621ccf96f", "type": "comment", "z": "a38a9db5ce759685", "name": "Chat Completion", "info": "", "x": 760, "y": 380, "wires": [] }, { "id": "17f5e6bbea345c66", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "complete_chat", "info": "describe your reusable flow here", "scope": "global", "x": 760, "y": 440, "wires": [ [ "d0ce83fc6847b3a3" ] ] }, { "id": "326cabf27ac56da3", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1100, "y": 420, "wires": [] }, { "id": "d0ce83fc6847b3a3", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n OptionsFrom, CompletionOfChat\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const ChatMessages = msg.payload\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await CompletionOfChat(ChatMessages, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 940, "y": 440, "wires": [ [ "326cabf27ac56da3" ], [ "6a2cbaa9d48b012e" ] ] }, { "id": "6a2cbaa9d48b012e", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1090, "y": 460, "wires": [] }, { "id": "9d2c1ea2be57fc38", "type": "comment", "z": "a38a9db5ce759685", "name": "Tokenization", "info": "", "x": 750, "y": 500, "wires": [] }, { "id": "f77c0f8fa19a2b60", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "tokenize_text", "info": "describe your reusable flow here", "scope": "global", "x": 750, "y": 560, "wires": [ [ "9794258f73de7ed1" ] ] }, { "id": "2c348d0c188be2ca", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1080, "y": 540, "wires": [] }, { "id": "9794258f73de7ed1", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, TokenizationOfText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await TokenizationOfText(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 920, "y": 560, "wires": [ [ "2c348d0c188be2ca" ], [ "f79d2227b49f5a1e" ] ] }, { "id": "f79d2227b49f5a1e", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1070, "y": 580, "wires": [] }, { "id": "bbec528975e3afa6", "type": "comment", "z": "a38a9db5ce759685", "name": "Embeddings Calculation", "info": "", "x": 790, "y": 620, "wires": [] }, { "id": "116a6903686ed624", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "calculate_embeddings", "info": "describe your reusable flow here", "scope": "global", "x": 780, "y": 680, "wires": [ [ "960554b7f1796b90" ] ] }, { "id": "d5aec8b7b51cab38", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1140, "y": 660, "wires": [] }, { "id": "960554b7f1796b90", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, EmbeddingsOfText\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await EmbeddingsOfText(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 980, "y": 680, "wires": [ [ "d5aec8b7b51cab38" ], [ "3dcfa399ebb7d740" ] ] }, { "id": "3dcfa399ebb7d740", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1130, "y": 700, "wires": [] }, { "id": "348a86265f575987", "type": "comment", "z": "a38a9db5ce759685", "name": "Human Language Detection", "info": "", "x": 1460, "y": 100, "wires": [] }, { "id": "e88a0b3547f6594c", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "language_of_text", "info": "describe your reusable flow here", "scope": "global", "x": 1420, "y": 160, "wires": [ [ "d03bb84a526ad431" ] ] }, { "id": "98cedf9a86bd6b9d", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1760, "y": 140, "wires": [] }, { "id": "d03bb84a526ad431", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, LanguageOfText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await LanguageOfText(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1600, "y": 160, "wires": [ [ "98cedf9a86bd6b9d" ], [ "b5638f3ac64c1674" ] ] }, { "id": "b5638f3ac64c1674", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1750, "y": 180, "wires": [] }, { "id": "3d827ad7bde5beea", "type": "comment", "z": "a38a9db5ce759685", "name": "Human Language Translation", "info": "", "x": 1460, "y": 220, "wires": [] }, { "id": "026b1705c622de13", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "translation_of_text", "info": "describe your reusable flow here", "scope": "global", "x": 1430, "y": 280, "wires": [ [ "aa416e40c794fa7d" ] ] }, { "id": "0e4f85f3a5c46b61", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1780, "y": 260, "wires": [] }, { "id": "aa416e40c794fa7d", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, TranslationOfText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Text = acceptableString(msg.payload)\n const originalLanguage = acceptableString(msg.originalLanguage, 'auto')\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await TranslationOfText(Text, Options, originalLanguage)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1620, "y": 280, "wires": [ [ "0e4f85f3a5c46b61" ], [ "9779b2e614b6abc2" ] ] }, { "id": "9779b2e614b6abc2", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1770, "y": 300, "wires": [] }, { "id": "e3094dbcff84f179", "type": "comment", "z": "a38a9db5ce759685", "name": "Document Retrieval", "info": "", "x": 1430, "y": 540, "wires": [] }, { "id": "51b0b932c17bfa2d", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "text_at_url", "info": "describe your reusable flow here", "scope": "global", "x": 1400, "y": 600, "wires": [ [ "d7dfd717dbdde363" ] ] }, { "id": "c158ce3d4af296f9", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1720, "y": 580, "wires": [] }, { "id": "d7dfd717dbdde363", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, TextAtURL\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await TextAtURL(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [ { "var": "axios", "module": "axios" }, { "var": "cheerio", "module": "cheerio" } ], "x": 1560, "y": 600, "wires": [ [ "c158ce3d4af296f9" ], [ "e66c826580621b7b" ] ] }, { "id": "e66c826580621b7b", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1710, "y": 620, "wires": [] }, { "id": "7ce3909c02c47c3f", "type": "comment", "z": "a38a9db5ce759685", "name": "Web Search", "info": "", "x": 1410, "y": 380, "wires": [] }, { "id": "846ed928e89db724", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "results_of_search", "info": "describe your reusable flow here", "scope": "global", "x": 1420, "y": 440, "wires": [ [ "b42b7932e7128830" ] ] }, { "id": "d86c44e95843ee79", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1760, "y": 420, "wires": [] }, { "id": "b42b7932e7128830", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, ResultsOfSearch\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await ResultsOfSearch(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [ { "var": "axios", "module": "axios" }, { "var": "cheerio", "module": "cheerio" } ], "x": 1600, "y": 440, "wires": [ [ "d86c44e95843ee79" ], [ "6e2a22ba9c013192" ] ] }, { "id": "6e2a22ba9c013192", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1750, "y": 460, "wires": [] }, { "id": "4df6b4aae91f115a", "type": "comment", "z": "a38a9db5ce759685", "name": "additional Functions", "info": "", "x": 1430, "y": 40, "wires": [] }, { "id": "9549044093d0ba17", "type": "comment", "z": "a38a9db5ce759685", "name": "LLMs", "info": "", "x": 730, "y": 40, "wires": [] }, { "id": "18984ea08c144398", "type": "comment", "z": "a38a9db5ce759685", "name": "Convenience Functions for Inspection and Test", "info": "", "x": 200, "y": 520, "wires": [] }, { "id": "01a3df754bc50d8c", "type": "comment", "z": "a38a9db5ce759685", "name": "Installation Requirements (dbl-click to reveal)", "info": "# Installation Requirements #\n\nPlease install the following nodes (use \"Manage Palette\" from the menu):\n\n* node-red-contrib-reusable-flows\n* TotallyInformation/node-red-contrib-events", "x": 410, "y": 40, "wires": [] }, { "id": "f2a03c81b8cc7e7a", "type": "comment", "z": "a38a9db5ce759685", "name": "Model Installation (dbl-click to reveal)", "info": "", "x": 1090, "y": 40, "wires": [] }, { "id": "46c89ac9fcb8e2c0", "type": "function", "z": "a38a9db5ce759685", "name": "common Code", "func": "node.status({ fill:'yellow', shape:'ring', text:'loading' })\n const {\n quoted,\n ValueIsBoolean,\n ValueIsNumber, ValueIsFiniteNumber, ValueIsNumberInRange,\n ValueIsInteger, ValueIsIntegerInRange,\n ValueIsString, ValueIsNonEmptyString, ValueIsStringMatching,\n ValueIsTextline,\n ValueIsPlainObject,\n ValueIsListSatisfying,\n ValueIsFunction,\n ValueIsOneOf,\n ValueIsURL,\n ValidatorForClassifier, acceptNil, rejectNil,\n allowNumber, allowCardinal,\n allowedString, expectString,\n allowNonEmptyString, expectNonEmptyString, expectedNonEmptyString,\n expectStringMatching, expectTextline,\n expectedObject, allowPlainObject, expectPlainObject,\n allowListSatisfying, expectListSatisfying,\n allowOneOf, expectOneOf,\n allowURL,\n } = global.get('JIL')\n\n/**** common Code ****/\n\n class commonCode {\n/**** throwError (Error object with HTTP status code) ****/\n\n static throwError (StatusCode, Message) {\n const decoratedError = new Error(Message)\n decoratedError['StatusCode'] = StatusCode\n throw decoratedError\n }\n\n/**** newUUID - generates a Type 4 UUID ****/\n\n static newUUID () {\n let UUID = '', UUIDPart\n UUIDPart = Math.round(Math.random()*0xffffffff).toString(16)\n UUID += UUIDPart + '00000000'.slice(UUIDPart.length) + '-'\n UUIDPart = Math.round(Math.random()*0xffff).toString(16)\n UUID += UUIDPart + '0000'.slice(UUIDPart.length) + '-4'\n UUIDPart = Math.round(Math.random()*0xfff).toString(16)\n UUID += UUIDPart + '000'.slice(UUIDPart.length) + '-'\n UUIDPart = Math.round(Math.random()*0x3fff+0x8000).toString(16)\n UUID += UUIDPart + '-'\n UUIDPart = Math.round(Math.random()*0xffffffffffff).toString(16)\n UUID += UUIDPart + '000000000000'.slice(UUIDPart.length)\n return UUID.toLowerCase()\n }\n\n/**** ProgressOf - auxiliary function for better readability ****/\n\n static ProgressOf (msg,Progress) {\n msg.Progress = Progress\n return msg\n }\n\n/**** ValueIsChatMessage ****/\n\n static ValueIsChatMessage (Value) {\n return (\n ValueIsPlainObject(Value) &&\n// ValueIsOneOf(Value.role,['system','user','assistant']) &&\n ValueIsNonEmptyString(Value.role) &&\n ValueIsString(Value.content)\n )\n }\n\n/**** ValueIsChatMessageList ****/\n\n static ValueIsChatMessageList (Value) {\n if (\n ValueIsListSatisfying(Value,ValueIsChatMessage) &&\n (Value.length > 0)\n ) {\n Value = Value.filter(\n (Message) => (['system','user','assistant'].indexOf(Message.role) >= 0)\n ) // keeps system/user/assistant messages which must have a specific order\n\n let i = 0, l = Value.length\n if (Value[0].role === 'system') { i++ }\n\n for (;i < l; i += 2) {\n if (Value[i].role !== 'user') { return false }\n if (i+1 === l) { break }\n\n if (Value[i+1].role !== 'assistant') { return false }\n }\n\n return true\n }\n return false\n }\n\n/**** allow/expect[ed]ChatMessageList ****/\n\n static allowChatMessageList = ValidatorForClassifier(\n commonCode.ValueIsChatMessageList, acceptNil, 'chat message list'\n )\n static allowedChatMessageList = commonCode.allowChatMessageList\n\n static expectChatMessageList = ValidatorForClassifier(\n commonCode.ValueIsChatMessageList, rejectNil, 'chat message list'\n )\n static expectedChatMessageList = commonCode.expectChatMessageList\n\n/**** ValueIsToolDescriptor ****/\n\n static ValueIsToolDescriptor (Value) {\n function ValueIsNumberList (Value) {\n return ValueIsListSatisfying(Value,ValueIsFiniteNumber)\n }\n\n return (\n ValueIsPlainObject(Value) &&\n ValueIsNonEmptyString(Value.Name) &&\n ValueIsNonEmptyString(Value.Description) &&\n ValueIsListSatisfying(Value.InputDescriptions,ValueIsNonEmptyString) && (\n ValueIsNonEmptyString(Value.Script) ||\n ValueIsFunction(Value.Code)\n ) && (\n (Value.Embeddings == null) ||\n ValueIsListSatisfying(Value.Embeddings,ValueIsNumberList)\n )\n )\n }\n\n/**** allow/expect[ed]ToolDescriptor ****/\n\n static allowToolDescriptor = ValidatorForClassifier(\n commonCode.ValueIsToolDescriptor, acceptNil, 'AI tool descriptor'\n )\n static allowedToolDescriptor = commonCode.allowToolDescriptor\n\n static expectToolDescriptor = ValidatorForClassifier(\n commonCode.ValueIsToolDescriptor, rejectNil, 'AI tool descriptor'\n )\n static expectedToolDescriptor = commonCode.expectToolDescriptor\n\n/**** ValueIsToolStore ****/\n\n static ValueIsToolStore (Value) {\n if (! ValueIsPlainObject(Value)) { return false }\n\n for (let Key in Value) {\n if (Key === '') {\n if (\n (Value[Key] != null) && ! ValueIsNonEmptyString(Value[Key])\n ) { return false }\n } else {\n if (! ValueIsToolDescriptor(Value[Key]) ) { return false }\n }\n }\n\n return true\n }\n\n/**** allow/expect[ed]ToolStore ****/\n\n static allowToolStore = ValidatorForClassifier(\n commonCode.ValueIsToolStore, acceptNil, 'AI tool store'\n )\n static allowedToolStore = commonCode.allowToolStore\n\n static expectToolStore = ValidatorForClassifier(\n commonCode.ValueIsToolStore, rejectNil, 'AI tool store'\n )\n static expectedToolStore = commonCode.expectToolStore\n\n/**** acceptableBoolean ****/\n\n static acceptableBoolean (Value, Default) {\n return (ValueIsBoolean(Value) ? Value : Default)\n }\n\n/**** acceptableNumber ****/\n\n static acceptableNumber (Value, Default) {\n return (ValueIsNumber(Value) ? Value : Default)\n }\n\n/**** acceptableNumberInRange ****/\n\n static acceptableNumberInRange (\n Value, Default,\n minValue = -Infinity, maxValue = Infinity, withMin = false, withMax = false\n ) {\n return (ValueIsNumberInRange(Value,minValue,maxValue,withMin,withMax) ? Value : Default)\n }\n\n/**** acceptableInteger ****/\n\n static acceptableInteger (Value, Default) {\n return (ValueIsInteger(Value) ? Value : Default)\n }\n\n/**** acceptableIntegerInRange ****/\n\n static acceptableIntegerInRange (\n Value, Default, minValue = -Infinity, maxValue = Infinity\n ) {\n return (ValueIsIntegerInRange(Value,minValue,maxValue) ? Value : Default)\n }\n\n/**** acceptableString ****/\n\n static acceptableString (Value, Default) {\n return (ValueIsString(Value) ? Value : Default)\n }\n\n/**** acceptableNonEmptyString ****/\n\n static acceptableNonEmptyString (Value, Default = undefined) {\n return (ValueIsString(Value) && (Value.trim() !== '') ? Value : Default)\n }\n\n/**** acceptableStringMatching ****/\n\n static acceptableStringMatching (Value, Default, Pattern) {\n return (ValueIsStringMatching(Value,Pattern) ? Value : Default)\n }\n\n/**** acceptableURL ****/\n\n static acceptableURL (Value, Default) {\n return (ValueIsURL(Value) ? Value : Default)\n }\n\n/**** acceptableModel ****/\n\n static acceptableModel (Value, Purpose) {\n if (! ValueIsTextline(Value)) { return undefined }\n\n const ModelInfo = knownModelSet[Value.toLowerCase()]\n return (\n (ModelInfo != null) && (ModelInfo.Purposes.indexOf(Purpose) >= 0)\n ) ? Value : undefined\n }\n\n/**** assertInspectableFolder ****/\n\n static async assertInspectableFolder (FolderPath) {\n try {\n const FileInfo = await fs.promises.stat(FolderPath)\n if (! FileInfo.isDirectory()) throwError(\n 500,quoted(FolderPath) + ' is not a directory'\n )\n } catch (Signal) {\n if (Signal.code === 'ENOENT') {\n throwError(500,quoted(FolderPath) + ' does not exist')\n } else {\n throwError(500,'internal error: ' + Signal)\n }\n }\n }\n\n/**** assertReadableFile ****/\n\n static async assertReadableFile (FilePath) {\n try {\n const FileInfo = await fs.promises.stat(FilePath)\n if (! FileInfo.isFile()) throwError(\n 500,quoted(FilePath) + ' is not a file'\n )\n } catch (Signal) {\n if (Signal.code === 'ENOENT') {\n throwError(500,quoted(FilePath) + ' does not exist')\n } else {\n throwError(500,'internal error: ' + Signal)\n }\n }\n\n try {\n await fs.promises.access(FilePath, fs.constants.R_OK)\n } catch (Signal) {\n throwError(500,quoted(FilePath) + ' can not be read')\n }\n }\n\n/**** assertExecutableFile ****/\n\n static async assertExecutableFile (FilePath) {\n try {\n const FileInfo = await fs.promises.stat(FilePath)\n if (! FileInfo.isFile()) throwError(\n 500,quoted(FilePath) + ' is not a file'\n )\n } catch (Signal) {\n if (Signal.code === 'ENOENT') {\n throwError(500,quoted(FilePath) + ' does not exist')\n } else {\n throwError(500,'internal error: ' + Signal)\n }\n }\n\n try {\n await fs.promises.access(FilePath, fs.constants.X_OK)\n } catch (Signal) {\n throwError(500,quoted(FilePath) + ' is not executable')\n }\n }\n\n/**** knownModels ****/\n\n static supportedArchitectures = ['llama','stablelm','gptneox']\n static supportedPurposes = ['text','phrasing','code','embeddings']\n\n static knownModelSet = Object.create(null)\n\n static knownModels () {\n return Object.keys(knownModelSet).map((Id) => knownModelSet[Id].Model)\n }\n\n static ModelIsKnown (Model) {\n expectNonEmptyString('searched model',Model)\n return (Model.trim().toLowerCase() in knownModelSet)\n }\n\n/**** learnModel ****/\n\n static learnModel (Descriptor) {\n let {\n Model, ModelURL, Creator, CreatorURL,\n Architecture, Purposes,\n Templates, ContextLength, ReversePrompts,\n Documentation, License, LicenseURL,\n } = expectedObject('model descriptor', Descriptor)\n\n expectTextline('model name',Model)\n\n allowURL('model URL',ModelURL)\n\n allowNonEmptyString('model creator name',Creator)\n allowURL ('model creator URL',CreatorURL)\n\n expectOneOf('model architecture',Architecture,supportedArchitectures)\n\n function ValueIsPurpose (Value) {\n return ValueIsOneOf(Value,supportedPurposes)\n }\n expectListSatisfying('intended model purposes',Purposes,ValueIsPurpose)\n\n function normalizedTemplates (Templates) {\n let { Prefix,System,User,Assistant,Suffix } = Templates\n Prefix = allowedString('model system message default',Prefix) || ''\n System = allowedString('model system message template',System) || '${Content}'\n User = allowedString('model user message template',User) || '${Content}'\n Assistant = allowedString('model assistant message template',Assistant) || '${Content}'\n Suffix = allowedString('model prompt suffic',Suffix) || ''\n return { Prefix,System,User,Assistant,Suffix }\n }\n allowPlainObject('message template set',Templates)\n Templates = normalizedTemplates(Templates || {})\n\n allowCardinal('model context length',ContextLength)\n if (ContextLength == null) { ContextLength = 4096 }\n allowListSatisfying('reverse prompt list',ReversePrompts, ValueIsNonEmptyString)\n if (ReversePrompts == null) { ReversePrompts = [] }\n\n allowURL('model documentation URL',Documentation)\n\n allowNonEmptyString('model license',License)\n allowURL ('model license URL',LicenseURL)\n\n const normalizedDescriptor = {\n Model, ModelURL, Creator, CreatorURL,\n Architecture, Purposes,\n Templates, ContextLength, ReversePrompts,\n Documentation, License, LicenseURL,\n }\n knownModelSet[Model.toLowerCase()] = normalizedDescriptor\n }\n\n/**** learnModels ****/\n\n static learnModels (DescriptorList) {\n expectListSatisfying('list of model descriptors',DescriptorList,ValueIsPlainObject)\n DescriptorList.forEach((Descriptor) => learnModel(Descriptor))\n }\n\n/**** FileLooksLikeAModel ****/\n\n static FileLooksLikeAModel (FilePath) {\n const FileSuffix = path.extname(FilePath)\n return /[.](bin|ggml|gguf)/.test(FileSuffix)\n }\n\n/**** ModelFromFileName ****/\n\n static ModelFromFileName (FilePath) {\n const FileName = path.basename(FilePath).replace(/[.](bin|ggml|gguf)$/,'')\n\n let ModelName = FileName\n .replace(/[-.]q\\d_[\\da-z](_[a-z])?/i,'')\n .replace(/[.]ggml[a-z0-9]*/i,'')\n .replace(/_q\\d_[\\da-z](_[a-z])?$/i,'')\n return ModelName\n }\n\n/**** availableModels ****/\n\n static async availableModels () {\n try {\n const ModelFolder = effectiveConfiguration().ModelFolder\n await assertInspectableFolder(ModelFolder)\n\n const FileNameList = await fs.promises.readdir(ModelFolder)\n const ModelNameList = FileNameList.filter(\n (FileName) => FileLooksLikeAModel(FileName)\n ).map(\n (FileName) => ModelFromFileName(FileName)\n )\n\n return ModelNameList\n } catch (Signal) {\n if (Signal.statusCode == null) {\n throwError(500,'Internal Error: ' + Signal)\n } else {\n throw Signal\n }\n }\n }\n\n/**** InfoForModel ****/\n\n static InfoForModel (Model) {\n return knownModelSet[Model.toLowerCase()]\n }\n\n/**** FileForModel ****/\n\n static async FileForModel (Model) {\n const ModelFolder = effectiveConfiguration().ModelFolder\n\n try {\n const FileNameList = await fs.promises.readdir(ModelFolder)\n const ModelFileList = FileNameList.filter((FileName) =>\n FileLooksLikeAModel(FileName) &&\n FileName.toLowerCase().startsWith(Model.toLowerCase())\n )\n if (ModelFileList.length > 0) {\n const FilePath = path.join(ModelFolder,ModelFileList[0])\n await assertReadableFile(FilePath)\n return FilePath\n } else {\n throwError(500,'no file for model ' + quoted(Model))\n }\n } catch (Signal) {\n if (Signal.statusCode == null) {\n throwError(500,'Internal Error: ' + Signal)\n } else {\n throw Signal\n }\n }\n }\n\n/**** configure ****/\n\n static async configure (msg, Context) {\n expectPlainObject('msg object',msg)\n allowOneOf ('Node-RED context',Context, [flow,global])\n\n if (Context == null) { Context = flow }\n\n let Configuration = Object.assign({\n ModelFolder:undefined, ExecutableFolder:undefined,\n ToolStoreFolder:undefined, RecipeStoreFolder:undefined,\n DefaultTextModel:undefined, DefaultPhrasingModel:undefined,\n DefaultCodeModel:undefined, DefaultEmbeddingsModel:undefined,\n }, Context.get('AI-Toolkit-Configuration') || {})\n\n /**** ModelFolder ****/\n\n let ModelFolder = acceptableNonEmptyString(msg.ModelFolder)\n if (ModelFolder != null) try {\n await assertInspectableFolder(ModelFolder)\n } catch (Signal) {\n node.warn(Signal.message)\n ModelFolder = undefined\n }\n if (ModelFolder != null) {\n Configuration.ModelFolder = ModelFolder\n }\n\n /**** ExecutableFolder ****/\n\n let ExecutableFolder = acceptableNonEmptyString(msg.ExecutableFolder)\n if (ExecutableFolder != null) try {\n await assertInspectableFolder(ExecutableFolder)\n } catch (Signal) {\n node.warn(Signal.message)\n ExecutableFolder = undefined\n }\n if (ExecutableFolder != null) {\n Configuration.ExecutableFolder = ExecutableFolder\n }\n\n /**** ToolStoreFolder ****/\n\n let ToolStoreFolder = acceptableNonEmptyString(msg.ToolStoreFolder)\n if (ToolStoreFolder != null) try {\n await assertInspectableFolder(ToolStoreFolder)\n } catch (Signal) {\n node.warn(Signal.message)\n ToolStoreFolder = undefined\n }\n if (ToolStoreFolder != null) {\n Configuration.ToolStoreFolder = ToolStoreFolder\n }\n\n /**** RecipeStoreFolder ****/\n\n let RecipeStoreFolder = acceptableNonEmptyString(msg.RecipeStoreFolder)\n if (RecipeStoreFolder != null) try {\n await assertInspectableFolder(RecipeStoreFolder)\n } catch (Signal) {\n node.warn(Signal.message)\n RecipeStoreFolder = undefined\n }\n if (RecipeStoreFolder != null) {\n Configuration.RecipeStoreFolder = RecipeStoreFolder\n }\n\n /**** DefaultTextModel ****/\n\n let DefaultTextModel = acceptableModel(msg.DefaultTextModel,'text')\n if (DefaultTextModel != null) {\n Configuration.DefaultTextModel = DefaultTextModel\n }\n\n /**** DefaultPhrasingModel ****/\n\n let DefaultPhrasingModel = acceptableModel(msg.DefaultPhrasingModel,'phrasing')\n if (DefaultPhrasingModel != null) {\n Configuration.DefaultPhrasingModel = DefaultPhrasingModel\n }\n\n /**** DefaultCodeModel ****/\n\n let DefaultCodeModel = acceptableModel(msg.DefaultCodeModel,'code')\n if (DefaultCodeModel != null) {\n Configuration.DefaultCodeModel = DefaultCodeModel\n }\n\n /**** DefaultEmbeddingsModel ****/\n\n let DefaultEmbeddingsModel = acceptableModel(msg.DefaultEmbeddingsModel,'embeddings')\n if (DefaultEmbeddingsModel != null) {\n Configuration.DefaultEmbeddingsModel = DefaultEmbeddingsModel\n }\n\n /**** Language Detection and Translation ****/\n\n let LanguageAPIKey = acceptableString(msg.LanguageAPIKey,'')\n let LanguageDetectorURL = acceptableURL(msg.LanguageDetectorURL,'https://libretranslate.com/detect')\n let LanguageTranslatorURL = acceptableURL(msg.LanguageTranslatorURL,'https://libretranslate.com/translate')\n\n /**** now configure potential \"options\" (DRY) ****/\n\n Object.assign(Configuration,await OptionsFrom(msg,{},Configuration))\n\n /**** that's it ****/\n\n Context.set('AI-Toolkit-Configuration',Configuration)\n }\n\n/**** configureGlobally ****/\n\n static async configureGlobally (msg) {\n configure(msg,global)\n }\n\n/**** effectiveConfiguration ****/\n\n static effectiveConfiguration () {\n const globalConfiguration = global.get('AI-Toolkit-Configuration')\n const localConfiguration = flow.get('AI-Toolkit-Configuration')\n\n if (\n (globalConfiguration == null) &&\n (localConfiguration == null)\n ) throwError(\n 500, 'missing or empty AI Toolkit Configuration'\n )\n\n return Object.assign({},\n globalConfiguration || {},\n localConfiguration || {}\n ) // local configurations may overwrite global ones\n }\n\n/**** OptionsFrom ****/\n// \"Options\" may be function-specific, a \"Configuration\" is function-independent\n\n static async OptionsFrom (specificSettings, generalSettings, Configuration) {\n if (Configuration == null) {\n Configuration = effectiveConfiguration()\n }\n\n if (generalSettings == null) { generalSettings = {} }\n if (specificSettings == null) { specificSettings = {} }\n\n /**** construct complete set of options ****/\n\n let Options = Object.assign(\n {}, Configuration, generalSettings, specificSettings\n )\n\n /**** now validate all options and correct invalid settings ****/\n\n let Model = acceptableString(Options.Model, '')\n if (knownModelSet[Model.toLowerCase()] == null) {\n Model = Configuration.DefaultTextModel\n }\n let ModelInfo = InfoForModel(Model)\n\n let Threads = acceptableIntegerInRange(Options.Threads, 4, 1,os.cpus().length)\n let Batches = acceptableIntegerInRange(Options.Batches, 8, 1,100)\n let Seed = acceptableIntegerInRange(Options.Seed, -1, -1)\n let ContextLength = acceptableIntegerInRange(Options.ContextLength, 512, 1,ModelInfo.ContextLength)\n let HeaderLength = acceptableIntegerInRange(Options.HeaderLength, 0, 0,ContextLength)\n let PredictionLength = acceptableIntegerInRange(Options.PredictionLength, 128, 1,ContextLength)\n let Temperature = acceptableNumberInRange(Options.Temperature, 0.8, 0.0,1.0, true,true)\n let topK = acceptableIntegerInRange(Options.topK, 40, 1,100)\n let topP = acceptableNumberInRange(Options.topP, 0.9, 0.1,1.0, true,true)\n let Grammar = acceptableString(Options.Grammar, '').trim()\n\n return {\n Model, Threads, Batches,\n Seed, ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n }\n }\n\n/**** CompletionOfText ****/\n\n static async CompletionOfText (Text, Options) {\n let Prompt = acceptableString(Text,'').trim()\n if (Prompt === '') throw new Error('missing or empty text')\n\n const Configuration = effectiveConfiguration()\n let ExecutableFolder = Configuration.ExecutableFolder\n\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n } = Options\n\n if (Model == null) { Model = Configuration.DefaultTextModel }\n\n let ModelFile = await FileForModel(Model)\n let ModelInfo = InfoForModel(Model)\n\n ContextLength = Math.min(ContextLength,ModelInfo.ContextLength)\n PredictionLength = Math.min(PredictionLength,ContextLength)\n HeaderLength = Math.min(HeaderLength,Math.max(0,ContextLength-PredictionLength))\n\n Prompt = Prompt.replace(/\"/g, '\\\\\"')\n\n /**** determine executable ****/\n\n let ExecutableFile = path.join(\n ExecutableFolder, ModelInfo.Architecture === 'gptneox' ? 'gpt-neox' : 'llama'\n )\n await assertExecutableFile(ExecutableFile)\n\n /**** combine all these settings into a command ****/\n\n let Command\n if (ModelInfo.Architecture === 'gptneox') {\n Command = (\n ExecutableFile + ' --model ' + ModelFile +\n ' --context ' + ContextLength +\n ' --n_predict ' + PredictionLength +\n ' --threads ' + Threads + ' --batch_size ' + Batches +\n (Seed < 0 ? '' : ' --seed ' + Seed) + ' --temp ' + Temperature +\n ' --top_k ' + topK + ' --top_p ' + topP +\n ' --prompt \\'' + encoded(Prompt) + '\\''\n )\n } else {\n Command = (\n ExecutableFile + ' --model ' + ModelFile + ' --mlock ' +\n ' --ctx_size ' + ContextLength + ' --keep ' + HeaderLength +\n ' --n_predict ' + PredictionLength +\n ' --threads ' + Threads + ' --batch_size ' + Batches +\n ' --seed ' + Seed + ' --temp ' + Temperature +\n ' --top_k ' + topK + ' --top_p ' + topP +\n ' --tfs 0.95 --mirostat 2'\n )\n\n ModelInfo.ReversePrompts.forEach(\n (ReversePrompt) => Command += ' --reverse-prompt ' + quoted(ReversePrompt)\n )\n\n Grammar = Grammar || ''\n Command += (\n (Grammar === '' ? '' : ' --grammar \\'' + encoded(Grammar.replace(/\\\\/g,'\\\\\\\\')) + '\\'') +\n ' --prompt \\'' + encoded(Prompt) + '\\''\n )\n }\nnode.warn('Command = ' + Command)\n\n const CommandOptions = {\n cwd:ExecutableFolder\n }\n\n /**** prepare response extraction from command output ****/\n\n let ResponseFrom\n if (ModelInfo.Architecture === 'gptneox') {\n ResponseFrom = function (Text) {\n let HeaderLength = Text.indexOf(\n '\\n', Text.indexOf(Prompt) + Prompt.length\n )\n Text = Text.slice(HeaderLength + 1)\n\n let TrailerIndex = Text.indexOf('<|endoftext|>')\n if (TrailerIndex < 0) {\n TrailerIndex = Text.indexOf('\\nmain: mem per token')\n }\n if (TrailerIndex >= 0) { Text = Text.slice(0, TrailerIndex) }\n\n return Text\n }\n } else {\n ResponseFrom = function (Text) {\n let HeaderLength = Text.indexOf('\\n\\n\\n')\n Text = Text.slice(HeaderLength + 1)\n\n let TrailerIndex = Text.indexOf('<|endoftext|>')\n if (TrailerIndex < 0) {\n TrailerIndex = Text.indexOf('\\nllama_print_timings')\n }\n if (TrailerIndex >= 0) { Text = Text.slice(0, TrailerIndex) }\n\n return Text\n }\n }\n\n /**** now infer a response from the given prompt ****/\n\n try {\n let stdout = '', stderr = ''\n const ShellProcess = child_process.exec(Command, CommandOptions)\n for await (const Chunk of ShellProcess.stdout) { stdout += Chunk }\n for await (const Chunk of ShellProcess.stderr) { stderr += Chunk }\n const ExitCode = (await new Promise((resolve) => {\n ShellProcess.on('close', resolve)\n })) || 0\n\n if (ExitCode !== 0) {\n// @ts-ignore 2365 (ExitCode is actually a number)\n throwError(500 + ExitCode,stderr || 'text completion failed')\n } else {\n return (stdout.trim() === '' ? '' : ResponseFrom(stdout))\n }\n } catch (Signal) {\n if (Signal.StatusCode == null) {\n throwError(500,'Internal Error: ' + Signal)\n } else {\n throw Signal\n }\n }\n\n /**** encoded ****/\n\n function encoded(Text) {\n return Text.replace(/'/g, \"'\\\"'\\\"'\")\n }\n }\n\n/**** CompletionOfChat ****/\n\n static async CompletionOfChat (ChatMessages, Options) {\n const Configuration = effectiveConfiguration()\n\n let Model = Options.Model\n if (Model == null) { Model = Configuration.DefaultTextModel }\n\n let Prompt = PromptFromChatMessages(ChatMessages,Model)\n\n return await CompletionOfText(Prompt,Options)\n }\n\n/**** TokenizationOfText ****/\n\n static async TokenizationOfText (Text, Options) {\n let Prompt = acceptableString(Text,'').trim()\n if (Prompt === '') throw new Error('missing or empty text')\n\n const Configuration = effectiveConfiguration()\n let ExecutableFolder = Configuration.ExecutableFolder\n\n let {\n Model,\n Threads,\n ContextLength,\n } = Options\n\n if (Model == null) { Model = Configuration.DefaultTextModel }\n\n let ModelFile = await FileForModel(Model)\n let ModelInfo = InfoForModel(Model)\n\n ContextLength = Math.min(ContextLength,ModelInfo.ContextLength)\n\n Prompt = Prompt.replace(/\"/g, '\\\\\"')\n Prompt = Prompt.replace(/'/g, '') // TODO: change!\n\n /**** determine executable ****/\n\n let ExecutableFile = path.join(\n ExecutableFolder, ModelInfo.Architecture === 'gptneox' ? 'gpt-neox' : 'llama-tokens'\n )\n await assertExecutableFile(ExecutableFile)\n\n /**** combine all these settings into a command ****/\n\n let Command\n if (ModelInfo.Architecture === 'gptneox') {\n Command = (\n ExecutableFile + ' --model ' + ModelFile +\n ' --context ' + ContextLength +\n ' --n_predict 0' +\n ' --threads ' + Threads +\n ' --prompt \\'' + encoded(Prompt) + '\\''\n )\n } else {\n Command = (\n ExecutableFile + ' --model ' + ModelFile + ' --mlock ' +\n ' --ctx_size ' + ContextLength +\n ' --threads ' + Threads +\n ' --prompt \\'' + encoded(Prompt) + '\\''\n )\n }\nnode.warn('Command = ' + Command)\n\n const CommandOptions = {\n cwd:ExecutableFolder\n }\n\n /**** prepare response extraction from command output ****/\n\n let ResponseFrom\n if (ModelInfo.Architecture === 'gptneox') {\n ResponseFrom = function (Text) {\n const HeaderLength = Text.indexOf('\\nmain: token[0]')\n Text = Text.slice(HeaderLength + 1)\n\n const TrailerIndex = Text.indexOf('\\n\\n')\n Text = Text.slice(0,TrailerIndex)\n\n return Text.replace(/^main: token\\[%d+\\] =%s+/g,'')\n }\n } else {\n ResponseFrom = function (Text) {\n let HeaderLength = Text.indexOf('system_info')\n Text = Text.slice(HeaderLength + 1)\n .replace(/^[^\\n]*\\n/,'')\n\n let TrailerIndex = Text.indexOf('\\n\\nllama_print_timings')\n Text = Text.slice(0,TrailerIndex)\n\n return Text.trim().split('\\n').map((Line) => {\n let Code = parseInt(Line.trim(),10)\n let Text = Line.replace(/^\\s*\\d+./,'')\n return { Code,Text }\n })\n }\n }\n\n /**** now tokenize the given prompt ****/\n\n try {\n let stdout = '', stderr = ''\n const ShellProcess = child_process.exec(Command, CommandOptions)\n for await (const Chunk of ShellProcess.stdout) { stdout += Chunk }\n for await (const Chunk of ShellProcess.stderr) { stderr += Chunk }\n const ExitCode = (await new Promise((resolve) => {\n ShellProcess.on('close', resolve)\n })) || 0\n\n if (ExitCode !== 0) {\n// @ts-ignore 2365 (ExitCode is actually a number)\n throwError(500 + ExitCode,stderr || 'text tokenization failed')\n } else {\n return (stdout.trim() === '' ? [] : ResponseFrom(stdout))\n }\n } catch (Signal) {\n if (Signal.StatusCode == null) {\n throwError(500,'Internal Error: ' + Signal)\n } else {\n throw Signal\n }\n }\n\n /**** encoded ****/\n\n function encoded(Text) {\n return Text.replace(/'/g, \"'\\\"'\\\"'\")\n }\n }\n\n/**** EmbeddingsOfText ****/\n\n static async EmbeddingsOfText (Text, Options) {\n let Prompt = acceptableString(Text,'').trim()\n if (Prompt === '') throw new Error('missing or empty text')\n\n const Configuration = effectiveConfiguration()\n let ExecutableFolder = Configuration.ExecutableFolder\n\n let {\n Model,\n Seed, Threads,\n ContextLength,\n } = Options\n\n if (Model == null) {\n Model = (\n Configuration.DefaultEmbeddingsModel ||\n Configuration.DefaultTextModel // which hopefully supports embeddings as well\n )\n }\n\n let ModelFile = await FileForModel(Model)\n let ModelInfo = InfoForModel(Model)\n\n ContextLength = Math.min(ContextLength,ModelInfo.ContextLength)\n\n Prompt = Prompt.replace(/\"/g, '\\\\\"')\n Prompt = Prompt.replace(/'/g, '') // TODO: change!\n\n /**** determine executable ****/\n\n let ExecutableFile = path.join(\n ExecutableFolder, 'llama-embeddings'\n )\n await assertExecutableFile(ExecutableFile)\n\n /**** combine all these settings into a command ****/\n\n let Command = (\n ExecutableFile + ' --model ' + ModelFile + ' --mlock ' +\n ' --ctx_size ' + ContextLength +\n ' --threads ' + Threads +\n ' --seed ' + Seed +\n ' --prompt \\'' + encoded(Prompt) + '\\''\n )\nnode.warn('Command = ' + Command)\n\n const CommandOptions = {\n cwd:ExecutableFolder\n }\n\n /**** prepare response extraction from command output ****/\n\n let ResponseFrom = function (Text) {\n return Text.trim().split(' ').map((x) => parseFloat(x))\n }\n\n /**** now calculate the embeddings of the given prompt ****/\n\n try {\n let stdout = '', stderr = ''\n const ShellProcess = child_process.exec(Command, CommandOptions)\n for await (const Chunk of ShellProcess.stdout) { stdout += Chunk }\n for await (const Chunk of ShellProcess.stderr) { stderr += Chunk }\n const ExitCode = (await new Promise((resolve) => {\n ShellProcess.on('close', resolve)\n })) || 0\n\n if (ExitCode !== 0) {\n// @ts-ignore 2365 (ExitCode is actually a number)\n throwError(500 + ExitCode,stderr || 'text tokenization failed')\n } else {\n return (stdout.trim() === '' ? [] : ResponseFrom(stdout))\n }\n } catch (Signal) {\n if (Signal.StatusCode == null) {\n throwError(500,'Internal Error: ' + Signal)\n } else {\n throw Signal\n }\n }\n\n /**** encoded ****/\n\n function encoded(Text) {\n return Text.replace(/'/g, \"'\\\"'\\\"'\")\n }\n }\n\n/**** PromptFromChatMessages ****/\n\n static PromptFromChatMessages (ChatMessageList,Model) {\n expectChatMessageList('list of chat messages',ChatMessageList)\n\n let ModelInfo = InfoForModel(Model)\n let Templates = ModelInfo.Templates\n\n let Prompt = ''\n if ((ChatMessageList[0] != null) && (ChatMessageList[0].role !== 'system')) {\n Prompt = Templates.Prefix || ''\n }\n\n ChatMessageList.forEach((ChatMessage) => {\n switch (ChatMessage.role) {\n case 'system':\n Prompt += Templates.System.replace('${Content}',ChatMessage.content)\n break\n case 'user':\n Prompt += Templates.User.replace('${Content}',ChatMessage.content)\n break\n case 'assistant':\n Prompt += Templates.Assistant.replace('${Content}',ChatMessage.content)\n break\n }\n })\n\n Prompt += Templates.Suffix || ''\n return Prompt\n }\n\n/**** SummaryOfText ****/\n\n static async SummaryOfText (Text, Options) {\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n } = Object.assign(\n { Model:Configuration.DefaultTextModel }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:'Condense the following text into a succinct summary: '\n },{\n role:'user', content:Text\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n })\n }\n\n/**** TextIsQuestion ****/\n\n static async TextIsQuestion (Text, Options) {\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n } = Object.assign(\n {\n Model:Configuration.DefaultTextModel, Grammar:'root ::= \"yes\"|\"no\"'\n }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:`\nDoes the following text form a question? Please answer with \"yes\" or \"no\".\n\nThe text to be analyzed is:\n `.trim() + ' '\n },{\n role:'user', content:Text\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n })\n }\n\n/**** ProblemAsQuestion ****/\n\n static async ProblemAsQuestion (Problem, Options) {\n if (Problem.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n } = Object.assign(\n { Model:Configuration.DefaultTextModel }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:'Please convert the following text into a question: '\n },{\n role:'user', content:Problem\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n })\n }\n\n/**** ExtractFromText ****/\n\n static async ExtractFromText (Question, Text, Options) {\n if (Question.trim() === '') throwError(500, 'missing or empty question')\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n } = Object.assign(\n { Model:Configuration.DefaultTextModel }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:`\nIdentify potential answers from the given text for the following question.\nOnly provide relevant information, not the answer. If the text lacks the\nrequested information, return an empty output without any explanation.\n\nThe question is: \"${Question}\".\n\nThe text to be analyzed is:\n `.trim() + ' '\n },{\n role:'user', content:Text\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n })\n }\n\n/**** DecisionFromText ****/\n\n static async DecisionFromText (Question, Text, Options) {\n if (Question.trim() === '') throwError(500, 'missing or empty question')\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n } = Object.assign(\n {\n Model:Configuration.DefaultTextModel, Grammar:'root ::= \"yes\"|\"no\"|\"unknown\"'\n }, Configuration, Options\n )\n\n if (Options.Model == null) {\n const Configuration = effectiveConfiguration()\n Options.Model = Configuration.DefaultTextModel\n }\n\n let ChatMessages = [{\n role:'system', content:`\nBased on the provided text, determine the answer to the following yes-no\nquestion. If the text contains sufficient information to answer the question,\nrespond with \"yes\" or \"no\" accordingly. If the text does not provide enough\ninformation to determine an answer, respond with \"unknown\".\n\nThe question is: \"${Question}\".\n\nThe text to be analyzed is:\n `.trim() + ' '\n },{\n role:'user', content:Text\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n })\n }\n\n/**** NumberFromText ****/\n\n static async NumberFromText (Question, Text, Options) {\n if (Question.trim() === '') throwError(500, 'missing or empty question')\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n } = Object.assign(\n {\n Model:Configuration.DefaultTextModel,\n Grammar:'root ::= [+-]?[0-9]+([.][0-9]+)?([eE][+-]?[0-9]+)?|\"\"'\n }, Configuration, Options\n )\n\n if (Options.Model == null) {\n const Configuration = effectiveConfiguration()\n Options.Model = Configuration.DefaultTextModel\n }\n\n let ChatMessages = [{\n role:'system', content:`\nAnalyze the provided text to find a numerical answer to the given question.\nUse only the information contained in the text. If the text does not provide\nsufficient information to answer the question, provide no output.\nOtherwise, extract and provide the requested number from the text.\n\nThe question is: \"${Question}\".\n\nThe text to be analyzed is:\n `.trim() + ' '\n },{\n role:'user', content:Text\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n })\n }\n\n/**** ListFromText ****/\n\n static async ListFromText (Request, Text, Options) {\n if (Request.trim() === '') throwError(500, 'missing or empty request')\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n } = Object.assign(\n { Model:Configuration.DefaultTextModel }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:`\nConsider the following text:\n\n\"${Text}\"\n\nNow analyze the text shown above and extract the information requested below.\nIf the text does not contain this information, provide no output. Otherwise,\npresent the information as a list with each item on a separate line starting\nwith \"- \".\n\nThe requested information is:\n `.trim() + ' '\n },{\n role:'user', content:Request\n }]\n\n let List = (await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n })).split('\\n')\n\n const NumberedListPattern = /^\\s*\\d+[.]?\\s*/\n switch (true) {\n case List.some((Element) => /^\\s*[-]\\s*/.test(Element)):\n return List\n .map((Element) => Element.replace(/^\\s*[-]\\s*/,''))\n .filter((Line) => Line.trim() !== '')\n case List.some((Element) => /^\\s*[*]\\s*/.test(Element)):\n return List\n .map((Element) => Element.replace(/^\\s*[*]\\s*/,''))\n .filter((Line) => Line.trim() !== '')\n case List.some((Element) => NumberedListPattern.test(Element)):\n return List\n .map((Element) => Element.replace(NumberedListPattern,''))\n .filter((Line) => Line.trim() !== '')\n default:\n return List.filter((Line) => Line.trim() !== '')\n }\n\n return []\n }\n\n/**** SearchPromptFromText ****/\n\n static async SearchPromptFromText (Text, Options) {\n if (Text.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n } = Object.assign(\n {\n Model:Configuration.DefaultTextModel, Grammar:'root ::= [^\\n]+'\n }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:`\nBased on the provided text, generate a single concise search query for a web\nsearch engine to find more related information.\n\nThe text is:\n `.trim() + ' '\n },{\n role:'user', content:Text\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n Grammar\n })\n }\n\n/**** ScriptToSolve ****/\n\n static async ScriptToSolve (Problem, Options) {\n if (Problem.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n } = Object.assign(\n { Model:Configuration.DefaultCodeModel }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:`\nGenerate a sequence of JavaScript statements that address a specified problem.\nThe statements should take data from an ‘input’ array and store the final result\nin an ‘output’ variable. Please ensure that the ‘output’ variable contains the\nsolution to the problem.\n `.trim() + ' '\n },{\n role:'user', content:Problem\n }]\n\n let Solution = await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n })\n\n if (Solution.indexOf('```') >= 0) {\n Solution = Solution\n .replace(/^((?!```)[\\s\\S])*```[^\\n]*[\\n]/,'')\n .replace(/```[\\s\\S]*$/,'')\n }\n\n let LogIndex = Solution.lastIndexOf('console.log')\n if (LogIndex >= 0) {\n Solution = (\n Solution.slice(0,LogIndex) + 'return ' + Solution.slice(LogIndex+11)\n )\n }\n\n return Solution\n }\n\n/**** QuintessenceOfOutput ****/\n\n static async QuintessenceOfOutput (Problem, Solution, Options) {\n if (Problem.trim() === '') { return '' }\n if (Solution.trim() === '') { return '' }\n\n let Configuration = effectiveConfiguration()\n let {\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n } = Object.assign(\n { Model:Configuration.DefaultTextModel }, Configuration, Options\n )\n\n let ChatMessages = [{\n role:'system', content:`\ncombine the details given after \"Input:\" and \"Output:\" into a concise,\nself-contained statement. This statement should be valid and understandable\nregardless of its context.\n `.trim() + ' '\n },{\n role:'user', content:`Input: \"${Problem}\"\\nOutput: \"${Solution}\"`\n }]\n\n return await CompletionOfChat(ChatMessages,{\n Model,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature, topK, topP,\n })\n }\n\n/**** ResultsOfSearch ****/\n\n static async ResultsOfSearch (Prompt) {\n if (Prompt.trim() === '') { return '' }\n\n let Response = await axios.get(\n `https://www.startpage.com/do/search?query=${encodeURIComponent(Prompt)}&lui=english`\n )\n\n /**** prepare response extraction from the received web page ****/\n\n function ResultsFrom (Response) {\n const $ = cheerio.load(Response.data)\n const Results = []\n $('.w-gl__result').each((index, element) => {\n const Title = $(element).find('.w-gl__result-title').text().trim()\n const URL = $(element).find('.w-gl__result-title').attr('href')\n const Description = $(element).find('.w-gl__description').text().trim()\n// @ts-ignore 2345 (calm the TypeScript validator)\n Results.push({ Date:Date.now(), Title, URL, Description })\n })\n return Results\n }\n\n /**** now analyze the received web page ****/\n\n switch (Response.status) {\n case 200: return ResultsFrom(Response)\n case 204: return []\n default: throwError(Response.status, Response.statusText)\n }\n }\n\n/**** TextAtURL ****/\n\n static async TextAtURL (URL, Options) {\n if (URL.trim() === '') { return '' }\n\n let Response = await axios.get(URL)\n\n /**** prepare response extraction from the received data ****/\n\n function ResultsFrom (Response) {\n const ContentType = Response.headers['content-type']\n switch (true) {\n case ContentType.includes('text/html'):\n let $ = cheerio.load(Response.data)\n $('body').find(\n 'style,script,nav,form,meter,progress,input,textarea,select,button,label'\n ).remove()\n\n return $('body').find(\n 'h1,h2,h3,h4,h5,h6,article,p,li,th,td,caption,blockquote'\n ).map((Index,Element) => $(Element).text()).get().join(' ')\n case ContentType.includes('text/'):\n return Response.data\n default:\n return ''\n }\n }\n\n /**** now analyze the received data ****/\n\n switch (Response.status) {\n case 200: return ResultsFrom(Response)\n case 204: return []\n default: throwError(Response.status, Response.statusText)\n }\n }\n\n/**** LanguageOfText ****/\n\n static async LanguageOfText (Text, Options) {\n if (Text.trim() === '') { return '' }\n\n const {\n LanguageDetectorURL, LanguageAPIKey\n } = Options\n\n const RequestBody = { q:Text }\n if ((LanguageAPIKey || '').trim() !== '') {\n RequestBody['api_key'] = LanguageAPIKey\n }\n\n let Response = await axios.post(\n LanguageDetectorURL || 'https://libretranslate.com/detect',\n RequestBody\n )\n\n switch (Response.status) {\n case 200: let { language:Language,confidence:Confidence } = Response.data[0]\n return { Language, Confidence }\n case 204: return ''\n case 400:\n case 403:\n case 429:\n case 500: throwError(Response.status, Response.data.error)\n default: throwError(Response.status, Response.statusText)\n }\n }\n\n/**** TranslationOfText ****/\n\n static async TranslationOfText (Text, Options, originalLanguage = 'auto') {\n if (Text.trim() === '') { return '' }\n\n const {\n LanguageTranslatorURL, LanguageAPIKey\n } = Options\n\n const RequestBody = {\n q:Text,\n source:originalLanguage, target:'en', format:'text',\n }\n if ((LanguageAPIKey || '').trim() !== '') {\n RequestBody['api_key'] = LanguageAPIKey\n }\n\n let Response = await axios.post(\n LanguageTranslatorURL || 'https://libretranslate.com/translate',\n RequestBody\n )\n\n switch (Response.status) {\n case 200: return Response.data.translatedText\n case 204: return ''\n case 400:\n case 403:\n case 429:\n case 500: throwError(Response.status, Response.data.error)\n default: throwError(Response.status, Response.statusText)\n }\n }\n\n/**** calculateEmbeddingsUsingModel ****/\n\n static async calculateEmbeddingsUsingModel (Text,EmbeddingsModel) {\n expectNonEmptyString ('text',Text)\n expectNonEmptyString('embeddings model',EmbeddingsModel)\n\n let {\n Seed, Threads,\n ContextLength,\n } = effectiveConfiguration()\n\n const Options = {\n Model:EmbeddingsModel, Seed, Threads, ContextLength\n }\n\n return await EmbeddingsOfText(Text, Options)\n }\n\n/**** CosineSimilarity ****/\n\n static CosineSimilarity (EmbeddingsA,EmbeddingsB) {\n expectListSatisfying('1st embeddings vector',EmbeddingsA, ValueIsNumber)\n expectListSatisfying('2nd embeddings vector',EmbeddingsB, ValueIsNumber)\n\n if (EmbeddingsA.length !== EmbeddingsB.length) {\n throwError(500,'embeddings vectors must always have the same length')\n }\n\n let ProductSum = 0, SquareASum = 0, SquareBSum = 0\n for (let i = 0, l = EmbeddingsA.length; i < l; i++) {\n const A = EmbeddingsA[i], B = EmbeddingsB[i]\n ProductSum += A*B; SquareASum += A*A; SquareBSum += B*B\n }\n return ProductSum / Math.sqrt(SquareASum*SquareBSum)\n }\n\n/**** resetToolStore - resets the Tool Store ****/\n\n static resetToolStore (EmbeddingsModel = undefined) {\n allowNonEmptyString('tool store embeddings model',EmbeddingsModel)\n\n global.set('AI-Toolkit-ToolStore',Object.create(null))\n global.get('AI-Toolkit-ToolStore')[''] = EmbeddingsModel // may be undef.\n storeIntrinsicTools()\n }\n\n/**** storeIntrinsicTools - writes intrinsic tools into current Tool Store ****/\n\n static storeIntrinsicTools () {\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n\n if (ToolStore['search-the-web'] == null) {\n ToolStore['search-the-web'] = {\n Name:'search-the-web',\n Description:'searches the web for a requested information',\n InputDescriptions:[\n 'the information to search the web for',\n ],\n Code: commonCode.WebSearchTool\n }\n }\n\n if (ToolStore['compute'] == null) {\n ToolStore['compute'] = {\n Name:'compute',\n Description:'computes a requested information',\n InputDescriptions:[\n 'the information to be computed',\n 'additional information needed to compute the requested information',\n ],\n Code: commonCode.ComputationTool\n }\n }\n\n if (ToolStore['finish'] == null) {\n ToolStore['finish'] = {\n Name:'finish',\n Description:'presents the final result and completes this task',\n InputDescriptions:[\n 'the final result of this task',\n ],\n Code: commonCode.FinishingTool\n }\n }\n\n if (ToolStore['abort'] == null) {\n ToolStore['abort'] ={\n Name:'abort',\n Description:'outputs an error message and aborts this task',\n InputDescriptions:[\n 'the error message to be shown',\n ],\n Code: commonCode.AbortionTool\n }\n }\n }\n\n/**** calculateToolStoreEmbeddingsUsingModel ****/\n\n static async calculateToolStoreEmbeddingsUsingModel (EmbeddingsModel) {\n expectNonEmptyString('tool store embeddings model',EmbeddingsModel)\n\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n ToolStore[''] = EmbeddingsModel\n\n for (let ToolName in ToolStore) {\n if (ToolName === '') { continue }\n await calculateEmbeddingsForTool(ToolStore[ToolName])\n }\n }\n\n/**** calculateEmbeddingsForTool ****/\n\n static async calculateEmbeddingsForTool (Tool,EmbeddingsModel = undefined) {\n if (EmbeddingsModel == null) {\n EmbeddingsModel = global.get('AI-Toolkit-ToolStore')['']\n }\n\n Tool['Embeddings'] = await calculateEmbeddingsUsingModel(\n Tool.Description, EmbeddingsModel\n )\n }\n\n/**** loadToolStoreFromFile - loads Tool Store from file ****/\n\n static async loadToolStoreFromFile (FilePath) {\n expectString('tool store file path',FilePath)\n\n resetToolStore() // yet without embeddings\n if (FilePath.trim() === '') { return }\n\n const { ToolStoreFolder } = effectiveConfiguration()\n\n const ToolStoreFile = path.join(ToolStoreFolder,FilePath)\n try {\n const FileContents = (await fs.promises.readFile(ToolStoreFile, 'utf8')).trim()\n if (FileContents === '') { return }\n\n let ToolSet = JSON.parse(FileContents)\n expectToolStore('AI tool store',ToolSet)\n\n for (let ToolName in ToolSet) {\n let Tool = ToolSet[ToolName]\n if (Tool.Code == null) {\n Tool.Code = compiledTool(Tool)\n }\n }\n\n let ToolStore = global.get('AI-Toolkit-ToolStore')\n if (ToolSet[''] != null) {\n const EmbeddingsModel = ToolSet['']\n if (EmbeddingsModel !== ToolStore['']) {\n for (let ToolName in ToolStore) {\n if (! (ToolName in ToolSet)) { // entry won't be overwritten\n await calculateEmbeddingsForTool(ToolStore[ToolName],EmbeddingsModel)\n }\n }\n }\n\n for (let ToolName in ToolSet) {\n if (ToolName === '') { continue }\n await calculateEmbeddingsForTool(ToolSet[ToolName],EmbeddingsModel)\n }\n }\n Object.assign(ToolStore,ToolSet)\n global.set('AI-Toolkit-ToolStore',ToolStore)\n } catch (Signal) {\n if (Signal.code === 'ENOENT') {\n return\n } else {\n throwError(500,'internal error: ' + Signal)\n }\n }\n }\n\n/**** saveToolStoreToFile - saves Tool Store to file ****/\n\n static async saveToolStoreToFile (FilePath) {\n expectNonEmptyString('tool store file path',FilePath)\n if (FilePath.trim() === '') { return }\n\n const { ToolStoreFolder } = effectiveConfiguration()\n\n const ToolStoreFile = path.join(ToolStoreFolder,FilePath)\n try {\n const ToolStore = {...global.get('AI-Toolkit-ToolStore')}\n for (let ToolName in ToolStore) {\n if (ToolName === '') { continue }\n\n let Tool = ToolStore[ToolName]\n if (Tool.Script == null) {\n Tool.Script = Tool.Code.toString()\n .replace(/^[^(]*[(][^)]*[)][^\\n]*[\\n]/,'')\n .replace(/[}]\\s*$/,'')\n delete Tool.Code\n }\n }\n\n await fs.promises.writeFile(\n ToolStoreFile, JSON.stringify(ToolStore, null, 2), 'utf8'\n )\n } catch (Signal) {\n throwError(500,'internal error: ' + Signal)\n }\n }\n\n/**** ListOfTools ****/\n\n static ListOfTools () {\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n return Object.keys(ToolStore).filter((Key) => Key !== '')\n }\n\n/**** storedTool ****/\n\n static storedTool (ToolName) {\n expectNonEmptyString('tool name',ToolName)\n\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n const Tool = ToolStore[ToolName]\n return (Tool == null ? undefined : {\n ...Tool, InputDescriptions:[...Tool.InputDescriptions]\n })\n }\n\n/**** storedToolForTask ****/\n\n static async storedToolForTask (Task, Threshold) {\n expectNonEmptyString ('tool task',Task)\n allowNumber('similarity threshold',Threshold)\n if (Threshold == null) { Threshold = 0 }\n\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n\n let EmbeddingsModel = ToolStore['']\n if (EmbeddingsModel == null) {\n EmbeddingsModel = effectiveConfiguration()['DefaultEmbeddingsModel']\n expectNonEmptyString('tool store embeddings model',EmbeddingsModel)\n\n await calculateToolStoreEmbeddingsUsingModel(EmbeddingsModel)\n }\n\n let TaskEmbeddings = await calculateEmbeddingsUsingModel(\n Task, EmbeddingsModel\n )\n\n let bestToolName, bestSimilarity = -1\n for (let ToolName in ToolStore) {\n if (ToolName === '') { continue }\n\n let Similarity = CosineSimilarity(TaskEmbeddings,ToolStore[ToolName].Embeddings)\n if (Similarity < Threshold) { continue }\n\n if (Similarity > bestSimilarity) {\n bestToolName = ToolName\n bestSimilarity = Similarity\n }\n }\n\n return bestToolName\n }\n\n/**** storeTool ****/\n\n static async storeTool (Tool) {\n expectToolDescriptor('tool',Tool)\n\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n ToolStore[Tool.Name] = {\n ...Tool, InputDescriptions:[...Tool.InputDescriptions]\n }\n\n if (ToolStore[Tool.Name].Code == null) {\n ToolStore[Tool.Name].Code = compiledTool(ToolStore[Tool.Name])\n }\n\n if ((ToolStore[''] != null) && (Tool.Embeddings == null)) {\n await calculateEmbeddingsForTool(ToolStore[Tool.Name],ToolStore[''])\n }\n }\n\n/**** unstoreTool ****/\n\n static unstoreTool (ToolName) {\n expectNonEmptyString('tool name',ToolName)\n\n const ToolStore = global.get('AI-Toolkit-ToolStore')\n delete ToolStore[ToolName]\n }\n\n/**** compiledTool ****/\n\n static compiledTool (Tool) {\n let Script = expectedNonEmptyString('tool script',Tool.Script)\n\n let compiledScript\n try {\n compiledScript = Function(\n 'InputList, JIL, commonCode, node, flow, global', Script\n )\n } catch (Signal) {\n throwError(500,'could not compile tool script, reason ' + Signal)\n }\n\n return compiledScript\n }\n\n\n/**** WebSearchTool ****/\n\n static async WebSearchTool (\n InputList, JIL, commonCode, node, flow, global\n ) {\n return (async () => {\n const { expectNonEmptyString } = JIL\n const {\n effectiveConfiguration,\n SearchPromptFromText, ResultsOfSearch\n } = commonCode\n\n let requestedInformation = InputList[0]\n expectNonEmptyString('information to search for',requestedInformation)\n\n let {\n DefaultTextModel,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n } = effectiveConfiguration()\n\n const Options = {\n Model:DefaultTextModel, Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature:0, topK:10, topP:0.95,\n }\n\n let SearchPrompt = (await SearchPromptFromText(requestedInformation,Options)).trim()\n expectNonEmptyString('search prompt',SearchPrompt)\n\n let SearchResults = await ResultsOfSearch(SearchPrompt)\n// @ts-ignore 18048, 2339\n return SearchResults.map((SearchResult) => SearchResult.URL)\n })()\n }\n\n/**** ComputationTool ****/\n\n static async ComputationTool (\n InputList, JIL, commonCode, node, flow, global\n ) {\n return (async () => {\n const { expectNonEmptyString } = JIL\n const {\n effectiveConfiguration,\n ScriptToSolve\n } = commonCode\n\n let requestedInformation = InputList[0]\n expectNonEmptyString('information to search for',requestedInformation)\n\n let {\n DefaultCodeModel,\n Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n } = effectiveConfiguration()\n\n const Options = {\n Model:DefaultCodeModel, Seed, Threads, Batches,\n ContextLength, HeaderLength, PredictionLength,\n Temperature:0, topK:10, topP:0.95,\n }\n\n let SourceCode = (await ScriptToSolve(requestedInformation,Options)).trim()\n expectNonEmptyString('JavaScript source code',SourceCode)\n\n let compiledScript\n try {\n compiledScript = Function(\n 'InputList, JIL, commonCode, node, flow, global', SourceCode\n )\n } catch (Signal) {\n throwError(500,'could not compile generated script, reason ' + Signal)\n }\n\n try {\n return await compiledScript(\n InputList, JIL, commonCode, node, flow, global\n )\n } catch (Signal) {\n throwError(500,'could not execute generated script, reason ' + Signal)\n }\n })()\n }\n\n/**** FinishingTool ****/\n\n static async FinishingTool (\n InputList, JIL, commonCode, node, flow, global\n ) {\n return (async () => {\n const { expectNonEmptyString } = JIL\n\n let finalResult = InputList[0]\n expectNonEmptyString('final result of this task',finalResult)\n\n// may be overwritten with additional functionality\n\n return finalResult\n })()\n }\n\n/**** AbortionTool ****/\n\n static async AbortionTool (\n InputList, JIL, commonCode, node, flow, global\n ) {\n return (async () => {\n const { expectNonEmptyString } = JIL\n\n let ErrorMessage = InputList[0]\n expectNonEmptyString('error message',ErrorMessage)\n\n// may be overwritten with additional functionality\n\n return ErrorMessage\n })()\n }\n\n/**** resetRecipeStore - resets the Recipe Store ****/\n\n static resetRecipeStore (EmbeddingsModel = undefined) {\n allowNonEmptyString('tool store embeddings model',EmbeddingsModel)\n\n global.set('AI-Toolkit-RecipeStore',Object.create(null))\n global.get('AI-Toolkit-RecipeStore')[''] =\n effectiveConfiguration()['DefaultEmbeddingsModel'] || 'stablelm-zephyr-3b'\n// storeIntrinsicRecipies()\n }\n\n\n }\n global.set('AI-Toolkit-commonCode',commonCode)\n\n/**** common Code methods needed by common Code itself ****/\n\n const {\n knownModelSet, supportedArchitectures, supportedPurposes,\n throwError,\n newUUID,\n ValueIsChatMessage,\n ValueIsChatMessageList,\n allowChatMessageList, allowedChatMessageList,\n expectChatMessageList, expectedChatMessageList,\n ValueIsToolDescriptor,\n allowToolDescriptor, allowedToolDescriptor,\n expectToolDescriptor, expectedToolDescriptor,\n ValueIsToolStore,\n allowToolStore, allowedToolStore,\n expectToolStore, expectedToolStore,\n acceptableBoolean,\n acceptableNumber, acceptableNumberInRange,\n acceptableInteger, acceptableIntegerInRange,\n acceptableString, acceptableStringMatching,\n acceptableNonEmptyString,\n acceptableURL,\n acceptableModel,\n assertInspectableFolder, assertReadableFile, assertExecutableFile,\n knownModels, ModelIsKnown,\n learnModel, learnModels,\n FileLooksLikeAModel, ModelFromFileName, availableModels,\n InfoForModel, FileForModel,\n configure, configureGlobally, effectiveConfiguration,\n OptionsFrom,\n ProgressOf,\n PromptFromChatMessages, CompletionOfText, CompletionOfChat,\n TokenizationOfText, EmbeddingsOfText,\n SummaryOfText, TextIsQuestion, ProblemAsQuestion,\n ExtractFromText, DecisionFromText, NumberFromText, ListFromText,\n SearchPromptFromText, ScriptToSolve, QuintessenceOfOutput,\n ResultsOfSearch, TextAtURL, LanguageOfText, TranslationOfText,\n calculateEmbeddingsUsingModel, CosineSimilarity,\n resetToolStore, storeIntrinsicTools, calculateToolStoreEmbeddingsUsingModel,\n calculateEmbeddingsForTool,\n loadToolStoreFromFile, saveToolStoreToFile,\n ListOfTools, storedTool, storedToolForTask, storeTool, unstoreTool,\n compiledTool,\n WebSearchTool, ComputationTool, FinishingTool, AbortionTool,\n resetRecipeStore,\n// ValueIsAgentStep, expectAgentMessage, expectedAgentMessage\n } = commonCode\n\n\n learnModels([\n/**** 1.3B ****/\n\n {\n Model: '42dot_LLM-SFT-1.3B',\n ModelURL:'https://huggingface.co/42dot/42dot_LLM-SFT-1.3B',\n\n Creator: '42dot',\n CreatorURL:'https://huggingface.co/42dot',\n\n Architecture: 'llama',\n Purposes: ['phrasing','embeddings'],\n Templates: {\n Prefix: undefined,\n System: '',\n User: ': ${Content}',\n Assistant:':${Content}',\n Suffix: ':',\n },\n ContextLength:4096,\n ReversePrompts:['<|endoftext|>'],\n\n Documentation:'https://github.com/42dot/42dot_LLM',\n\n License: 'CC BY-NC 4.0',\n LicenseURL:'https://creativecommons.org/licenses/by-nc/4.0/',\n },\n\n\n/**** 3B ****/\n\n {\n Model: 'StableLM-3B-4E1T',\n ModelURL:'https://huggingface.co/stabilityai/stablelm-3b-4e1t',\n\n Creator: 'Stability AI',\n CreatorURL:'https://huggingface.co/stabilityai',\n\n Architecture: 'stablelm',\n Purposes: ['phrasing','embeddings'],\n Templates: {\n Prefix: undefined,\n System: '${Content}\\n',\n User: '${Content}\\n',\n Assistant:'[COMPLETION START]\\n${Content}\\n[COMPLETION END]\\n',\n Suffix: '[COMPLETION START]\\n',\n },\n ContextLength:4096,\n ReversePrompts:['[COMPLETION END]','[end of text]','<|endoftext|>'],\n\n Documentation:'https://stability.wandb.io/stability-llm/stable-lm/reports/StableLM-3B-4E1T--VmlldzoyMjU4?accessToken=u3zujipenkx5g7rtcj9qojjgxpconyjktjkli2po09nffrffdhhchq045vp0wyfo',\n\n License: 'CC BY-SA-4.0',\n LicenseURL:'https://creativecommons.org/licenses/by-sa/4.0/',\n },\n\n\n {\n Model: 'StableCode-Completion-Alpha-3B-4K',\n ModelURL:'https://huggingface.co/stabilityai/stablecode-completion-alpha-3b-4k',\n\n Creator: 'Stability AI',\n CreatorURL:'https://huggingface.co/stabilityai',\n\n Architecture: 'gptneox',\n Purposes: ['code'],\n Templates: {\n Prefix: undefined,\n System: '${Content}\\n',\n User: '${Content}\\n',\n Assistant:'${Content}\\n',\n Suffix: '',\n },\n ContextLength:4096,\n ReversePrompts:[],\n\n Documentation:undefined,\n\n License: 'Apache 2.0',\n LicenseURL:'https://www.apache.org/licenses/LICENSE-2.0',\n },\n\n\n {\n Model: 'stablelm-zephyr-3b',\n ModelURL:'https://huggingface.co/stabilityai/stablelm-zephyr-3b',\n\n Creator: 'Stability AI',\n CreatorURL:'https://huggingface.co/stabilityai',\n\n Architecture: 'stablelm',\n Purposes: ['phrasing','embeddings'],\n Templates: {\n Prefix: undefined,\n System: '',\n User: '<|user|>\\n${Content}\\n', // <|endoftext|>\\n',\n Assistant:'<|assistant|>\\n${Content}\\n', // <|endoftext|>\\n',\n Suffix: '<|assistant|>\\n',\n },\n ContextLength:4096,\n ReversePrompts:['<|endoftext|>','[end of text]'],\n\n Documentation:'https://stability.ai/news/stablelm-zephyr-3b-stability-llm',\n\n License: 'StabilityAI Non-Commercial Research Community License',\n LicenseURL:'https://huggingface.co/stabilityai/stablelm-zephyr-3b/raw/main/LICENSE',\n },\n\n\n {\n Model: 'MiniChat-1.5-3B',\n ModelURL:'https://huggingface.co/GeneZC/MiniChat-1.5-3B',\n\n Creator: 'Chen Zhang',\n CreatorURL:'https://huggingface.co/GeneZC',\n\n Architecture: 'llama',\n Purposes: ['phrasing','embeddings'],\n Templates: {\n Prefix: undefined,\n System: '',\n User: '[INST]\\n${Content}',\n Assistant:' [/INST] ${Content} ',\n Suffix: ' [/INST]',\n },\n ContextLength:4096,\n ReversePrompts:[],\n\n Documentation:'https://github.com/GeneZC/MiniMA',\n\n License: 'Apache 2.0',\n LicenseURL:'https://www.apache.org/licenses/LICENSE-2.0',\n },\n\n\n/**** 7B ****/\n\n {\n Model: 'Dans-TotSirocco-7b',\n ModelURL:'https://huggingface.co/PocketDoc/Dans-TotSirocco-7b',\n\n Creator: 'PocketDoc Labs',\n CreatorURL:'https://huggingface.co/PocketDoc',\n\n Architecture: 'llama',\n Purposes: ['text','phrasing','embeddings'],\n Templates: {\n Prefix: undefined,\n System: '<|system|>${Content}',\n User: '<|user|>${Content}',\n Assistant:'<|model|>${Content}',\n Suffix: '<|model|>',\n },\n ContextLength:4096,\n ReversePrompts:[],\n\n Documentation:undefined,\n\n License: 'Apache 2..0',\n LicenseURL:'https://choosealicense.com/licenses/apache-2.0/',\n },\n\n\n {\n Model: 'deepseek-coder-6.7b-instruct',\n ModelURL:'https://huggingface.co/deepseek-ai/deepseek-coder-6.7b-instruct',\n\n Creator: 'DeepSeek',\n CreatorURL:'https://huggingface.co/deepseek-ai',\n\n Architecture: 'llama',\n Purposes: ['code'],\n Templates: {\n Prefix: 'You are an AI programming assistant, utilizing the Deepseek ' +\n 'Coder model, developed by Deepseek Company, and you only ' +\n 'answer questions related to computer science. For politically ' +\n 'sensitive questions, security and privacy issues, and other ' +\n 'non-computer science questions, you will refuse to answer.\\n',\n System: '${Content}\\n',\n User: '### Instruction:\\n${Content}\\n',\n Assistant:'### Response:\\n${Content}\\n<|EOT|>\\n',\n Suffix: '### Response:\\n',\n },\n ContextLength:16384,\n ReversePrompts:['<|EOT|>','<|end▁of▁sentence|>'],\n\n Documentation:'https://deepseekcoder.github.io/',\n\n License: 'deepseek',\n LicenseURL:'https://github.com/deepseek-ai/deepseek-coder/blob/main/LICENSE-MODEL',\n },\n\n ])\n\n resetToolStore()\n resetRecipeStore()\nnode.status({ fill:'green', shape:'dot', text:'loaded' })\n\nreturn msg", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "node.status({ fill: 'red', shape: 'dot', text: 'pending' })\n", "finalize": "", "libs": [ { "var": "fs", "module": "fs" }, { "var": "path", "module": "path" }, { "var": "child_process", "module": "child_process" }, { "var": "os", "module": "os" }, { "var": "axios", "module": "axios" }, { "var": "cheerio", "module": "cheerio" } ], "x": 380, "y": 100, "wires": [ [ "ecaedff977981d84" ] ] }, { "id": "f1a04b041f3a7c8d", "type": "function", "z": "a38a9db5ce759685", "name": "javascript-interface-library", "func": "// no code here, only in the \"Start\" tab!\n// no code here, only in the \"Start\" tab!\n// no code here, only in the \"Start\" tab!\n// no code here, only in the \"Start\" tab!\n// no code here, only in the \"Start\" tab!\n// no code here, only in the \"Start\" tab!", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "node.status({ fill: 'yellow', shape: 'ring', text: 'loading' })\nglobal.set('JIL', JIL)\n\n/**** very special version of \"ValueIsPlainObject\" for Node-RED ****/\n\nJIL.ValueIsPlainObject = function (Value) {\n return (\n (Value != null) && (typeof Value === 'object') &&\n (Object.getPrototypeOf(Value.constructor.prototype) == null)\n )\n}\n\n/**** very special version of \"allow/expect[ed]PlainObject\" for Node-RED ****/\n\nconst { ValidatorForClassifier, acceptNil, rejectNil } = JIL\n\nJIL.allowPlainObject = ValidatorForClassifier(\n JIL.ValueIsPlainObject, acceptNil, '\"plain\" JavaScript object'\n)\nJIL.allowedPlainObject = JIL.allowPlainObject\n\nJIL.expectPlainObject = ValidatorForClassifier(\n JIL.ValueIsPlainObject, rejectNil, '\"plain\" JavaScript object'\n)\nJIL.expectedPlainObject = JIL.expectPlainObject\nnode.status({ fill: 'green', shape: 'dot', text: 'loaded' })\n\nnode.send({ payload: 'continue initialization' })", "finalize": "", "libs": [ { "var": "JIL", "module": "node-red-javascript-interface-library" } ], "x": 140, "y": 100, "wires": [ [ "46c89ac9fcb8e2c0" ] ] }, { "id": "ecaedff977981d84", "type": "function", "z": "a38a9db5ce759685", "name": "Configuration Presets", "func": ";(async function () {\n node.status({ fill:'yellow', shape:'ring', text:'configuring' })\n const {\n configureGlobally\n } = global.get('AI-Toolkit-commonCode')\n\n await configureGlobally({\n ModelFolder: path.join(process.env.HOME,'.node-red'),\n ExecutableFolder: path.join(process.env.HOME,'.node-red'),\n ToolStoreFolder: path.join(process.env.HOME,'.node-red'),\n RecipeStoreFolder:path.join(process.env.HOME,'.node-red'),\n\n DefaultTextModel: 'dans-totsirocco-7b',\n DefaultPhrasingModel: 'stablelm-zephyr-3b',\n DefaultCodeModel: 'deepseek-coder-6.7b-instruct',\n DefaultEmbeddingsModel:'stablelm-zephyr-3b',\n\n Threads: 4,\n Batches: 8,\n Seed: -1,\n ContextLength: 512,\n HeaderLength: 0,\n PredictionLength:128,\n Temperature: 0.8,\n topK: 40,\n topP: 0.9,\n })\n node.status({ fill:'green', shape:'dot', text:'configured' })\n\n node.send(msg)\n node.done()\n})()\n", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "node.status({ fill: 'red', shape: 'dot', text: 'pending' })\n", "finalize": "", "libs": [ { "var": "path", "module": "path" }, { "var": "process", "module": "process" } ], "x": 160, "y": 160, "wires": [ [] ] }, { "id": "1f372c8542188445", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 90, "y": 580, "wires": [ [ "e2790890721563b6" ] ] }, { "id": "e2790890721563b6", "type": "function", "z": "a38a9db5ce759685", "name": "show Configuration", "func": "const { effectiveConfiguration } = global.get('AI-Toolkit-commonCode')\n\nconst Configuration = effectiveConfiguration()\nmsg.payload = Configuration\n\nreturn msg\n", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 270, "y": 580, "wires": [ [ "f2b7401102bdf031" ] ] }, { "id": "f2b7401102bdf031", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 580, "wires": [] }, { "id": "6558b11c4289f9c6", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 90, "y": 640, "wires": [ [ "76c933574bf8c042" ] ] }, { "id": "76c933574bf8c042", "type": "function", "z": "a38a9db5ce759685", "name": "known Models", "func": "const { knownModels } = global.get('AI-Toolkit-commonCode')\nmsg.payload = knownModels()\nreturn msg", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 260, "y": 640, "wires": [ [ "415d29ca95598351" ] ] }, { "id": "415d29ca95598351", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 640, "wires": [] }, { "id": "ba7842c92190468e", "type": "catch", "z": "a38a9db5ce759685", "name": "uncaught Errors", "scope": null, "uncaught": false, "x": 100, "y": 440, "wires": [ [ "d55e24703a9bb9d8" ] ] }, { "id": "d55e24703a9bb9d8", "type": "debug", "z": "a38a9db5ce759685", "name": "show in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 320, "y": 440, "wires": [] }, { "id": "bc97f2e5530b884c", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 90, "y": 700, "wires": [ [ "6d952867b596713a" ] ] }, { "id": "17cf8173d1c65be2", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 700, "wires": [] }, { "id": "6d952867b596713a", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "list_models", "outputs": 2, "x": 250, "y": 700, "wires": [ [ "17cf8173d1c65be2" ], [ "17cf8173d1c65be2" ] ], "outputLabels": [ "success", "failure" ] }, { "id": "01d0aa91818dd92f", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "who was Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 780, "wires": [ [ "e9b4b5b0f0ffe5e0" ] ] }, { "id": "b740f18f5871563a", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 780, "wires": [] }, { "id": "e9b4b5b0f0ffe5e0", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "complete_text", "outputs": 2, "x": 260, "y": 780, "wires": [ [ "b740f18f5871563a" ], [ "b740f18f5871563a" ] ] }, { "id": "ce9c7859366054d1", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "[{\"role\":\"system\",\"content\":\"respond as exactly and concisely as possible\"},{\"role\":\"user\",\"content\":\"who was Joseph Weizenbaum?\"}]", "payloadType": "json", "x": 90, "y": 840, "wires": [ [ "9ec586fd8d9ee012" ] ] }, { "id": "541e11a8b10bf4b8", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 840, "wires": [] }, { "id": "9ec586fd8d9ee012", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "complete_chat", "outputs": 2, "x": 260, "y": 840, "wires": [ [ "541e11a8b10bf4b8" ], [ "541e11a8b10bf4b8" ] ] }, { "id": "06b3f1c3b6e3169e", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "who was Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 900, "wires": [ [ "836d0e8fd3ef4ea9" ] ] }, { "id": "9017030c0dcd990d", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 900, "wires": [] }, { "id": "836d0e8fd3ef4ea9", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "tokenize_text", "outputs": 2, "x": 250, "y": 900, "wires": [ [ "9017030c0dcd990d" ], [ "9017030c0dcd990d" ] ] }, { "id": "4f5667356723b90d", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "who was Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 960, "wires": [ [ "a3eda5d3f760a9ad" ] ] }, { "id": "a47a311b348c30c3", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 960, "wires": [] }, { "id": "a3eda5d3f760a9ad", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "calculate_embeddings", "outputs": 2, "x": 280, "y": 960, "wires": [ [ "a47a311b348c30c3" ], [ "a47a311b348c30c3" ] ] }, { "id": "661923d1506f1f18", "type": "comment", "z": "a38a9db5ce759685", "name": "Error Reporting", "info": "", "x": 100, "y": 380, "wires": [] }, { "id": "6f73807dd3eed032", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "who was Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 1040, "wires": [ [ "699181e7e7615fc4" ] ] }, { "id": "fb5d8588a2adf981", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1040, "wires": [] }, { "id": "699181e7e7615fc4", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "results_of_search", "outputs": 2, "x": 270, "y": 1040, "wires": [ [ "fb5d8588a2adf981" ], [ "fb5d8588a2adf981" ] ], "outputLabels": [ "success", "failure", "" ] }, { "id": "a1ea563aeb9b3751", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "https://en.wikipedia.org/wiki/Joseph_Weizenbaum", "payloadType": "str", "x": 90, "y": 1100, "wires": [ [ "8f5a61c59a6945cf" ] ] }, { "id": "6b032f8f53fec70e", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1100, "wires": [] }, { "id": "8f5a61c59a6945cf", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "text_at_url", "outputs": 2, "x": 250, "y": 1100, "wires": [ [ "6b032f8f53fec70e" ], [ "6b032f8f53fec70e" ] ] }, { "id": "211d24b5b7366338", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "validated_extract_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 800, "y": 1240, "wires": [ [ "c963b65fc2b1091f" ] ] }, { "id": "0864d228a1e1655c", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1180, "y": 1220, "wires": [] }, { "id": "c963b65fc2b1091f", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, ExtractFromText, DecisionFromText\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Request = msg.Request\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n\n let Extract\n try {\n Extract = await ExtractFromText(Request, Text, Options)\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n\n try {\n let Question = `\n does the following text contain this information \"${Request}\"?\n `\n\n let Decision = await DecisionFromText(Question, Extract, Options)\n\n msg.payload = (Decision.trim() === 'yes' ? Extract : '')\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1020, "y": 1240, "wires": [ [ "0864d228a1e1655c" ], [ "8823295882e41af3" ] ] }, { "id": "8823295882e41af3", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1170, "y": 1260, "wires": [] }, { "id": "4890a9abef285710", "type": "comment", "z": "a38a9db5ce759685", "name": "Text Summary", "info": "", "x": 750, "y": 980, "wires": [] }, { "id": "55937eeb4762bb09", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "summary_of_text", "info": "describe your reusable flow here", "scope": "global", "x": 760, "y": 1040, "wires": [ [ "2043d742f6c12acd" ] ] }, { "id": "b9f605592394942a", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1100, "y": 1020, "wires": [] }, { "id": "2043d742f6c12acd", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, SummaryOfText\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await SummaryOfText(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 940, "y": 1040, "wires": [ [ "b9f605592394942a" ], [ "fa8ccd4edd8c1615" ] ] }, { "id": "fa8ccd4edd8c1615", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1090, "y": 1060, "wires": [] }, { "id": "6d6e2238c7e1647a", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Alice, a young girl, sits bored by a riverbank and spots a White Rabbit with a pocket watch and waistcoat lamenting that he is late. Surprised, Alice follows him down a rabbit hole, which sends her into a lengthy plummet but to a safe landing. Inside a room with a table, she finds a key to a tiny door, beyond which is a garden. While pondering how to fit through the door, she discovers a bottle reading \"Drink me\". Alice drinks a portion of the bottle's contents, and to her astonishment, she shrinks small enough to enter the door. However, she had left the key upon the table and cannot reach it. Alice then discovers and eats a cake, which causes her to grow to a tremendous size. Unhappy, Alice bursts into tears, and the passing White Rabbit flees in a panic, dropping a fan and two gloves. Alice uses the fan for herself, which causes her to shrink once more and leaves her swimming in a pool of her own tears. Within the pool, Alice meets various animals and birds, who convene on a bank and engage in a \"Caucus Race\" to dry themselves. Following the end of the race, Alice inadvertently frightens the animals away by discussing her cat. The Cheshire Cat The White Rabbit appears looking for the gloves and fan. Mistaking Alice for his maidservant, he orders her to go into his house and retrieve them. Alice finds another bottle and drinks from it, which causes her to grow to such an extent that she gets stuck in the house. Attempting to extract her, The White Rabbit and his neighbors eventually take to hurling pebbles that turn into small cakes. Alice eats one and shrinks herself, allowing her to flee into the forest. She meets a Caterpillar seated on a mushroom and smoking a hookah. Amidst the Caterpillar's questioning, Alice begins to admit to her current identity crisis, compounded by her inability to remember a poem. Before crawling away, the Caterpillar says that a bite of one side of the mushroom will make her larger, while a bite from the other side will make her smaller. During a period of trial and error, Alice's neck extends between the treetops, frightening a pigeon who mistakes her for a serpent. After shrinking to an appropriate height, Alice arrives at the home of a Duchess, who owns a perpetually grinning Cheshire Cat. The Duchess's baby, whom she hands to Alice, transforms into a piglet, which Alice releases into the woods. The Cheshire Cat appears to Alice and directs her toward the Hatter and March Hare before disappearing, leaving his grin behind. Alice finds the Hatter, March Hare, and a sleepy Dormouse in the midst of a tea party. The Hatter explains that it is always 6 pm (tea time), claiming that time is standing still as punishment for the Hatter trying to \"kill it\". A conversation ensues around the table, and the riddle \"Why is a raven like a writing desk?\" is brought up. Alice impatiently decides to leave, calling the party stupid. Alice trying to play croquet with a Flamingo Noticing a door on a tree, Alice passes through and finds herself back in the room from the beginning of her journey. She takes the key and uses it to open the door to the garden, which turns out to be the croquet court of the Queen of Hearts, whose guard consists of living playing cards. Alice participates in a croquet game, in which hedgehogs are used as balls, flamingos are used as mallets, and soldiers act as gates. The Queen is short-tempered and constantly orders beheadings. When the Cheshire Cat appears as only a head, the Queen orders his beheading, only to be told that such an act is impossible. Because the cat belongs to the Duchess, Alice prompts the Queen to release the Duchess from prison to resolve the matter. When the Duchess ruminates on finding morals in everything around her, the Queen dismisses her on the threat of execution. Alice then meets a Gryphon and a Mock Turtle, who dance to the Lobster Quadrille while Alice recites (rather incorrectly) a poem. The Mock Turtle sings them \"Beautiful Soup\" during which the Gryphon drags Alice away for a trial, in which the Knave of Hearts stands accused of stealing the Queen's tarts. The trial is conducted by the King of Hearts, and the jury is composed of animals that Alice previously met. Alice gradually grows in size and confidence, allowing herself increasingly frequent remarks on the irrationality of the proceedings. The Queen eventually commands Alice's beheading, but Alice scoffs that the Queen's guard is only a pack of cards. Although Alice holds her own for a time, the guards soon gang up and start to swarm all over her. Alice's sister wakes her up from a dream, brushing what turns out to be leaves from Alice's face. Alice leaves her sister on the bank to imagine all the curious happenings for herself.", "payloadType": "str", "x": 90, "y": 1180, "wires": [ [ "de75c7ea27a03baa" ] ] }, { "id": "613dc209d541155f", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1180, "wires": [] }, { "id": "de75c7ea27a03baa", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "summary_of_text", "outputs": 2, "x": 270, "y": 1180, "wires": [ [ "613dc209d541155f" ], [ "613dc209d541155f" ] ] }, { "id": "6d265de4e561324a", "type": "comment", "z": "a38a9db5ce759685", "name": "Knowledge Extraction", "info": "", "x": 780, "y": 1100, "wires": [] }, { "id": "8fd1aa6374bdd57b", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "extract_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 760, "y": 1160, "wires": [ [ "17b78be783b969cf" ] ] }, { "id": "e58e7c1e6638b2c6", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1100, "y": 1140, "wires": [] }, { "id": "17b78be783b969cf", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, ExtractFromText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Request = msg.Request\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await ExtractFromText(Request, Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 940, "y": 1160, "wires": [ [ "e58e7c1e6638b2c6" ], [ "d511c77631bf08ae" ] ] }, { "id": "d511c77631bf08ae", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1090, "y": 1180, "wires": [] }, { "id": "2c68d959bdaaa2f7", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "how does Alice change her size?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Alice, a young girl, sits bored by a riverbank and spots a White Rabbit with a pocket watch and waistcoat lamenting that he is late. Surprised, Alice follows him down a rabbit hole, which sends her into a lengthy plummet but to a safe landing. Inside a room with a table, she finds a key to a tiny door, beyond which is a garden. While pondering how to fit through the door, she discovers a bottle reading \"Drink me\". Alice drinks a portion of the bottle's contents, and to her astonishment, she shrinks small enough to enter the door. However, she had left the key upon the table and cannot reach it. Alice then discovers and eats a cake, which causes her to grow to a tremendous size. Unhappy, Alice bursts into tears, and the passing White Rabbit flees in a panic, dropping a fan and two gloves. Alice uses the fan for herself, which causes her to shrink once more and leaves her swimming in a pool of her own tears. Within the pool, Alice meets various animals and birds, who convene on a bank and engage in a \"Caucus Race\" to dry themselves. Following the end of the race, Alice inadvertently frightens the animals away by discussing her cat. The Cheshire Cat The White Rabbit appears looking for the gloves and fan. Mistaking Alice for his maidservant, he orders her to go into his house and retrieve them. Alice finds another bottle and drinks from it, which causes her to grow to such an extent that she gets stuck in the house. Attempting to extract her, The White Rabbit and his neighbors eventually take to hurling pebbles that turn into small cakes. Alice eats one and shrinks herself, allowing her to flee into the forest. She meets a Caterpillar seated on a mushroom and smoking a hookah. Amidst the Caterpillar's questioning, Alice begins to admit to her current identity crisis, compounded by her inability to remember a poem. Before crawling away, the Caterpillar says that a bite of one side of the mushroom will make her larger, while a bite from the other side will make her smaller. During a period of trial and error, Alice's neck extends between the treetops, frightening a pigeon who mistakes her for a serpent. After shrinking to an appropriate height, Alice arrives at the home of a Duchess, who owns a perpetually grinning Cheshire Cat. The Duchess's baby, whom she hands to Alice, transforms into a piglet, which Alice releases into the woods. The Cheshire Cat appears to Alice and directs her toward the Hatter and March Hare before disappearing, leaving his grin behind. Alice finds the Hatter, March Hare, and a sleepy Dormouse in the midst of a tea party. The Hatter explains that it is always 6 pm (tea time), claiming that time is standing still as punishment for the Hatter trying to \"kill it\". A conversation ensues around the table, and the riddle \"Why is a raven like a writing desk?\" is brought up. Alice impatiently decides to leave, calling the party stupid. Alice trying to play croquet with a Flamingo Noticing a door on a tree, Alice passes through and finds herself back in the room from the beginning of her journey. She takes the key and uses it to open the door to the garden, which turns out to be the croquet court of the Queen of Hearts, whose guard consists of living playing cards. Alice participates in a croquet game, in which hedgehogs are used as balls, flamingos are used as mallets, and soldiers act as gates. The Queen is short-tempered and constantly orders beheadings. When the Cheshire Cat appears as only a head, the Queen orders his beheading, only to be told that such an act is impossible. Because the cat belongs to the Duchess, Alice prompts the Queen to release the Duchess from prison to resolve the matter. When the Duchess ruminates on finding morals in everything around her, the Queen dismisses her on the threat of execution. Alice then meets a Gryphon and a Mock Turtle, who dance to the Lobster Quadrille while Alice recites (rather incorrectly) a poem. The Mock Turtle sings them \"Beautiful Soup\" during which the Gryphon drags Alice away for a trial, in which the Knave of Hearts stands accused of stealing the Queen's tarts. The trial is conducted by the King of Hearts, and the jury is composed of animals that Alice previously met. Alice gradually grows in size and confidence, allowing herself increasingly frequent remarks on the irrationality of the proceedings. The Queen eventually commands Alice's beheading, but Alice scoffs that the Queen's guard is only a pack of cards. Although Alice holds her own for a time, the guards soon gang up and start to swarm all over her. Alice's sister wakes her up from a dream, brushing what turns out to be leaves from Alice's face. Alice leaves her sister on the bank to imagine all the curious happenings for herself.", "payloadType": "str", "x": 90, "y": 1360, "wires": [ [ "61fa64e9fd4904ab" ] ] }, { "id": "9bd924defd4b5c79", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1360, "wires": [] }, { "id": "61fa64e9fd4904ab", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "extract_from_text", "outputs": 2, "x": 270, "y": 1360, "wires": [ [ "9bd924defd4b5c79" ], [ "9bd924defd4b5c79" ] ] }, { "id": "e6cd70be2ae38caa", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "how many months did Joseph Weizenbaum teach at MIT?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Alice, a young girl, sits bored by a riverbank and spots a White Rabbit with a pocket watch and waistcoat lamenting that he is late. Surprised, Alice follows him down a rabbit hole, which sends her into a lengthy plummet but to a safe landing. Inside a room with a table, she finds a key to a tiny door, beyond which is a garden. While pondering how to fit through the door, she discovers a bottle reading \"Drink me\". Alice drinks a portion of the bottle's contents, and to her astonishment, she shrinks small enough to enter the door. However, she had left the key upon the table and cannot reach it. Alice then discovers and eats a cake, which causes her to grow to a tremendous size. Unhappy, Alice bursts into tears, and the passing White Rabbit flees in a panic, dropping a fan and two gloves. Alice uses the fan for herself, which causes her to shrink once more and leaves her swimming in a pool of her own tears. Within the pool, Alice meets various animals and birds, who convene on a bank and engage in a \"Caucus Race\" to dry themselves. Following the end of the race, Alice inadvertently frightens the animals away by discussing her cat. The Cheshire Cat The White Rabbit appears looking for the gloves and fan. Mistaking Alice for his maidservant, he orders her to go into his house and retrieve them. Alice finds another bottle and drinks from it, which causes her to grow to such an extent that she gets stuck in the house. Attempting to extract her, The White Rabbit and his neighbors eventually take to hurling pebbles that turn into small cakes. Alice eats one and shrinks herself, allowing her to flee into the forest. She meets a Caterpillar seated on a mushroom and smoking a hookah. Amidst the Caterpillar's questioning, Alice begins to admit to her current identity crisis, compounded by her inability to remember a poem. Before crawling away, the Caterpillar says that a bite of one side of the mushroom will make her larger, while a bite from the other side will make her smaller. During a period of trial and error, Alice's neck extends between the treetops, frightening a pigeon who mistakes her for a serpent. After shrinking to an appropriate height, Alice arrives at the home of a Duchess, who owns a perpetually grinning Cheshire Cat. The Duchess's baby, whom she hands to Alice, transforms into a piglet, which Alice releases into the woods. The Cheshire Cat appears to Alice and directs her toward the Hatter and March Hare before disappearing, leaving his grin behind. Alice finds the Hatter, March Hare, and a sleepy Dormouse in the midst of a tea party. The Hatter explains that it is always 6 pm (tea time), claiming that time is standing still as punishment for the Hatter trying to \"kill it\". A conversation ensues around the table, and the riddle \"Why is a raven like a writing desk?\" is brought up. Alice impatiently decides to leave, calling the party stupid. Alice trying to play croquet with a Flamingo Noticing a door on a tree, Alice passes through and finds herself back in the room from the beginning of her journey. She takes the key and uses it to open the door to the garden, which turns out to be the croquet court of the Queen of Hearts, whose guard consists of living playing cards. Alice participates in a croquet game, in which hedgehogs are used as balls, flamingos are used as mallets, and soldiers act as gates. The Queen is short-tempered and constantly orders beheadings. When the Cheshire Cat appears as only a head, the Queen orders his beheading, only to be told that such an act is impossible. Because the cat belongs to the Duchess, Alice prompts the Queen to release the Duchess from prison to resolve the matter. When the Duchess ruminates on finding morals in everything around her, the Queen dismisses her on the threat of execution. Alice then meets a Gryphon and a Mock Turtle, who dance to the Lobster Quadrille while Alice recites (rather incorrectly) a poem. The Mock Turtle sings them \"Beautiful Soup\" during which the Gryphon drags Alice away for a trial, in which the Knave of Hearts stands accused of stealing the Queen's tarts. The trial is conducted by the King of Hearts, and the jury is composed of animals that Alice previously met. Alice gradually grows in size and confidence, allowing herself increasingly frequent remarks on the irrationality of the proceedings. The Queen eventually commands Alice's beheading, but Alice scoffs that the Queen's guard is only a pack of cards. Although Alice holds her own for a time, the guards soon gang up and start to swarm all over her. Alice's sister wakes her up from a dream, brushing what turns out to be leaves from Alice's face. Alice leaves her sister on the bank to imagine all the curious happenings for herself.", "payloadType": "str", "x": 90, "y": 1420, "wires": [ [ "3ac1902b52917f7e" ] ] }, { "id": "bb9ac895738abbf7", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 540, "y": 1420, "wires": [] }, { "id": "3ac1902b52917f7e", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "validated_extract_from_text", "outputs": 2, "x": 300, "y": 1420, "wires": [ [ "bb9ac895738abbf7" ], [ "bb9ac895738abbf7" ] ] }, { "id": "b3d7ac2ee5fdd007", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "decision_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 770, "y": 1320, "wires": [ [ "61a23a40f80b750e" ] ] }, { "id": "41e2a7bee8efc609", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1120, "y": 1300, "wires": [] }, { "id": "61a23a40f80b750e", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, DecisionFromText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Question = msg.Request\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await DecisionFromText(Question, Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 960, "y": 1320, "wires": [ [ "41e2a7bee8efc609" ], [ "d386d6529fb8bf7a" ] ] }, { "id": "d386d6529fb8bf7a", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1110, "y": 1340, "wires": [] }, { "id": "5eaa3f8da8490654", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "number_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 770, "y": 1400, "wires": [ [ "57fc4ed7f1dd6334" ] ] }, { "id": "a615b98e07d7fbca", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1120, "y": 1380, "wires": [] }, { "id": "57fc4ed7f1dd6334", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, NumberFromText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Question = msg.Request\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await NumberFromText(Question, Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 960, "y": 1400, "wires": [ [ "a615b98e07d7fbca" ], [ "1d8b35017d6d8e6b" ] ] }, { "id": "1d8b35017d6d8e6b", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1110, "y": 1420, "wires": [] }, { "id": "9f149e68da088d4b", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "list_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 750, "y": 1480, "wires": [ [ "08448cee13a644ab" ] ] }, { "id": "e4c86bd804244f4a", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1080, "y": 1460, "wires": [] }, { "id": "08448cee13a644ab", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, ListFromText\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Request = msg.Request\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await ListFromText(Request, Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 920, "y": 1480, "wires": [ [ "e4c86bd804244f4a" ], [ "b77c28c8fc16c2ac" ] ] }, { "id": "b77c28c8fc16c2ac", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1070, "y": 1500, "wires": [] }, { "id": "573f283437fe501d", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "does the white rabbit wear a waistcoat?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Alice, a young girl, sits bored by a riverbank and spots a White Rabbit with a pocket watch and waistcoat lamenting that he is late. Surprised, Alice follows him down a rabbit hole, which sends her into a lengthy plummet but to a safe landing. Inside a room with a table, she finds a key to a tiny door, beyond which is a garden. While pondering how to fit through the door, she discovers a bottle reading \"Drink me\". Alice drinks a portion of the bottle's contents, and to her astonishment, she shrinks small enough to enter the door. However, she had left the key upon the table and cannot reach it. Alice then discovers and eats a cake, which causes her to grow to a tremendous size. Unhappy, Alice bursts into tears, and the passing White Rabbit flees in a panic, dropping a fan and two gloves. Alice uses the fan for herself, which causes her to shrink once more and leaves her swimming in a pool of her own tears. Within the pool, Alice meets various animals and birds, who convene on a bank and engage in a \"Caucus Race\" to dry themselves. Following the end of the race, Alice inadvertently frightens the animals away by discussing her cat. The Cheshire Cat The White Rabbit appears looking for the gloves and fan. Mistaking Alice for his maidservant, he orders her to go into his house and retrieve them. Alice finds another bottle and drinks from it, which causes her to grow to such an extent that she gets stuck in the house. Attempting to extract her, The White Rabbit and his neighbors eventually take to hurling pebbles that turn into small cakes. Alice eats one and shrinks herself, allowing her to flee into the forest. She meets a Caterpillar seated on a mushroom and smoking a hookah. Amidst the Caterpillar's questioning, Alice begins to admit to her current identity crisis, compounded by her inability to remember a poem. Before crawling away, the Caterpillar says that a bite of one side of the mushroom will make her larger, while a bite from the other side will make her smaller. During a period of trial and error, Alice's neck extends between the treetops, frightening a pigeon who mistakes her for a serpent. After shrinking to an appropriate height, Alice arrives at the home of a Duchess, who owns a perpetually grinning Cheshire Cat. The Duchess's baby, whom she hands to Alice, transforms into a piglet, which Alice releases into the woods. The Cheshire Cat appears to Alice and directs her toward the Hatter and March Hare before disappearing, leaving his grin behind. Alice finds the Hatter, March Hare, and a sleepy Dormouse in the midst of a tea party. The Hatter explains that it is always 6 pm (tea time), claiming that time is standing still as punishment for the Hatter trying to \"kill it\". A conversation ensues around the table, and the riddle \"Why is a raven like a writing desk?\" is brought up. Alice impatiently decides to leave, calling the party stupid. Alice trying to play croquet with a Flamingo Noticing a door on a tree, Alice passes through and finds herself back in the room from the beginning of her journey. She takes the key and uses it to open the door to the garden, which turns out to be the croquet court of the Queen of Hearts, whose guard consists of living playing cards. Alice participates in a croquet game, in which hedgehogs are used as balls, flamingos are used as mallets, and soldiers act as gates. The Queen is short-tempered and constantly orders beheadings. When the Cheshire Cat appears as only a head, the Queen orders his beheading, only to be told that such an act is impossible. Because the cat belongs to the Duchess, Alice prompts the Queen to release the Duchess from prison to resolve the matter. When the Duchess ruminates on finding morals in everything around her, the Queen dismisses her on the threat of execution. Alice then meets a Gryphon and a Mock Turtle, who dance to the Lobster Quadrille while Alice recites (rather incorrectly) a poem. The Mock Turtle sings them \"Beautiful Soup\" during which the Gryphon drags Alice away for a trial, in which the Knave of Hearts stands accused of stealing the Queen's tarts. The trial is conducted by the King of Hearts, and the jury is composed of animals that Alice previously met. Alice gradually grows in size and confidence, allowing herself increasingly frequent remarks on the irrationality of the proceedings. The Queen eventually commands Alice's beheading, but Alice scoffs that the Queen's guard is only a pack of cards. Although Alice holds her own for a time, the guards soon gang up and start to swarm all over her. Alice's sister wakes her up from a dream, brushing what turns out to be leaves from Alice's face. Alice leaves her sister on the bank to imagine all the curious happenings for herself.", "payloadType": "str", "x": 90, "y": 1480, "wires": [ [ "8ecced0cea1bd79d" ] ] }, { "id": "9cbc0dfbcec9d8db", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1480, "wires": [] }, { "id": "8ecced0cea1bd79d", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "decision_from_text", "outputs": 2, "x": 270, "y": 1480, "wires": [ [ "9cbc0dfbcec9d8db" ], [ "9cbc0dfbcec9d8db" ] ] }, { "id": "a916fc8a3e5cb3d4", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "how many sisters does Alice have?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Alice, a young girl, sits bored by a riverbank and spots a White Rabbit with a pocket watch and waistcoat lamenting that he is late. Surprised, Alice follows him down a rabbit hole, which sends her into a lengthy plummet but to a safe landing. Inside a room with a table, she finds a key to a tiny door, beyond which is a garden. While pondering how to fit through the door, she discovers a bottle reading \"Drink me\". Alice drinks a portion of the bottle's contents, and to her astonishment, she shrinks small enough to enter the door. However, she had left the key upon the table and cannot reach it. Alice then discovers and eats a cake, which causes her to grow to a tremendous size. Unhappy, Alice bursts into tears, and the passing White Rabbit flees in a panic, dropping a fan and two gloves. Alice uses the fan for herself, which causes her to shrink once more and leaves her swimming in a pool of her own tears. Within the pool, Alice meets various animals and birds, who convene on a bank and engage in a \"Caucus Race\" to dry themselves. Following the end of the race, Alice inadvertently frightens the animals away by discussing her cat. The Cheshire Cat The White Rabbit appears looking for the gloves and fan. Mistaking Alice for his maidservant, he orders her to go into his house and retrieve them. Alice finds another bottle and drinks from it, which causes her to grow to such an extent that she gets stuck in the house. Attempting to extract her, The White Rabbit and his neighbors eventually take to hurling pebbles that turn into small cakes. Alice eats one and shrinks herself, allowing her to flee into the forest. She meets a Caterpillar seated on a mushroom and smoking a hookah. Amidst the Caterpillar's questioning, Alice begins to admit to her current identity crisis, compounded by her inability to remember a poem. Before crawling away, the Caterpillar says that a bite of one side of the mushroom will make her larger, while a bite from the other side will make her smaller. During a period of trial and error, Alice's neck extends between the treetops, frightening a pigeon who mistakes her for a serpent. After shrinking to an appropriate height, Alice arrives at the home of a Duchess, who owns a perpetually grinning Cheshire Cat. The Duchess's baby, whom she hands to Alice, transforms into a piglet, which Alice releases into the woods. The Cheshire Cat appears to Alice and directs her toward the Hatter and March Hare before disappearing, leaving his grin behind. Alice finds the Hatter, March Hare, and a sleepy Dormouse in the midst of a tea party. The Hatter explains that it is always 6 pm (tea time), claiming that time is standing still as punishment for the Hatter trying to \"kill it\". A conversation ensues around the table, and the riddle \"Why is a raven like a writing desk?\" is brought up. Alice impatiently decides to leave, calling the party stupid. Alice trying to play croquet with a Flamingo Noticing a door on a tree, Alice passes through and finds herself back in the room from the beginning of her journey. She takes the key and uses it to open the door to the garden, which turns out to be the croquet court of the Queen of Hearts, whose guard consists of living playing cards. Alice participates in a croquet game, in which hedgehogs are used as balls, flamingos are used as mallets, and soldiers act as gates. The Queen is short-tempered and constantly orders beheadings. When the Cheshire Cat appears as only a head, the Queen orders his beheading, only to be told that such an act is impossible. Because the cat belongs to the Duchess, Alice prompts the Queen to release the Duchess from prison to resolve the matter. When the Duchess ruminates on finding morals in everything around her, the Queen dismisses her on the threat of execution. Alice then meets a Gryphon and a Mock Turtle, who dance to the Lobster Quadrille while Alice recites (rather incorrectly) a poem. The Mock Turtle sings them \"Beautiful Soup\" during which the Gryphon drags Alice away for a trial, in which the Knave of Hearts stands accused of stealing the Queen's tarts. The trial is conducted by the King of Hearts, and the jury is composed of animals that Alice previously met. Alice gradually grows in size and confidence, allowing herself increasingly frequent remarks on the irrationality of the proceedings. The Queen eventually commands Alice's beheading, but Alice scoffs that the Queen's guard is only a pack of cards. Although Alice holds her own for a time, the guards soon gang up and start to swarm all over her. Alice's sister wakes her up from a dream, brushing what turns out to be leaves from Alice's face. Alice leaves her sister on the bank to imagine all the curious happenings for herself.", "payloadType": "str", "x": 90, "y": 1540, "wires": [ [ "a1700a40bd0c18ea" ] ] }, { "id": "8b7bafef9b77a4ab", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1540, "wires": [] }, { "id": "a1700a40bd0c18ea", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "number_from_text", "outputs": 2, "x": 270, "y": 1540, "wires": [ [ "8b7bafef9b77a4ab" ], [ "8b7bafef9b77a4ab" ] ] }, { "id": "8b1f0fe7853e0fd3", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "list all characters mentioned", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Alice, a young girl, sits bored by a riverbank and spots a White Rabbit with a pocket watch and waistcoat lamenting that he is late. Surprised, Alice follows him down a rabbit hole, which sends her into a lengthy plummet but to a safe landing. Inside a room with a table, she finds a key to a tiny door, beyond which is a garden. While pondering how to fit through the door, she discovers a bottle reading \"Drink me\". Alice drinks a portion of the bottle's contents, and to her astonishment, she shrinks small enough to enter the door. However, she had left the key upon the table and cannot reach it. Alice then discovers and eats a cake, which causes her to grow to a tremendous size. Unhappy, Alice bursts into tears, and the passing White Rabbit flees in a panic, dropping a fan and two gloves. Alice uses the fan for herself, which causes her to shrink once more and leaves her swimming in a pool of her own tears. Within the pool, Alice meets various animals and birds, who convene on a bank and engage in a \"Caucus Race\" to dry themselves. Following the end of the race, Alice inadvertently frightens the animals away by discussing her cat. The Cheshire Cat The White Rabbit appears looking for the gloves and fan. Mistaking Alice for his maidservant, he orders her to go into his house and retrieve them. Alice finds another bottle and drinks from it, which causes her to grow to such an extent that she gets stuck in the house. Attempting to extract her, The White Rabbit and his neighbors eventually take to hurling pebbles that turn into small cakes. Alice eats one and shrinks herself, allowing her to flee into the forest. She meets a Caterpillar seated on a mushroom and smoking a hookah. Amidst the Caterpillar's questioning, Alice begins to admit to her current identity crisis, compounded by her inability to remember a poem. Before crawling away, the Caterpillar says that a bite of one side of the mushroom will make her larger, while a bite from the other side will make her smaller. During a period of trial and error, Alice's neck extends between the treetops, frightening a pigeon who mistakes her for a serpent. After shrinking to an appropriate height, Alice arrives at the home of a Duchess, who owns a perpetually grinning Cheshire Cat. The Duchess's baby, whom she hands to Alice, transforms into a piglet, which Alice releases into the woods. The Cheshire Cat appears to Alice and directs her toward the Hatter and March Hare before disappearing, leaving his grin behind. Alice finds the Hatter, March Hare, and a sleepy Dormouse in the midst of a tea party. The Hatter explains that it is always 6 pm (tea time), claiming that time is standing still as punishment for the Hatter trying to \"kill it\". A conversation ensues around the table, and the riddle \"Why is a raven like a writing desk?\" is brought up. Alice impatiently decides to leave, calling the party stupid. Alice trying to play croquet with a Flamingo Noticing a door on a tree, Alice passes through and finds herself back in the room from the beginning of her journey. She takes the key and uses it to open the door to the garden, which turns out to be the croquet court of the Queen of Hearts, whose guard consists of living playing cards. Alice participates in a croquet game, in which hedgehogs are used as balls, flamingos are used as mallets, and soldiers act as gates. The Queen is short-tempered and constantly orders beheadings. When the Cheshire Cat appears as only a head, the Queen orders his beheading, only to be told that such an act is impossible. Because the cat belongs to the Duchess, Alice prompts the Queen to release the Duchess from prison to resolve the matter. When the Duchess ruminates on finding morals in everything around her, the Queen dismisses her on the threat of execution. Alice then meets a Gryphon and a Mock Turtle, who dance to the Lobster Quadrille while Alice recites (rather incorrectly) a poem. The Mock Turtle sings them \"Beautiful Soup\" during which the Gryphon drags Alice away for a trial, in which the Knave of Hearts stands accused of stealing the Queen's tarts. The trial is conducted by the King of Hearts, and the jury is composed of animals that Alice previously met. Alice gradually grows in size and confidence, allowing herself increasingly frequent remarks on the irrationality of the proceedings. The Queen eventually commands Alice's beheading, but Alice scoffs that the Queen's guard is only a pack of cards. Although Alice holds her own for a time, the guards soon gang up and start to swarm all over her. Alice's sister wakes her up from a dream, brushing what turns out to be leaves from Alice's face. Alice leaves her sister on the bank to imagine all the curious happenings for herself.", "payloadType": "str", "x": 90, "y": 1600, "wires": [ [ "4c8420e648134530" ] ] }, { "id": "9db9a4aa752759b3", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1600, "wires": [] }, { "id": "4c8420e648134530", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "list_from_text", "outputs": 2, "x": 260, "y": 1600, "wires": [ [ "9db9a4aa752759b3" ], [ "9db9a4aa752759b3" ] ] }, { "id": "dd2b4de50a8cc619", "type": "comment", "z": "a38a9db5ce759685", "name": "Questionization", "info": "", "x": 760, "y": 760, "wires": [] }, { "id": "d132ccf4937ee542", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "text_is_a_question", "info": "describe your reusable flow here", "scope": "global", "x": 770, "y": 820, "wires": [ [ "b97251e2568d0374" ] ] }, { "id": "6307a177ec8e5a9f", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1120, "y": 800, "wires": [] }, { "id": "b97251e2568d0374", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, TextIsQuestion\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await TextIsQuestion(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 960, "y": 820, "wires": [ [ "6307a177ec8e5a9f" ], [ "74c7a2e3b97f2ea6" ] ] }, { "id": "74c7a2e3b97f2ea6", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1110, "y": 840, "wires": [] }, { "id": "5ce6f67404ce9b68", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "problem_as_question", "info": "describe your reusable flow here", "scope": "global", "x": 780, "y": 900, "wires": [ [ "76c456d6c50998f1" ] ] }, { "id": "44b0c82ef27c652d", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1140, "y": 880, "wires": [] }, { "id": "76c456d6c50998f1", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, ProblemAsQuestion\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Problem = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await ProblemAsQuestion(Problem, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 980, "y": 900, "wires": [ [ "44b0c82ef27c652d" ], [ "326ced018e7208c9" ] ] }, { "id": "326ced018e7208c9", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1130, "y": 920, "wires": [] }, { "id": "329f5a5fdf125087", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "how does Alice change her size?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Joseph Weizenbaum (8 January 1923 – 5 March 2008) was a German American computer scientist and a professor at MIT. The Weizenbaum Award is named after him.", "payloadType": "str", "x": 90, "y": 1240, "wires": [ [ "8c6086a1222ce023" ] ] }, { "id": "c5a9c547d32ded0b", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1240, "wires": [] }, { "id": "8c6086a1222ce023", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "text_is_a_question", "outputs": 2, "x": 270, "y": 1240, "wires": [ [ "c5a9c547d32ded0b" ], [ "c5a9c547d32ded0b" ] ] }, { "id": "5824213f18f72f14", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Request", "v": "how does Alice change her size?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "calculate the number of months Joseph Weizenbaum taught at MIT", "payloadType": "str", "x": 90, "y": 1300, "wires": [ [ "47436a963aa093aa" ] ] }, { "id": "0f383b98c296edde", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1300, "wires": [] }, { "id": "47436a963aa093aa", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "problem_as_question", "outputs": 2, "x": 280, "y": 1300, "wires": [ [ "0f383b98c296edde" ], [ "0f383b98c296edde" ] ] }, { "id": "1d8533b64f42c964", "type": "comment", "z": "a38a9db5ce759685", "name": "Quintessence Extraction", "info": "", "x": 790, "y": 1740, "wires": [] }, { "id": "3959f3d1f060db12", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "quintessence_of_output", "info": "describe your reusable flow here", "scope": "global", "x": 780, "y": 1800, "wires": [ [ "c946a0d64bdd72c6" ] ] }, { "id": "5e9cea0bdd72fddc", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1140, "y": 1780, "wires": [] }, { "id": "c946a0d64bdd72c6", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, QuintessenceOfOutput\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Input = acceptableString(msg.Input)\n const Output = acceptableString(msg.Output || msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await QuintessenceOfOutput(Input, Output, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 980, "y": 1800, "wires": [ [ "5e9cea0bdd72fddc" ], [ "3d8d691686263e7c" ] ] }, { "id": "3d8d691686263e7c", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1130, "y": 1820, "wires": [] }, { "id": "3086fd83793646ae", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" }, { "p": "Input", "v": "How many months did Joseph Weizenbaum teach at MIT?", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Joseph Weizenbaum started his tenure at the Massachusetts Institute of Technology (MIT) in 1963. He served as an Associate Professor from 1964 to 1970, and then as a Professor from 1970 until his retirement. He passed away in 2008. Therefore, he taught at MIT for approximately 45 years.", "payloadType": "str", "x": 90, "y": 1780, "wires": [ [ "18283bb3d35fa0c7" ] ] }, { "id": "c3081111e8f22a49", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 520, "y": 1780, "wires": [] }, { "id": "18283bb3d35fa0c7", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "quintessence_of_output", "outputs": 2, "x": 290, "y": 1780, "wires": [ [ "c3081111e8f22a49" ], [ "c3081111e8f22a49" ] ] }, { "id": "39a5ebce7c638946", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "wer war Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 2520, "wires": [ [ "4625000f4136c135" ] ] }, { "id": "8144572db2ff4a8a", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 500, "y": 2520, "wires": [] }, { "id": "4625000f4136c135", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "language_of_text", "outputs": 2, "x": 270, "y": 2520, "wires": [ [ "8144572db2ff4a8a" ], [ "8144572db2ff4a8a" ] ] }, { "id": "9825829c009b9262", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "originalLanguage", "v": "de", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "wer war Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 2580, "wires": [ [ "0cc55c7df9665b47" ] ] }, { "id": "b76c6d5899b6b456", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 2580, "wires": [] }, { "id": "0cc55c7df9665b47", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "translation_of_text", "outputs": 2, "x": 270, "y": 2580, "wires": [ [ "b76c6d5899b6b456" ], [ "b76c6d5899b6b456" ] ] }, { "id": "ae933960b2f16763", "type": "comment", "z": "a38a9db5ce759685", "name": "Tool Store", "info": "", "x": 2060, "y": 40, "wires": [] }, { "id": "2984887b78317ca1", "type": "comment", "z": "a38a9db5ce759685", "name": "File System Persistence", "info": "", "x": 2100, "y": 100, "wires": [] }, { "id": "902ac545fd6525e6", "type": "comment", "z": "a38a9db5ce759685", "name": "Conversions", "info": "", "x": 750, "y": 1540, "wires": [] }, { "id": "31eb2b63e14d5fb3", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "search_prompt_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 790, "y": 1600, "wires": [ [ "303ece75df035a5b" ] ] }, { "id": "8165adb99cda22a0", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1160, "y": 1580, "wires": [] }, { "id": "303ece75df035a5b", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, SearchPromptFromText\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Text = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await SearchPromptFromText(Text, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1000, "y": 1600, "wires": [ [ "8165adb99cda22a0" ], [ "49dc4833fbdcbb6c" ] ] }, { "id": "49dc4833fbdcbb6c", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1150, "y": 1620, "wires": [] }, { "id": "c3adbc8bbc03fbab", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "script_from_text", "info": "describe your reusable flow here", "scope": "global", "x": 760, "y": 1680, "wires": [ [ "838856d7cc82a7b8" ] ] }, { "id": "3fba63fe5c42ced0", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 1100, "y": 1660, "wires": [] }, { "id": "838856d7cc82a7b8", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, OptionsFrom, ScriptToSolve\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Problem = acceptableString(msg.payload)\n const Options = await OptionsFrom(msg)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await ScriptToSolve(Problem, Options)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 940, "y": 1680, "wires": [ [ "3fba63fe5c42ced0" ], [ "82e49c66977bd84c" ] ] }, { "id": "82e49c66977bd84c", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 1090, "y": 1700, "wires": [] }, { "id": "9bd9244fa026afc1", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "who was Joseph Weizenbaum?", "payloadType": "str", "x": 90, "y": 1660, "wires": [ [ "89b9b733ba7d1f6a" ] ] }, { "id": "611b160b1022d3a4", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 520, "y": 1660, "wires": [] }, { "id": "89b9b733ba7d1f6a", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "search_prompt_from_text", "outputs": 2, "x": 290, "y": 1660, "wires": [ [ "611b160b1022d3a4" ], [ "611b160b1022d3a4" ] ] }, { "id": "b384d50ecaf8884a", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" }, { "p": "Model", "v": "stablelm-zephyr-3b", "vt": "str" }, { "p": "Temperature", "v": "0", "vt": "num" }, { "p": "topK", "v": "10", "vt": "num" }, { "p": "topP", "v": "0.95", "vt": "num" }, { "p": "ContextLength", "v": "4096", "vt": "num" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "give me the sum of the ASCII codes of all characters in the text \"Alice in Wonderland\"", "payloadType": "str", "x": 90, "y": 1720, "wires": [ [ "fe7462e7e46e9e85" ] ] }, { "id": "5205013b8af9c25e", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 520, "y": 1720, "wires": [] }, { "id": "fe7462e7e46e9e85", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "script_from_text", "outputs": 2, "x": 260, "y": 1720, "wires": [ [ "5205013b8af9c25e" ], [ "5205013b8af9c25e" ] ], "outputLabels": [ "success", "failure" ] }, { "id": "2469abc8b85f74b3", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "load_toolstore_from_file", "info": "describe your reusable flow here", "scope": "global", "x": 2100, "y": 160, "wires": [ [ "8ece61471e47e9a9" ] ] }, { "id": "ce60631227dda458", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2460, "y": 140, "wires": [] }, { "id": "8ece61471e47e9a9", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, loadToolStoreFromFile\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const FilePath = acceptableString(msg.payload)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n await loadToolStoreFromFile(FilePath)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2300, "y": 160, "wires": [ [ "ce60631227dda458" ], [ "85855b69f52277fb" ] ] }, { "id": "85855b69f52277fb", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2450, "y": 180, "wires": [] }, { "id": "22903e472c02e180", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "save_toolstore_to_file", "info": "describe your reusable flow here", "scope": "global", "x": 2100, "y": 240, "wires": [ [ "9991f6d89fdfc36b" ] ] }, { "id": "e2073a80d6c31aa5", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2460, "y": 220, "wires": [] }, { "id": "9991f6d89fdfc36b", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, saveToolStoreToFile\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const FilePath = acceptableString(msg.payload)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n await saveToolStoreToFile(FilePath)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2300, "y": 240, "wires": [ [ "e2073a80d6c31aa5" ], [ "a0860ca3282a067b" ] ] }, { "id": "a0860ca3282a067b", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2450, "y": 260, "wires": [] }, { "id": "cf7e798913fc582b", "type": "comment", "z": "a38a9db5ce759685", "name": "Tool Store Access", "info": "", "x": 2090, "y": 320, "wires": [] }, { "id": "2672e310a9bbf29c", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "list_of_tools", "info": "describe your reusable flow here", "scope": "global", "x": 2070, "y": 380, "wires": [ [ "a1652a479da995b9" ] ] }, { "id": "57561af074646718", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2400, "y": 360, "wires": [] }, { "id": "a1652a479da995b9", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, ListOfTools\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const FilePath = acceptableString(msg.payload)\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = ListOfTools()\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2240, "y": 380, "wires": [ [ "57561af074646718" ], [ "ec9aa795bad84875" ] ] }, { "id": "ec9aa795bad84875", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2390, "y": 400, "wires": [] }, { "id": "d94f48eea2fc0794", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "stored_tool", "info": "describe your reusable flow here", "scope": "global", "x": 2060, "y": 460, "wires": [ [ "b342d66104fb6cac" ] ] }, { "id": "928bb7dd5faf422a", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2380, "y": 440, "wires": [] }, { "id": "b342d66104fb6cac", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, storedTool\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const ToolName = acceptableString(msg.payload)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = storedTool(ToolName)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2220, "y": 460, "wires": [ [ "928bb7dd5faf422a" ], [ "d56cc23ecf425352" ] ] }, { "id": "d56cc23ecf425352", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2370, "y": 480, "wires": [] }, { "id": "6df7cb65efffb610", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "stored_tool_for_task", "info": "describe your reusable flow here", "scope": "global", "x": 2090, "y": 540, "wires": [ [ "37dbd53c1d7268ed" ] ] }, { "id": "bda75a6f3f146240", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2440, "y": 520, "wires": [] }, { "id": "37dbd53c1d7268ed", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableNumber, acceptableString, storedToolForTask\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const Task = acceptableString(msg.payload)\n const Threshold = acceptableNumber(msg.Threshold)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n msg.payload = await storedToolForTask(Task, Threshold)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2280, "y": 540, "wires": [ [ "bda75a6f3f146240" ], [ "1efcca9a8a9104cd" ] ] }, { "id": "1efcca9a8a9104cd", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2430, "y": 560, "wires": [] }, { "id": "b98e167ba4ce59d1", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "store_tool", "info": "describe your reusable flow here", "scope": "global", "x": 2060, "y": 620, "wires": [ [ "b1909eb33934f4f6" ] ] }, { "id": "031345e143c63ef5", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2380, "y": 600, "wires": [] }, { "id": "b1909eb33934f4f6", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n storeTool\n} = global.get('AI-Toolkit-commonCode')\n\n;(async function () {\n const Tool = msg.payload\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n await storeTool(Tool)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg,null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null,msg])\n node.done()\n }\n})()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2220, "y": 620, "wires": [ [ "031345e143c63ef5" ], [ "8b39241b37bea6fd" ] ] }, { "id": "8b39241b37bea6fd", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2370, "y": 640, "wires": [] }, { "id": "9498ab4a75cb2fc2", "type": "reusable-in", "z": "a38a9db5ce759685", "name": "unstore_tool", "info": "describe your reusable flow here", "scope": "global", "x": 2070, "y": 700, "wires": [ [ "20f50f50890801b4" ] ] }, { "id": "20b3534437066c6e", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "success", "position": 1, "x": 2400, "y": 680, "wires": [] }, { "id": "20f50f50890801b4", "type": "function", "z": "a38a9db5ce759685", "name": "execute", "func": "const {\n acceptableString, unstoreTool\n} = global.get('AI-Toolkit-commonCode')\n\n ; (async function () {\n const ToolName = acceptableString(msg.payload)\n\n node.status({ fill: 'yellow', shape: 'ring', text: 'running' })\n try {\n unstoreTool(ToolName)\n\n node.status({ fill: 'green', shape: 'dot', text: 'finished' })\n\n node.send([msg, null])\n node.done()\n } catch (Signal) {\n msg.statusCode = Signal.StatusCode || 500\n msg.payload = Signal.message || ''\n\n node.status({ fill: 'red', shape: 'dot', text: 'ExitCode = ' + (Signal.StatusCode || 'unknown') })\n\n node.send([null, msg])\n node.done()\n }\n })()\n", "outputs": 2, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2240, "y": 700, "wires": [ [ "20b3534437066c6e" ], [ "8aced34feadacae9" ] ] }, { "id": "8aced34feadacae9", "type": "reusable-out", "z": "a38a9db5ce759685", "name": "failure", "position": "2", "x": 2390, "y": 720, "wires": [] }, { "id": "fb507dd4e8e29834", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 90, "y": 1980, "wires": [ [ "71e1c91c54545a33" ] ] }, { "id": "24b5aafda713f0af", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 440, "y": 1980, "wires": [] }, { "id": "71e1c91c54545a33", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "list_of_tools", "outputs": 2, "x": 250, "y": 1980, "wires": [ [ "24b5aafda713f0af" ], [ "24b5aafda713f0af" ] ] }, { "id": "0ee8ada163ec318a", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "search-the-web", "payloadType": "str", "x": 90, "y": 2040, "wires": [ [ "0e465af2bd02cf24" ] ] }, { "id": "9b27a0f36ce40f01", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 440, "y": 2040, "wires": [] }, { "id": "0e465af2bd02cf24", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "stored_tool", "outputs": 2, "x": 250, "y": 2040, "wires": [ [ "9b27a0f36ce40f01" ], [ "9b27a0f36ce40f01" ] ] }, { "id": "74695505424fd5d7", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "search something in the internet", "payloadType": "str", "x": 90, "y": 2100, "wires": [ [ "7018b1ebb60d35e1" ] ] }, { "id": "dd042ee6a00a5c69", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 2100, "wires": [] }, { "id": "7018b1ebb60d35e1", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "stored_tool_for_task", "outputs": 2, "x": 280, "y": 2100, "wires": [ [ "dd042ee6a00a5c69" ], [ "dd042ee6a00a5c69" ] ] }, { "id": "131e784870efe8af", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"Name\":\"Hello, World\",\"Description\":\"just outputs 'Hello, World!'\",\"InputDescriptions\":[],\"Script\":\"return 'Hello ,World!'\"}", "payloadType": "json", "x": 90, "y": 2160, "wires": [ [ "0981756701351a6e" ] ] }, { "id": "2bdd4254d8cbee2c", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 420, "y": 2160, "wires": [] }, { "id": "0981756701351a6e", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "store_tool", "outputs": 2, "x": 240, "y": 2160, "wires": [ [ "2bdd4254d8cbee2c" ], [ "2bdd4254d8cbee2c" ] ] }, { "id": "3245d48ffba641ee", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Hello, World", "payloadType": "str", "x": 90, "y": 2220, "wires": [ [ "bee75d32609285c0" ] ] }, { "id": "98b9fa9ad2ae33d5", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 440, "y": 2220, "wires": [] }, { "id": "bee75d32609285c0", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "unstore_tool", "outputs": 2, "x": 250, "y": 2220, "wires": [ [ "98b9fa9ad2ae33d5" ], [ "98b9fa9ad2ae33d5" ] ] }, { "id": "5928e72a65483f34", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "ToolStore.json", "payloadType": "str", "x": 90, "y": 1920, "wires": [ [ "9c1ca6b4ffbcf9ec" ] ] }, { "id": "b06dcfc6e14adb86", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 500, "y": 1920, "wires": [] }, { "id": "9c1ca6b4ffbcf9ec", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "save_toolstore_to_file", "outputs": 2, "x": 280, "y": 1920, "wires": [ [ "b06dcfc6e14adb86" ], [ "b06dcfc6e14adb86" ] ] }, { "id": "b747e73af3a4a5bb", "type": "inject", "z": "a38a9db5ce759685", "name": "show", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "ToolStore.json", "payloadType": "str", "x": 90, "y": 1860, "wires": [ [ "4cc83c8761b5e339" ] ] }, { "id": "e4a83d7b038a3f04", "type": "debug", "z": "a38a9db5ce759685", "name": "in Debug Pane", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 520, "y": 1860, "wires": [] }, { "id": "4cc83c8761b5e339", "type": "reusable", "z": "a38a9db5ce759685", "name": "", "target": "load_toolstore_from_file", "outputs": 2, "x": 290, "y": 1860, "wires": [ [ "e4a83d7b038a3f04" ], [ "e4a83d7b038a3f04" ] ] }, { "id": "d3ae3bb29995ee15", "type": "comment", "z": "a38a9db5ce759685", "name": "Recipe Store", "info": "", "x": 2070, "y": 800, "wires": [] } ]