From e67e55d94e66909a30f7748aaa77f97728609658 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 22 Jun 2023 15:12:38 -0300 Subject: [PATCH 001/367] feat(API): add UpdateTemplate function to update templates via API call --- src/frontend/src/controllers/API/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 40b132261..f19dbd5d8 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -3,6 +3,8 @@ import { PromptTypeAPI, errorsTypeAPI, InitTypeAPI, + TemplateVariableType, + APITemplateType, } from "./../../types/api/index"; import { APIObjectType, sendAllProps } from "../../types/api/index"; import axios, { AxiosResponse } from "axios"; @@ -319,3 +321,7 @@ export async function postBuildInit( ): Promise> { return await axios.post(`/api/v1/build/init`, flow); } + +export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ + return await axios.post(`/api/v1/UpdateTemplate`); +} \ No newline at end of file From ec517fd9b64307e96d1eee0d59902ad5a6846a01 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:00:02 +0100 Subject: [PATCH 002/367] Endpoint dynamic_node template to test --- src/backend/langflow/main.py | 226 +++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index ad3217eb5..53749d9c8 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -4,6 +4,228 @@ from fastapi.middleware.cors import CORSMiddleware from langflow.api import router from langflow.database.base import create_db_and_tables +template_node = { + "template": { + "lc_kwargs": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "lc_kwargs", + "advanced": "true", + "type": "code", + "list": "false" + }, + "verbose": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": "false", + "password": "false", + "name": "verbose", + "advanced": "false", + "type": "bool", + "list": "false" + }, + "callbacks": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "callbacks", + "advanced": "false", + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": "true" + }, + "tags": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "tags", + "advanced": "false", + "type": "str", + "list": "true" + }, + "client": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "client", + "advanced": "false", + "type": "Any", + "list": "false" + }, + "model_name": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "value": "gpt-3.5-turbo", + "password": "false", + "options": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "name": "model_name", + "advanced": "false", + "type": "str", + "list": "true" + }, + "temperature": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "value": 0.7, + "password": "false", + "name": "temperature", + "advanced": "false", + "type": "float", + "list": "false" + }, + "model_kwargs": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "password": "false", + "name": "model_kwargs", + "advanced": "true", + "type": "code", + "list": "false" + }, + "openai_api_key": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "value": "", + "password": "true", + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": "false", + "type": "str", + "list": "false" + }, + "openai_api_base": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "password": "false", + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": "false", + "type": "str", + "list": "false" + }, + "openai_organization": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": "false", + "type": "str", + "list": "false" + }, + "openai_proxy": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": "false", + "type": "str", + "list": "false" + }, + "request_timeout": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "request_timeout", + "advanced": "false", + "type": "float", + "list": "false" + }, + "max_retries": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": 6, + "password": "false", + "name": "max_retries", + "advanced": "false", + "type": "int", + "list": "false" + }, + "streaming": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": "false", + "password": "false", + "name": "streaming", + "advanced": "false", + "type": "bool", + "list": "false" + }, + "n": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": 1, + "password": "false", + "name": "n", + "advanced": "false", + "type": "int", + "list": "false" + }, + "max_tokens": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "password": "true", + "name": "max_tokens", + "advanced": "false", + "type": "int", + "list": "false" + }, + "_type": "ChatOpenAI" + }, + "description": "Wrapper around OpenAI Chat large language models.", + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "display_name": "ChatOpenAI" +} + def create_app(): """Create the FastAPI app and include the router.""" @@ -18,6 +240,10 @@ def create_app(): def get_health(): return {"status": "OK"} + @app.get("/dynamic_node") + def get_dynamic_nome(): + return template_node + app.add_middleware( CORSMiddleware, allow_origins=origins, From 2c256421f45e9c66067c0e727b89872b78ff68f9 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:16:10 +0100 Subject: [PATCH 003/367] Remove description --- src/backend/langflow/main.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 53749d9c8..d93d0efab 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -215,15 +215,7 @@ template_node = { "list": "false" }, "_type": "ChatOpenAI" - }, - "description": "Wrapper around OpenAI Chat large language models.", - "base_classes": [ - "BaseChatModel", - "Serializable", - "BaseLanguageModel", - "ChatOpenAI" - ], - "display_name": "ChatOpenAI" + } } From a458b2d91c04b2c8e18ecd6f5e301446b6f9f3e5 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:26:25 +0100 Subject: [PATCH 004/367] Change type str to bool --- src/backend/langflow/main.py | 208 +++++++++++++++++------------------ 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index d93d0efab..713c921cd 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -7,68 +7,68 @@ from langflow.database.base import create_db_and_tables template_node = { "template": { "lc_kwargs": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "lc_kwargs", - "advanced": "true", + "advanced": True, "type": "code", - "list": "false" + "list": False }, "verbose": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "value": "false", - "password": "false", + "show": False, + "multiline": False, + "value": False, + "password": False, "name": "verbose", - "advanced": "false", + "advanced": False, "type": "bool", - "list": "false" + "list": False }, "callbacks": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "callbacks", - "advanced": "false", + "advanced": False, "type": "langchain.callbacks.base.BaseCallbackHandler", - "list": "true" + "list": True }, "tags": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "tags", - "advanced": "false", + "advanced": False, "type": "str", - "list": "true" + "list": True }, "client": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "client", - "advanced": "false", + "advanced": False, "type": "Any", - "list": "false" + "list": False }, "model_name": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", + "show": True, + "multiline": False, "value": "gpt-3.5-turbo", - "password": "false", + "password": False, "options": [ "gpt-3.5-turbo-0613", "gpt-3.5-turbo", @@ -80,139 +80,139 @@ template_node = { "gpt-4-32k" ], "name": "model_name", - "advanced": "false", + "advanced": False, "type": "str", - "list": "true" + "list": True }, "temperature": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", + "show": True, + "multiline": False, "value": 0.7, - "password": "false", + "password": False, "name": "temperature", - "advanced": "false", + "advanced": False, "type": "float", - "list": "false" + "list": False }, "model_kwargs": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", - "password": "false", + "show": True, + "multiline": False, + "password": False, "name": "model_kwargs", - "advanced": "true", + "advanced": True, "type": "code", - "list": "false" + "list": False }, "openai_api_key": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", + "show": True, + "multiline": False, "value": "", - "password": "true", + "password": True, "name": "openai_api_key", "display_name": "OpenAI API Key", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "openai_api_base": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", - "password": "false", + "show": True, + "multiline": False, + "password": False, "name": "openai_api_base", "display_name": "OpenAI API Base", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "openai_organization": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "openai_organization", "display_name": "OpenAI Organization", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "openai_proxy": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "openai_proxy", "display_name": "OpenAI Proxy", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "request_timeout": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "request_timeout", - "advanced": "false", + "advanced": False, "type": "float", - "list": "false" + "list": False }, "max_retries": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", + "show": False, + "multiline": False, "value": 6, - "password": "false", + "password": False, "name": "max_retries", - "advanced": "false", + "advanced": False, "type": "int", - "list": "false" + "list": False }, "streaming": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "value": "false", - "password": "false", + "show": False, + "multiline": False, + "value": False, + "password": False, "name": "streaming", - "advanced": "false", + "advanced": False, "type": "bool", - "list": "false" + "list": False }, "n": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", + "show": False, + "multiline": False, "value": 1, - "password": "false", + "password": False, "name": "n", - "advanced": "false", + "advanced": False, "type": "int", - "list": "false" + "list": False }, "max_tokens": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", - "password": "true", + "show": True, + "multiline": False, + "password": True, "name": "max_tokens", - "advanced": "false", + "advanced": False, "type": "int", - "list": "false" + "list": False }, "_type": "ChatOpenAI" } From a47dc9ae92d44a4018fcae432b4e30d1f7963f7c Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 22 Jun 2023 17:30:04 -0300 Subject: [PATCH 005/367] feat(frontend): add support for updating node template on code change in CodeAreaModal fix(API): fix UpdateTemplate function return type to match the actual response fix(vite.config.ts): add dynamic_node route to apiRoutes array to proxy requests to backend --- .../components/parameterComponent/index.tsx | 2 + .../src/CustomNodes/GenericNode/index.tsx | 2 +- .../components/codeAreaComponent/index.tsx | 10 +- src/frontend/src/controllers/API/index.ts | 4 +- .../src/modals/codeAreaModal/index.tsx | 102 +++++++++++------- src/frontend/src/types/components/index.ts | 10 ++ src/frontend/vite.config.ts | 2 +- 7 files changed, 86 insertions(+), 46 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 65f946ba2..c35fd869b 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -227,6 +227,8 @@ export default function ParameterComponent({ ) : left === true && type === "code" ? ( {data.node.template = template}} + template={data.node.template} disabled={disabled} value={data.node.template[name].value ?? ""} onChange={handleOnNewValue} diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index fb1ed5f59..e2ddc051f 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -62,7 +62,7 @@ export default function GenericNode({ } useEffect(() => {}, [closePopUp, data.node.template]); - + console.log({data}) return ( <> diff --git a/src/frontend/src/components/codeAreaComponent/index.tsx b/src/frontend/src/components/codeAreaComponent/index.tsx index 399ab40b2..a4b7231c8 100644 --- a/src/frontend/src/components/codeAreaComponent/index.tsx +++ b/src/frontend/src/components/codeAreaComponent/index.tsx @@ -3,7 +3,7 @@ import { useContext, useEffect, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; import CodeAreaModal from "../../modals/codeAreaModal"; import TextAreaModal from "../../modals/textAreaModal"; -import { TextAreaComponentType } from "../../types/components"; +import { CodeAreaComponentType, TextAreaComponentType } from "../../types/components"; import { INPUT_STYLE } from "../../constants"; export default function CodeAreaComponent({ @@ -11,7 +11,9 @@ export default function CodeAreaComponent({ onChange, disabled, editNode = false, -}: TextAreaComponentType) { + template, + setTemplate, +}: CodeAreaComponentType) { const [myValue, setMyValue] = useState(value); const { openPopUp } = useContext(PopUpContext); useEffect(() => { @@ -37,6 +39,8 @@ export default function CodeAreaComponent({ openPopUp( { setMyValue(t); onChange(t); @@ -59,7 +63,9 @@ export default function CodeAreaComponent({ onClick={() => { openPopUp( { setMyValue(t); onChange(t); diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index f19dbd5d8..60820bb7e 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -322,6 +322,6 @@ export async function postBuildInit( return await axios.post(`/api/v1/build/init`, flow); } -export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ - return await axios.post(`/api/v1/UpdateTemplate`); +export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ + return await axios.get(`/dynamic_node`); } \ No newline at end of file diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index 9f8815f4b..451946b0e 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -8,7 +8,7 @@ import "ace-builds/src-noconflict/theme-twilight"; import "ace-builds/src-noconflict/ext-language_tools"; // import "ace-builds/webpack-resolver"; import { darkContext } from "../../contexts/darkContext"; -import { postValidateCode } from "../../controllers/API"; +import { UpdateTemplate, postValidateCode } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; import { TabsContext } from "../../contexts/tabsContext"; import { @@ -22,16 +22,23 @@ import { } from "../../components/ui/dialog"; import { Button } from "../../components/ui/button"; import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants"; +import Loading from "../../components/ui/loading"; +import { APITemplateType } from "../../types/api"; export default function CodeAreaModal({ value, setValue, + template, + setTemplate }: { setValue: (value: string) => void; value: string; + template: APITemplateType, + setTemplate: (template: APITemplateType) => void; }) { const [open, setOpen] = useState(true); const [code, setCode] = useState(value); + const [loading, setLoading] = useState(false); const { dark } = useContext(darkContext); const { setErrorData, setSuccessData } = useContext(alertContext); const { closePopUp } = useContext(PopUpContext); @@ -44,6 +51,58 @@ export default function CodeAreaModal({ }, 300); } } + + function handleClick() { + setLoading(true); + postValidateCode(code) + .then((apiReturn) => { + setLoading(false); + if (apiReturn.data) { + let importsErrors = apiReturn.data.imports.errors; + let funcErrors = apiReturn.data.function.errors; + if (funcErrors.length === 0 && importsErrors.length === 0) { + setSuccessData({ + title: "Code is ready to run", + }); + // setValue(code); + } else { + if (funcErrors.length !== 0) { + setErrorData({ + title: "There is an error in your function", + list: funcErrors, + }); + } + if (importsErrors.length !== 0) { + setErrorData({ + title: "There is an error in your imports", + list: importsErrors, + }); + } + } + } else { + setErrorData({ + title: "Something went wrong, please try again", + }); + } + }) + .catch((_) => { + setLoading(false); + setErrorData({ + title: + "There is something wrong with this code, please review it", + }) + } + ); + UpdateTemplate('code',template).then((apiReturn) => { + const data = apiReturn.data; + if (data.template) { + console.log('updated') + setTemplate(data.template); + setModalOpen(false); + } + }) + } + return ( @@ -80,47 +139,10 @@ export default function CodeAreaModal({ diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 11f8aec07..5b31d63f1 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -1,6 +1,7 @@ import { ForwardRefExoticComponent, ReactElement, ReactNode } from "react"; import { NodeDataType } from "../flow/index"; import { typesContextType } from "../typesContext"; +import { APITemplateType } from "../api"; export type InputComponentType = { value: string; disabled?: boolean; @@ -50,6 +51,15 @@ export type TextAreaComponentType = { editNode?: boolean; }; +export type CodeAreaComponentType = { + disabled: boolean; + onChange: (value: string[] | string) => void; + value: string; + editNode?: boolean; + template: APITemplateType; + setTemplate: (value: APITemplateType) => void; +}; + export type FileComponentType = { disabled: boolean; onChange: (value: string[] | string) => void; diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index 860c690ea..176c73aea 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import svgr from "vite-plugin-svgr"; -const apiRoutes = ["^/api/v1/", "/health"]; +const apiRoutes = ["^/api/v1/", "/health","/dynamic_node"]; // Use environment variable to determine the target. const target = process.env.VITE_PROXY_TARGET || "http://127.0.0.1:7860"; From 6736288e6f5542552df58d1953a0afb0bc2a2e5b Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:37:01 +0100 Subject: [PATCH 006/367] Add code section --- src/backend/langflow/main.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 713c921cd..caa70a79b 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -6,6 +6,18 @@ from langflow.database.base import create_db_and_tables template_node = { "template": { + "code": { + "required": True, + "placeholder": "", + "show": True, + "multiline": True, + "value": "\ndef my_user_python_function(text: str) -> str:\n \"\"\"This is a default python function that returns the input text\"\"\"\n return text.upper()\n", + "password": False, + "name": "code", + "advanced": False, + "type": "code", + "list": False + }, "lc_kwargs": { "required": False, "placeholder": "", From 531b3b3f7abdcebaca181384b8794395ef602861 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:49:22 +0100 Subject: [PATCH 007/367] Base classes data added --- src/backend/langflow/main.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index caa70a79b..801abbe3a 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -226,6 +226,13 @@ template_node = { "type": "int", "list": False }, + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "description": "Wrapper around OpenAI Chat large language models.", "_type": "ChatOpenAI" } } From 37e1ea05b428f82d7c8dcb760d39f43cab8b0b9e Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 22:15:59 +0100 Subject: [PATCH 008/367] Base classes data moved --- src/backend/langflow/main.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 801abbe3a..7f5644d69 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -226,15 +226,15 @@ template_node = { "type": "int", "list": False }, - "base_classes": [ - "BaseChatModel", - "Serializable", - "BaseLanguageModel", - "ChatOpenAI" - ], - "description": "Wrapper around OpenAI Chat large language models.", "_type": "ChatOpenAI" - } + }, + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "description": "Wrapper around OpenAI Chat large language models." } From 19be2e81780d70ff32dceb29596b68d0770b5eb9 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 22 Jun 2023 18:21:41 -0300 Subject: [PATCH 009/367] refactor(parameterComponent): change setTemplate to setNodeClass to improve semantics and fix bug refactor(codeAreaComponent): change template to nodeClass and setTemplate to setNodeClass to improve semantics refactor(API): change UpdateTemplate function parameter from template to nodeClass to improve semantics refactor(codeAreaModal): change template to nodeClass and setTemplate to setNodeClass to improve semantics and fix bug refactor(types): add APIClassType to import and change APITemplateType to import in relevant files to improve semantics --- .../components/parameterComponent/index.tsx | 4 ++-- .../src/components/codeAreaComponent/index.tsx | 12 ++++++------ src/frontend/src/controllers/API/index.ts | 3 ++- .../src/modals/codeAreaModal/index.tsx | 18 +++++++++--------- src/frontend/src/types/components/index.ts | 6 +++--- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index c35fd869b..915ab41ae 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -227,8 +227,8 @@ export default function ParameterComponent({ ) : left === true && type === "code" ? ( {data.node.template = template}} - template={data.node.template} + setNodeClass={(nodeClass)=>{data.node = nodeClass}} + nodeClass={data.node} disabled={disabled} value={data.node.template[name].value ?? ""} onChange={handleOnNewValue} diff --git a/src/frontend/src/components/codeAreaComponent/index.tsx b/src/frontend/src/components/codeAreaComponent/index.tsx index a4b7231c8..14e444ccc 100644 --- a/src/frontend/src/components/codeAreaComponent/index.tsx +++ b/src/frontend/src/components/codeAreaComponent/index.tsx @@ -11,8 +11,8 @@ export default function CodeAreaComponent({ onChange, disabled, editNode = false, - template, - setTemplate, + nodeClass, + setNodeClass, }: CodeAreaComponentType) { const [myValue, setMyValue] = useState(value); const { openPopUp } = useContext(PopUpContext); @@ -39,8 +39,8 @@ export default function CodeAreaComponent({ openPopUp( { setMyValue(t); onChange(t); @@ -63,9 +63,9 @@ export default function CodeAreaComponent({ onClick={() => { openPopUp( { setMyValue(t); onChange(t); diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 60820bb7e..c7a8ee776 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -5,6 +5,7 @@ import { InitTypeAPI, TemplateVariableType, APITemplateType, + APIClassType, } from "./../../types/api/index"; import { APIObjectType, sendAllProps } from "../../types/api/index"; import axios, { AxiosResponse } from "axios"; @@ -322,6 +323,6 @@ export async function postBuildInit( return await axios.post(`/api/v1/build/init`, flow); } -export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ +export async function UpdateTemplate(type:string, nodeClass:APIClassType):Promise>{ return await axios.get(`/dynamic_node`); } \ No newline at end of file diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index 451946b0e..6448702a7 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -23,18 +23,18 @@ import { import { Button } from "../../components/ui/button"; import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants"; import Loading from "../../components/ui/loading"; -import { APITemplateType } from "../../types/api"; +import { APIClassType, APITemplateType } from "../../types/api"; export default function CodeAreaModal({ value, setValue, - template, - setTemplate + nodeClass, + setNodeClass }: { setValue: (value: string) => void; value: string; - template: APITemplateType, - setTemplate: (template: APITemplateType) => void; + nodeClass: APIClassType, + setNodeClass: (Class: APIClassType) => void; }) { const [open, setOpen] = useState(true); const [code, setCode] = useState(value); @@ -93,11 +93,11 @@ export default function CodeAreaModal({ }) } ); - UpdateTemplate('code',template).then((apiReturn) => { + UpdateTemplate('code',nodeClass).then((apiReturn) => { const data = apiReturn.data; - if (data.template) { - console.log('updated') - setTemplate(data.template); + if (data) { + console.log(data) + setNodeClass(data); setModalOpen(false); } }) diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 5b31d63f1..845b853c8 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -1,7 +1,7 @@ import { ForwardRefExoticComponent, ReactElement, ReactNode } from "react"; import { NodeDataType } from "../flow/index"; import { typesContextType } from "../typesContext"; -import { APITemplateType } from "../api"; +import { APIClassType, APITemplateType } from "../api"; export type InputComponentType = { value: string; disabled?: boolean; @@ -56,8 +56,8 @@ export type CodeAreaComponentType = { onChange: (value: string[] | string) => void; value: string; editNode?: boolean; - template: APITemplateType; - setTemplate: (value: APITemplateType) => void; + nodeClass: APIClassType; + setNodeClass: (value: APIClassType) => void; }; export type FileComponentType = { From cf7cd979dc9ccb6dd9d00448bb3424568fed33c4 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Fri, 23 Jun 2023 02:54:43 +0100 Subject: [PATCH 010/367] feat: Add ClassCodeExtractor and is_valid_class_template functions, and custom_component endpoint This commit adds a new file called `extract_info_from_class.py` containing a `ClassCodeExtractor` class that can extract information (imports, class details and functions) from a Python class code. It also adds a function called `is_valid_class_template` that checks if a given Python class code matches a certain template. Additionally, the commit adds a new endpoint in the `/custom_component` route of `endpoints.py` that returns a dictionary of all `langchain` types created by a specific creator. Finally, the commit adds a new section to `types.py` named `template_node`, which describes a default dictionary that can be used to define a new node for Langflow's template editor. --- .../langflow/api/extract_info_from_class.py | 70 ++++++ src/backend/langflow/api/v1/endpoints.py | 12 +- src/backend/langflow/api/v1/schemas.py | 8 +- src/backend/langflow/interface/types.py | 25 ++ src/backend/langflow/main.py | 237 ++++++++++++++++++ 5 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 src/backend/langflow/api/extract_info_from_class.py diff --git a/src/backend/langflow/api/extract_info_from_class.py b/src/backend/langflow/api/extract_info_from_class.py new file mode 100644 index 000000000..4dfb24e03 --- /dev/null +++ b/src/backend/langflow/api/extract_info_from_class.py @@ -0,0 +1,70 @@ +import ast + + +class ClassCodeExtractor: + def __init__(self, code): + self.code = code + self.data = { + "imports": [], + "class": { + "inherited_classes": "", + "name": "", + "init": "" + }, + "functions": [] + } + + def _handle_import(self, node): + for alias in node.names: + module_name = getattr(node, 'module', None) + self.data['imports'].append( + f"{module_name}.{alias.name}" if module_name else alias.name) + + def _handle_class(self, node): + self.data['class'].update({ + 'name': node.name, + 'inherited_classes': [ast.unparse(base) for base in node.bases] + }) + + for inner_node in node.body: + if isinstance(inner_node, ast.FunctionDef): + self._handle_function(inner_node) + + def _handle_function(self, node): + function_name = node.name + function_args_str = ast.unparse(node.args) + function_args = function_args_str.split( + ", ") if function_args_str else [] + + return_type = ast.unparse(node.returns) if node.returns else "None" + + function_data = { + "name": function_name, + "arguments": function_args, + "return_type": return_type + } + + if function_name == "__init__": + self.data['class']['init'] = function_args_str.split( + ", ") if function_args_str else [] + else: + self.data["functions"].append(function_data) + + def extract_class_info(self): + module = ast.parse(self.code) + + for node in module.body: + if isinstance(node, (ast.Import, ast.ImportFrom)): + self._handle_import(node) + elif isinstance(node, ast.ClassDef): + self._handle_class(node) + + return self.data + + +def is_valid_class_template(code: dict) -> bool: + class_name_ok = code["class"]["name"] == "PythonFunction" + function_run_exists = len( + [f for f in code["functions"] if f["name"] == "run"]) == 1 + + return (class_name_ok and function_run_exists) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 6fea926d7..4d3ac9f5e 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -7,9 +7,13 @@ from fastapi import APIRouter, Depends, HTTPException from langflow.api.v1.schemas import ( PredictRequest, PredictResponse, + CustomComponentResponse, ) -from langflow.interface.types import build_langchain_types_dict +from langflow.interface.types import ( + build_langchain_types_dict, + build_langchain_types_dict_by_creator +) from langflow.database.base import get_session from sqlmodel import Session @@ -62,3 +66,9 @@ def get_version(): from langflow import __version__ return {"version": __version__} + + +# @router.post("/custom_component", response_model=CustomComponentResponse, status_code=200) +@router.post("/custom_component", status_code=200) +def custom_component(code: dict): + return build_langchain_types_dict_by_creator("a") diff --git a/src/backend/langflow/api/v1/schemas.py b/src/backend/langflow/api/v1/schemas.py index fc2e8c69d..145ac9365 100644 --- a/src/backend/langflow/api/v1/schemas.py +++ b/src/backend/langflow/api/v1/schemas.py @@ -69,7 +69,8 @@ class ChatResponse(ChatMessage): @validator("type") def validate_message_type(cls, v): if v not in ["start", "stream", "end", "error", "info", "file"]: - raise ValueError("type must be start, stream, end, error, info, or file") + raise ValueError( + "type must be start, stream, end, error, info, or file") return v @@ -110,3 +111,8 @@ class StreamData(BaseModel): def __str__(self) -> str: return f"event: {self.event}\ndata: {json.dumps(self.data)}\n\n" + + +class CustomComponentResponse(BaseModel): + model: str = "" + step: str = "" diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index 085537756..ac1b59e6f 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -52,3 +52,28 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union if created_types[creator.type_name].values(): all_types.update(created_types) return all_types + + +# sourcery skip: dict-assign-update-to-union +def build_langchain_types_dict_by_creator(creator: str): + """Build a dictionary of all langchain types""" + + all_types = {} + + creators = [ + chain_creator, + agent_creator, + prompt_creator, + llm_creator, + memory_creator, + tool_creator, + toolkits_creator, + wrapper_creator, + embedding_creator, + vectorstore_creator, + documentloader_creator, + textsplitter_creator, + utility_creator, + ] + + return chain_creator.to_dict()['chains']['ConversationChain'] diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index ad3217eb5..7f5644d69 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -4,6 +4,239 @@ from fastapi.middleware.cors import CORSMiddleware from langflow.api import router from langflow.database.base import create_db_and_tables +template_node = { + "template": { + "code": { + "required": True, + "placeholder": "", + "show": True, + "multiline": True, + "value": "\ndef my_user_python_function(text: str) -> str:\n \"\"\"This is a default python function that returns the input text\"\"\"\n return text.upper()\n", + "password": False, + "name": "code", + "advanced": False, + "type": "code", + "list": False + }, + "lc_kwargs": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "lc_kwargs", + "advanced": True, + "type": "code", + "list": False + }, + "verbose": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "value": False, + "password": False, + "name": "verbose", + "advanced": False, + "type": "bool", + "list": False + }, + "callbacks": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "callbacks", + "advanced": False, + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": True + }, + "tags": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "tags", + "advanced": False, + "type": "str", + "list": True + }, + "client": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "client", + "advanced": False, + "type": "Any", + "list": False + }, + "model_name": { + "required": False, + "placeholder": "", + "show": True, + "multiline": False, + "value": "gpt-3.5-turbo", + "password": False, + "options": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "name": "model_name", + "advanced": False, + "type": "str", + "list": True + }, + "temperature": { + "required": False, + "placeholder": "", + "show": True, + "multiline": False, + "value": 0.7, + "password": False, + "name": "temperature", + "advanced": False, + "type": "float", + "list": False + }, + "model_kwargs": { + "required": False, + "placeholder": "", + "show": True, + "multiline": False, + "password": False, + "name": "model_kwargs", + "advanced": True, + "type": "code", + "list": False + }, + "openai_api_key": { + "required": False, + "placeholder": "", + "show": True, + "multiline": False, + "value": "", + "password": True, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": False, + "type": "str", + "list": False + }, + "openai_api_base": { + "required": False, + "placeholder": "", + "show": True, + "multiline": False, + "password": False, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": False, + "type": "str", + "list": False + }, + "openai_organization": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": False, + "type": "str", + "list": False + }, + "openai_proxy": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": False, + "type": "str", + "list": False + }, + "request_timeout": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "password": False, + "name": "request_timeout", + "advanced": False, + "type": "float", + "list": False + }, + "max_retries": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "value": 6, + "password": False, + "name": "max_retries", + "advanced": False, + "type": "int", + "list": False + }, + "streaming": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "value": False, + "password": False, + "name": "streaming", + "advanced": False, + "type": "bool", + "list": False + }, + "n": { + "required": False, + "placeholder": "", + "show": False, + "multiline": False, + "value": 1, + "password": False, + "name": "n", + "advanced": False, + "type": "int", + "list": False + }, + "max_tokens": { + "required": False, + "placeholder": "", + "show": True, + "multiline": False, + "password": True, + "name": "max_tokens", + "advanced": False, + "type": "int", + "list": False + }, + "_type": "ChatOpenAI" + }, + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "description": "Wrapper around OpenAI Chat large language models." +} + def create_app(): """Create the FastAPI app and include the router.""" @@ -18,6 +251,10 @@ def create_app(): def get_health(): return {"status": "OK"} + @app.get("/dynamic_node") + def get_dynamic_nome(): + return template_node + app.add_middleware( CORSMiddleware, allow_origins=origins, From ff0abf51839dec1113e350e403055e40f6954e49 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 26 Jun 2023 10:20:28 -0300 Subject: [PATCH 011/367] =?UTF-8?q?=F0=9F=94=A7=20refactor(chat.py):=20ref?= =?UTF-8?q?actor=20stream=5Fbuild=20function=20to=20send=20input=5Fkeys=20?= =?UTF-8?q?to=20the=20client=20The=20stream=5Fbuild=20function=20has=20bee?= =?UTF-8?q?n=20refactored=20to=20send=20input=5Fkeys=20to=20the=20client?= =?UTF-8?q?=20if=20the=20langchain=5Fobject=20has=20the=20attribute=20"inp?= =?UTF-8?q?ut=5Fkeys".=20This=20change=20improves=20the=20user=20experienc?= =?UTF-8?q?e=20by=20providing=20the=20client=20with=20the=20necessary=20in?= =?UTF-8?q?put=20keys=20to=20continue=20the=20conversation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/chat.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index be9d6802c..666c5d3cd 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -120,7 +120,15 @@ async def stream_build(flow_id: str): yield str(StreamData(event="message", data=response)) - chat_manager.set_cache(flow_id, graph.build()) + langchain_object = graph.build() + # Now we need to check the input_keys to send them to the client + if hasattr(langchain_object, "input_keys"): + input_keys_response = { + "input_keys": langchain_object.input_keys, + } + yield str(StreamData(event="input_keys", data=input_keys_response)) + + chat_manager.set_cache(flow_id, langchain_object) except Exception as exc: logger.error("Error while building the flow: %s", exc) yield str(StreamData(event="error", data={"error": str(exc)})) From ebcaedb84000008c4fced20d6c078b5e92ee791d Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 26 Jun 2023 10:20:48 -0300 Subject: [PATCH 012/367] =?UTF-8?q?=E2=9C=A8=20feat(base.py):=20add=20inpu?= =?UTF-8?q?t=20validation=20for=20PromptTemplate=20to=20ensure=20that=20th?= =?UTF-8?q?e=20template=20and=20input=20variables=20are=20valid=20The=20co?= =?UTF-8?q?mmented=20out=20code=20was=20removed=20to=20improve=20code=20re?= =?UTF-8?q?adability.=20Input=20validation=20was=20added=20to=20ensure=20t?= =?UTF-8?q?hat=20the=20template=20and=20input=20variables=20are=20valid=20?= =?UTF-8?q?before=20creating=20a=20PromptTemplate=20object.=20This=20helps?= =?UTF-8?q?=20to=20prevent=20errors=20that=20may=20occur=20when=20the=20ob?= =?UTF-8?q?ject=20is=20created=20with=20invalid=20input.=20=F0=9F=94=92=20?= =?UTF-8?q?chore(base.py):=20remove=20commented=20out=20code=20and=20add?= =?UTF-8?q?=20input=20validation=20for=20PromptTemplate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/base.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/backend/langflow/api/v1/base.py b/src/backend/langflow/api/v1/base.py index 6941bedf3..d595210bb 100644 --- a/src/backend/langflow/api/v1/base.py +++ b/src/backend/langflow/api/v1/base.py @@ -1,6 +1,7 @@ from pydantic import BaseModel, validator from langflow.interface.utils import extract_input_variables_from_prompt +from langchain.prompts import PromptTemplate class CacheResponse(BaseModel): @@ -57,6 +58,13 @@ def validate_prompt(template: str): # Check if there are invalid characters in the input_variables input_variables = check_input_variables(input_variables) + try: + PromptTemplate(template=template, input_variables=input_variables) + except Exception as exc: + raise ValueError(str(exc)) from exc + + # if len(input_variables) > 1: + # # If there's more than one input variable return PromptValidationResponse(input_variables=input_variables) From 423caa5ddccf7e2ece70badcee9767fedec84070 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 26 Jun 2023 10:22:27 -0300 Subject: [PATCH 013/367] =?UTF-8?q?=F0=9F=94=8D=20chore(.gitignore):=20add?= =?UTF-8?q?=20prepare-commit-msg=20to=20avoid=20pushing=20Opencommit=20hoo?= =?UTF-8?q?k=20The=20prepare-commit-msg=20file=20is=20added=20to=20the=20.?= =?UTF-8?q?gitignore=20file=20to=20avoid=20pushing=20the=20Opencommit=20ho?= =?UTF-8?q?ok=20to=20the=20remote=20repository.=20This=20is=20done=20to=20?= =?UTF-8?q?prevent=20the=20hook=20from=20being=20executed=20on=20other=20m?= =?UTF-8?q?achines=20and=20to=20avoid=20any=20issues=20that=20may=20arise?= =?UTF-8?q?=20from=20the=20hook=20being=20executed=20on=20different=20mach?= =?UTF-8?q?ines.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 36af35fa2..ee56c6e1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +# This is to avoid Opencommit hook from getting pushed +prepare-commit-msg # Logs logs *.log From 5a6d75a38c60ceae5d726ccd2d19d8b7b06f7cc7 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Mon, 26 Jun 2023 10:23:00 -0300 Subject: [PATCH 014/367] =?UTF-8?q?=F0=9F=94=A5=20chore(.gitignore):=20rem?= =?UTF-8?q?ove=20.githooks/prepare-commit-msg=20from=20git=20tracking=20to?= =?UTF-8?q?=20avoid=20committing=20hooks=20accidentally?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 36af35fa2..c1decc34c 100644 --- a/.gitignore +++ b/.gitignore @@ -242,3 +242,4 @@ dmypy.json # Poetry .testenv/* langflow.db +.githooks/prepare-commit-msg From 89286c64563b757a3974f4875ecba2c50caa05d1 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 26 Jun 2023 10:52:53 -0300 Subject: [PATCH 015/367] =?UTF-8?q?=F0=9F=94=A8=20refactor(utils.py):=20ex?= =?UTF-8?q?tract=20build=5Finput=5Fkeys=5Fresponse=20function=20to=20impro?= =?UTF-8?q?ve=20code=20reusability=20=F0=9F=9A=80=20feat(chat.py):=20use?= =?UTF-8?q?=20build=5Finput=5Fkeys=5Fresponse=20function=20to=20build=20in?= =?UTF-8?q?put=20keys=20response=20The=20build=5Finput=5Fkeys=5Fresponse?= =?UTF-8?q?=20function=20was=20extracted=20from=20the=20remove=5Fapi=5Fkey?= =?UTF-8?q?s=20function=20to=20improve=20code=20reusability.=20It=20builds?= =?UTF-8?q?=20the=20input=20keys=20response=20object,=20which=20contains?= =?UTF-8?q?=20the=20input=20keys=20and=20memory=20keys=20of=20a=20langchai?= =?UTF-8?q?n=20object.=20The=20chat.py=20file=20now=20uses=20this=20functi?= =?UTF-8?q?on=20to=20build=20the=20input=20keys=20response=20object=20inst?= =?UTF-8?q?ead=20of=20building=20it=20manually.=20This=20improves=20code?= =?UTF-8?q?=20readability=20and=20reduces=20code=20duplication.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/utils.py | 23 +++++++++++++++++++++++ src/backend/langflow/api/v1/chat.py | 5 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/backend/langflow/api/utils.py b/src/backend/langflow/api/utils.py index bfd9e3da5..cd7daa5d2 100644 --- a/src/backend/langflow/api/utils.py +++ b/src/backend/langflow/api/utils.py @@ -22,3 +22,26 @@ def remove_api_keys(flow: dict): value["value"] = None return flow + + +def build_input_keys_response(langchain_object): + """Build the input keys response.""" + input_keys_response = { + "input_keys": langchain_object.input_keys, + "memory_keys": [], + } + # If the object has memory, that memory will have a memory_variables attribute + # memory variables should be removed from the input keys + if hasattr(langchain_object, "memory") and hasattr( + langchain_object.memory, "memory_variables" + ): + # Remove memory variables from input keys + input_keys_response["input_keys"] = [ + key + for key in input_keys_response["input_keys"] + if key not in langchain_object.memory.memory_variables + ] + # Add memory variables to memory_keys + input_keys_response["memory_keys"] = langchain_object.memory.memory_variables + + return input_keys_response diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index 666c5d3cd..5054bf107 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -6,6 +6,7 @@ from fastapi import ( status, ) from fastapi.responses import StreamingResponse +from langflow.api.utils import build_input_keys_response from langflow.api.v1.schemas import BuiltResponse, InitResponse, StreamData from langflow.chat.manager import ChatManager @@ -123,9 +124,7 @@ async def stream_build(flow_id: str): langchain_object = graph.build() # Now we need to check the input_keys to send them to the client if hasattr(langchain_object, "input_keys"): - input_keys_response = { - "input_keys": langchain_object.input_keys, - } + input_keys_response = build_input_keys_response(langchain_object) yield str(StreamData(event="input_keys", data=input_keys_response)) chat_manager.set_cache(flow_id, langchain_object) From 90cc4023e5d168ba75d1933cc2f989c326121cff Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Mon, 26 Jun 2023 11:45:27 -0300 Subject: [PATCH 016/367] Added form button to bottom right and copied chat modal --- .../chatComponent/chatTrigger/index.tsx | 2 +- .../chatComponent/formTrigger/index.tsx | 51 +++ .../src/components/chatComponent/index.tsx | 5 + .../src/modals/formModal/chatInput/index.tsx | 78 ++++ .../formModal/chatMessage/codeBlock/index.tsx | 82 ++++ .../modals/formModal/chatMessage/index.tsx | 166 +++++++ .../modals/formModal/fileComponent/index.tsx | 79 ++++ src/frontend/src/modals/formModal/index.tsx | 415 ++++++++++++++++++ 8 files changed, 877 insertions(+), 1 deletion(-) create mode 100644 src/frontend/src/components/chatComponent/formTrigger/index.tsx create mode 100644 src/frontend/src/modals/formModal/chatInput/index.tsx create mode 100644 src/frontend/src/modals/formModal/chatMessage/codeBlock/index.tsx create mode 100644 src/frontend/src/modals/formModal/chatMessage/index.tsx create mode 100644 src/frontend/src/modals/formModal/fileComponent/index.tsx create mode 100644 src/frontend/src/modals/formModal/index.tsx diff --git a/src/frontend/src/components/chatComponent/chatTrigger/index.tsx b/src/frontend/src/components/chatComponent/chatTrigger/index.tsx index db1c030ae..857a628c6 100644 --- a/src/frontend/src/components/chatComponent/chatTrigger/index.tsx +++ b/src/frontend/src/components/chatComponent/chatTrigger/index.tsx @@ -29,7 +29,7 @@ export default function ChatTrigger({ open, setOpen, isBuilt }) { leaveFrom="translate-y-0" leaveTo="translate-y-96" > -
+
+
+
+ +
+
+ + ); +} diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index 6c451fc31..cff74cd46 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -7,9 +7,12 @@ import ChatModal from "../../modals/chatModal"; import { getBuildStatus } from "../../controllers/API"; import { NodeType } from "../../types/flow"; +import FormTrigger from "./formTrigger"; +import FormModal from "../../modals/formModal"; export default function Chat({ flow }: ChatType) { const [open, setOpen] = useState(false); + const [openForm, setOpenForm] = useState(false); const [isBuilt, setIsBuilt] = useState(false); useEffect(() => { @@ -69,7 +72,9 @@ export default function Chat({ flow }: ChatType) { isBuilt={isBuilt} /> + +
) : ( { + if (!lockChat && inputRef.current) { + inputRef.current.focus(); + } + }, [lockChat, inputRef]); + + useEffect(() => { + if (inputRef.current) { + inputRef.current.style.height = "inherit"; // Reset the height + inputRef.current.style.height = `${inputRef.current.scrollHeight}px`; // Set it to the scrollHeight + } + }, [chatValue]); + + return ( +
+ +
+ + + ))} + {tabsState[id.current].formKeysData.memory_keys.map((i, k) => ( + +
+
{i}
+ Message Key +
+
+ ))} +
-
-
+
+
-
-
+
+
Date: Tue, 27 Jun 2023 19:15:44 -0300 Subject: [PATCH 035/367] =?UTF-8?q?=F0=9F=8E=A8=20style(chatMessage.tsx):?= =?UTF-8?q?=20remove=20unused=20classNames=20and=20add=20primary=20color?= =?UTF-8?q?=20to=20chat=20message=20text=20=F0=9F=9A=80=20feat(formModal.t?= =?UTF-8?q?sx):=20add=20support=20for=20multiple=20input=20keys=20and=20va?= =?UTF-8?q?lues=20to=20be=20sent=20in=20the=20chat=20message=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(formModal.tsx):=20fix=20keysValue=20state=20?= =?UTF-8?q?initialization=20and=20message=20object=20creation=20?= =?UTF-8?q?=F0=9F=9A=80=20feat(formModal.tsx):=20add=20switch=20component?= =?UTF-8?q?=20to=20select=20which=20input=20key=20to=20send=20in=20the=20c?= =?UTF-8?q?hat=20message=20=F0=9F=8E=A8=20style(formModal.tsx):=20add=20mu?= =?UTF-8?q?ted=20background=20color=20to=20input=20keys=20container=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(api/index.ts):=20change=20message=20type=20t?= =?UTF-8?q?o=20any=20to=20support=20multiple=20input=20keys=20and=20values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modals/formModal/chatMessage/index.tsx | 6 ++-- src/frontend/src/modals/formModal/index.tsx | 33 +++++++++++++++---- src/frontend/src/types/api/index.ts | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/frontend/src/modals/formModal/chatMessage/index.tsx b/src/frontend/src/modals/formModal/chatMessage/index.tsx index 5078e251d..a819bc8d3 100644 --- a/src/frontend/src/modals/formModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/formModal/chatMessage/index.tsx @@ -33,7 +33,7 @@ export default function ChatMessage({ className={classNames( "w-full py-2 px-2 pl-4 flex", chat.isSend - ? "bg-input dark:bg-gray-900 " + ? " dark:bg-gray-900 " : " dark:bg-gray-800" )} > @@ -151,9 +151,9 @@ export default function ChatMessage({
) : (
-
+
"), }} diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 347c61dae..f7baab69a 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -37,6 +37,7 @@ import { AccordionHeader } from "@radix-ui/react-accordion"; import { Textarea } from "../../components/ui/textarea"; import { Badge } from "../../components/ui/badge"; import { Separator } from "../../components/ui/separator"; +import { Switch } from "../../components/ui/switch"; export default function FormModal({ flow, @@ -48,6 +49,7 @@ export default function FormModal({ flow: FlowType; }) { const [chatValue, setChatValue] = useState(""); + const [keysValue, setKeysValue] = useState([]); const [chatHistory, setChatHistory] = useState([]); const { reactFlowInstance } = useContext(typesContext); const { setErrorData, setNoticeData } = useContext(alertContext); @@ -57,6 +59,7 @@ export default function FormModal({ const isOpen = useRef(open); const messagesRef = useRef(null); const id = useRef(flow.id); + const [chatKey, setChatKey] = useState(0); useEffect(() => { if (messagesRef.current) { @@ -69,7 +72,7 @@ export default function FormModal({ }, [open]); useEffect(() => { id.current = flow.id; - console.log(tabsState[flow.id]); + setKeysValue(Array(tabsState[flow.id].formKeysData.input_keys.length).fill("")); }, [flow.id]); var isStream = false; @@ -309,9 +312,15 @@ export default function FormModal({ let nodeValidationErrors = validateNodes(reactFlowInstance); if (nodeValidationErrors.length === 0) { setLockChat(true); - let message = chatValue; + // Message variable makes a object with the keys being the names from tabsState[flow.id].formKeysData.input_keys and the values being the keysValue of the correspondent index + let keys = tabsState[flow.id].formKeysData.input_keys; // array of keys + let values = keysValue.map((k, i) => i == chatKey ? chatValue : k); // array of values + let message = keys.reduce((object, key, index) => { + object[key] = values[index]; + return object; + }, {}); setChatValue(""); - addChatHistory(message, true); + addChatHistory(message.toString(), true); sendAll({ ...reactFlowInstance.toObject(), message, @@ -341,6 +350,12 @@ export default function FormModal({ function setModalOpen(x: boolean) { setOpen(x); } + + function handleOnCheckedChange(checked: boolean, index: number) { + if(checked === true){ + setChatKey(index); + } + } return ( @@ -362,8 +377,12 @@ export default function FormModal({ {i} -
- +
+
+ handleOnCheckedChange(value, k)}/> + +
+
@@ -372,14 +391,14 @@ export default function FormModal({
{i}
- Message Key + Memory Key
))}
-
+
Date: Tue, 27 Jun 2023 19:17:14 -0300 Subject: [PATCH 036/367] =?UTF-8?q?=F0=9F=94=A5=20chore(endpoints.py):=20r?= =?UTF-8?q?emove=20unused=20custom=5Fcomponent=20endpoint=20The=20custom?= =?UTF-8?q?=5Fcomponent=20endpoint=20was=20commented=20out=20and=20unused.?= =?UTF-8?q?=20It=20has=20been=20removed=20to=20improve=20code=20readabilit?= =?UTF-8?q?y=20and=20maintainability.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/endpoints.py | 43 ------------------------ 1 file changed, 43 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 2d93aebb1..1114412c5 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -13,7 +13,6 @@ from langflow.api.v1.schemas import ( from langflow.interface.types import ( build_langchain_types_dict, - build_langchain_template_custom_component, ) from langflow.database.base import get_session from sqlmodel import Session @@ -84,45 +83,3 @@ def get_version(): from langflow import __version__ return {"version": __version__} - - -# @router.post("/custom_component", response_model=CustomComponentResponse, status_code=200) -@router.post("/custom_component", status_code=200) -def custom_component( - code: CustomComponentCode, - session: Session = Depends(get_session), -): - code_test = """ -from langflow.interface.chains.base import ChainCreator -from langflow.interface.tools.base import ToolCreator - - -class MyPythonClass(): - def __init__(self, title: str, author: str, year_published: int): - self.title = title - self.author = author - self.year_published = year_published - - def get_details(self): - return f"Title: {self.title}, Author: {self.author}, Year Published: {self.year_published}" - - def update_year_published(self, new_year: int): - self.year_published = new_year - print(f"The year of publication has been updated to {new_year}.") - - def build(self, name: str, id: int, other: str) -> ChainCreator: - return ChainCreator() -""" - - extractor = ClassCodeExtractor(code_test) - data = extractor.extract_class_info() - is_valid_class_template(data) - - ( - function_args, - function_return_type, - ) = extractor.get_entrypoint_function_args_and_return_type() - - return build_langchain_template_custom_component( - code_test, function_args, function_return_type - ) From e760f228478facb655a02faf12fdc8fed05f3df8 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 19:17:46 -0300 Subject: [PATCH 037/367] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20change?= =?UTF-8?q?=20frontend=5Fnode=20field=20in=20ValidatePromptRequest=20to=20?= =?UTF-8?q?use=20FrontendNodeRequest=20instead=20of=20FrontendNode=20?= =?UTF-8?q?=F0=9F=94=A5=20chore(base.py):=20remove=20unused=20FrontendNode?= =?UTF-8?q?Request=20class=20=F0=9F=94=A8=20refactor(validate.py):=20modif?= =?UTF-8?q?y=20post=5Fvalidate=5Fprompt=20function=20to=20update=20the=20t?= =?UTF-8?q?emplate=20field=20in=20the=20frontend=5Fnode=20object=20The=20V?= =?UTF-8?q?alidatePromptRequest=20class=20was=20using=20the=20FrontendNode?= =?UTF-8?q?=20class=20instead=20of=20the=20FrontendNodeRequest=20class,=20?= =?UTF-8?q?which=20caused=20an=20error.=20The=20unused=20FrontendNodeReque?= =?UTF-8?q?st=20class=20was=20removed.=20The=20post=5Fvalidate=5Fprompt=20?= =?UTF-8?q?function=20was=20modified=20to=20update=20the=20template=20fiel?= =?UTF-8?q?d=20in=20the=20frontend=5Fnode=20object=20instead=20of=20append?= =?UTF-8?q?ing=20to=20the=20fields=20list.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/base.py | 8 ++++++-- src/backend/langflow/api/v1/validate.py | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/backend/langflow/api/v1/base.py b/src/backend/langflow/api/v1/base.py index 1a4936a2f..5c32536c8 100644 --- a/src/backend/langflow/api/v1/base.py +++ b/src/backend/langflow/api/v1/base.py @@ -13,9 +13,13 @@ class Code(BaseModel): code: str +class FrontendNodeRequest(FrontendNode): + template: dict + + class ValidatePromptRequest(BaseModel): template: str - frontend_node: FrontendNode + frontend_node: FrontendNodeRequest # Build ValidationResponse class for {"imports": {"errors": []}, "function": {"errors": []}} @@ -34,7 +38,7 @@ class CodeValidationResponse(BaseModel): class PromptValidationResponse(BaseModel): input_variables: list - frontend_node: FrontendNode + frontend_node: FrontendNodeRequest INVALID_CHARACTERS = { diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py index 3046ad9ba..658e5b274 100644 --- a/src/backend/langflow/api/v1/validate.py +++ b/src/backend/langflow/api/v1/validate.py @@ -36,7 +36,8 @@ def post_validate_prompt(prompt: ValidatePromptRequest): template_field = TemplateField( name=variable, field_type="str", show=True, advanced=False ) - prompt.frontend_node.template.fields.append(template_field) + + prompt.frontend_node.template[variable] = template_field.dict() prompt.frontend_node.custom_fields.append(variable) except Exception as exc: logger.exception(exc) From 5a57de5425d4436271f4665fea26d92a3bb55596 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 19:18:14 -0300 Subject: [PATCH 038/367] =?UTF-8?q?=F0=9F=94=A8=20refactor(promptComponent?= =?UTF-8?q?,=20genericModal,=20promptModal,=20API):=20rename=20checkPrompt?= =?UTF-8?q?=20to=20postValidatePrompt=20=E2=9C=A8=20feat(promptComponent,?= =?UTF-8?q?=20genericModal):=20add=20setNodeClass=20prop=20to=20PromptArea?= =?UTF-8?q?Component=20and=20GenericModal=20to=20update=20nodeClass=20The?= =?UTF-8?q?=20checkPrompt=20function=20has=20been=20renamed=20to=20postVal?= =?UTF-8?q?idatePrompt=20to=20better=20reflect=20its=20functionality.=20Th?= =?UTF-8?q?e=20PromptTypeAPI=20now=20includes=20a=20frontend=5Fnode=20prop?= =?UTF-8?q?erty,=20which=20is=20used=20to=20update=20the=20nodeClass=20in?= =?UTF-8?q?=20the=20PromptAreaComponent=20and=20GenericModal=20components.?= =?UTF-8?q?=20The=20setNodeClass=20prop=20has=20been=20added=20to=20both?= =?UTF-8?q?=20components=20to=20allow=20for=20updating=20the=20nodeClass.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/promptComponent/index.tsx | 2 ++ src/frontend/src/controllers/API/index.ts | 5 +++-- src/frontend/src/modals/genericModal/index.tsx | 15 ++++++++------- src/frontend/src/modals/promptModal/index.tsx | 4 ++-- src/frontend/src/types/api/index.ts | 6 +++++- src/frontend/src/types/components/index.ts | 1 + 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/components/promptComponent/index.tsx b/src/frontend/src/components/promptComponent/index.tsx index abc16c8db..fa18bd001 100644 --- a/src/frontend/src/components/promptComponent/index.tsx +++ b/src/frontend/src/components/promptComponent/index.tsx @@ -8,6 +8,7 @@ import { ExternalLink } from "lucide-react"; export default function PromptAreaComponent({ nodeClass, + setNodeClass, value, onChange, disabled, @@ -46,6 +47,7 @@ export default function PromptAreaComponent({ onChange(t); }} nodeClass={nodeClass} + setNodeClass={setNodeClass} /> ); }} diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 5c5c43a4d..9f212895e 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -1,10 +1,10 @@ import { BuildStatusTypeAPI, - PromptTypeAPI, errorsTypeAPI, InitTypeAPI, UploadFileTypeAPI, APIClassType, + PromptTypeAPI, } from "./../../types/api/index"; import { APIObjectType, sendAllProps } from "../../types/api/index"; import axios, { AxiosResponse } from "axios"; @@ -54,9 +54,10 @@ export async function postValidateCode( * Checks the prompt for the code block by sending it to an API endpoint. * * @param {string} template - The template string of the prompt to check. + * @param {APIClassType} frontend_node - The frontend node to check. * @returns {Promise>} A promise that resolves to an AxiosResponse containing the validation results. */ -export async function checkPrompt( +export async function postValidatePrompt( template: string, frontend_node: APIClassType ): Promise> { diff --git a/src/frontend/src/modals/genericModal/index.tsx b/src/frontend/src/modals/genericModal/index.tsx index 8f7dcefc8..215ba0585 100644 --- a/src/frontend/src/modals/genericModal/index.tsx +++ b/src/frontend/src/modals/genericModal/index.tsx @@ -1,7 +1,7 @@ import { useContext, useRef, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; import { darkContext } from "../../contexts/darkContext"; -import { checkPrompt } from "../../controllers/API"; +import { postValidatePrompt } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; import { Dialog, @@ -25,13 +25,15 @@ export default function GenericModal({ modalTitle, type, nodeClass, + setNodeClass, }: { setValue: (value: string) => void; value: string; buttonText: string; modalTitle: string; type: number; - nodeClass: APIClassType; + nodeClass?: APIClassType; + setNodeClass?: (Class: APIClassType) => void; }) { const [myButtonText] = useState(buttonText); const [myModalTitle] = useState(modalTitle); @@ -99,13 +101,12 @@ export default function GenericModal({ setModalOpen(false); break; case 2: - checkPrompt(myValue, nodeClass) + postValidatePrompt(myValue, nodeClass) .then((apiReturn) => { if (apiReturn.data) { - if (apiReturn.data) { - setNodeClass(data); - setModalOpen(false); - } + setNodeClass(apiReturn.data.frontend_node); + setModalOpen(false); + let inputVariables = apiReturn.data.input_variables; if (inputVariables.length === 0) { setErrorData({ diff --git a/src/frontend/src/modals/promptModal/index.tsx b/src/frontend/src/modals/promptModal/index.tsx index 8a3ce4185..2ab1c140a 100644 --- a/src/frontend/src/modals/promptModal/index.tsx +++ b/src/frontend/src/modals/promptModal/index.tsx @@ -3,7 +3,7 @@ import { XMarkIcon, DocumentTextIcon } from "@heroicons/react/24/outline"; import { Fragment, useContext, useRef, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; import { darkContext } from "../../contexts/darkContext"; -import { checkPrompt } from "../../controllers/API"; +import { postValidatePrompt } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; export default function PromptAreaModal({ value, @@ -107,7 +107,7 @@ export default function PromptAreaModal({ type="button" className="inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-ring focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:ring-offset-1 sm:ml-3 sm:w-auto sm:text-sm" onClick={() => { - checkPrompt(myValue) + postValidatePrompt(myValue) .then((apiReturn) => { if (apiReturn.data) { let inputVariables = diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 92827cc4e..d47663d18 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -14,6 +14,7 @@ export type APIClassType = { display_name: string; [key: string]: Array | string | APITemplateType; }; + export type TemplateVariableType = { type: string; required: boolean; @@ -38,7 +39,10 @@ export type errorsTypeAPI = { function: { errors: Array }; imports: { errors: Array }; }; -export type PromptTypeAPI = { input_variables: Array }; +export type PromptTypeAPI = { + input_variables: Array; + frontend_node: APIClassType; +}; export type BuildStatusTypeAPI = { built: boolean; diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index c1cc3756c..090d3a49f 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -46,6 +46,7 @@ export type InputListComponentType = { export type TextAreaComponentType = { nodeClass?: APIClassType; + setNodeClass?: (value: APIClassType) => void; disabled: boolean; onChange: (value: string[] | string) => void; value: string; From 64fa0c0dcb651579e06489b603fa4bd9f2b3bfcd Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 27 Jun 2023 19:31:37 -0300 Subject: [PATCH 039/367] =?UTF-8?q?=F0=9F=8E=A8=20style(chatInput.tsx):=20?= =?UTF-8?q?add=20padding=20to=20the=20chat=20input=20to=20improve=20readab?= =?UTF-8?q?ility=20and=20aesthetics=20=F0=9F=8E=A8=20style(chatMessage.tsx?= =?UTF-8?q?):=20change=20icon=20from=20MessageCircle=20to=20MessageSquare?= =?UTF-8?q?=20to=20improve=20semantics=20=F0=9F=8E=A8=20style(index.tsx):?= =?UTF-8?q?=20add=20new=20icons=20to=20the=20import=20statement=20and=20ch?= =?UTF-8?q?ange=20MessageSquareDashed=20to=20MessageSquare=20to=20improve?= =?UTF-8?q?=20semantics.=20Add=20padding=20to=20the=20chat=20modal=20to=20?= =?UTF-8?q?improve=20aesthetics.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/modals/formModal/chatInput/index.tsx | 4 ++-- src/frontend/src/modals/formModal/chatMessage/index.tsx | 4 ++-- src/frontend/src/modals/formModal/index.tsx | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/modals/formModal/chatInput/index.tsx b/src/frontend/src/modals/formModal/chatInput/index.tsx index 69d382748..cb77cd277 100644 --- a/src/frontend/src/modals/formModal/chatInput/index.tsx +++ b/src/frontend/src/modals/formModal/chatInput/index.tsx @@ -53,12 +53,12 @@ export default function ChatInput({ lockChat ? " bg-input text-black dark:bg-gray-700 dark:text-gray-300" : " bg-white-200 text-black dark:bg-gray-900 dark:text-gray-300", - "form-input block w-full custom-scroll rounded-md border-gray-300 dark:border-gray-600 pr-10 sm:text-sm" + + "p-4 form-input block w-full custom-scroll rounded-md border-gray-300 dark:border-gray-600 pr-12 sm:text-sm" + INPUT_STYLE )} placeholder={"Send a message..."} /> -
+
)} {chat.thought && chat.thought !== "" && !hidden && ( diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index f7baab69a..7c1add07e 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -5,7 +5,7 @@ import { alertContext } from "../../contexts/alertContext"; import { validateNodes } from "../../utils"; import { typesContext } from "../../contexts/typesContext"; import ChatMessage from "./chatMessage"; -import { X, MessagesSquare, Eraser, TerminalSquare } from "lucide-react"; +import { X, MessagesSquare, Eraser, TerminalSquare, MessageCircle, MessageSquareDashed, MessageSquare } from "lucide-react"; import { sendAllProps } from "../../types/api"; import { ChatMessageType } from "../../types/chat"; import ChatInput from "./chatInput"; @@ -425,7 +425,7 @@ export default function FormModal({ Start a conversation and click the agent’s thoughts{" "} - + {" "} to inspect the chaining process. @@ -434,7 +434,7 @@ export default function FormModal({ )}
-
+
Date: Tue, 27 Jun 2023 19:35:16 -0300 Subject: [PATCH 040/367] =?UTF-8?q?=F0=9F=90=9B=20fix(formModal):=20replac?= =?UTF-8?q?e=20double=20quotes=20with=20single=20quotes=20to=20improve=20c?= =?UTF-8?q?onsistency=20and=20avoid=20escaping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/modals/formModal/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 7c1add07e..e1d2e1067 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -423,7 +423,7 @@ export default function FormModal({
- Start a conversation and click the agent’s thoughts{" "} + Start a conversation and click the agent's thoughts{" "} {" "} From e5676337b5c25c19f9dd463d7f8d713c38ab7ec5 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 19:49:18 -0300 Subject: [PATCH 041/367] =?UTF-8?q?=F0=9F=90=9B=20fix(utils.ts):=20add=20t?= =?UTF-8?q?ry-catch=20blocks=20to=20handle=20errors=20in=20groupByFamily?= =?UTF-8?q?=20function=20The=20try-catch=20blocks=20were=20added=20to=20ha?= =?UTF-8?q?ndle=20errors=20that=20may=20occur=20when=20the=20function=20is?= =?UTF-8?q?=20called.=20This=20improves=20the=20robustness=20of=20the=20fu?= =?UTF-8?q?nction=20and=20prevents=20it=20from=20crashing=20when=20an=20er?= =?UTF-8?q?ror=20occurs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/utils.ts | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/utils.ts b/src/frontend/src/utils.ts index 834094ef0..46b9c51cd 100644 --- a/src/frontend/src/utils.ts +++ b/src/frontend/src/utils.ts @@ -830,10 +830,16 @@ export function groupByFamily(data, baseClasses) { Object.keys(data).map((d) => { Object.keys(data[d]).map((n) => { - if ( - data[d][n].base_classes.some((r) => baseClasses.split("\n").includes(r)) - ) { - arrOfParent.push(d); + try { + if ( + data[d][n].base_classes.some((r) => + baseClasses.split("\n").includes(r) + ) + ) { + arrOfParent.push(d); + } + } catch (e) { + console.log(e); } }); }); @@ -844,16 +850,20 @@ export function groupByFamily(data, baseClasses) { Object.keys(data).map((d) => { Object.keys(data[d]).map((n) => { - baseClasses.split("\n").forEach((tol) => { - data[d][n].base_classes.forEach((data) => { - if (tol == data) { - arrOfType.push({ - family: d, - type: data, - }); - } + try { + baseClasses.split("\n").forEach((tol) => { + data[d][n].base_classes.forEach((data) => { + if (tol == data) { + arrOfType.push({ + family: d, + type: data, + }); + } + }); }); - }); + } catch (e) { + console.log(e); + } }); }); From 753eae28c777d31141c6587247f3e3426c811985 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 19:49:30 -0300 Subject: [PATCH 042/367] =?UTF-8?q?=F0=9F=90=9B=20fix(validate.py):=20chan?= =?UTF-8?q?ge=20dict()=20to=20to=5Fdict()=20method=20to=20fix=20TypeError?= =?UTF-8?q?=20The=20`dict()`=20method=20was=20causing=20a=20TypeError=20wh?= =?UTF-8?q?en=20trying=20to=20serialize=20the=20`template=5Ffield`=20objec?= =?UTF-8?q?t.=20The=20`to=5Fdict()`=20method=20is=20the=20correct=20method?= =?UTF-8?q?=20to=20use=20to=20serialize=20the=20object.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/validate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py index 658e5b274..fada9ce23 100644 --- a/src/backend/langflow/api/v1/validate.py +++ b/src/backend/langflow/api/v1/validate.py @@ -37,7 +37,7 @@ def post_validate_prompt(prompt: ValidatePromptRequest): name=variable, field_type="str", show=True, advanced=False ) - prompt.frontend_node.template[variable] = template_field.dict() + prompt.frontend_node.template[variable] = template_field.to_dict() prompt.frontend_node.custom_fields.append(variable) except Exception as exc: logger.exception(exc) From aee34c87f26ad080c59c5bc94da60e79d745a922 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 19:49:41 -0300 Subject: [PATCH 043/367] =?UTF-8?q?=F0=9F=90=9B=20fix(parameterComponent):?= =?UTF-8?q?=20setNodeClass=20function=20is=20now=20passed=20down=20to=20Pr?= =?UTF-8?q?omptAreaComponent=20The=20setNodeClass=20function=20is=20now=20?= =?UTF-8?q?passed=20down=20to=20PromptAreaComponent=20from=20ParameterComp?= =?UTF-8?q?onent.=20This=20allows=20the=20nodeClass=20to=20be=20set=20when?= =?UTF-8?q?=20a=20prompt=20is=20used.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GenericNode/components/parameterComponent/index.tsx | 3 +++ src/frontend/src/components/promptComponent/index.tsx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 9b7590213..6b12d8b35 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -260,6 +260,9 @@ export default function ParameterComponent({
) : left === true && type === "prompt" ? ( { + data.node = nodeClass; + }} nodeClass={data.node} disabled={disabled} value={data.node.template[name].value ?? ""} diff --git a/src/frontend/src/components/promptComponent/index.tsx b/src/frontend/src/components/promptComponent/index.tsx index fa18bd001..9e85868ed 100644 --- a/src/frontend/src/components/promptComponent/index.tsx +++ b/src/frontend/src/components/promptComponent/index.tsx @@ -7,8 +7,8 @@ import { INPUT_STYLE } from "../../constants"; import { ExternalLink } from "lucide-react"; export default function PromptAreaComponent({ - nodeClass, setNodeClass, + nodeClass, value, onChange, disabled, From 2cf16de113e120e2fbb8b582839d3330dec97e4f Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 19:51:18 -0300 Subject: [PATCH 044/367] =?UTF-8?q?=F0=9F=90=9B=20fix(validate.py):=20remo?= =?UTF-8?q?ve=20unused=20template=20fields=20from=20frontend=5Fnode=20The?= =?UTF-8?q?=20code=20now=20removes=20any=20unused=20template=20fields=20fr?= =?UTF-8?q?om=20the=20frontend=5Fnode=20to=20avoid=20any=20potential=20err?= =?UTF-8?q?ors.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/validate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py index fada9ce23..802ee3e3d 100644 --- a/src/backend/langflow/api/v1/validate.py +++ b/src/backend/langflow/api/v1/validate.py @@ -39,6 +39,9 @@ def post_validate_prompt(prompt: ValidatePromptRequest): prompt.frontend_node.template[variable] = template_field.to_dict() prompt.frontend_node.custom_fields.append(variable) + for key in prompt.frontend_node.template: + if key not in input_variables: + prompt.frontend_node.template.pop(key, None) except Exception as exc: logger.exception(exc) raise HTTPException(status_code=500, detail=str(exc)) from exc From 526f5847c6a4dce8609a8e98db913d0292b593c6 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 20:54:00 -0300 Subject: [PATCH 045/367] =?UTF-8?q?=F0=9F=90=9B=20fix(validate.py):=20remo?= =?UTF-8?q?ve=20unused=20variables=20from=20prompt.frontend=5Fnode.templat?= =?UTF-8?q?e=20=E2=9C=A8=20feat(validate.py):=20add=20support=20for=20dyna?= =?UTF-8?q?mic=20template=20fields=20in=20prompt=20validation=20The=20chan?= =?UTF-8?q?ges=20in=20this=20commit=20remove=20unused=20variables=20from?= =?UTF-8?q?=20the=20prompt.frontend=5Fnode.template.=20The=20commit=20also?= =?UTF-8?q?=20adds=20support=20for=20dynamic=20template=20fields=20in=20pr?= =?UTF-8?q?ompt=20validation.=20The=20new=20variables=20are=20added=20to?= =?UTF-8?q?=20the=20template=20and=20the=20custom=5Ffields=20list.=20The?= =?UTF-8?q?=20old=20custom=5Ffields=20list=20is=20copied=20and=20then=20up?= =?UTF-8?q?dated=20with=20the=20new=20variables.=20The=20variables=20that?= =?UTF-8?q?=20are=20not=20in=20the=20template=20anymore=20are=20removed=20?= =?UTF-8?q?from=20the=20prompt.frontend=5Fnode.template.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/validate.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py index 802ee3e3d..431945602 100644 --- a/src/backend/langflow/api/v1/validate.py +++ b/src/backend/langflow/api/v1/validate.py @@ -31,6 +31,10 @@ def post_validate_code(code: Code): def post_validate_prompt(prompt: ValidatePromptRequest): try: input_variables = validate_prompt(prompt.template) + # Reinitialize custom_fields + old_custom_fields = prompt.frontend_node.custom_fields.copy() + prompt.frontend_node.custom_fields = [] + # Add new variables to the template for variable in input_variables: try: template_field = TemplateField( @@ -39,13 +43,20 @@ def post_validate_prompt(prompt: ValidatePromptRequest): prompt.frontend_node.template[variable] = template_field.to_dict() prompt.frontend_node.custom_fields.append(variable) - for key in prompt.frontend_node.template: - if key not in input_variables: - prompt.frontend_node.template.pop(key, None) + except Exception as exc: logger.exception(exc) raise HTTPException(status_code=500, detail=str(exc)) from exc + # Remove variables that are not in the template anymore + for variable in old_custom_fields: + if variable not in input_variables: + try: + prompt.frontend_node.template.pop(variable, None) + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + return PromptValidationResponse( input_variables=input_variables, frontend_node=prompt.frontend_node, From 355b846be435bae8ce5f38f87fe9d93dc3dd5610 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 27 Jun 2023 20:54:24 -0300 Subject: [PATCH 046/367] =?UTF-8?q?=F0=9F=8E=A8=20style(constants.tsx):=20?= =?UTF-8?q?add=20CHAT=5FFORM=5FDIALOG=5FSUBTITLE=20constant=20to=20improve?= =?UTF-8?q?=20code=20readability=20=E2=9C=A8=20feat(formModal):=20add=20In?= =?UTF-8?q?put=20Variables=20section=20to=20Chat=20Form=20modal=20to=20all?= =?UTF-8?q?ow=20users=20to=20input=20variables=20=F0=9F=8E=A8=20style(form?= =?UTF-8?q?Modal):=20adjust=20width=20of=20Chat=20Form=20modal=20and=20Inp?= =?UTF-8?q?ut=20Variables=20section=20to=20improve=20UI=20=F0=9F=8E=A8=20s?= =?UTF-8?q?tyle(formModal):=20adjust=20layout=20of=20Input=20Variables=20s?= =?UTF-8?q?ection=20to=20improve=20UI=20=F0=9F=8E=A8=20style(formModal):?= =?UTF-8?q?=20adjust=20layout=20of=20From=20Chat=20switch=20to=20improve?= =?UTF-8?q?=20UI=20=F0=9F=90=9B=20fix(formModal):=20replace=20Switch=20com?= =?UTF-8?q?ponent=20with=20custom=20ToggleShadComponent=20to=20fix=20styli?= =?UTF-8?q?ng=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/constants.tsx | 7 ++++++ src/frontend/src/modals/formModal/index.tsx | 26 ++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/constants.tsx b/src/frontend/src/constants.tsx index f569046ea..d87008971 100644 --- a/src/frontend/src/constants.tsx +++ b/src/frontend/src/constants.tsx @@ -22,6 +22,13 @@ export const SETTINGS_DIALOG_SUBTITLE = "Edit details about your project."; export const CODE_DIALOG_SUBTITLE = "Export your flow to use it with this code."; +/** + * The base text for subtitle of Chat Form + * @constant + */ +export const CHAT_FORM_DIALOG_SUBTITLE = + "Export your flow to use it with this code."; + /** * The base text for subtitle of Edit Node Dialog * @constant diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index e1d2e1067..0d139a2d6 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -5,7 +5,7 @@ import { alertContext } from "../../contexts/alertContext"; import { validateNodes } from "../../utils"; import { typesContext } from "../../contexts/typesContext"; import ChatMessage from "./chatMessage"; -import { X, MessagesSquare, Eraser, TerminalSquare, MessageCircle, MessageSquareDashed, MessageSquare } from "lucide-react"; +import { X, MessagesSquare, Eraser, TerminalSquare, MessageCircle, MessageSquareDashed, MessageSquare, Variable } from "lucide-react"; import { sendAllProps } from "../../types/api"; import { ChatMessageType } from "../../types/chat"; import ChatInput from "./chatInput"; @@ -21,7 +21,7 @@ import { DialogTrigger, } from "../../components/ui/dialog"; import { dark } from "@mui/material/styles/createPalette"; -import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants"; +import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants"; import { postValidateCode } from "../../controllers/API"; import { Button } from "../../components/ui/button"; import { Input } from "../../components/ui/input"; @@ -38,6 +38,8 @@ import { Textarea } from "../../components/ui/textarea"; import { Badge } from "../../components/ui/badge"; import { Separator } from "../../components/ui/separator"; import { Switch } from "../../components/ui/switch"; +import { CardTitle } from "../../components/ui/card"; +import ToggleShadComponent from "../../components/toggleShadComponent"; export default function FormModal({ flow, @@ -359,19 +361,26 @@ export default function FormModal({ return ( - + - Chat Form + Chat + {CHAT_FORM_DIALOG_SUBTITLE}
-
+
+
+ + + Input Variables + +
{tabsState[id.current].formKeysData.input_keys.map((i, k) => ( @@ -379,8 +388,13 @@ export default function FormModal({
- handleOnCheckedChange(value, k)}/> + handleOnCheckedChange(value, k)} + size="small" + disabled={false} + />
From 8c721b0b8e930e53dfcfb27315e6a1c33549c90f Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 27 Jun 2023 20:58:01 -0300 Subject: [PATCH 047/367] =?UTF-8?q?=F0=9F=90=9B=20fix(formModal):=20fix=20?= =?UTF-8?q?keysValue=20state=20initialization=20to=20prevent=20undefined?= =?UTF-8?q?=20error=20=E2=9C=A8=20feat(formModal):=20add=20support=20for?= =?UTF-8?q?=20memory=5Fkeys=20in=20input=20variables=20accordion=20to=20di?= =?UTF-8?q?splay=20memory=20keys=20in=20chat=20form=20modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/modals/formModal/index.tsx | 224 +++++++++++--------- 1 file changed, 123 insertions(+), 101 deletions(-) diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 0d139a2d6..b0cdaf484 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -5,7 +5,16 @@ import { alertContext } from "../../contexts/alertContext"; import { validateNodes } from "../../utils"; import { typesContext } from "../../contexts/typesContext"; import ChatMessage from "./chatMessage"; -import { X, MessagesSquare, Eraser, TerminalSquare, MessageCircle, MessageSquareDashed, MessageSquare, Variable } from "lucide-react"; +import { + X, + MessagesSquare, + Eraser, + TerminalSquare, + MessageCircle, + MessageSquareDashed, + MessageSquare, + Variable, +} from "lucide-react"; import { sendAllProps } from "../../types/api"; import { ChatMessageType } from "../../types/chat"; import ChatInput from "./chatInput"; @@ -74,8 +83,10 @@ export default function FormModal({ }, [open]); useEffect(() => { id.current = flow.id; - setKeysValue(Array(tabsState[flow.id].formKeysData.input_keys.length).fill("")); - }, [flow.id]); + setKeysValue( + Array(tabsState[flow.id].formKeysData.input_keys.length).fill("") + ); + }, [flow.id, tabsState[flow.id], tabsState[flow.id].formKeysData]); var isStream = false; @@ -316,7 +327,7 @@ export default function FormModal({ setLockChat(true); // Message variable makes a object with the keys being the names from tabsState[flow.id].formKeysData.input_keys and the values being the keysValue of the correspondent index let keys = tabsState[flow.id].formKeysData.input_keys; // array of keys - let values = keysValue.map((k, i) => i == chatKey ? chatValue : k); // array of values + let values = keysValue.map((k, i) => (i == chatKey ? chatValue : k)); // array of values let message = keys.reduce((object, key, index) => { object[key] = values[index]; return object; @@ -354,115 +365,126 @@ export default function FormModal({ } function handleOnCheckedChange(checked: boolean, index: number) { - if(checked === true){ + if (checked === true) { setChatKey(index); } } return ( - - - - Chat - - {CHAT_FORM_DIALOG_SUBTITLE} - + {tabsState[flow.id].formKeysData && ( + + + + Chat + + {CHAT_FORM_DIALOG_SUBTITLE} + -
-
-
- - - Input Variables - -
- - {tabsState[id.current].formKeysData.input_keys.map((i, k) => ( - - {i} - -
-
- - handleOnCheckedChange(value, k)} - size="small" - disabled={false} - /> -
- -
-
-
- ))} - {tabsState[id.current].formKeysData.memory_keys.map((i, k) => ( - -
-
{i}
- Memory Key -
-
- ))} -
-
-
-
-
- {chatHistory.length > 0 ? ( - chatHistory.map((c, i) => ( - - )) - ) : ( -
- - 👋{" "} - - LangFlow Chat - - -
-
- - Start a conversation and click the agent's thoughts{" "} - - - {" "} - to inspect the chaining process. - -
-
- )} -
+
+
+
+ + + Input Variables +
-
-
- + + {tabsState[id.current].formKeysData.input_keys.map((i, k) => ( + + {i} + +
+
+ + + handleOnCheckedChange(value, k) + } + size="small" + disabled={false} + /> +
+ +
+
+
+ ))} + {tabsState[id.current].formKeysData.memory_keys.map((i, k) => ( + +
+
{i}
+ Memory Key +
+
+ ))} +
+
+
+
+
+ {chatHistory.length > 0 ? ( + chatHistory.map((c, i) => ( + + )) + ) : ( +
+ + 👋{" "} + + LangFlow Chat + + +
+
+ + Start a conversation and click the agent's thoughts{" "} + + + {" "} + to inspect the chaining process. + +
+
+ )} +
+
+
+
+ +
-
- + + )}
); } From a4101dac536b61fcbc877c3f7c193c1fa62f708a Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 21:31:47 -0300 Subject: [PATCH 048/367] =?UTF-8?q?=F0=9F=94=A5=20refactor(formModal):=20r?= =?UTF-8?q?emove=20unused=20imports=20and=20variables=20=E2=9C=A8=20feat(f?= =?UTF-8?q?ormModal):=20add=20function=20to=20format=20message=20inputs=20?= =?UTF-8?q?into=20a=20string=20This=20commit=20removes=20unused=20imports?= =?UTF-8?q?=20and=20variables=20from=20the=20file.=20A=20new=20function=20?= =?UTF-8?q?was=20added=20to=20format=20the=20message=20inputs=20into=20a?= =?UTF-8?q?=20string,=20which=20is=20used=20to=20display=20the=20message?= =?UTF-8?q?=20in=20the=20chat.=20This=20improves=20the=20readability=20of?= =?UTF-8?q?=20the=20code=20and=20makes=20it=20easier=20to=20understand=20h?= =?UTF-8?q?ow=20the=20message=20is=20being=20constructed.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/modals/formModal/index.tsx | 57 +++++++++++---------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index b0cdaf484..f0e5e0f5c 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -1,20 +1,10 @@ -import { Transition } from "@headlessui/react"; -import { Fragment, useContext, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useRef, useState } from "react"; import { FlowType } from "../../types/flow"; import { alertContext } from "../../contexts/alertContext"; import { validateNodes } from "../../utils"; import { typesContext } from "../../contexts/typesContext"; import ChatMessage from "./chatMessage"; -import { - X, - MessagesSquare, - Eraser, - TerminalSquare, - MessageCircle, - MessageSquareDashed, - MessageSquare, - Variable, -} from "lucide-react"; +import { TerminalSquare, MessageSquare, Variable } from "lucide-react"; import { sendAllProps } from "../../types/api"; import { ChatMessageType } from "../../types/chat"; import ChatInput from "./chatInput"; @@ -24,16 +14,11 @@ import { Dialog, DialogContent, DialogDescription, - DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "../../components/ui/dialog"; -import { dark } from "@mui/material/styles/createPalette"; import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants"; -import { postValidateCode } from "../../controllers/API"; -import { Button } from "../../components/ui/button"; -import { Input } from "../../components/ui/input"; import { Label } from "../../components/ui/label"; import { TabsContext } from "../../contexts/tabsContext"; import { @@ -42,12 +27,8 @@ import { AccordionItem, AccordionTrigger, } from "../../components/ui/accordion"; -import { AccordionHeader } from "@radix-ui/react-accordion"; import { Textarea } from "../../components/ui/textarea"; import { Badge } from "../../components/ui/badge"; -import { Separator } from "../../components/ui/separator"; -import { Switch } from "../../components/ui/switch"; -import { CardTitle } from "../../components/ui/card"; import ToggleShadComponent from "../../components/toggleShadComponent"; export default function FormModal({ @@ -83,9 +64,12 @@ export default function FormModal({ }, [open]); useEffect(() => { id.current = flow.id; - setKeysValue( - Array(tabsState[flow.id].formKeysData.input_keys.length).fill("") - ); + + if (tabsState[flow.id].formKeysData) { + setKeysValue( + Array(tabsState[flow.id].formKeysData.input_keys.length).fill("") + ); + } }, [flow.id, tabsState[flow.id], tabsState[flow.id].formKeysData]); var isStream = false; @@ -303,7 +287,7 @@ export default function FormModal({ title: "There was an error sending the message", list: [error.message], }); - setChatValue(data.message); + setChatValue(data.inputs); connectWS(); } } @@ -319,6 +303,22 @@ export default function FormModal({ ref.current.focus(); } }, [open]); + function formatMessage(inputs: any): string { + if (inputs) { + // inputs is a object with the keys and values being input_keys and keysValue + // so the formated message is a string with the keys and values separated by ": " + let message = ""; + for (const [key, value] of Object.entries(inputs)) { + // make key bold + // dangerouslySetInnerHTML={{ + // __html: message.replace(/\n/g, "
"), + // }} + message += `${key}: ${value}\n`; + } + return message; + } + return ""; + } function sendMessage() { if (chatValue !== "") { @@ -328,15 +328,16 @@ export default function FormModal({ // Message variable makes a object with the keys being the names from tabsState[flow.id].formKeysData.input_keys and the values being the keysValue of the correspondent index let keys = tabsState[flow.id].formKeysData.input_keys; // array of keys let values = keysValue.map((k, i) => (i == chatKey ? chatValue : k)); // array of values - let message = keys.reduce((object, key, index) => { + let inputs = keys.reduce((object, key, index) => { object[key] = values[index]; return object; }, {}); setChatValue(""); - addChatHistory(message.toString(), true); + const message = formatMessage(inputs); + addChatHistory(message, true); sendAll({ ...reactFlowInstance.toObject(), - message, + inputs: inputs, chatHistory, name: flow.name, description: flow.description, From 5a9c1ae1b71244741c7067c1fd2dc0c8571d5a62 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 21:32:09 -0300 Subject: [PATCH 049/367] =?UTF-8?q?=F0=9F=94=80=20chore(schemas.py):=20add?= =?UTF-8?q?=20support=20for=20dict=20type=20in=20message=20field=20of=20Ch?= =?UTF-8?q?atMessage=20schema=20The=20message=20field=20of=20the=20ChatMes?= =?UTF-8?q?sage=20schema=20now=20supports=20a=20dictionary=20type=20in=20a?= =?UTF-8?q?ddition=20to=20the=20previous=20string=20and=20None=20types.=20?= =?UTF-8?q?This=20change=20was=20made=20to=20allow=20for=20more=20complex?= =?UTF-8?q?=20messages=20to=20be=20sent=20and=20received=20in=20the=20chat?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/schemas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/schemas.py b/src/backend/langflow/api/v1/schemas.py index ed5bf8b3b..1739310e9 100644 --- a/src/backend/langflow/api/v1/schemas.py +++ b/src/backend/langflow/api/v1/schemas.py @@ -43,7 +43,7 @@ class ChatMessage(BaseModel): """Chat message schema.""" is_bot: bool = False - message: Union[str, None] = None + message: Union[str, None, dict] = None type: str = "human" From c39e94d584522188d6e54f80c3510de9e3d392ab Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 21:32:46 -0300 Subject: [PATCH 050/367] =?UTF-8?q?=F0=9F=94=A8=20refactor(base.py):=20cha?= =?UTF-8?q?nge=20message=20parameter=20to=20inputs=20parameter=20to=20impr?= =?UTF-8?q?ove=20semantics=20The=20message=20parameter=20was=20not=20being?= =?UTF-8?q?=20used=20in=20the=20function,=20so=20it=20was=20changed=20to?= =?UTF-8?q?=20inputs=20to=20better=20reflect=20the=20purpose=20of=20the=20?= =?UTF-8?q?parameter.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/processing/base.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/backend/langflow/processing/base.py b/src/backend/langflow/processing/base.py index 97b0d5be0..ca86d1a83 100644 --- a/src/backend/langflow/processing/base.py +++ b/src/backend/langflow/processing/base.py @@ -6,23 +6,12 @@ from langflow.processing.process import fix_memory_inputs, format_actions from langflow.utils.logger import logger -async def get_result_and_steps(langchain_object, message: str, **kwargs): +async def get_result_and_steps(langchain_object, inputs: dict, **kwargs): """Get result and thought from extracted json""" try: if hasattr(langchain_object, "verbose"): langchain_object.verbose = True - chat_input = None - memory_key = "" - if hasattr(langchain_object, "memory") and langchain_object.memory is not None: - memory_key = langchain_object.memory.memory_key - - if hasattr(langchain_object, "input_keys"): - for key in langchain_object.input_keys: - if key not in [memory_key, "chat_history"]: - chat_input = {key: message} - else: - chat_input = message # type: ignore if hasattr(langchain_object, "return_intermediate_steps"): # https://github.com/hwchase17/langchain/issues/2068 @@ -33,12 +22,12 @@ async def get_result_and_steps(langchain_object, message: str, **kwargs): fix_memory_inputs(langchain_object) try: async_callbacks = [AsyncStreamingLLMCallbackHandler(**kwargs)] - output = await langchain_object.acall(chat_input, callbacks=async_callbacks) + output = await langchain_object.acall(inputs, callbacks=async_callbacks) except Exception as exc: # make the error message more informative logger.debug(f"Error: {str(exc)}") sync_callbacks = [StreamingLLMCallbackHandler(**kwargs)] - output = langchain_object(chat_input, callbacks=sync_callbacks) + output = langchain_object(inputs, callbacks=sync_callbacks) intermediate_steps = ( output.get("intermediate_steps", []) if isinstance(output, dict) else [] From 2e09d7026b1d3b21f4d527b8417382e352b0e91c Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 27 Jun 2023 21:33:06 -0300 Subject: [PATCH 051/367] =?UTF-8?q?=F0=9F=94=80=20chore(api):=20rename=20m?= =?UTF-8?q?essage=20property=20to=20inputs=20in=20sendAllProps=20type=20Th?= =?UTF-8?q?e=20message=20property=20in=20the=20sendAllProps=20type=20has?= =?UTF-8?q?=20been=20renamed=20to=20inputs=20to=20better=20reflect=20its?= =?UTF-8?q?=20purpose.=20This=20change=20improves=20the=20semantics=20of?= =?UTF-8?q?=20the=20code=20and=20makes=20it=20easier=20to=20understand=20t?= =?UTF-8?q?he=20purpose=20of=20the=20property.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/types/api/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index d47663d18..7fc10f309 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -31,7 +31,7 @@ export type sendAllProps = { name: string; description: string; viewport: Viewport; - message: any; + inputs: any; chatHistory: { message: string; isSend: boolean }[]; }; From d59b648b75e3ea1790869ba3c5da86362154a067 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Wed, 28 Jun 2023 00:38:21 -0300 Subject: [PATCH 052/367] =?UTF-8?q?=F0=9F=94=A5=20refactor(formTrigger):?= =?UTF-8?q?=20remove=20unused=20FormTrigger=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🔥 refactor(chatComponent): remove import and usage of FormTrigger component 🔥 refactor(ui/badge): remove unused size variant in Badge component 🔥 refactor(formModal/chatInput): remove unused Eraser icon import and clearChat function 🔥 refactor(formModal/chatMessage): remove unused classNames import and remove dark mode classes 🔥 refactor(formModal): remove unused Eraser icon import and clearChat function --- .../chatComponent/formTrigger/index.tsx | 51 ------------------- .../src/components/chatComponent/index.tsx | 9 ++-- src/frontend/src/components/ui/badge.tsx | 13 +++-- .../src/modals/formModal/chatInput/index.tsx | 21 +++++--- .../modals/formModal/chatMessage/index.tsx | 4 +- src/frontend/src/modals/formModal/index.tsx | 26 +++++++--- 6 files changed, 48 insertions(+), 76 deletions(-) delete mode 100644 src/frontend/src/components/chatComponent/formTrigger/index.tsx diff --git a/src/frontend/src/components/chatComponent/formTrigger/index.tsx b/src/frontend/src/components/chatComponent/formTrigger/index.tsx deleted file mode 100644 index c281a92e3..000000000 --- a/src/frontend/src/components/chatComponent/formTrigger/index.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Transition } from "@headlessui/react"; -import { FormInput, MessagesSquare } from "lucide-react"; - -import { alertContext } from "../../../contexts/alertContext"; -import { useContext } from "react"; - -export default function FormTrigger({ open, setOpen, isBuilt }) { - const { setErrorData } = useContext(alertContext); - - function handleClick() { - if (isBuilt) { - setOpen(true); - } else { - setErrorData({ - title: "Flow not built", - list: ["Please build the flow before chatting"], - }); - } - } - - return ( - -
-
- -
-
-
- ); -} diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index 741cf4ec8..eaf0ba4ef 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -7,7 +7,6 @@ import ChatModal from "../../modals/chatModal"; import { getBuildStatus } from "../../controllers/API"; import { NodeType } from "../../types/flow"; -import FormTrigger from "./formTrigger"; import FormModal from "../../modals/formModal"; export default function Chat({ flow }: ChatType) { @@ -66,15 +65,13 @@ export default function Chat({ flow }: ChatType) { {isBuilt ? (
- - - - + +
) : ( , VariantProps {} -function Badge({ className, variant, ...props }: BadgeProps) { +function Badge({ className, variant, size, ...props }: BadgeProps) { return ( -
+
); } diff --git a/src/frontend/src/modals/formModal/chatInput/index.tsx b/src/frontend/src/modals/formModal/chatInput/index.tsx index cb77cd277..c03ab2003 100644 --- a/src/frontend/src/modals/formModal/chatInput/index.tsx +++ b/src/frontend/src/modals/formModal/chatInput/index.tsx @@ -2,12 +2,13 @@ import { classNames } from "../../../utils"; import { useContext, useEffect, useRef, useState } from "react"; import { TabsContext } from "../../../contexts/tabsContext"; import { INPUT_STYLE } from "../../../constants"; -import { Lock, Send } from "lucide-react"; +import { Eraser, Lock, LucideSend, Send } from "lucide-react"; export default function ChatInput({ lockChat, chatValue, sendMessage, + clearChat, setChatValue, inputRef, }) { @@ -58,16 +59,24 @@ export default function ChatInput({ )} placeholder={"Send a message..."} /> -
- +
*/} +
+ +
Date: Wed, 28 Jun 2023 00:44:48 -0300 Subject: [PATCH 053/367] Deleted chat modal and changed disposition of clearChat button --- .../src/modals/chatModal/chatInput/index.tsx | 78 ---- .../chatModal/chatMessage/codeBlock/index.tsx | 82 ---- .../modals/chatModal/chatMessage/index.tsx | 166 ------- .../modals/chatModal/fileComponent/index.tsx | 79 ---- src/frontend/src/modals/chatModal/index.tsx | 415 ------------------ .../src/modals/formModal/chatInput/index.tsx | 13 +- .../modals/formModal/chatMessage/index.tsx | 2 +- src/frontend/src/modals/formModal/index.tsx | 6 +- 8 files changed, 5 insertions(+), 836 deletions(-) delete mode 100644 src/frontend/src/modals/chatModal/chatInput/index.tsx delete mode 100644 src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx delete mode 100644 src/frontend/src/modals/chatModal/chatMessage/index.tsx delete mode 100644 src/frontend/src/modals/chatModal/fileComponent/index.tsx delete mode 100644 src/frontend/src/modals/chatModal/index.tsx diff --git a/src/frontend/src/modals/chatModal/chatInput/index.tsx b/src/frontend/src/modals/chatModal/chatInput/index.tsx deleted file mode 100644 index 69d382748..000000000 --- a/src/frontend/src/modals/chatModal/chatInput/index.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { classNames } from "../../../utils"; -import { useContext, useEffect, useRef, useState } from "react"; -import { TabsContext } from "../../../contexts/tabsContext"; -import { INPUT_STYLE } from "../../../constants"; -import { Lock, Send } from "lucide-react"; - -export default function ChatInput({ - lockChat, - chatValue, - sendMessage, - setChatValue, - inputRef, -}) { - useEffect(() => { - if (!lockChat && inputRef.current) { - inputRef.current.focus(); - } - }, [lockChat, inputRef]); - - useEffect(() => { - if (inputRef.current) { - inputRef.current.style.height = "inherit"; // Reset the height - inputRef.current.style.height = `${inputRef.current.scrollHeight}px`; // Set it to the scrollHeight - } - }, [chatValue]); - - return ( -
-
@@ -486,7 +486,11 @@ export default function FormModal({ chatValue={chatValue} lockChat={lockChat} sendMessage={sendMessage} - setChatValue={setChatValue} + setChatValue={(value) => {setChatValue(value); setTabsState((old) => { + let newTabsState = _.cloneDeep(old); + newTabsState[id.current].formKeysData.input_keys[chatKey] = chatValue; + return newTabsState; + });}} inputRef={ref} />
From 9acff51555262c54755015bca810f216c66a8113 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 29 Jun 2023 23:19:44 -0300 Subject: [PATCH 106/367] =?UTF-8?q?=F0=9F=94=A7=20chore(codeBlock/index.ts?= =?UTF-8?q?x):=20adjust=20className=20to=20use=20relative=20width=20instea?= =?UTF-8?q?d=20of=20fixed=20width=20to=20improve=20responsiveness?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modals/formModal/chatMessage/codeBlock/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/modals/formModal/chatMessage/codeBlock/index.tsx b/src/frontend/src/modals/formModal/chatMessage/codeBlock/index.tsx index 851f5118a..dcb478ae1 100644 --- a/src/frontend/src/modals/formModal/chatMessage/codeBlock/index.tsx +++ b/src/frontend/src/modals/formModal/chatMessage/codeBlock/index.tsx @@ -69,7 +69,7 @@ export const CodeBlock: FC = memo(({ language, value }) => {
Date: Fri, 30 Jun 2023 00:09:34 -0300 Subject: [PATCH 107/367] =?UTF-8?q?=F0=9F=94=A8=20refactor(formModal/index?= =?UTF-8?q?.tsx):=20organize=20imports=20and=20format=20code=20for=20bette?= =?UTF-8?q?r=20readability=20=E2=9C=A8=20feat(formModal/index.tsx):=20add?= =?UTF-8?q?=20support=20for=20dropdown=20menu=20component=20and=20button?= =?UTF-8?q?=20component=20=F0=9F=94=A7=20chore(formModal/index.tsx):=20fix?= =?UTF-8?q?=20indentation=20and=20spacing=20issues=20for=20better=20code?= =?UTF-8?q?=20formatting=20=F0=9F=90=9B=20fix(formModal/index.tsx):=20fix?= =?UTF-8?q?=20type=20error=20and=20handle=20input=20value=20changes=20corr?= =?UTF-8?q?ectly=20=F0=9F=94=A7=20chore(formModal/index.tsx):=20fix=20inde?= =?UTF-8?q?ntation=20and=20spacing=20issues=20for=20better=20code=20format?= =?UTF-8?q?ting=20=E2=9C=A8=20feat(formModal/index.tsx):=20add=20support?= =?UTF-8?q?=20for=20textarea=20component=20and=20handle=20input=20value=20?= =?UTF-8?q?changes=20correctly=20=F0=9F=94=A7=20chore(formModal/index.tsx)?= =?UTF-8?q?:=20fix=20indentation=20and=20spacing=20issues=20for=20better?= =?UTF-8?q?=20code=20formatting=20=E2=9C=A8=20feat(formModal/index.tsx):?= =?UTF-8?q?=20add=20support=20for=20toggle=20component=20and=20handle=20in?= =?UTF-8?q?put=20value=20changes=20correctly=20=F0=9F=94=A7=20chore(formMo?= =?UTF-8?q?dal/index.tsx):=20fix=20indentation=20and=20spacing=20issues=20?= =?UTF-8?q?for=20better=20code=20formatting=20=E2=9C=A8=20feat(formModal/i?= =?UTF-8?q?ndex.tsx):=20add=20support=20for=20dropdown=20menu=20component?= =?UTF-8?q?=20and=20button=20component=20=F0=9F=94=A7=20chore(formModal/in?= =?UTF-8?q?dex.tsx):=20fix=20indentation=20and=20spacing=20issues=20for=20?= =?UTF-8?q?better=20code=20formatting=20=E2=9C=A8=20feat(formModal/index.t?= =?UTF-8?q?sx):=20add=20support=20for=20textarea=20component=20and=20handl?= =?UTF-8?q?e=20input=20value=20changes=20correctly=20=F0=9F=94=A7=20chore(?= =?UTF-8?q?formModal/index.tsx):=20fix=20indentation=20and=20spacing=20iss?= =?UTF-8?q?ues=20for=20better=20code=20formatting=20=E2=9C=A8=20feat(formM?= =?UTF-8?q?odal/index.tsx):=20add=20support=20for=20toggle=20component=20a?= =?UTF-8?q?nd=20handle=20input=20value=20changes=20correctly=20?= =?UTF-8?q?=F0=9F=94=A7=20chore(formModal/index.tsx):=20fix=20indentation?= =?UTF-8?q?=20and=20spacing=20issues=20for=20better=20code=20formatting=20?= =?UTF-8?q?=E2=9C=A8=20feat(formModal/index.tsx):=20add=20support=20for=20?= =?UTF-8?q?dropdown=20menu=20component=20and=20button=20component=20?= =?UTF-8?q?=F0=9F=94=A7=20chore(formModal/index.tsx):=20fix=20indentation?= =?UTF-8?q?=20and=20spacing=20issues=20for=20better=20code=20formatting=20?= =?UTF-8?q?=E2=9C=A8=20feat(formModal/index.tsx):=20add=20support=20for=20?= =?UTF-8?q?textarea=20component=20and=20handle=20input=20value=20changes?= =?UTF-8?q?=20correctly=20=F0=9F=94=A7=20chore(formModal/index.tsx):=20fix?= =?UTF-8?q?=20indentation=20and=20spacing=20issues=20for=20better=20code?= =?UTF-8?q?=20formatting=20=E2=9C=A8=20feat(formModal/index.tsx):=20add=20?= =?UTF-8?q?support=20for=20toggle=20component=20and=20handle=20input=20val?= =?UTF-8?q?ue=20changes=20correctly=20=F0=9F=94=A7=20chore(formModal/index?= =?UTF-8?q?.tsx):=20fix=20indentation=20and=20spacing=20issues=20for=20bet?= =?UTF-8?q?ter=20code=20formatting=20=E2=9C=A8=20feat(formModal/index.tsx)?= =?UTF-8?q?:=20add=20support=20for=20dropdown=20menu=20component=20and=20b?= =?UTF-8?q?utton=20component=20=F0=9F=94=A7=20chore(formModal/index.tsx):?= =?UTF-8?q?=20fix=20indentation=20and=20spacing=20issues=20for=20better=20?= =?UTF-8?q?code=20formatting=20=E2=9C=A8=20feat(formModal/index.tsx):=20ad?= =?UTF-8?q?d=20support=20for=20textarea=20component=20and=20handle=20input?= =?UTF-8?q?=20value=20changes=20correctly=20=F0=9F=94=A7=20chore(formModal?= =?UTF-8?q?/index.tsx):=20fix=20indentation=20and=20spacing=20issues=20for?= =?UTF-8?q?=20better=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/modals/formModal/index.tsx | 165 ++++++++++++++------ 1 file changed, 113 insertions(+), 52 deletions(-) diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 0992c4c50..134536ac3 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -30,6 +30,14 @@ import { import { Textarea } from "../../components/ui/textarea"; import { Badge } from "../../components/ui/badge"; import ToggleShadComponent from "../../components/toggleShadComponent"; +import Dropdown from "../../components/dropdownComponent"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "../../components/ui/dropdown-menu"; +import { Button } from "../../components/ui/button"; export default function FormModal({ flow, @@ -41,7 +49,13 @@ export default function FormModal({ flow: FlowType; }) { const { tabsState, setTabsState } = useContext(TabsContext); - const [chatValue, setChatValue] = useState(tabsState[flow.id].formKeysData.input_keys[Object.keys(tabsState[flow.id].formKeysData.input_keys).find((k) => !tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k))]); + const [chatValue, setChatValue] = useState( + tabsState[flow.id].formKeysData.input_keys[ + Object.keys(tabsState[flow.id].formKeysData.input_keys).find( + (k) => !tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k) + ) + ] + ); const [chatHistory, setChatHistory] = useState([]); const { reactFlowInstance } = useContext(typesContext); const { setErrorData, setNoticeData } = useContext(alertContext); @@ -50,7 +64,11 @@ export default function FormModal({ const isOpen = useRef(open); const messagesRef = useRef(null); const id = useRef(flow.id); - const [chatKey, setChatKey] = useState(Object.keys(tabsState[flow.id].formKeysData.input_keys).find((k) => !tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k))); + const [chatKey, setChatKey] = useState( + Object.keys(tabsState[flow.id].formKeysData.input_keys).find( + (k) => !tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k) + ) + ); useEffect(() => { if (messagesRef.current) { @@ -298,7 +316,7 @@ export default function FormModal({ }, [open]); function formatMessage(inputs: any): string { if (inputs) { - if(typeof inputs == "string") return inputs; + if (typeof inputs == "string") return inputs; // inputs is a object with the keys and values being input_keys and keysValue // so the formated message is a string with the keys and values separated by ": " let message = ""; @@ -382,53 +400,86 @@ export default function FormModal({
+
Input Variables
+ + Chat + +
- {Object.keys(tabsState[id.current].formKeysData.input_keys).map((i, k) => ( - - {i} - -
- {tabsState[id.current].formKeysData.handle_keys.some((t) => t === i) ?
Handle
: -
- - - handleOnCheckedChange(value, i) - } - size="small" - disabled={false} - /> -
- } - + {Object.keys(tabsState[id.current].formKeysData.input_keys).map( + (i, k) => ( +
+ + +
+ + {i} + + +
+ + handleOnCheckedChange(value, i) + } + size="small" + disabled={false} + />
- -
- ))} + + +
+ {tabsState[id.current].formKeysData.handle_keys.some( + (t) => t === i + ) ? ( +
+ Handle +
+ ) : ( + <> + )} + +
+
+ + +
+ ) + )} {tabsState[id.current].formKeysData.memory_keys.map((i, k) => (
-
{i}
+
+ + {i} + +
Used as Memory Key
@@ -437,14 +488,19 @@ export default function FormModal({
-
- -
+
+ +
{setChatValue(value); setTabsState((old) => { - let newTabsState = _.cloneDeep(old); - newTabsState[id.current].formKeysData.input_keys[chatKey] = chatValue; - return newTabsState; - });}} + setChatValue={(value) => { + setChatValue(value); + setTabsState((old) => { + let newTabsState = _.cloneDeep(old); + newTabsState[id.current].formKeysData.input_keys[ + chatKey + ] = chatValue; + return newTabsState; + }); + }} inputRef={ref} />
From 3ae84bea132369dae562ce7e6b12615e0b9efaf2 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 30 Jun 2023 06:46:00 -0300 Subject: [PATCH 108/367] =?UTF-8?q?=F0=9F=94=A7=20chore(validate.py):=20ad?= =?UTF-8?q?d=20display=5Fname=20field=20to=20TemplateField=20in=20post=5Fv?= =?UTF-8?q?alidate=5Fprompt=20function=20The=20display=5Fname=20field=20is?= =?UTF-8?q?=20added=20to=20the=20TemplateField=20object=20in=20the=20post?= =?UTF-8?q?=5Fvalidate=5Fprompt=20function.=20This=20field=20allows=20for?= =?UTF-8?q?=20a=20more=20user-friendly=20display=20of=20the=20variable=20n?= =?UTF-8?q?ame=20in=20the=20UI.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/validate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py index 184657a63..23fad5711 100644 --- a/src/backend/langflow/api/v1/validate.py +++ b/src/backend/langflow/api/v1/validate.py @@ -39,6 +39,7 @@ def post_validate_prompt(prompt: ValidatePromptRequest): try: template_field = TemplateField( name=variable, + display_name=variable, field_type="str", show=True, advanced=False, From 5520ecea7a7cfb473dbb400cfbeaaa5094ba1178 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 30 Jun 2023 10:31:03 -0300 Subject: [PATCH 109/367] =?UTF-8?q?=F0=9F=90=9B=20fix(formModal/index.tsx)?= =?UTF-8?q?:=20stop=20propagation=20of=20click=20event=20at=20the=20toggle?= =?UTF-8?q?=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/modals/formModal/index.tsx | 116 +++++++++++--------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 134536ac3..5ed82d0d7 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -401,74 +401,82 @@ export default function FormModal({
-
- - - Input Variables - -
- - Chat +
+ + + Input Variables + +
+ + Chat Input
{Object.keys(tabsState[id.current].formKeysData.input_keys).map( (i, k) => (
- - -
- - {i} - - -
- + +
+ + {i} + + +
{ + event.stopPropagation(); + }} + > + handleOnCheckedChange(value, i) } size="small" disabled={false} - />
-
-
- -
- {tabsState[id.current].formKeysData.handle_keys.some( - (t) => t === i - ) ? ( -
- Handle + />
- ) : ( - <> - )} - -
-
- - + ].formKeysData.handle_keys.some( + (t) => t === i + ) + ) + setTabsState((old) => { + let newTabsState = _.cloneDeep(old); + newTabsState[ + id.current + ].formKeysData.input_keys[i] = + e.target.value; + return newTabsState; + }); + }} + disabled={chatKey === i} + placeholder="Enter text..." + > +
+ +
) )} From fe1646791419c3fc92f31ad6d8a708237060a40d Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 30 Jun 2023 10:48:51 -0300 Subject: [PATCH 110/367] =?UTF-8?q?=F0=9F=90=9B=20fix(toggleShadComponent)?= =?UTF-8?q?:=20remove=20unused=20useEffect=20hook=20to=20improve=20code=20?= =?UTF-8?q?readability=20and=20maintainability=20=E2=9C=A8=20feat(toggleSh?= =?UTF-8?q?adComponent):=20add=20disabled=20prop=20to=20Switch=20component?= =?UTF-8?q?=20to=20disable=20interaction=20when=20disabled=20is=20true?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 fix(formModal): remove unused imports to improve code cleanliness ✨ feat(formModal): add MessageSquarePlus icon to represent chat input ✨ feat(formModal): add multiple collapsible accordions for input variables 🐛 fix(formModal): disable Toggle component when handle key is present in formKeysData --- .../components/toggleShadComponent/index.tsx | 8 +-- src/frontend/src/modals/formModal/index.tsx | 53 ++++++++++--------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/frontend/src/components/toggleShadComponent/index.tsx b/src/frontend/src/components/toggleShadComponent/index.tsx index 290a46cb4..6619c1d36 100644 --- a/src/frontend/src/components/toggleShadComponent/index.tsx +++ b/src/frontend/src/components/toggleShadComponent/index.tsx @@ -8,11 +8,6 @@ export default function ToggleShadComponent({ disabled, size, }: ToggleComponentType) { - useEffect(() => { - if (disabled) { - setEnabled(false); - } - }, [disabled, setEnabled]); let scaleX, scaleY; switch (size) { case "small": @@ -32,11 +27,12 @@ export default function ToggleShadComponent({ scaleY = 1; } return ( -
+
{ diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 5ed82d0d7..a41c53a46 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -4,7 +4,13 @@ import { alertContext } from "../../contexts/alertContext"; import { classNames, validateNodes } from "../../utils"; import { typesContext } from "../../contexts/typesContext"; import ChatMessage from "./chatMessage"; -import { TerminalSquare, MessageSquare, Variable, Eraser } from "lucide-react"; +import { + TerminalSquare, + MessageSquare, + Variable, + Eraser, + MessageSquarePlus, +} from "lucide-react"; import { sendAllProps } from "../../types/api"; import { ChatMessageType } from "../../types/chat"; import ChatInput from "./chatInput"; @@ -401,17 +407,20 @@ export default function FormModal({
-
- +
+ Input Variables
- - Chat Input - +
+ + + Chat Input + +
- + {Object.keys(tabsState[id.current].formKeysData.input_keys).map( (i, k) => (
@@ -434,7 +443,9 @@ export default function FormModal({ handleOnCheckedChange(value, i) } size="small" - disabled={false} + disabled={tabsState[ + id.current + ].formKeysData.handle_keys.some((t) => t === i)} />
@@ -443,33 +454,23 @@ export default function FormModal({
{tabsState[ id.current - ].formKeysData.handle_keys.some((t) => t === i) ? ( + ].formKeysData.handle_keys.some((t) => t === i) && (
- Handle + Source: Component
- ) : ( - <> )}