diff --git a/packages/components/nodes/tools/RequestsGet/RequestsGet.ts b/packages/components/nodes/tools/RequestsGet/RequestsGet.ts index 2085187b5b5..0b7f0ac8098 100644 --- a/packages/components/nodes/tools/RequestsGet/RequestsGet.ts +++ b/packages/components/nodes/tools/RequestsGet/RequestsGet.ts @@ -1,6 +1,6 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses } from '../../../src/utils' -import { RequestsGetTool } from 'langchain/tools' +import { desc, RequestParameters, RequestsGetTool } from './core' class RequestsGet_Tools implements INode { label: string @@ -22,9 +22,22 @@ class RequestsGet_Tools implements INode { this.baseClasses = [this.type, ...getBaseClasses(RequestsGetTool)] this.inputs = [ { - label: 'Max Output Length', - name: 'maxOutputLength', - type: 'number', + label: 'URL', + name: 'url', + type: 'string', + description: + 'Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided', + additionalParams: true, + optional: true + }, + { + label: 'Description', + name: 'description', + type: 'string', + rows: 4, + default: desc, + description: 'Acts like a prompt to tell agent when it should use this tool', + additionalParams: true, optional: true }, { @@ -39,18 +52,18 @@ class RequestsGet_Tools implements INode { async init(nodeData: INodeData): Promise { const headers = nodeData.inputs?.headers as string - const maxOutputLength = nodeData.inputs?.maxOutputLength as string - - const obj: any = {} - if (maxOutputLength) { - obj.maxOutputLength = parseInt(maxOutputLength, 10) - } + const url = nodeData.inputs?.url as string + const description = nodeData.inputs?.description as string + const obj: RequestParameters = {} + if (url) obj.url = url + if (description) obj.description = description if (headers) { const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(headers) - return Object.keys(obj).length ? new RequestsGetTool(parsedHeaders, obj) : new RequestsGetTool(parsedHeaders) + obj.headers = parsedHeaders } - return Object.keys(obj).length ? new RequestsGetTool(undefined, obj) : new RequestsGetTool() + + return new RequestsGetTool(obj) } } diff --git a/packages/components/nodes/tools/RequestsGet/core.ts b/packages/components/nodes/tools/RequestsGet/core.ts new file mode 100644 index 00000000000..14bc07f3a79 --- /dev/null +++ b/packages/components/nodes/tools/RequestsGet/core.ts @@ -0,0 +1,46 @@ +import fetch from 'node-fetch' +import { Tool } from 'langchain/tools' + +export const desc = `A portal to the internet. Use this when you need to get specific content from a website. +Input should be a url (i.e. https://www.google.com). The output will be the text response of the GET request.` + +export interface Headers { + [key: string]: string +} + +export interface RequestParameters { + headers?: Headers + url?: string + description?: string + maxOutputLength?: number +} + +export class RequestsGetTool extends Tool { + name = 'requests_get' + url = '' + description = desc + maxOutputLength = 2000 + headers = {} + + constructor(args?: RequestParameters) { + super() + this.url = args?.url ?? this.url + this.headers = args?.headers ?? this.headers + this.description = args?.description ?? this.description + this.maxOutputLength = args?.maxOutputLength ?? this.maxOutputLength + } + + /** @ignore */ + async _call(input: string) { + const inputUrl = !this.url ? input : this.url + + if (process.env.DEBUG === 'true') console.info(`Making GET API call to ${inputUrl}`) + + const res = await fetch(inputUrl, { + headers: this.headers + }) + + const text = await res.text() + return text.slice(0, this.maxOutputLength) + } +} diff --git a/packages/components/nodes/tools/RequestsPost/RequestsPost.ts b/packages/components/nodes/tools/RequestsPost/RequestsPost.ts index f0535c97ed1..0e64556fa33 100644 --- a/packages/components/nodes/tools/RequestsPost/RequestsPost.ts +++ b/packages/components/nodes/tools/RequestsPost/RequestsPost.ts @@ -1,6 +1,6 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses } from '../../../src/utils' -import { RequestsPostTool } from 'langchain/tools' +import { RequestParameters, desc, RequestsPostTool } from './core' class RequestsPost_Tools implements INode { label: string @@ -22,9 +22,31 @@ class RequestsPost_Tools implements INode { this.baseClasses = [this.type, ...getBaseClasses(RequestsPostTool)] this.inputs = [ { - label: 'Max Output Length', - name: 'maxOutputLength', - type: 'number', + label: 'URL', + name: 'url', + type: 'string', + description: + 'Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided', + additionalParams: true, + optional: true + }, + { + label: 'Body', + name: 'body', + type: 'json', + description: + 'JSON body for the POST request. If not specified, agent will try to figure out itself from AIPlugin if provided', + additionalParams: true, + optional: true + }, + { + label: 'Description', + name: 'description', + type: 'string', + rows: 4, + default: desc, + description: 'Acts like a prompt to tell agent when it should use this tool', + additionalParams: true, optional: true }, { @@ -39,18 +61,23 @@ class RequestsPost_Tools implements INode { async init(nodeData: INodeData): Promise { const headers = nodeData.inputs?.headers as string - const maxOutputLength = nodeData.inputs?.maxOutputLength as string - - const obj: any = {} - if (maxOutputLength) { - obj.maxOutputLength = parseInt(maxOutputLength, 10) - } + const url = nodeData.inputs?.url as string + const description = nodeData.inputs?.description as string + const body = nodeData.inputs?.body as string + const obj: RequestParameters = {} + if (url) obj.url = url + if (description) obj.description = description if (headers) { const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(headers) - return Object.keys(obj).length ? new RequestsPostTool(parsedHeaders, obj) : new RequestsPostTool(parsedHeaders) + obj.headers = parsedHeaders + } + if (body) { + const parsedBody = typeof body === 'object' ? body : JSON.parse(body) + obj.body = parsedBody } - return Object.keys(obj).length ? new RequestsPostTool(undefined, obj) : new RequestsPostTool() + + return new RequestsPostTool(obj) } } diff --git a/packages/components/nodes/tools/RequestsPost/core.ts b/packages/components/nodes/tools/RequestsPost/core.ts new file mode 100644 index 00000000000..403ba42b032 --- /dev/null +++ b/packages/components/nodes/tools/RequestsPost/core.ts @@ -0,0 +1,72 @@ +import { Tool } from 'langchain/tools' +import fetch from 'node-fetch' + +export const desc = `Use this when you want to POST to a website. +Input should be a json string with two keys: "url" and "data". +The value of "url" should be a string, and the value of "data" should be a dictionary of +key-value pairs you want to POST to the url as a JSON body. +Be careful to always use double quotes for strings in the json string +The output will be the text response of the POST request.` + +export interface Headers { + [key: string]: string +} + +export interface Body { + [key: string]: any +} + +export interface RequestParameters { + headers?: Headers + body?: Body + url?: string + description?: string + maxOutputLength?: number +} + +export class RequestsPostTool extends Tool { + name = 'requests_post' + url = '' + description = desc + maxOutputLength = Infinity + headers = {} + body = {} + + constructor(args?: RequestParameters) { + super() + this.url = args?.url ?? this.url + this.headers = args?.headers ?? this.headers + this.body = args?.body ?? this.body + this.description = args?.description ?? this.description + this.maxOutputLength = args?.maxOutputLength ?? this.maxOutputLength + } + + /** @ignore */ + async _call(input: string) { + try { + let inputUrl = '' + let inputBody = {} + if (Object.keys(this.body).length || this.url) { + if (this.url) inputUrl = this.url + if (Object.keys(this.body).length) inputBody = this.body + } else { + const { url, data } = JSON.parse(input) + inputUrl = url + inputBody = data + } + + if (process.env.DEBUG === 'true') console.info(`Making POST API call to ${inputUrl} with body ${JSON.stringify(inputBody)}`) + + const res = await fetch(inputUrl, { + method: 'POST', + headers: this.headers, + body: JSON.stringify(inputBody) + }) + + const text = await res.text() + return text.slice(0, this.maxOutputLength) + } catch (error) { + return `${error}` + } + } +} diff --git a/packages/components/package.json b/packages/components/package.json index b51f8534659..9c77db8e3bc 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -33,13 +33,14 @@ "linkifyjs": "^4.1.1", "mammoth": "^1.5.1", "moment": "^2.29.3", - "node-fetch": "2", + "node-fetch": "^2.6.11", "pdf-parse": "^1.1.1", "weaviate-ts-client": "^1.1.0", "ws": "^8.9.0" }, "devDependencies": { "@types/gulp": "4.0.9", + "@types/node-fetch": "2.6.2", "@types/ws": "^8.5.3", "gulp": "^4.0.2", "typescript": "^4.8.4" diff --git a/packages/server/marketplaces/ChatGPTPlugin.json b/packages/server/marketplaces/ChatGPTPlugin.json index 5c4296c75e6..4eec2ccc12e 100644 --- a/packages/server/marketplaces/ChatGPTPlugin.json +++ b/packages/server/marketplaces/ChatGPTPlugin.json @@ -3,78 +3,109 @@ "nodes": [ { "width": 300, - "height": 143, - "id": "requestsPost_1", + "height": 278, + "id": "aiPlugin_0", "position": { - "x": 568.1004839170901, - "y": 232.90925136881856 + "x": 1086.2925487205378, + "y": 84.92168014974317 }, "type": "customNode", "data": { - "id": "requestsPost_1", - "label": "Requests Post", - "name": "requestsPost", - "type": "RequestsPost", - "baseClasses": ["RequestsPost", "Tool", "StructuredTool", "BaseLangChain"], + "id": "aiPlugin_0", + "label": "AI Plugin", + "name": "aiPlugin", + "type": "AIPlugin", + "baseClasses": ["AIPlugin", "Tool"], "category": "Tools", - "description": "Execute HTTP POST requests", - "inputParams": [], + "description": "Execute actions using ChatGPT Plugin Url", + "inputParams": [ + { + "label": "Plugin Url", + "name": "pluginUrl", + "type": "string", + "placeholder": "https://www.klarna.com/.well-known/ai-plugin.json" + } + ], "inputAnchors": [], - "inputs": {}, + "inputs": { + "pluginUrl": "https://www.klarna.com/.well-known/ai-plugin.json" + }, "outputAnchors": [ { - "id": "requestsPost_1-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain", - "name": "requestsPost", - "label": "RequestsPost", - "type": "RequestsPost | Tool | StructuredTool | BaseLangChain" + "id": "aiPlugin_0-output-aiPlugin-AIPlugin|Tool", + "name": "aiPlugin", + "label": "AIPlugin", + "type": "AIPlugin | Tool" } ], - "outputs": {}, "selected": false }, "selected": false, "positionAbsolute": { - "x": 568.1004839170901, - "y": 232.90925136881856 + "x": 1086.2925487205378, + "y": 84.92168014974317 }, "dragging": false }, { "width": 300, - "height": 278, - "id": "aiPlugin_1", + "height": 251, + "id": "requestsGet_0", "position": { - "x": 1112.7719277555257, - "y": 111.01026928924571 + "x": 761.713884489628, + "y": 170.84830553778124 }, "type": "customNode", "data": { - "id": "aiPlugin_1", - "label": "AI Plugin", - "name": "aiPlugin", - "type": "AIPlugin", - "baseClasses": ["AIPlugin", "Tool", "StructuredTool", "BaseLangChain"], + "id": "requestsGet_0", + "label": "Requests Get", + "name": "requestsGet", + "type": "RequestsGet", + "baseClasses": ["RequestsGet", "Tool", "StructuredTool", "BaseLangChain"], "category": "Tools", - "description": "Execute actions using ChatGPT Plugin Url", + "description": "Execute HTTP GET requests", "inputParams": [ { - "label": "Plugin Url", - "name": "pluginUrl", + "label": "URL", + "name": "url", "type": "string", - "placeholder": "https://www.klarna.com/.well-known/ai-plugin.json", - "id": "aiPlugin_1-input-pluginUrl-string" + "description": "Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided", + "additionalParams": true, + "optional": true, + "id": "requestsGet_0-input-url-string" + }, + { + "label": "Description", + "name": "description", + "type": "string", + "rows": 4, + "default": "A portal to the internet. Use this when you need to get specific content from a website. \nInput should be a url (i.e. https://www.google.com). The output will be the text response of the GET request.", + "description": "Acts like a prompt to tell agent when it should use this tool", + "additionalParams": true, + "optional": true, + "id": "requestsGet_0-input-description-string" + }, + { + "label": "Headers", + "name": "headers", + "type": "json", + "additionalParams": true, + "optional": true, + "id": "requestsGet_0-input-headers-json" } ], "inputAnchors": [], "inputs": { - "pluginUrl": "https://www.klarna.com/.well-known/ai-plugin.json" + "url": "", + "description": "A portal to the internet. Use this when you need to get specific content from a website. \nInput should be a url (i.e. https://www.google.com). The output will be the text response of the GET request.", + "headers": "" }, "outputAnchors": [ { - "id": "aiPlugin_1-output-aiPlugin-AIPlugin|Tool|StructuredTool|BaseLangChain", - "name": "aiPlugin", - "label": "AIPlugin", - "type": "AIPlugin | Tool | StructuredTool | BaseLangChain" + "id": "requestsGet_0-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain", + "name": "requestsGet", + "label": "RequestsGet", + "type": "RequestsGet | Tool | StructuredTool | BaseLangChain" } ], "outputs": {}, @@ -82,37 +113,80 @@ }, "selected": false, "positionAbsolute": { - "x": 1112.7719277555257, - "y": 111.01026928924571 + "x": 761.713884489628, + "y": 170.84830553778124 }, "dragging": false }, { "width": 300, - "height": 143, - "id": "requestsGet_1", + "height": 251, + "id": "requestsPost_0", "position": { - "x": 539.1692455622626, - "y": 432.7978072748991 + "x": 436.4125209312256, + "y": 306.87715502984184 }, "type": "customNode", "data": { - "id": "requestsGet_1", - "label": "Requests Get", - "name": "requestsGet", - "type": "RequestsGet", - "baseClasses": ["RequestsGet", "Tool", "StructuredTool", "BaseLangChain"], + "id": "requestsPost_0", + "label": "Requests Post", + "name": "requestsPost", + "type": "RequestsPost", + "baseClasses": ["RequestsPost", "Tool", "StructuredTool", "BaseLangChain"], "category": "Tools", - "description": "Execute HTTP GET requests", - "inputParams": [], + "description": "Execute HTTP POST requests", + "inputParams": [ + { + "label": "URL", + "name": "url", + "type": "string", + "description": "Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided", + "additionalParams": true, + "optional": true, + "id": "requestsPost_0-input-url-string" + }, + { + "label": "Body", + "name": "body", + "type": "json", + "description": "JSON body for the POST request. If not specified, agent will try to figure out itself from AIPlugin if provided", + "additionalParams": true, + "optional": true, + "id": "requestsPost_0-input-body-json" + }, + { + "label": "Description", + "name": "description", + "type": "string", + "rows": 4, + "default": "Use this when you want to POST to a website.\nInput should be a json string with two keys: \"url\" and \"data\".\nThe value of \"url\" should be a string, and the value of \"data\" should be a dictionary of \nkey-value pairs you want to POST to the url as a JSON body.\nBe careful to always use double quotes for strings in the json string\nThe output will be the text response of the POST request.", + "description": "Acts like a prompt to tell agent when it should use this tool", + "additionalParams": true, + "optional": true, + "id": "requestsPost_0-input-description-string" + }, + { + "label": "Headers", + "name": "headers", + "type": "json", + "additionalParams": true, + "optional": true, + "id": "requestsPost_0-input-headers-json" + } + ], "inputAnchors": [], - "inputs": {}, + "inputs": { + "url": "", + "body": "", + "description": "Use this when you want to POST to a website.\nInput should be a json string with two keys: \"url\" and \"data\".\nThe value of \"url\" should be a string, and the value of \"data\" should be a dictionary of \nkey-value pairs you want to POST to the url as a JSON body.\nBe careful to always use double quotes for strings in the json string\nThe output will be the text response of the POST request.", + "headers": "" + }, "outputAnchors": [ { - "id": "requestsGet_1-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain", - "name": "requestsGet", - "label": "RequestsGet", - "type": "RequestsGet | Tool | StructuredTool | BaseLangChain" + "id": "requestsPost_0-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain", + "name": "requestsPost", + "label": "RequestsPost", + "type": "RequestsPost | Tool | StructuredTool | BaseLangChain" } ], "outputs": {}, @@ -120,22 +194,77 @@ }, "selected": false, "positionAbsolute": { - "x": 539.1692455622626, - "y": 432.7978072748991 + "x": 436.4125209312256, + "y": 306.87715502984184 + }, + "dragging": false + }, + { + "width": 300, + "height": 280, + "id": "mrklAgentChat_0", + "position": { + "x": 1416.2054860029416, + "y": 451.43299014109715 + }, + "type": "customNode", + "data": { + "id": "mrklAgentChat_0", + "label": "MRKL Agent for Chat Models", + "name": "mrklAgentChat", + "type": "AgentExecutor", + "baseClasses": ["AgentExecutor", "BaseChain", "BaseLangChain"], + "category": "Agents", + "description": "Agent that uses the ReAct Framework to decide what action to take, optimized to be used with Chat Models", + "inputParams": [], + "inputAnchors": [ + { + "label": "Allowed Tools", + "name": "tools", + "type": "Tool", + "list": true, + "id": "mrklAgentChat_0-input-tools-Tool" + }, + { + "label": "Language Model", + "name": "model", + "type": "BaseLanguageModel", + "id": "mrklAgentChat_0-input-model-BaseLanguageModel" + } + ], + "inputs": { + "tools": ["{{requestsGet_0.data.instance}}", "{{requestsPost_0.data.instance}}", "{{aiPlugin_0.data.instance}}"], + "model": "{{chatOpenAI_0.data.instance}}" + }, + "outputAnchors": [ + { + "id": "mrklAgentChat_0-output-mrklAgentChat-AgentExecutor|BaseChain|BaseLangChain", + "name": "mrklAgentChat", + "label": "AgentExecutor", + "type": "AgentExecutor | BaseChain | BaseLangChain" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 1416.2054860029416, + "y": 451.43299014109715 }, "dragging": false }, { "width": 300, "height": 524, - "id": "chatOpenAI_1", + "id": "chatOpenAI_0", "position": { - "x": 800.6881372203391, - "y": 599.3478727476577 + "x": 797.0574814814245, + "y": 578.7641992971934 }, "type": "customNode", "data": { - "id": "chatOpenAI_1", + "id": "chatOpenAI_0", "label": "ChatOpenAI", "name": "chatOpenAI", "type": "ChatOpenAI", @@ -147,7 +276,7 @@ "label": "OpenAI Api Key", "name": "openAIApiKey", "type": "password", - "id": "chatOpenAI_1-input-openAIApiKey-password" + "id": "chatOpenAI_0-input-openAIApiKey-password" }, { "label": "Model Name", @@ -177,7 +306,7 @@ ], "default": "gpt-3.5-turbo", "optional": true, - "id": "chatOpenAI_1-input-modelName-options" + "id": "chatOpenAI_0-input-modelName-options" }, { "label": "Temperature", @@ -185,7 +314,7 @@ "type": "number", "default": 0.9, "optional": true, - "id": "chatOpenAI_1-input-temperature-number" + "id": "chatOpenAI_0-input-temperature-number" }, { "label": "Max Tokens", @@ -193,7 +322,7 @@ "type": "number", "optional": true, "additionalParams": true, - "id": "chatOpenAI_1-input-maxTokens-number" + "id": "chatOpenAI_0-input-maxTokens-number" }, { "label": "Top Probability", @@ -201,7 +330,7 @@ "type": "number", "optional": true, "additionalParams": true, - "id": "chatOpenAI_1-input-topP-number" + "id": "chatOpenAI_0-input-topP-number" }, { "label": "Frequency Penalty", @@ -209,7 +338,7 @@ "type": "number", "optional": true, "additionalParams": true, - "id": "chatOpenAI_1-input-frequencyPenalty-number" + "id": "chatOpenAI_0-input-frequencyPenalty-number" }, { "label": "Presence Penalty", @@ -217,7 +346,7 @@ "type": "number", "optional": true, "additionalParams": true, - "id": "chatOpenAI_1-input-presencePenalty-number" + "id": "chatOpenAI_0-input-presencePenalty-number" }, { "label": "Timeout", @@ -225,13 +354,13 @@ "type": "number", "optional": true, "additionalParams": true, - "id": "chatOpenAI_1-input-timeout-number" + "id": "chatOpenAI_0-input-timeout-number" } ], "inputAnchors": [], "inputs": { "modelName": "gpt-3.5-turbo", - "temperature": "0", + "temperature": 0.9, "maxTokens": "", "topP": "", "frequencyPenalty": "", @@ -240,7 +369,7 @@ }, "outputAnchors": [ { - "id": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|BaseLangChain", + "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|BaseLangChain", "name": "chatOpenAI", "label": "ChatOpenAI", "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | BaseLangChain" @@ -251,108 +380,53 @@ }, "selected": false, "positionAbsolute": { - "x": 800.6881372203391, - "y": 599.3478727476577 - }, - "dragging": false - }, - { - "width": 300, - "height": 280, - "id": "mrklAgentChat_2", - "position": { - "x": 1503.5956978371041, - "y": 418.46259909490925 + "x": 797.0574814814245, + "y": 578.7641992971934 }, - "type": "customNode", - "data": { - "id": "mrklAgentChat_2", - "label": "MRKL Agent for Chat Models", - "name": "mrklAgentChat", - "type": "AgentExecutor", - "baseClasses": ["AgentExecutor", "BaseChain", "BaseLangChain"], - "category": "Agents", - "description": "Agent that uses the ReAct Framework to decide what action to take, optimized to be used with Chat Models", - "inputParams": [], - "inputAnchors": [ - { - "label": "Allowed Tools", - "name": "tools", - "type": "Tool", - "list": true, - "id": "mrklAgentChat_2-input-tools-Tool" - }, - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "mrklAgentChat_2-input-model-BaseLanguageModel" - } - ], - "inputs": { - "tools": ["{{requestsGet_1.data.instance}}", "{{requestsPost_1.data.instance}}", "{{aiPlugin_1.data.instance}}"], - "model": "{{chatOpenAI_1.data.instance}}" - }, - "outputAnchors": [ - { - "id": "mrklAgentChat_2-output-mrklAgentChat-AgentExecutor|BaseChain|BaseLangChain", - "name": "mrklAgentChat", - "label": "AgentExecutor", - "type": "AgentExecutor | BaseChain | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "positionAbsolute": { - "x": 1503.5956978371041, - "y": 418.46259909490925 - }, - "selected": false, "dragging": false } ], "edges": [ { - "source": "aiPlugin_1", - "sourceHandle": "aiPlugin_1-output-aiPlugin-AIPlugin|Tool|StructuredTool|BaseLangChain", - "target": "mrklAgentChat_2", - "targetHandle": "mrklAgentChat_2-input-tools-Tool", + "source": "requestsGet_0", + "sourceHandle": "requestsGet_0-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain", + "target": "mrklAgentChat_0", + "targetHandle": "mrklAgentChat_0-input-tools-Tool", "type": "buttonedge", - "id": "aiPlugin_1-aiPlugin_1-output-aiPlugin-AIPlugin|Tool|StructuredTool|BaseLangChain-mrklAgentChat_2-mrklAgentChat_2-input-tools-Tool", + "id": "requestsGet_0-requestsGet_0-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool", "data": { "label": "" } }, { - "source": "requestsPost_1", - "sourceHandle": "requestsPost_1-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain", - "target": "mrklAgentChat_2", - "targetHandle": "mrklAgentChat_2-input-tools-Tool", + "source": "aiPlugin_0", + "sourceHandle": "aiPlugin_0-output-aiPlugin-AIPlugin|Tool", + "target": "mrklAgentChat_0", + "targetHandle": "mrklAgentChat_0-input-tools-Tool", "type": "buttonedge", - "id": "requestsPost_1-requestsPost_1-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain-mrklAgentChat_2-mrklAgentChat_2-input-tools-Tool", + "id": "aiPlugin_0-aiPlugin_0-output-aiPlugin-AIPlugin|Tool-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool", "data": { "label": "" } }, { - "source": "requestsGet_1", - "sourceHandle": "requestsGet_1-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain", - "target": "mrklAgentChat_2", - "targetHandle": "mrklAgentChat_2-input-tools-Tool", + "source": "requestsPost_0", + "sourceHandle": "requestsPost_0-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain", + "target": "mrklAgentChat_0", + "targetHandle": "mrklAgentChat_0-input-tools-Tool", "type": "buttonedge", - "id": "requestsGet_1-requestsGet_1-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain-mrklAgentChat_2-mrklAgentChat_2-input-tools-Tool", + "id": "requestsPost_0-requestsPost_0-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool", "data": { "label": "" } }, { - "source": "chatOpenAI_1", - "sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|BaseLangChain", - "target": "mrklAgentChat_2", - "targetHandle": "mrklAgentChat_2-input-model-BaseLanguageModel", + "source": "chatOpenAI_0", + "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|BaseLangChain", + "target": "mrklAgentChat_0", + "targetHandle": "mrklAgentChat_0-input-model-BaseLanguageModel", "type": "buttonedge", - "id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|BaseLangChain-mrklAgentChat_2-mrklAgentChat_2-input-model-BaseLanguageModel", + "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|BaseLangChain-mrklAgentChat_0-mrklAgentChat_0-input-model-BaseLanguageModel", "data": { "label": "" } diff --git a/packages/ui/src/ui-component/tooltip/TooltipWithParser.js b/packages/ui/src/ui-component/tooltip/TooltipWithParser.js index a470837793c..7362b55c088 100644 --- a/packages/ui/src/ui-component/tooltip/TooltipWithParser.js +++ b/packages/ui/src/ui-component/tooltip/TooltipWithParser.js @@ -4,18 +4,27 @@ import parser from 'html-react-parser' import PropTypes from 'prop-types' import { useSelector } from 'react-redux' -export const TooltipWithParser = ({ title }) => { +export const TooltipWithParser = ({ title, style }) => { const customization = useSelector((state) => state.customization) return ( - - + + ) } TooltipWithParser.propTypes = { - title: PropTypes.node + title: PropTypes.node, + style: PropTypes.any } diff --git a/packages/ui/src/views/canvas/CanvasNode.js b/packages/ui/src/views/canvas/CanvasNode.js index c59b288d3d0..9263d4b6acc 100644 --- a/packages/ui/src/views/canvas/CanvasNode.js +++ b/packages/ui/src/views/canvas/CanvasNode.js @@ -134,7 +134,16 @@ const CanvasNode = ({ data }) => { ))} {data.inputParams.find((param) => param.additionalParams) && ( -
+
param.additionalParams).length === + data.inputParams.length + data.inputAnchors.length + ? 20 + : 0 + }} + > diff --git a/packages/ui/src/views/canvas/NodeInputHandler.js b/packages/ui/src/views/canvas/NodeInputHandler.js index 99b0aed40e1..1dc656e8f05 100644 --- a/packages/ui/src/views/canvas/NodeInputHandler.js +++ b/packages/ui/src/views/canvas/NodeInputHandler.js @@ -17,6 +17,7 @@ import { SwitchInput } from 'ui-component/switch/Switch' import { flowContext } from 'store/context/ReactFlowContext' import { isValidConnection, getAvailableNodesForVariable } from 'utils/genericHelper' import { JsonEditorInput } from 'ui-component/json/JsonEditor' +import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser' const CustomWidthTooltip = styled(({ className, ...props }) => )({ [`& .${tooltipClasses.tooltip}`]: { @@ -123,6 +124,7 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA {inputParam.label} {!inputParam.optional &&  *} + {inputParam.description && }
{inputParam.type === 'string' && inputParam.rows && (