From d397f4457facb78262afc96387990c53da9cf5eb Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Wed, 2 Aug 2023 22:05:52 -0300 Subject: [PATCH 01/45] =?UTF-8?q?=F0=9F=94=80=20merge(base.py):=20add=20SQ?= =?UTF-8?q?LDatabaseChain=20to=20the=20ChainCreator's=20type=5Fdict=20to?= =?UTF-8?q?=20enable=20support=20for=20SQL=20database=20chains=20?= =?UTF-8?q?=F0=9F=93=A6=20chore(pyproject.toml):=20add=20langchain-experim?= =?UTF-8?q?ental=20package=20as=20a=20dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- poetry.lock | 16 +++++++++++++++- pyproject.toml | 1 + src/backend/langflow/interface/chains/base.py | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index b53c4820e..5564c1fdd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2890,6 +2890,20 @@ openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.4.0)"] qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] +[[package]] +name = "langchain-experimental" +version = "0.0.8" +description = "Building applications with LLMs through composability" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "langchain_experimental-0.0.8-py3-none-any.whl", hash = "sha256:34cf202ba29fdef178c5d68772cf2fa08dd2a0fad588ca3ef324ae71e596cc21"}, + {file = "langchain_experimental-0.0.8.tar.gz", hash = "sha256:35d198f8e70a053ccd84273198ff08b4b700ac03ec5f43ba9b7ef797dd42ad14"}, +] + +[package.dependencies] +langchain = ">=0.0.239" + [[package]] name = "langchain-serve" version = "0.0.58" @@ -7564,4 +7578,4 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.11" -content-hash = "154238df4e8b249196011f592d63e2fad0e18316960e400037f54453c813d47a" +content-hash = "57abce2ebcdc3cd7e359c36805822b9398d3bfb500c175b173a6d784d1276df6" diff --git a/pyproject.toml b/pyproject.toml index 849130a74..ef5360662 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,7 @@ google-cloud-aiplatform = "^1.26.1" psycopg = "^3.1.9" psycopg-binary = "^3.1.9" fastavro = "^1.8.0" +langchain-experimental = "^0.0.8" [tool.poetry.group.dev.dependencies] black = "^23.1.0" diff --git a/src/backend/langflow/interface/chains/base.py b/src/backend/langflow/interface/chains/base.py index 67d31308f..3ec8b9e4d 100644 --- a/src/backend/langflow/interface/chains/base.py +++ b/src/backend/langflow/interface/chains/base.py @@ -8,6 +8,7 @@ from langflow.template.frontend_node.chains import ChainFrontendNode from langflow.utils.logger import logger from langflow.utils.util import build_template_from_class, build_template_from_method from langchain import chains +from langchain_experimental.sql import SQLDatabaseChain # Assuming necessary imports for Field, Template, and FrontendNode classes @@ -35,6 +36,8 @@ class ChainCreator(LangChainTypeCreator): } from langflow.interface.chains.custom import CUSTOM_CHAINS + self.type_dict["SQLDatabaseChain"] = SQLDatabaseChain + self.type_dict.update(CUSTOM_CHAINS) # Filter according to settings.chains self.type_dict = { From f4829bf21d9ebf0c6347db40317cb01acf836568 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Wed, 2 Aug 2023 22:12:45 -0300 Subject: [PATCH 02/45] =?UTF-8?q?=F0=9F=94=80=20chore(base.py):=20import?= =?UTF-8?q?=20SQLDatabaseChain=20from=20langchain=5Fexperimental.sql=20wit?= =?UTF-8?q?h=20type=20ignore=20to=20suppress=20type=20checking=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/chains/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/chains/base.py b/src/backend/langflow/interface/chains/base.py index 3ec8b9e4d..56e040618 100644 --- a/src/backend/langflow/interface/chains/base.py +++ b/src/backend/langflow/interface/chains/base.py @@ -8,7 +8,7 @@ from langflow.template.frontend_node.chains import ChainFrontendNode from langflow.utils.logger import logger from langflow.utils.util import build_template_from_class, build_template_from_method from langchain import chains -from langchain_experimental.sql import SQLDatabaseChain +from langchain_experimental.sql import SQLDatabaseChain # type: ignore # Assuming necessary imports for Field, Template, and FrontendNode classes From d90b6c2691144e65dbff7184b21084ae90562448 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 11:43:18 -0300 Subject: [PATCH 03/45] =?UTF-8?q?=F0=9F=90=9B=20fix(types.py):=20change=20?= =?UTF-8?q?update=5Fdisplay=5Fname=5Fand=5Fdescription=20function=20name?= =?UTF-8?q?=20to=20update=5Fattributes=20to=20reflect=20its=20purpose=20mo?= =?UTF-8?q?re=20accurately=20=F0=9F=90=9B=20fix(component.py):=20change=20?= =?UTF-8?q?field=5Fconfig=20key=20to=20beta=20in=20template=5Fconfig=20dic?= =?UTF-8?q?tionary=20to=20match=20the=20expected=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/component.py | 4 ++-- src/backend/langflow/interface/types.py | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/backend/langflow/interface/custom/component.py b/src/backend/langflow/interface/custom/component.py index a9dc0f323..e18be4fa2 100644 --- a/src/backend/langflow/interface/custom/component.py +++ b/src/backend/langflow/interface/custom/component.py @@ -63,8 +63,8 @@ class Component(BaseModel): elif "description" in item_name: template_config["description"] = ast.literal_eval(item_value) - elif "field_config" in item_name: - template_config["field_config"] = ast.literal_eval(item_value) + elif "beta" in item_name: + template_config["beta"] = ast.literal_eval(item_value) return template_config diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index 46fa781d6..a0ad518bd 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -145,7 +145,7 @@ def add_code_field(template, raw_code, field_config): "dynamic": True, "required": True, "placeholder": "", - "show": True, + "show": field_config.pop("show", True), "multiline": True, "value": raw_code, "password": False, @@ -186,7 +186,7 @@ def build_frontend_node(custom_component: CustomComponent): return None -def update_display_name_and_description(frontend_node, template_config): +def update_attributes(frontend_node, template_config): """Update the display name and description of a frontend node""" if "display_name" in template_config: frontend_node["display_name"] = template_config["display_name"] @@ -194,6 +194,9 @@ def update_display_name_and_description(frontend_node, template_config): if "description" in template_config: frontend_node["description"] = template_config["description"] + if "beta" in template_config: + frontend_node["beta"] = template_config["beta"] + def build_field_config(custom_component: CustomComponent): """Build the field configuration for a custom component""" @@ -281,7 +284,7 @@ def build_langchain_template_custom_component(custom_component: CustomComponent) template_config = custom_component.build_template_config - update_display_name_and_description(frontend_node, template_config) + update_attributes(frontend_node, template_config) field_config = build_field_config(custom_component) add_extra_fields( From 9d3ea4f7794f613a043d2896b3a2eb406f59f6f5 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 11:47:40 -0300 Subject: [PATCH 04/45] =?UTF-8?q?=F0=9F=94=96=20chore(pyproject.toml):=20b?= =?UTF-8?q?ump=20version=20from=200.4.0=20to=200.4.1=20for=20langflow=20pa?= =?UTF-8?q?ckage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- poetry.lock | 79 +++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5564c1fdd..7d0da2cbc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -146,13 +146,13 @@ files = [ [[package]] name = "anthropic" -version = "0.3.7" +version = "0.3.8" description = "Client library for the anthropic API" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "anthropic-0.3.7-py3-none-any.whl", hash = "sha256:ca57635d7f13d609aa8a5b93a834e067760d96b9657bdf81e0c7444ddf41fc64"}, - {file = "anthropic-0.3.7.tar.gz", hash = "sha256:0453f80ba8224364c8b0dae0b5088becd67277de57708d7b887ebb6c2ceb3c49"}, + {file = "anthropic-0.3.8-py3-none-any.whl", hash = "sha256:97ffe1bacc4214dc89b19f496cf2769746971e86f7c835a05aa21b76f260d279"}, + {file = "anthropic-0.3.8.tar.gz", hash = "sha256:6651099807456c3b95b3879f5ad7d00f7e7e4f7649a2394d18032ab8be54ef16"}, ] [package.dependencies] @@ -924,13 +924,13 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "ctransformers" -version = "0.2.17" +version = "0.2.18" description = "Python bindings for the Transformer models implemented in C/C++ using GGML library." optional = true python-versions = "*" files = [ - {file = "ctransformers-0.2.17-py3-none-any.whl", hash = "sha256:903c16b38f5b2750ee34b90107c3a72351d7a9a201a6987a6560bd50874e9698"}, - {file = "ctransformers-0.2.17.tar.gz", hash = "sha256:0c9de34cc8295ba6cb940e413130e6658fac54a99cecfa6098ac04638fd9301e"}, + {file = "ctransformers-0.2.18-py3-none-any.whl", hash = "sha256:6d693e269d797f2485c86c9e8a322acb1464e782bf22547ec57e09d4ccbb4523"}, + {file = "ctransformers-0.2.18.tar.gz", hash = "sha256:fc09c399baf16d99dd44aa6671d49aa4060d8904324c2527aa58e8831476c370"}, ] [package.dependencies] @@ -938,6 +938,7 @@ huggingface-hub = "*" py-cpuinfo = ">=9.0.0,<10.0.0" [package.extras] +gptq = ["exllama (==0.1.0)"] tests = ["pytest"] [[package]] @@ -957,29 +958,29 @@ typing-inspect = ">=0.4.0,<1" [[package]] name = "debugpy" -version = "1.6.7" +version = "1.6.8" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.7" files = [ - {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"}, - {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"}, - {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"}, - {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"}, - {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"}, - {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"}, - {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"}, - {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"}, - {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"}, - {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"}, - {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"}, - {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"}, - {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"}, - {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"}, - {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"}, - {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"}, - {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"}, - {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"}, + {file = "debugpy-1.6.8-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:8c1f5a3286fb633f691c594649e9d2e8e30292c9eaf49e38d7da525151b33a83"}, + {file = "debugpy-1.6.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406b3a6cb7548d73260f69a511178ec9196779cafda68e563488c6f94cc88670"}, + {file = "debugpy-1.6.8-cp310-cp310-win32.whl", hash = "sha256:6830947f68b41cd6abe20941ec3303a8452c40ff5fe3637c6efe233e395ecebc"}, + {file = "debugpy-1.6.8-cp310-cp310-win_amd64.whl", hash = "sha256:1fe3baa28f5a14d8d2a60dded9ea088e27b33f1854ae9a0a1faa1ba03a8b7e47"}, + {file = "debugpy-1.6.8-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:5502e14de6b7241ecf7c4fa4ec6dd61d0824da7a09020c7ffe7be4cd09d36f24"}, + {file = "debugpy-1.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4a7193cec3f1e188963f6e8699e1187f758a0a4bbce511b3ad40caf618fc888"}, + {file = "debugpy-1.6.8-cp37-cp37m-win32.whl", hash = "sha256:591aac0e69bc75102d9f9294f1228e5d9ff9aa17b8c88e48b1bbb3dab8a54dcc"}, + {file = "debugpy-1.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:bb27b8e08f8e60705de6cf05b5da4c21e5a0bc2ca73f06fc36646f456df18ff5"}, + {file = "debugpy-1.6.8-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:6ca1c92e30e2aaeca156d5bd76e1587c23e332474a7b12e1900dd632b31ce05e"}, + {file = "debugpy-1.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959f9b8181a4c544b067daff8d881cd3ac4c7aec1a3a4f41f81c529795b3d864"}, + {file = "debugpy-1.6.8-cp38-cp38-win32.whl", hash = "sha256:4172383b961a2334d29168c7f7b24f2f99d29291a945016986c78a5683fba915"}, + {file = "debugpy-1.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:05d1b288167ce3bfc8e1912ebed036207a27b9569ae4476f18287902501689c6"}, + {file = "debugpy-1.6.8-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:95f7ce92450b72abcf0c479539a7d00c20e68f1f1fb447eef0b08d2a635d96d7"}, + {file = "debugpy-1.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f16bb157b6018ce6a23b64653a6b1892f046cc2b0576df1794c6b22f9fd82118"}, + {file = "debugpy-1.6.8-cp39-cp39-win32.whl", hash = "sha256:f7a80c50b89d8fb49c9e5b6ee28c0bfb822fbd33fef0f2f9843724d0d1984e4e"}, + {file = "debugpy-1.6.8-cp39-cp39-win_amd64.whl", hash = "sha256:2345beced3e79fd8ac4158e839a1604d5cccd19beb45561a1ffe2e5b33465f28"}, + {file = "debugpy-1.6.8-py2.py3-none-any.whl", hash = "sha256:1ca76d3ebb0e6368e107cf2e005e848d3c7705a5b513fdf65470a6f4e49a2de7"}, + {file = "debugpy-1.6.8.zip", hash = "sha256:3b7091d908dec70022b8966c32b1e9eaf183ff05291edf1d147fee153f4cb9f8"}, ] [[package]] @@ -1641,13 +1642,13 @@ six = "*" [[package]] name = "google-cloud-aiplatform" -version = "1.28.1" +version = "1.29.0" description = "Vertex AI API client library" optional = false python-versions = ">=3.7" files = [ - {file = "google-cloud-aiplatform-1.28.1.tar.gz", hash = "sha256:b6468db7dc50295c988edf6505f0bf4d4bb2321de28873b2a4a87fd384be6308"}, - {file = "google_cloud_aiplatform-1.28.1-py2.py3-none-any.whl", hash = "sha256:5587b8d4599047117b0c787635a00e8e3893b75944993e2faf784176442e9de4"}, + {file = "google-cloud-aiplatform-1.29.0.tar.gz", hash = "sha256:fceabb924d2d26057e3c8c5c2e251929389aa6d553361377bc402781150c0db3"}, + {file = "google_cloud_aiplatform-1.29.0-py2.py3-none-any.whl", hash = "sha256:cf81c1d93c61ccf3df60a65e3a5a1e465e044059d36b6fc1202b940c46c4c1e1"}, ] [package.dependencies] @@ -2561,12 +2562,12 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", [[package]] name = "jcloud" -version = "0.2.14" +version = "0.2.15" description = "Simplify deploying and managing Jina projects on Jina Cloud" optional = false python-versions = "*" files = [ - {file = "jcloud-0.2.14.tar.gz", hash = "sha256:60798a41be370cacf380bb024f04086df8b0e65f20e51b4fbe1dd11e04d95be7"}, + {file = "jcloud-0.2.15.tar.gz", hash = "sha256:be3af2d8c9c7746bc5e2d4a77a383b0401848bcb1a8d590ed0205d0c3baa230f"}, ] [package.dependencies] @@ -2931,13 +2932,13 @@ test = ["psutil", "pytest", "pytest-asyncio"] [[package]] name = "langsmith" -version = "0.0.16" +version = "0.0.18" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langsmith-0.0.16-py3-none-any.whl", hash = "sha256:a9a5b30dc1c0ee0c9f8bbd2076856f1db3856a9521464f130be1db519c7077e5"}, - {file = "langsmith-0.0.16.tar.gz", hash = "sha256:0729df30dd5b1c9d0c83614b5d348c7358ac182d7e3003dafbfcbedb88cbc8b8"}, + {file = "langsmith-0.0.18-py3-none-any.whl", hash = "sha256:58f3eb029495e3696c3c94c95adfb2dd15043d82928ef932a7829fe020ad5522"}, + {file = "langsmith-0.0.18.tar.gz", hash = "sha256:d8d97542f99352c5470bff74a4fbc9bd322dea850217a8ab71badcefa041566b"}, ] [package.dependencies] @@ -5491,13 +5492,13 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "qdrant-client" -version = "1.3.2" +version = "1.4.0" description = "Client library for the Qdrant vector search engine" optional = false python-versions = ">=3.7,<3.12" files = [ - {file = "qdrant_client-1.3.2-py3-none-any.whl", hash = "sha256:66a076016fb9d33bec8170e96516d7e4a0ee5c611824cc9be18590ffeb3cf9aa"}, - {file = "qdrant_client-1.3.2.tar.gz", hash = "sha256:6638c9eac027f2c0fdb1f63c3bd7b403fe8c3f73cb1f21fd15fd60f71012d537"}, + {file = "qdrant_client-1.4.0-py3-none-any.whl", hash = "sha256:2f9e563955b5163da98016f2ed38d9aea5058576c7c5844e9aa205d28155f56d"}, + {file = "qdrant_client-1.4.0.tar.gz", hash = "sha256:2e54f5a80eb1e7e67f4603b76365af4817af15fb3d0c0f44de4fd93afbbe5537"}, ] [package.dependencies] @@ -6394,13 +6395,13 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] [[package]] name = "textual" -version = "0.31.0" +version = "0.32.0" description = "Modern Text User Interface framework" optional = true python-versions = ">=3.7,<4.0" files = [ - {file = "textual-0.31.0-py3-none-any.whl", hash = "sha256:1243bccadb28e1ff46bdfe676ee25a6ce52756842bc9dca4d824e0bc4d7d9a42"}, - {file = "textual-0.31.0.tar.gz", hash = "sha256:e2b43f1c26b21731ee83f558f8d6cb4f7163e3a713854c36cd7785139a0e4e51"}, + {file = "textual-0.32.0-py3-none-any.whl", hash = "sha256:81fc68406c8806bc864e2f035874a868b4ff0cf466289dce5f7b31869949383b"}, + {file = "textual-0.32.0.tar.gz", hash = "sha256:f7b6683bc18faee6fd3c47cfbad43fbf8273c5fecc12230d52ce5ee089021327"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index ef5360662..a29ae46ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.4.0" +version = "0.4.1" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [ From 8db39dbb30cb1c4d05df9b74ad2fdce9b8853fe2 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 12:49:49 -0300 Subject: [PATCH 05/45] fix: :bug: fixes condition in release workflow --- .github/workflows/release.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 12f72f5f8..2a258949e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,9 +14,7 @@ env: jobs: if_release: - if: | - ${{ github.event.pull_request.merged == true }} - && ${{ contains(github.event.pull_request.labels.*.name, 'Release') }} + if: ${{ (github.event.pull_request.merged == true) && contains(github.event.pull_request.labels.*.name, 'Release') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From c11204d3c5e306a12c885ee537862f5f8f0a4353 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 13:48:57 -0300 Subject: [PATCH 06/45] =?UTF-8?q?=F0=9F=94=A7=20fix(directory=5Freader.py)?= =?UTF-8?q?:=20change=20component=20name=20from=20snake=5Fcase=20to=20Came?= =?UTF-8?q?lCase=20for=20better=20UI=20display=20=F0=9F=93=9D=20chore(dire?= =?UTF-8?q?ctory=5Freader.py):=20add=20comments=20to=20explain=20the=20pur?= =?UTF-8?q?pose=20of=20changing=20the=20component=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/directory_reader.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/custom/directory_reader.py b/src/backend/langflow/interface/custom/directory_reader.py index 3357d164f..309577544 100644 --- a/src/backend/langflow/interface/custom/directory_reader.py +++ b/src/backend/langflow/interface/custom/directory_reader.py @@ -224,9 +224,15 @@ class DirectoryReader: "path": os.path.dirname(file_path), "components": [], } + component_name = filename.split(".")[0] + # This is the name of the file which will be displayed in the UI + # We need to change it from snake_case to CamelCase + camel_case_name = " ".join( + word.title() for word in component_name.split("_") + ) component_info = { - "name": filename.split(".")[0], + "name": camel_case_name, "file": filename, "code": result_content if validation_result else "", "error": "" if validation_result else result_content, From ee63e5432d9226b29acbfd2d0c2fad1ae69373dd Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 14:22:20 -0300 Subject: [PATCH 07/45] =?UTF-8?q?=F0=9F=90=9B=20fix(directory=5Freader.py)?= =?UTF-8?q?:=20fix=20the=20name=20of=20the=20custom=20component=20to=20alw?= =?UTF-8?q?ays=20be=20"CustomComponent"=20for=20consistency=20=F0=9F=90=9B?= =?UTF-8?q?=20fix(directory=5Freader.py):=20add=20the=20output=20types=20o?= =?UTF-8?q?f=20the=20custom=20component=20to=20the=20component=20template?= =?UTF-8?q?=20to=20ensure=20correct=20behavior=20=F0=9F=90=9B=20fix(types.?= =?UTF-8?q?py):=20add=20the=20output=20types=20of=20the=20custom=20compone?= =?UTF-8?q?nt=20to=20the=20component=20template=20to=20ensure=20correct=20?= =?UTF-8?q?behavior?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/directory_reader.py | 5 +++-- src/backend/langflow/interface/types.py | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/interface/custom/directory_reader.py b/src/backend/langflow/interface/custom/directory_reader.py index 309577544..3613de5d4 100644 --- a/src/backend/langflow/interface/custom/directory_reader.py +++ b/src/backend/langflow/interface/custom/directory_reader.py @@ -227,12 +227,13 @@ class DirectoryReader: component_name = filename.split(".")[0] # This is the name of the file which will be displayed in the UI # We need to change it from snake_case to CamelCase - camel_case_name = " ".join( + component_name_camelcase = " ".join( word.title() for word in component_name.split("_") ) component_info = { - "name": camel_case_name, + "name": "CustomComponent", + "output_types": [component_name_camelcase], "file": filename, "code": result_content if validation_result else "", "error": "" if validation_result else result_content, diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index a0ad518bd..eb43d95b9 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -330,12 +330,14 @@ def build_valid_menu(valid_components): try: component_name = component["name"] component_code = component["code"] + component_output_types = component["output_types"] component_extractor = CustomComponent(code=component_code) component_extractor.is_check_valid() component_template = build_langchain_template_custom_component( component_extractor ) + component_template["output_types"] = component_output_types valid_menu[menu_name][component_name] = component_template From 6fbf7f7a545632e7a7235d225d3e55d408856d92 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 14:29:31 -0300 Subject: [PATCH 08/45] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20skip=20val?= =?UTF-8?q?ues=20with=20show=20=3D=3D=20False=20and=20key=20!=3D=20"code"?= =?UTF-8?q?=20when=20iterating=20over=20template=5Fdict=20to=20improve=20f?= =?UTF-8?q?iltering=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/graph/vertex/base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/graph/vertex/base.py b/src/backend/langflow/graph/vertex/base.py index 2c749b85f..57a890562 100644 --- a/src/backend/langflow/graph/vertex/base.py +++ b/src/backend/langflow/graph/vertex/base.py @@ -100,7 +100,9 @@ class Vertex: params[param_key] = edge.source for key, value in template_dict.items(): - if key == "_type" or not value.get("show"): + # Skip _type and any value that has show == False and is not code + # If we don't want to show code but we want to use it + if key == "_type" or (not value.get("show") and key != "code"): continue # If the type is not transformable to a python base class # then we need to get the edge that connects to this node From d1657eb9e73d890fcbe0066e2f8272ed9e28800f Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 14:32:00 -0300 Subject: [PATCH 09/45] =?UTF-8?q?=F0=9F=94=A5=20refactor(endpoints.py):=20?= =?UTF-8?q?remove=20unused=20imports=20and=20endpoints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following changes were made: - Removed unused imports from the file - Removed the unused `get_load_custom_component_from_path` endpoint - Removed the unused `get_load_custom_component_from_path_test` endpoint --- src/backend/langflow/api/v1/endpoints.py | 30 ------------------------ 1 file changed, 30 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index f11a23340..c8e3673a8 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -11,9 +11,6 @@ from fastapi import APIRouter, Depends, HTTPException, UploadFile, Body from langflow.interface.custom.custom_component import CustomComponent -from langflow.interface.custom.directory_reader import ( - CustomComponentPathValueError, -) from langflow.api.v1.schemas import ( ProcessResponse, @@ -39,7 +36,6 @@ router = APIRouter(tags=["Base"]) @router.get("/all") def get_all(): native_components = build_langchain_types_dict() - # custom_components is a list of dicts # need to merge all the keys into one dict custom_components_from_file = {} @@ -55,32 +51,6 @@ def get_all(): return merge_nested_dicts(native_components, custom_components_from_file) -@router.get("/load_custom_component_from_path") -def get_load_custom_component_from_path(path: str): - try: - data = build_langchain_custom_component_list_from_path(path) - except CustomComponentPathValueError as err: - raise HTTPException( - status_code=400, - detail={"error": type(err).__name__, "traceback": str(err)}, - ) from err - - return data - - -@router.get("/load_custom_component_from_path_TEST") -def get_load_custom_component_from_path_test(path: str): - from langflow.interface.custom.directory_reader import ( - DirectoryReader, - ) - - reader = DirectoryReader(path, False) - file_list = reader.get_files() - data = reader.build_component_menu_list(file_list) - - return reader.filter_loaded_components(data, True) - - # For backwards compatibility we will keep the old endpoint @router.post("/predict/{flow_id}", response_model=ProcessResponse) @router.post("/process/{flow_id}", response_model=ProcessResponse) From 18949de603dde776d77af2cb177d957f8a67bff9 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 15:27:43 -0300 Subject: [PATCH 10/45] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20handle=20p?= =?UTF-8?q?arsing=20of=20code=20type=20values=20in=20Vertex=20class=20to?= =?UTF-8?q?=20prevent=20errors=20and=20improve=20error=20logging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/graph/vertex/base.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/graph/vertex/base.py b/src/backend/langflow/graph/vertex/base.py index 57a890562..5139b6e90 100644 --- a/src/backend/langflow/graph/vertex/base.py +++ b/src/backend/langflow/graph/vertex/base.py @@ -1,3 +1,4 @@ +import ast from langflow.interface.initialize import loading from langflow.interface.listing import ALL_TYPES_DICT from langflow.utils.constants import DIRECT_TYPES @@ -114,7 +115,14 @@ class Vertex: params[key] = file_path elif value.get("type") in DIRECT_TYPES and params.get(key) is None: - params[key] = value.get("value") + if value.get("type") == "code": + try: + params[key] = ast.literal_eval(value.get("value")) + except Exception as exc: + logger.debug(f"Error parsing code: {exc}") + params[key] = value.get("value") + else: + params[key] = value.get("value") if not value.get("required") and params.get(key) is None: if value.get("default"): From dc8097ebd7ce0983802c542b60f92d6e384f1dff Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 3 Aug 2023 15:28:15 -0300 Subject: [PATCH 11/45] =?UTF-8?q?=F0=9F=94=A7=20fix(types.py):=20add=20exc?= =?UTF-8?q?eption=20handling=20when=20evaluating=20field=5Fvalue=20using?= =?UTF-8?q?=20ast.literal=5Feval=20to=20prevent=20potential=20errors=20?= =?UTF-8?q?=F0=9F=94=80=20chore(types.py):=20import=20ast=20and=20contextl?= =?UTF-8?q?ib=20modules=20for=20future=20use?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/types.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index eb43d95b9..e33e003d4 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -1,3 +1,5 @@ +import ast +import contextlib from typing import Any from langflow.interface.agents.base import agent_creator from langflow.interface.chains.base import chain_creator @@ -250,6 +252,8 @@ def get_field_properties(extra_field): if not field_required: field_type = extract_type_from_optional(field_type) + with contextlib.suppress(Exception): + field_value = ast.literal_eval(field_value) return field_name, field_type, field_value, field_required From 0a5ad3b06df2bf9450a93176709ca5c899012da3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:04:35 -0300 Subject: [PATCH 12/45] refactor settings --- src/backend/langflow/api/v1/endpoints.py | 4 +- src/backend/langflow/api/v1/flows.py | 2 +- src/backend/langflow/interface/agents/base.py | 2 +- src/backend/langflow/interface/base.py | 2 +- src/backend/langflow/interface/chains/base.py | 2 +- .../interface/document_loaders/base.py | 2 +- .../langflow/interface/embeddings/base.py | 2 +- src/backend/langflow/interface/llms/base.py | 2 +- .../langflow/interface/memories/base.py | 2 +- .../langflow/interface/output_parsers/base.py | 2 +- .../langflow/interface/prompts/base.py | 2 +- .../langflow/interface/retrievers/base.py | 2 +- .../langflow/interface/text_splitters/base.py | 2 +- .../langflow/interface/toolkits/base.py | 2 +- src/backend/langflow/interface/tools/base.py | 2 +- .../langflow/interface/utilities/base.py | 2 +- src/backend/langflow/interface/utils.py | 2 +- .../langflow/interface/vector_store/base.py | 2 +- src/backend/langflow/settings.py | 143 ++++++++++-------- tests/test_graph.py | 11 +- tests/test_llms_template.py | 2 +- tests/test_prompts_template.py | 2 +- tests/test_vectorstore_template.py | 2 +- 23 files changed, 109 insertions(+), 89 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index c8e3673a8..296a549c8 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -39,10 +39,10 @@ def get_all(): # custom_components is a list of dicts # need to merge all the keys into one dict custom_components_from_file = {} - if settings.components_path: + if settings.COMPONENTS_PATH: custom_component_dicts = [ build_langchain_custom_component_list_from_path(str(path)) - for path in settings.components_path + for path in settings.COMPONENTS_PATH ] for custom_component_dict in custom_component_dicts: custom_components_from_file = merge_nested_dicts( diff --git a/src/backend/langflow/api/v1/flows.py b/src/backend/langflow/api/v1/flows.py index 4e000a128..9f5042fcb 100644 --- a/src/backend/langflow/api/v1/flows.py +++ b/src/backend/langflow/api/v1/flows.py @@ -61,7 +61,7 @@ def update_flow( if not db_flow: raise HTTPException(status_code=404, detail="Flow not found") flow_data = flow.dict(exclude_unset=True) - if settings.remove_api_keys: + if settings.REMOVE_API_KEYS: flow_data = remove_api_keys(flow_data) for key, value in flow_data.items(): setattr(db_flow, key, value) diff --git a/src/backend/langflow/interface/agents/base.py b/src/backend/langflow/interface/agents/base.py index b272144bc..cc5214c0c 100644 --- a/src/backend/langflow/interface/agents/base.py +++ b/src/backend/langflow/interface/agents/base.py @@ -59,7 +59,7 @@ class AgentCreator(LangChainTypeCreator): if hasattr(agent, "function_name") else agent.__name__ ) - if agent_name in settings.agents or settings.dev: + if agent_name in settings.AGENTS or settings.DEV: names.append(agent_name) return names diff --git a/src/backend/langflow/interface/base.py b/src/backend/langflow/interface/base.py index e6a28bf7d..76d859b1f 100644 --- a/src/backend/langflow/interface/base.py +++ b/src/backend/langflow/interface/base.py @@ -28,7 +28,7 @@ class LangChainTypeCreator(BaseModel, ABC): """A dict with the name of the component as key and the documentation link as value.""" if self.name_docs_dict is None: try: - type_settings = getattr(settings, self.type_name) + type_settings = getattr(settings, self.type_name.upper()) self.name_docs_dict = { name: value_dict["documentation"] for name, value_dict in type_settings.items() diff --git a/src/backend/langflow/interface/chains/base.py b/src/backend/langflow/interface/chains/base.py index 56e040618..fe58397b2 100644 --- a/src/backend/langflow/interface/chains/base.py +++ b/src/backend/langflow/interface/chains/base.py @@ -43,7 +43,7 @@ class ChainCreator(LangChainTypeCreator): self.type_dict = { name: chain for name, chain in self.type_dict.items() - if name in settings.chains or settings.dev + if name in settings.CHAINS or settings.DEV } return self.type_dict diff --git a/src/backend/langflow/interface/document_loaders/base.py b/src/backend/langflow/interface/document_loaders/base.py index 5219fbd13..ebae1e5a4 100644 --- a/src/backend/langflow/interface/document_loaders/base.py +++ b/src/backend/langflow/interface/document_loaders/base.py @@ -33,7 +33,7 @@ class DocumentLoaderCreator(LangChainTypeCreator): return [ documentloader.__name__ for documentloader in self.type_to_loader_dict.values() - if documentloader.__name__ in settings.documentloaders or settings.dev + if documentloader.__name__ in settings.DOCUMENTLOADERS or settings.DEV ] diff --git a/src/backend/langflow/interface/embeddings/base.py b/src/backend/langflow/interface/embeddings/base.py index 1dfa05a99..7572a06cc 100644 --- a/src/backend/langflow/interface/embeddings/base.py +++ b/src/backend/langflow/interface/embeddings/base.py @@ -35,7 +35,7 @@ class EmbeddingCreator(LangChainTypeCreator): return [ embedding.__name__ for embedding in self.type_to_loader_dict.values() - if embedding.__name__ in settings.embeddings or settings.dev + if embedding.__name__ in settings.EMBEDDINGS or settings.DEV ] diff --git a/src/backend/langflow/interface/llms/base.py b/src/backend/langflow/interface/llms/base.py index 66e153880..06aedd3cb 100644 --- a/src/backend/langflow/interface/llms/base.py +++ b/src/backend/langflow/interface/llms/base.py @@ -36,7 +36,7 @@ class LLMCreator(LangChainTypeCreator): return [ llm.__name__ for llm in self.type_to_loader_dict.values() - if llm.__name__ in settings.llms or settings.dev + if llm.__name__ in settings.LLMS or settings.DEV ] diff --git a/src/backend/langflow/interface/memories/base.py b/src/backend/langflow/interface/memories/base.py index 0f97a02fe..9cd25381c 100644 --- a/src/backend/langflow/interface/memories/base.py +++ b/src/backend/langflow/interface/memories/base.py @@ -51,7 +51,7 @@ class MemoryCreator(LangChainTypeCreator): return [ memory.__name__ for memory in self.type_to_loader_dict.values() - if memory.__name__ in settings.memories or settings.dev + if memory.__name__ in settings.MEMORIES or settings.DEV ] diff --git a/src/backend/langflow/interface/output_parsers/base.py b/src/backend/langflow/interface/output_parsers/base.py index 79cbdd98c..b5235ad58 100644 --- a/src/backend/langflow/interface/output_parsers/base.py +++ b/src/backend/langflow/interface/output_parsers/base.py @@ -33,7 +33,7 @@ class OutputParserCreator(LangChainTypeCreator): self.type_dict = { name: output_parser for name, output_parser in self.type_dict.items() - if name in settings.output_parsers or settings.dev + if name in settings.OUTPUT_PARSERS or settings.DEV } return self.type_dict diff --git a/src/backend/langflow/interface/prompts/base.py b/src/backend/langflow/interface/prompts/base.py index 39bd94c5b..c062a4a35 100644 --- a/src/backend/langflow/interface/prompts/base.py +++ b/src/backend/langflow/interface/prompts/base.py @@ -34,7 +34,7 @@ class PromptCreator(LangChainTypeCreator): self.type_dict = { name: prompt for name, prompt in self.type_dict.items() - if name in settings.prompts or settings.dev + if name in settings.PROMPTS or settings.DEV } return self.type_dict diff --git a/src/backend/langflow/interface/retrievers/base.py b/src/backend/langflow/interface/retrievers/base.py index dc6056656..759cd5916 100644 --- a/src/backend/langflow/interface/retrievers/base.py +++ b/src/backend/langflow/interface/retrievers/base.py @@ -51,7 +51,7 @@ class RetrieverCreator(LangChainTypeCreator): return [ retriever for retriever in self.type_to_loader_dict.keys() - if retriever in settings.retrievers or settings.dev + if retriever in settings.RETRIEVERS or settings.DEV ] diff --git a/src/backend/langflow/interface/text_splitters/base.py b/src/backend/langflow/interface/text_splitters/base.py index 203f30086..787f20d82 100644 --- a/src/backend/langflow/interface/text_splitters/base.py +++ b/src/backend/langflow/interface/text_splitters/base.py @@ -33,7 +33,7 @@ class TextSplitterCreator(LangChainTypeCreator): return [ textsplitter.__name__ for textsplitter in self.type_to_loader_dict.values() - if textsplitter.__name__ in settings.textsplitters or settings.dev + if textsplitter.__name__ in settings.TEXTSPLITTERS or settings.DEV ] diff --git a/src/backend/langflow/interface/toolkits/base.py b/src/backend/langflow/interface/toolkits/base.py index be2345c02..b7c165a4d 100644 --- a/src/backend/langflow/interface/toolkits/base.py +++ b/src/backend/langflow/interface/toolkits/base.py @@ -35,7 +35,7 @@ class ToolkitCreator(LangChainTypeCreator): ) # if toolkit_name is not lower case it is a class for toolkit_name in agent_toolkits.__all__ - if not toolkit_name.islower() and toolkit_name in settings.toolkits + if not toolkit_name.islower() and toolkit_name in settings.TOOLKITS } return self.type_dict diff --git a/src/backend/langflow/interface/tools/base.py b/src/backend/langflow/interface/tools/base.py index f8965134d..8c9158c05 100644 --- a/src/backend/langflow/interface/tools/base.py +++ b/src/backend/langflow/interface/tools/base.py @@ -74,7 +74,7 @@ class ToolCreator(LangChainTypeCreator): tool_name = tool_params.get("name") or tool - if tool_name in settings.tools or settings.dev: + if tool_name in settings.TOOLS or settings.DEV: if tool_name == "JsonSpec": tool_params["path"] = tool_params.pop("dict_") # type: ignore all_tools[tool_name] = { diff --git a/src/backend/langflow/interface/utilities/base.py b/src/backend/langflow/interface/utilities/base.py index 6c12b0186..b0ee4d4be 100644 --- a/src/backend/langflow/interface/utilities/base.py +++ b/src/backend/langflow/interface/utilities/base.py @@ -35,7 +35,7 @@ class UtilityCreator(LangChainTypeCreator): self.type_dict = { name: utility for name, utility in self.type_dict.items() - if name in settings.utilities or settings.dev + if name in settings.UTILITIES or settings.DEV } return self.type_dict diff --git a/src/backend/langflow/interface/utils.py b/src/backend/langflow/interface/utils.py index 9203915cf..c6650ac60 100644 --- a/src/backend/langflow/interface/utils.py +++ b/src/backend/langflow/interface/utils.py @@ -69,7 +69,7 @@ def setup_llm_caching(): try: set_langchain_cache(settings) except ImportError: - logger.warning(f"Could not import {settings.cache}. ") + logger.warning(f"Could not import {settings.CACHE}. ") except Exception as exc: logger.warning(f"Could not setup LLM caching. Error: {exc}") diff --git a/src/backend/langflow/interface/vector_store/base.py b/src/backend/langflow/interface/vector_store/base.py index 7ec1e0f5b..4a937ba89 100644 --- a/src/backend/langflow/interface/vector_store/base.py +++ b/src/backend/langflow/interface/vector_store/base.py @@ -46,7 +46,7 @@ class VectorstoreCreator(LangChainTypeCreator): return [ vectorstore for vectorstore in self.type_to_loader_dict.keys() - if vectorstore in settings.vectorstores or settings.dev + if vectorstore in settings.VECTORSTORES or settings.DEV ] diff --git a/src/backend/langflow/settings.py b/src/backend/langflow/settings.py index 08400a811..e0f2200b9 100644 --- a/src/backend/langflow/settings.py +++ b/src/backend/langflow/settings.py @@ -3,69 +3,76 @@ from typing import Optional, List from pathlib import Path import yaml -from pydantic import BaseSettings, root_validator +from pydantic import BaseSettings, root_validator, validator from langflow.utils.logger import logger BASE_COMPONENTS_PATH = Path(__file__).parent / "components" class Settings(BaseSettings): - chains: dict = {} - agents: dict = {} - prompts: dict = {} - llms: dict = {} - tools: dict = {} - memories: dict = {} - embeddings: dict = {} - vectorstores: dict = {} - documentloaders: dict = {} - wrappers: dict = {} - retrievers: dict = {} - toolkits: dict = {} - textsplitters: dict = {} - utilities: dict = {} - output_parsers: dict = {} - custom_components: dict = {} + CHAINS: dict = {} + AGENTS: dict = {} + PROMPTS: dict = {} + LLMS: dict = {} + TOOLS: dict = {} + MEMORIES: dict = {} + EMBEDDINGS: dict = {} + VECTORSTORES: dict = {} + DOCUMENTLOADERS: dict = {} + WRAPPERS: dict = {} + RETRIEVERS: dict = {} + TOOLKITS: dict = {} + TEXTSPLITTERS: dict = {} + UTILITIES: dict = {} + OUTPUT_PARSERS: dict = {} + CUSTOM_COMPONENTS: dict = {} - dev: bool = False - database_url: Optional[str] = None - cache: str = "InMemoryCache" - remove_api_keys: bool = False - components_path: List[Path] + DEV: bool = False + DATABASE_URL: Optional[str] = None + CACHE: str = "InMemoryCache" + REMOVE_API_KEYS: bool = False + COMPONENTS_PATH: List[Path] = [] - @root_validator(pre=True) - def set_env_variables(cls, values): - if "database_url" not in values: + @validator("DATABASE_URL", pre=True) + def set_database_url(cls, value): + if not value: logger.debug( "No database_url provided, trying LANGFLOW_DATABASE_URL env variable" ) if langflow_database_url := os.getenv("LANGFLOW_DATABASE_URL"): - values["database_url"] = langflow_database_url + value = langflow_database_url + logger.debug("Using LANGFLOW_DATABASE_URL env variable.") else: logger.debug("No DATABASE_URL env variable, using sqlite database") - values["database_url"] = "sqlite:///./langflow.db" + value = "sqlite:///./langflow.db" - if not values.get("components_path"): - values["components_path"] = [BASE_COMPONENTS_PATH] - logger.debug("No components_path provided, using default components path") - elif BASE_COMPONENTS_PATH not in values["components_path"]: - values["components_path"].append(BASE_COMPONENTS_PATH) - logger.debug("Adding default components path to components_path") + return value + @validator("COMPONENTS_PATH", pre=True) + def set_components_path(cls, value): if os.getenv("LANGFLOW_COMPONENTS_PATH"): logger.debug("Adding LANGFLOW_COMPONENTS_PATH to components_path") langflow_component_path = Path(os.getenv("LANGFLOW_COMPONENTS_PATH")) if ( langflow_component_path.exists() - and langflow_component_path not in values["components_path"] + and langflow_component_path not in value ): - values["components_path"].append(langflow_component_path) + value.append(langflow_component_path) logger.debug(f"Adding {langflow_component_path} to components_path") - return values + + if not value: + value = [BASE_COMPONENTS_PATH] + logger.debug("No components_path provided, using default components path") + elif BASE_COMPONENTS_PATH not in value: + value.append(BASE_COMPONENTS_PATH) + logger.debug("Adding default components path to components_path") + + return value class Config: validate_assignment = True extra = "ignore" + env_prefix = "LANGFLOW_" @root_validator(allow_reuse=True) def validate_lists(cls, values): @@ -76,35 +83,43 @@ class Settings(BaseSettings): def update_from_yaml(self, file_path: str, dev: bool = False): new_settings = load_settings_from_yaml(file_path) - self.chains = new_settings.chains or {} - self.agents = new_settings.agents or {} - self.prompts = new_settings.prompts or {} - self.llms = new_settings.llms or {} - self.tools = new_settings.tools or {} - self.memories = new_settings.memories or {} - self.wrappers = new_settings.wrappers or {} - self.toolkits = new_settings.toolkits or {} - self.textsplitters = new_settings.textsplitters or {} - self.utilities = new_settings.utilities or {} - self.embeddings = new_settings.embeddings or {} - self.vectorstores = new_settings.vectorstores or {} - self.documentloaders = new_settings.documentloaders or {} - self.retrievers = new_settings.retrievers or {} - self.output_parsers = new_settings.output_parsers or {} - self.custom_components = new_settings.custom_components or {} - self.components_path = new_settings.components_path or [] - self.dev = dev + self.CHAINS = new_settings.CHAINS or {} + self.AGENTS = new_settings.AGENTS or {} + self.PROMPTS = new_settings.PROMPTS or {} + self.LLMS = new_settings.LLMS or {} + self.TOOLS = new_settings.TOOLS or {} + self.MEMORIES = new_settings.MEMORIES or {} + self.WRAPPERS = new_settings.WRAPPERS or {} + self.TOOLKITS = new_settings.TOOLKITS or {} + self.TEXTSPLITTERS = new_settings.TEXTSPLITTERS or {} + self.UTILITIES = new_settings.UTILITIES or {} + self.EMBEDDINGS = new_settings.EMBEDDINGS or {} + self.VECTORSTORES = new_settings.VECTORSTORES or {} + self.DOCUMENTLOADERS = new_settings.DOCUMENTLOADERS or {} + self.RETRIEVERS = new_settings.RETRIEVERS or {} + self.OUTPUT_PARSERS = new_settings.OUTPUT_PARSERS or {} + self.CUSTOM_COMPONENTS = new_settings.CUSTOM_COMPONENTS or {} + self.COMPONENTS_PATH = new_settings.COMPONENTS_PATH or [] + self.DEV = dev def update_settings(self, **kwargs): + logger.debug("Updating settings") for key, value in kwargs.items(): - if hasattr(self, key): - if isinstance(getattr(self, key), list): - if isinstance(value, list): - getattr(self, key).extend(value) - else: - getattr(self, key).append(value) + # value may contain sensitive information, so we don't want to log it + if not hasattr(self, key): + logger.debug(f"Key {key} not found in settings") + continue + logger.debug(f"Updating {key}") + if isinstance(getattr(self, key), list): + if isinstance(value, list): + getattr(self, key).extend(value) + logger.debug(f"Extended {key}") else: - setattr(self, key, value) + getattr(self, key).append(value) + logger.debug(f"Appended {key}") + else: + setattr(self, key, value) + logger.debug(f"Updated {key}") def save_settings_to_yaml(settings: Settings, file_path: str): @@ -123,6 +138,12 @@ def load_settings_from_yaml(file_path: str) -> Settings: with open(file_path, "r") as f: settings_dict = yaml.safe_load(f) + settings_dict = {k.upper(): v for k, v in settings_dict.items()} + + for key in settings_dict: + if key not in Settings.__fields__.keys(): + raise KeyError(f"Key {key} not found in settings") + logger.debug(f"Loading {len(settings_dict[key])} {key} from {file_path}") return Settings(**settings_dict) diff --git a/tests/test_graph.py b/tests/test_graph.py index 228bbb4d6..f3efe3614 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -12,7 +12,6 @@ from langflow.graph.vertex.types import ( FileToolVertex, LLMVertex, ToolkitVertex, - WrapperVertex, ) from langflow.processing.process import get_result_and_thought from langflow.utils.payload import get_root_node @@ -292,11 +291,11 @@ def test_file_tool_node_build(openapi_graph): assert not Path(file_path).exists() -def test_wrapper_node_build(openapi_graph): - wrapper_node = get_node_by_type(openapi_graph, WrapperVertex) - assert wrapper_node is not None - built_object = wrapper_node.build() - assert built_object is not None +# def test_wrapper_node_build(openapi_graph): +# wrapper_node = get_node_by_type(openapi_graph, WrapperVertex) +# assert wrapper_node is not None +# built_object = wrapper_node.build() +# assert built_object is not None def test_get_result_and_thought(basic_graph): diff --git a/tests/test_llms_template.py b/tests/test_llms_template.py index 6bb1bc28d..d8f9e96f3 100644 --- a/tests/test_llms_template.py +++ b/tests/test_llms_template.py @@ -7,7 +7,7 @@ def test_llms_settings(client: TestClient): assert response.status_code == 200 json_response = response.json() llms = json_response["llms"] - assert set(llms.keys()) == set(settings.llms) + assert set(llms.keys()) == set(settings.LLMS) # def test_hugging_face_hub(client: TestClient): diff --git a/tests/test_prompts_template.py b/tests/test_prompts_template.py index afc595a41..fa7a683bd 100644 --- a/tests/test_prompts_template.py +++ b/tests/test_prompts_template.py @@ -7,7 +7,7 @@ def test_prompts_settings(client: TestClient): assert response.status_code == 200 json_response = response.json() prompts = json_response["prompts"] - assert set(prompts.keys()) == set(settings.prompts) + assert set(prompts.keys()) == set(settings.PROMPTS) def test_prompt_template(client: TestClient): diff --git a/tests/test_vectorstore_template.py b/tests/test_vectorstore_template.py index 0aa823786..bac950ee1 100644 --- a/tests/test_vectorstore_template.py +++ b/tests/test_vectorstore_template.py @@ -9,4 +9,4 @@ def test_vectorstores_settings(client: TestClient): assert response.status_code == 200 json_response = response.json() vectorstores = json_response["vectorstores"] - assert set(vectorstores.keys()) == set(settings.vectorstores) + assert set(vectorstores.keys()) == set(settings.VECTORSTORES) From c64d469a833d88a61a4a3d44ace6f1cae04d3570 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:05:03 -0300 Subject: [PATCH 13/45] =?UTF-8?q?=F0=9F=94=A7=20chore(=5F=5Fmain=5F=5F.py)?= =?UTF-8?q?:=20remove=20unused=20database=5Furl=20parameter=20and=20relate?= =?UTF-8?q?d=20code=20for=20simplification=20=F0=9F=94=A7=20chore(=5F=5Fma?= =?UTF-8?q?in=5F=5F.py):=20remove=20unused=20env=5Ffile=20parameter=20and?= =?UTF-8?q?=20related=20code=20for=20simplification=20=F0=9F=94=A7=20chore?= =?UTF-8?q?(=5F=5Fmain=5F=5F.py):=20remove=20unused=20imports=20and=20vari?= =?UTF-8?q?ables=20for=20cleaner=20code=20=F0=9F=94=A7=20chore(=5F=5Fmain?= =?UTF-8?q?=5F=5F.py):=20remove=20unused=20load=5Fparams=20function=20for?= =?UTF-8?q?=20code=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/__main__.py | 47 ++++++++------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/src/backend/langflow/__main__.py b/src/backend/langflow/__main__.py index 58789908a..fa167f188 100644 --- a/src/backend/langflow/__main__.py +++ b/src/backend/langflow/__main__.py @@ -1,4 +1,3 @@ -import os import sys import time import httpx @@ -25,49 +24,25 @@ def update_settings( config: str, cache: str, dev: bool = False, - database_url: Optional[str] = None, remove_api_keys: bool = False, components_path: Optional[Path] = None, ): """Update the settings from a config file.""" # Check for database_url in the environment variables - database_url = database_url or os.getenv("langflow_database_url") if config: logger.debug(f"Loading settings from {config}") settings.update_from_yaml(config, dev=dev) - if database_url: - settings.update_settings(database_url=database_url) if remove_api_keys: logger.debug(f"Setting remove_api_keys to {remove_api_keys}") - settings.update_settings(remove_api_keys=remove_api_keys) + settings.update_settings(REMOVE_API_KEYS=remove_api_keys) if cache: logger.debug(f"Setting cache to {cache}") - settings.update_settings(cache=cache) + settings.update_settings(CACHE=cache) if components_path: logger.debug(f"Adding component path {components_path}") - settings.update_settings(components_path=components_path) - - -def load_params(): - """ - Load the parameters from the environment variables. - """ - global_vars = globals() - - for key, value in global_vars.items(): - env_key = f"LANGFLOW_{key.upper()}" - if env_key in os.environ: - if isinstance(value, bool): - # Handle booleans - global_vars[key] = os.getenv(env_key, str(value)).lower() == "true" - elif isinstance(value, int): - # Handle integers - global_vars[key] = int(os.getenv(env_key, str(value))) - elif isinstance(value, str) or value is None: - # Handle strings and None values - global_vars[key] = os.getenv(env_key, str(value)) + settings.update_settings(COMPONENTS_PATH=components_path) def serve_on_jcloud(): @@ -134,7 +109,7 @@ def serve( config: str = typer.Option("config.yaml", help="Path to the configuration file."), # .env file param env_file: Path = typer.Option( - ".env", help="Path to the .env file containing environment variables." + None, help="Path to the .env file containing environment variables." ), log_level: str = typer.Option( "critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL" @@ -149,11 +124,13 @@ def serve( ), jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"), dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"), - database_url: str = typer.Option( - None, - help="Database URL to connect to. If not provided, a local SQLite database will be used.", - envvar="LANGFLOW_DATABASE_URL", - ), + # This variable does not work but is set by the .env file + # and works with Pydantic + # database_url: str = typer.Option( + # None, + # help="Database URL to connect to. If not provided, a local SQLite database will be used.", + # envvar="LANGFLOW_DATABASE_URL", + # ), path: str = typer.Option( None, help="Path to the frontend directory containing build files. This is for development purposes only.", @@ -176,7 +153,6 @@ def serve( # override env variables with .env file if env_file: load_dotenv(env_file, override=True) - load_params() if jcloud: return serve_on_jcloud() @@ -185,7 +161,6 @@ def serve( update_settings( config, dev=dev, - database_url=database_url, remove_api_keys=remove_api_keys, cache=cache, components_path=components_path, From b0346bd405325098a288474207201165fb64ab47 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:05:43 -0300 Subject: [PATCH 14/45] =?UTF-8?q?=F0=9F=94=A7=20chore(main.py):=20import?= =?UTF-8?q?=20Engine=20from=20langflow.database.base=20to=20fix=20missing?= =?UTF-8?q?=20reference=20error=20=E2=9C=A8=20feat(main.py):=20add=20Engin?= =?UTF-8?q?e.update=20as=20a=20startup=20event=20to=20update=20the=20engin?= =?UTF-8?q?e=20on=20app=20startup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 43a63d564..5b3341693 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -6,7 +6,7 @@ from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from langflow.api import router -from langflow.database.base import create_db_and_tables +from langflow.database.base import create_db_and_tables, Engine from langflow.interface.utils import setup_llm_caching from langflow.utils.logger import configure @@ -34,6 +34,7 @@ def create_app(): ) app.include_router(router) + app.on_event("startup")(Engine.update) app.on_event("startup")(create_db_and_tables) app.on_event("startup")(setup_llm_caching) return app From bc69e7ae4889f0440b68b632e5a9c72386ffe6f2 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:06:57 -0300 Subject: [PATCH 15/45] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20refactor?= =?UTF-8?q?=20database=20engine=20creation=20and=20retrieval=20to=20use=20?= =?UTF-8?q?a=20singleton=20pattern=20for=20better=20performance=20and=20ma?= =?UTF-8?q?intainability=20=E2=9C=A8=20feat(base.py):=20add=20support=20fo?= =?UTF-8?q?r=20LANGFLOW=5FDATABASE=5FURL=20environment=20variable=20to=20o?= =?UTF-8?q?verride=20the=20database=20URL=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/database/base.py | 49 +++++++++++++++++++++------ 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/backend/langflow/database/base.py b/src/backend/langflow/database/base.py index 338298a6b..546c341c1 100644 --- a/src/backend/langflow/database/base.py +++ b/src/backend/langflow/database/base.py @@ -1,21 +1,48 @@ from contextlib import contextmanager -from langflow.settings import settings +import os + from sqlmodel import SQLModel, Session, create_engine from langflow.utils.logger import logger -if settings.database_url and settings.database_url.startswith("sqlite"): - connect_args = {"check_same_thread": False} -else: - connect_args = {} -if not settings.database_url: - raise RuntimeError("No database_url provided") -engine = create_engine(settings.database_url, connect_args=connect_args) + +class Engine: + _instance = None + + @classmethod + def get(cls): + logger.debug("Getting database engine") + if cls._instance is None: + cls.create() + return cls._instance + + @classmethod + def create(cls): + logger.debug("Creating database engine") + from langflow.settings import settings + + if langflow_database_url := os.getenv("LANGFLOW_DATABASE_URL"): + settings.DATABASE_URL = langflow_database_url + logger.debug("Using LANGFLOW_DATABASE_URL") + + if settings.DATABASE_URL and settings.DATABASE_URL.startswith("sqlite"): + connect_args = {"check_same_thread": False} + else: + connect_args = {} + if not settings.DATABASE_URL: + raise RuntimeError("No database_url provided") + cls._instance = create_engine(settings.DATABASE_URL, connect_args=connect_args) + + @classmethod + def update(cls): + logger.debug("Updating database engine") + cls._instance = None + cls.create() def create_db_and_tables(): logger.debug("Creating database and tables") try: - SQLModel.metadata.create_all(engine) + SQLModel.metadata.create_all(Engine.get()) except Exception as exc: logger.error(f"Error creating database and tables: {exc}") raise RuntimeError("Error creating database and tables") from exc @@ -23,7 +50,7 @@ def create_db_and_tables(): # and we need to create the tables again. from sqlalchemy import inspect - inspector = inspect(engine) + inspector = inspect(Engine.get()) if "flow" not in inspector.get_table_names(): logger.error("Something went wrong creating the database and tables.") logger.error("Please check your database settings.") @@ -36,7 +63,7 @@ def create_db_and_tables(): @contextmanager def session_getter(): try: - session = Session(engine) + session = Session(Engine.get()) yield session except Exception as e: print("Session rollback because of exception:", e) From 3ce502f2981ead18cd6020471d91d90831a27a64 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:07:49 -0300 Subject: [PATCH 16/45] =?UTF-8?q?=F0=9F=90=9B=20fix(types.py):=20fix=20pro?= =?UTF-8?q?mpt=20template=20formatting=20to=20handle=20missing=20artifacts?= =?UTF-8?q?=20gracefully?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/graph/vertex/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/graph/vertex/types.py b/src/backend/langflow/graph/vertex/types.py index 5aee7b14c..b7ac17983 100644 --- a/src/backend/langflow/graph/vertex/types.py +++ b/src/backend/langflow/graph/vertex/types.py @@ -226,7 +226,11 @@ class PromptVertex(Vertex): # so the prompt format doesn't break artifacts.pop("handle_keys", None) try: - template = self._built_object.format(**artifacts) + template = self._built_object.template + for key, value in artifacts.items(): + if value: + replace_key = "{" + key + "}" + template = template.replace(replace_key, value) return ( template if isinstance(template, str) From 7a82519262bbb715d9ab6af0c903a47a9955e8c0 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:09:39 -0300 Subject: [PATCH 17/45] =?UTF-8?q?=F0=9F=90=9B=20fix(loading.py):=20import?= =?UTF-8?q?=20handle=5Fpartial=5Fvariables=20function=20to=20fix=20NameErr?= =?UTF-8?q?or=20when=20using=20it=20in=20instantiate=5Fprompt=20function?= =?UTF-8?q?=20=F0=9F=90=9B=20fix(utils.py):=20add=20handle=5Fpartial=5Fvar?= =?UTF-8?q?iables=20function=20to=20handle=20partial=20variables=20in=20pr?= =?UTF-8?q?ompt=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/initialize/loading.py | 9 ++++++++- src/backend/langflow/interface/initialize/utils.py | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/initialize/loading.py b/src/backend/langflow/interface/initialize/loading.py index f52b2e56c..974b9c454 100644 --- a/src/backend/langflow/interface/initialize/loading.py +++ b/src/backend/langflow/interface/initialize/loading.py @@ -6,7 +6,11 @@ from langchain.agents.agent import AgentExecutor from langchain.agents.agent_toolkits.base import BaseToolkit from langchain.agents.tools import BaseTool from langflow.interface.initialize.llm import initialize_vertexai -from langflow.interface.initialize.utils import handle_format_kwargs, handle_node_type +from langflow.interface.initialize.utils import ( + handle_format_kwargs, + handle_node_type, + handle_partial_variables, +) from langflow.interface.initialize.vector_store import vecstore_initializer @@ -217,6 +221,9 @@ def instantiate_agent(node_type, class_object: Type[agent_module.Agent], params: def instantiate_prompt(node_type, class_object, params: Dict): params, prompt = handle_node_type(node_type, class_object, params) format_kwargs = handle_format_kwargs(prompt, params) + # Now we'll use partial_format to format the prompt + if format_kwargs: + prompt = handle_partial_variables(prompt, format_kwargs) return prompt, format_kwargs diff --git a/src/backend/langflow/interface/initialize/utils.py b/src/backend/langflow/interface/initialize/utils.py index 31fbc6d8b..976d8906c 100644 --- a/src/backend/langflow/interface/initialize/utils.py +++ b/src/backend/langflow/interface/initialize/utils.py @@ -44,6 +44,16 @@ def handle_format_kwargs(prompt, params: Dict): return format_kwargs +def handle_partial_variables(prompt, format_kwargs: Dict): + partial_variables = format_kwargs.copy() + partial_variables = { + key: value for key, value in partial_variables.items() if value + } + # Remove handle_keys otherwise LangChain raises an error + partial_variables.pop("handle_keys", None) + return prompt.partial(**partial_variables) + + def handle_variable(params: Dict, input_variable: str, format_kwargs: Dict): variable = params[input_variable] if isinstance(variable, str): From d99bcbd80b4fe1ee91206a114711307b02899906 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:11:00 -0300 Subject: [PATCH 18/45] =?UTF-8?q?=E2=9C=A8=20feat(prompt=5Frunner.py):=20a?= =?UTF-8?q?dd=20PromptRunner=20component=20to=20run=20a=20Chain=20with=20a?= =?UTF-8?q?=20given=20PromptTemplate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/chains/prompt_runner.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/backend/langflow/components/chains/prompt_runner.py diff --git a/src/backend/langflow/components/chains/prompt_runner.py b/src/backend/langflow/components/chains/prompt_runner.py new file mode 100644 index 000000000..ebc1d0167 --- /dev/null +++ b/src/backend/langflow/components/chains/prompt_runner.py @@ -0,0 +1,31 @@ +from langflow import CustomComponent + +from langchain.llms.base import BaseLLM +from langchain import PromptTemplate +from langchain.schema import Document + + +class PromptRunner(CustomComponent): + display_name: str = "Prompt Runner" + description: str = "Run a Chain with the given PromptTemplate" + beta = True + field_config = { + "llm": {"display_name": "LLM"}, + "prompt": { + "display_name": "Prompt Template", + "info": "Make sure the prompt has all variables filled.", + }, + "code": {"show": False}, + "inputs": {"field_type": "code"}, + } + + def build( + self, + llm: BaseLLM, + prompt: PromptTemplate, + ) -> Document: + chain = prompt | llm + result = chain.invoke() + result = result[chain.output_key] + self.repr_value = result + return Document(page_content=str(result)) From 3fe6a029fcaeeb43c07f09a04d42a3f3731c0ee3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:11:28 -0300 Subject: [PATCH 19/45] =?UTF-8?q?=F0=9F=93=9D=20docs(README.md):=20update?= =?UTF-8?q?=20CLI=20options=20section=20to=20remove=20`--database-url`=20o?= =?UTF-8?q?ption?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `--database-url` option has been removed from the CLI options. Instead, a local SQLite database will be used if no database URL is provided. This change simplifies the configuration process and aligns with the default behavior. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index dcd91e075..3d795015d 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ - [HuggingFace Spaces](#huggingface-spaces) - [🖥️ Command Line Interface (CLI)](#️-command-line-interface-cli) - [Usage](#usage) - - [Environment Variables](#environment-variables) + - [Environment Variables](#environment-variables) - [Deployment](#deployment) - [Deploy Langflow on Google Cloud Platform](#deploy-langflow-on-google-cloud-platform) - [Deploy Langflow on Jina AI Cloud](#deploy-langflow-on-jina-ai-cloud) @@ -112,7 +112,6 @@ Each option is detailed below: - `--cache`: Selects the type of cache to use. Options are `InMemoryCache` and `SQLiteCache`. Can be set using the `LANGFLOW_LANGCHAIN_CACHE` environment variable. The default is `SQLiteCache`. - `--jcloud/--no-jcloud`: Toggles the option to deploy on Jina AI Cloud. The default is `no-jcloud`. - `--dev/--no-dev`: Toggles the development mode. The default is `no-dev`. -- `--database-url`: Sets the database URL to connect to. If not provided, a local SQLite database will be used. Can be set using the `LANGFLOW_DATABASE_URL` environment variable. - `--path`: Specifies the path to the frontend directory containing build files. This option is for development purposes only. Can be set using the `LANGFLOW_FRONTEND_PATH` environment variable. - `--open-browser/--no-open-browser`: Toggles the option to open the browser after starting the server. Can be set using the `LANGFLOW_OPEN_BROWSER` environment variable. The default is `open-browser`. - `--remove-api-keys/--no-remove-api-keys`: Toggles the option to remove API keys from the projects saved in the database. Can be set using the `LANGFLOW_REMOVE_API_KEYS` environment variable. The default is `no-remove-api-keys`. From d5a33d56bf838f3eb33a134ec2be3a98e7e8ebef Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:19:52 -0300 Subject: [PATCH 20/45] =?UTF-8?q?=F0=9F=94=A5=20refactor(component.py):=20?= =?UTF-8?q?remove=20unused=20build=20method=20from=20Component=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🔥 refactor(custom_component.py): remove unused build method from CustomComponent class --- src/backend/langflow/interface/custom/component.py | 3 --- src/backend/langflow/interface/custom/custom_component.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/backend/langflow/interface/custom/component.py b/src/backend/langflow/interface/custom/component.py index e18be4fa2..0ba90650f 100644 --- a/src/backend/langflow/interface/custom/component.py +++ b/src/backend/langflow/interface/custom/component.py @@ -67,6 +67,3 @@ class Component(BaseModel): template_config["beta"] = ast.literal_eval(item_value) return template_config - - def build(self): - raise NotImplementedError diff --git a/src/backend/langflow/interface/custom/custom_component.py b/src/backend/langflow/interface/custom/custom_component.py index 4d65070bf..27c3340cf 100644 --- a/src/backend/langflow/interface/custom/custom_component.py +++ b/src/backend/langflow/interface/custom/custom_component.py @@ -189,6 +189,3 @@ class CustomComponent(Component, extra=Extra.allow): if not flow: raise ValueError(f"Flow {flow_name or flow_id} not found") return self.load_flow(flow.id, tweaks) - - def build(self): - raise NotImplementedError From 0cf1fb09a9618c452ba21445c35cd59c2a85d4a5 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 00:20:16 -0300 Subject: [PATCH 21/45] =?UTF-8?q?=F0=9F=90=9B=20fix(prompt=5Frunner.py):?= =?UTF-8?q?=20fix=20issue=20with=20accessing=20result=20content=20when=20i?= =?UTF-8?q?nvoking=20chain=20with=20an=20empty=20dict=20input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/components/chains/prompt_runner.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/components/chains/prompt_runner.py b/src/backend/langflow/components/chains/prompt_runner.py index ebc1d0167..141941c38 100644 --- a/src/backend/langflow/components/chains/prompt_runner.py +++ b/src/backend/langflow/components/chains/prompt_runner.py @@ -25,7 +25,9 @@ class PromptRunner(CustomComponent): prompt: PromptTemplate, ) -> Document: chain = prompt | llm - result = chain.invoke() - result = result[chain.output_key] + # The input is an empty dict because the prompt is already filled + result = chain.invoke({}) + if hasattr(result, "content"): + result = result.content self.repr_value = result return Document(page_content=str(result)) From 91ce0189278dfa5dd3c8b82b93d84e972feef1d2 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 07:45:45 -0300 Subject: [PATCH 22/45] =?UTF-8?q?=F0=9F=94=A7=20chore(settings.py):=20upda?= =?UTF-8?q?te=20debug=20log=20messages=20for=20setting=20default=20compone?= =?UTF-8?q?nts=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/settings.py b/src/backend/langflow/settings.py index e0f2200b9..6b878dc42 100644 --- a/src/backend/langflow/settings.py +++ b/src/backend/langflow/settings.py @@ -62,7 +62,7 @@ class Settings(BaseSettings): if not value: value = [BASE_COMPONENTS_PATH] - logger.debug("No components_path provided, using default components path") + logger.debug("Setting default components path to components_path") elif BASE_COMPONENTS_PATH not in value: value.append(BASE_COMPONENTS_PATH) logger.debug("Adding default components path to components_path") From e9400c04df3b6a2daac96a806beda6df38f5415b Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 07:49:42 -0300 Subject: [PATCH 23/45] =?UTF-8?q?=F0=9F=94=80=20chore(utils.py):=20rename?= =?UTF-8?q?=20`cache`=20variable=20to=20`CACHE`=20for=20consistency=20with?= =?UTF-8?q?=20other=20settings=20=F0=9F=94=80=20chore(utils.py):=20rename?= =?UTF-8?q?=20`LANGFLOW=5FLANGCHAIN=5FCACHE`=20environment=20variable=20to?= =?UTF-8?q?=20`CACHE`=20for=20clarity=20and=20consistency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/langflow/interface/utils.py b/src/backend/langflow/interface/utils.py index c6650ac60..d6c7b9023 100644 --- a/src/backend/langflow/interface/utils.py +++ b/src/backend/langflow/interface/utils.py @@ -74,13 +74,12 @@ def setup_llm_caching(): logger.warning(f"Could not setup LLM caching. Error: {exc}") -# TODO Rename this here and in `setup_llm_caching` def set_langchain_cache(settings): import langchain from langflow.interface.importing.utils import import_class cache_type = os.getenv("LANGFLOW_LANGCHAIN_CACHE") - cache_class = import_class(f"langchain.cache.{cache_type or settings.cache}") + cache_class = import_class(f"langchain.cache.{cache_type or settings.CACHE}") logger.debug(f"Setting up LLM caching with {cache_class.__name__}") langchain.llm_cache = cache_class() From 840629bef492d19d163ea163f6db84f5172c2974 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 08:31:36 -0300 Subject: [PATCH 24/45] =?UTF-8?q?=F0=9F=94=A7=20chore(constants.py):=20imp?= =?UTF-8?q?ort=20BaseOutputParser=20from=20langchain.schema=20to=20use=20i?= =?UTF-8?q?t=20in=20LANGCHAIN=5FBASE=5FTYPES?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/langflow/interface/custom/constants.py b/src/backend/langflow/interface/custom/constants.py index 0e747d0ca..83cf4b463 100644 --- a/src/backend/langflow/interface/custom/constants.py +++ b/src/backend/langflow/interface/custom/constants.py @@ -7,6 +7,7 @@ from langchain.schema import BaseRetriever, Document from langchain.text_splitter import TextSplitter from langchain.tools import Tool from langchain.vectorstores.base import VectorStore +from langchain.schema import BaseOutputParser LANGCHAIN_BASE_TYPES = { @@ -20,6 +21,7 @@ LANGCHAIN_BASE_TYPES = { "VectorStore": VectorStore, "Embeddings": Embeddings, "BaseRetriever": BaseRetriever, + "BaseOutputParser": BaseOutputParser, } # Langchain base types plus Python base types From a1cca2afc884c35b3a03783955d899342d90394e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 08:33:39 -0300 Subject: [PATCH 25/45] =?UTF-8?q?=F0=9F=94=A8=20refactor(custom=5Fcomponen?= =?UTF-8?q?t.py):=20read=20build=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/custom_component.py | 3 +++ src/backend/langflow/interface/types.py | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/custom/custom_component.py b/src/backend/langflow/interface/custom/custom_component.py index 27c3340cf..b1d7a5e76 100644 --- a/src/backend/langflow/interface/custom/custom_component.py +++ b/src/backend/langflow/interface/custom/custom_component.py @@ -189,3 +189,6 @@ class CustomComponent(Component, extra=Extra.allow): if not flow: raise ValueError(f"Flow {flow_name or flow_id} not found") return self.load_flow(flow.id, tweaks) + + def build(self, *args: Any, **kwargs: Any) -> Any: + raise NotImplementedError diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index e33e003d4..7fa25414b 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -331,6 +331,7 @@ def build_valid_menu(valid_components): valid_menu[menu_name] = {} for component in menu_item["components"]: + logger.debug(f"Building component: {component}") try: component_name = component["name"] component_code = component["code"] @@ -346,7 +347,10 @@ def build_valid_menu(valid_components): valid_menu[menu_name][component_name] = component_template except Exception as exc: - logger.error(f"Error while building custom component: {exc}") + logger.error(f"Error loading Component: {component}") + logger.exception( + f"Error while building custom component {component_output_types}: {exc}" + ) return valid_menu From 941ec72fc1e79fa42ed2182ab50aa74590a7024d Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 08:34:01 -0300 Subject: [PATCH 26/45] =?UTF-8?q?=E2=9C=A8=20feat(components):=20add=20new?= =?UTF-8?q?=20custom=20component=20and=20chains=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added a new file `__init__.py` in the `components` directory to import the `CustomComponent` class from `langflow.interface.custom.custom_component`. - Created a new package `chains` in the `components` directory. --- src/backend/langflow/components/__init__.py | 4 ++++ src/backend/langflow/components/chains/__init__.py | 0 2 files changed, 4 insertions(+) create mode 100644 src/backend/langflow/components/__init__.py create mode 100644 src/backend/langflow/components/chains/__init__.py diff --git a/src/backend/langflow/components/__init__.py b/src/backend/langflow/components/__init__.py new file mode 100644 index 000000000..765042210 --- /dev/null +++ b/src/backend/langflow/components/__init__.py @@ -0,0 +1,4 @@ +from langflow.interface.custom.custom_component import CustomComponent + + +__all__ = ["CustomComponent"] diff --git a/src/backend/langflow/components/chains/__init__.py b/src/backend/langflow/components/chains/__init__.py new file mode 100644 index 000000000..e69de29bb From 2efa7022f0b97c4fe3248aa2eb6f4574e787b554 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 08:34:25 -0300 Subject: [PATCH 27/45] =?UTF-8?q?=F0=9F=94=A7=20fix(settings.py):=20conver?= =?UTF-8?q?t=20BASE=5FCOMPONENTS=5FPATH=20to=20string=20to=20ensure=20comp?= =?UTF-8?q?atibility=20with=20other=20parts=20of=20the=20codebase=20?= =?UTF-8?q?=F0=9F=94=A7=20fix(settings.py):=20update=20COMPONENTS=5FPATH?= =?UTF-8?q?=20to=20accept=20a=20list=20of=20strings=20instead=20of=20a=20l?= =?UTF-8?q?ist=20of=20Paths=20to=20improve=20flexibility=20and=20compatibi?= =?UTF-8?q?lity=20=F0=9F=94=A7=20fix(settings.py):=20update=20set=5Fcompon?= =?UTF-8?q?ents=5Fpath=20method=20to=20handle=20LANGFLOW=5FCOMPONENTS=5FPA?= =?UTF-8?q?TH=20as=20a=20list=20of=20paths=20or=20a=20single=20path=20stri?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/settings.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/backend/langflow/settings.py b/src/backend/langflow/settings.py index 6b878dc42..18c4a01de 100644 --- a/src/backend/langflow/settings.py +++ b/src/backend/langflow/settings.py @@ -6,7 +6,7 @@ import yaml from pydantic import BaseSettings, root_validator, validator from langflow.utils.logger import logger -BASE_COMPONENTS_PATH = Path(__file__).parent / "components" +BASE_COMPONENTS_PATH = str(Path(__file__).parent / "components") class Settings(BaseSettings): @@ -31,7 +31,7 @@ class Settings(BaseSettings): DATABASE_URL: Optional[str] = None CACHE: str = "InMemoryCache" REMOVE_API_KEYS: bool = False - COMPONENTS_PATH: List[Path] = [] + COMPONENTS_PATH: List[str] = [] @validator("DATABASE_URL", pre=True) def set_database_url(cls, value): @@ -52,12 +52,15 @@ class Settings(BaseSettings): def set_components_path(cls, value): if os.getenv("LANGFLOW_COMPONENTS_PATH"): logger.debug("Adding LANGFLOW_COMPONENTS_PATH to components_path") - langflow_component_path = Path(os.getenv("LANGFLOW_COMPONENTS_PATH")) + langflow_component_path = os.getenv("LANGFLOW_COMPONENTS_PATH") if ( - langflow_component_path.exists() + Path(langflow_component_path).exists() and langflow_component_path not in value ): - value.append(langflow_component_path) + if isinstance(langflow_component_path, list): + value.extend(langflow_component_path) + else: + value.append(langflow_component_path) logger.debug(f"Adding {langflow_component_path} to components_path") if not value: From e985b15af6a47d9847065a8cae8bf9b0edd6822c Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 08:36:53 -0300 Subject: [PATCH 28/45] =?UTF-8?q?=F0=9F=90=9B=20fix(types.py):=20update=20?= =?UTF-8?q?error=20message=20to=20include=20the=20output=20types=20of=20th?= =?UTF-8?q?e=20component=20that=20failed=20to=20load=20for=20better=20debu?= =?UTF-8?q?gging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index 7fa25414b..fff429733 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -347,7 +347,7 @@ def build_valid_menu(valid_components): valid_menu[menu_name][component_name] = component_template except Exception as exc: - logger.error(f"Error loading Component: {component}") + logger.error(f"Error loading Component: {component['output_types']}") logger.exception( f"Error while building custom component {component_output_types}: {exc}" ) From 56dfa2015cbe3be937ff439827b5d357ff9fabfc Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:51:41 -0300 Subject: [PATCH 29/45] =?UTF-8?q?=F0=9F=90=9B=20fix(settings.py):=20fix=20?= =?UTF-8?q?issue=20with=20extending=20components=5Fpath=20list=20with=20du?= =?UTF-8?q?plicate=20paths=20=E2=9C=A8=20feat(settings.py):=20add=20loggin?= =?UTF-8?q?g=20of=20components=5Fpath=20and=20updated=20settings=20values?= =?UTF-8?q?=20for=20debugging=20purposes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/settings.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/backend/langflow/settings.py b/src/backend/langflow/settings.py index 18c4a01de..439b3a1e4 100644 --- a/src/backend/langflow/settings.py +++ b/src/backend/langflow/settings.py @@ -1,3 +1,5 @@ +import contextlib +import json import os from typing import Optional, List from pathlib import Path @@ -58,10 +60,17 @@ class Settings(BaseSettings): and langflow_component_path not in value ): if isinstance(langflow_component_path, list): - value.extend(langflow_component_path) - else: + for path in langflow_component_path: + if path not in value: + value.append(path) + logger.debug( + f"Extending {langflow_component_path} to components_path" + ) + elif langflow_component_path not in value: value.append(langflow_component_path) - logger.debug(f"Adding {langflow_component_path} to components_path") + logger.debug( + f"Appending {langflow_component_path} to components_path" + ) if not value: value = [BASE_COMPONENTS_PATH] @@ -70,6 +79,7 @@ class Settings(BaseSettings): value.append(BASE_COMPONENTS_PATH) logger.debug("Adding default components path to components_path") + logger.debug(f"Components path: {value}") return value class Config: @@ -114,15 +124,22 @@ class Settings(BaseSettings): continue logger.debug(f"Updating {key}") if isinstance(getattr(self, key), list): + # value might be a '[something]' string + with contextlib.suppress(json.decoder.JSONDecodeError): + value = json.loads(str(value)) if isinstance(value, list): - getattr(self, key).extend(value) + for item in value: + if item not in getattr(self, key): + getattr(self, key).append(item) logger.debug(f"Extended {key}") else: getattr(self, key).append(value) logger.debug(f"Appended {key}") + else: setattr(self, key, value) logger.debug(f"Updated {key}") + logger.debug(f"{key}: {getattr(self, key)}") def save_settings_to_yaml(settings: Settings, file_path: str): From d3fab9ac445cc2ccf0f39fe7a0e43b205a7fc879 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:52:07 -0300 Subject: [PATCH 30/45] =?UTF-8?q?=F0=9F=94=A7=20fix(endpoints.py):=20add?= =?UTF-8?q?=20logging=20statements=20to=20improve=20debugging=20and=20moni?= =?UTF-8?q?toring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🔧 fix(endpoints.py): add logging statements to improve debugging and monitoring in the get_all() function --- src/backend/langflow/api/v1/endpoints.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 296a549c8..f4817d12a 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -35,19 +35,24 @@ router = APIRouter(tags=["Base"]) @router.get("/all") def get_all(): + logger.debug("Building langchain types dict") native_components = build_langchain_types_dict() # custom_components is a list of dicts # need to merge all the keys into one dict custom_components_from_file = {} if settings.COMPONENTS_PATH: + logger.info(f"Building custom components from {settings.COMPONENTS_PATH}") custom_component_dicts = [ build_langchain_custom_component_list_from_path(str(path)) for path in settings.COMPONENTS_PATH ] + logger.info(f"Loading {len(custom_component_dicts)} custom components") + for custom_component_dict in custom_component_dicts: custom_components_from_file = merge_nested_dicts( custom_components_from_file, custom_component_dict ) + logger.info(f"Loaded {custom_component_dict}") return merge_nested_dicts(native_components, custom_components_from_file) From 27c7923ee33be472a92b046a861f0ca50a187810 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:52:31 -0300 Subject: [PATCH 31/45] =?UTF-8?q?=F0=9F=94=A8=20refactor(types.py):=20add?= =?UTF-8?q?=20logging=20statements=20for=20debugging=20purposes=20in=20bui?= =?UTF-8?q?ld=5Flangchain=5Ftemplate=5Fcustom=5Fcomponent=20function=20?= =?UTF-8?q?=F0=9F=94=A8=20refactor(types.py):=20add=20logging=20statements?= =?UTF-8?q?=20for=20debugging=20purposes=20in=20build=5Fand=5Fvalidate=5Fa?= =?UTF-8?q?ll=5Ffiles=20function=20=F0=9F=94=A8=20refactor(types.py):=20ad?= =?UTF-8?q?d=20logging=20statements=20for=20debugging=20purposes=20in=20bu?= =?UTF-8?q?ild=5Fvalid=5Fmenu=20function=20=F0=9F=94=A8=20refactor(types.p?= =?UTF-8?q?y):=20add=20logging=20statements=20for=20debugging=20purposes?= =?UTF-8?q?=20in=20build=5Finvalid=5Fmenu=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/types.py | 27 +++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index fff429733..ad91bc596 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -281,28 +281,30 @@ def add_base_classes(frontend_node, return_type): def build_langchain_template_custom_component(custom_component: CustomComponent): """Build a custom component template for the langchain""" + logger.debug("Building custom component template") frontend_node = build_frontend_node(custom_component) if frontend_node is None: return None - + logger.debug("Built base frontend node") template_config = custom_component.build_template_config update_attributes(frontend_node, template_config) - + logger.debug("Updated attributes") field_config = build_field_config(custom_component) + logger.debug("Built field config") add_extra_fields( frontend_node, field_config, custom_component.get_function_entrypoint_args ) - + logger.debug("Added extra fields") frontend_node = add_code_field( frontend_node, custom_component.code, field_config.get("code", {}) ) - + logger.debug("Added code field") add_base_classes( frontend_node, custom_component.get_function_entrypoint_return_type ) - + logger.debug("Added base classes") return frontend_node @@ -313,7 +315,7 @@ def load_files_from_path(path: str): return reader.get_files() -def build_and_validate_all_files(reader, file_list): +def build_and_validate_all_files(reader: DirectoryReader, file_list): """Build and validate all files""" data = reader.build_component_menu_list(file_list) @@ -326,6 +328,7 @@ def build_and_validate_all_files(reader, file_list): def build_valid_menu(valid_components): """Build the valid menu""" valid_menu = {} + logger.debug("------------------- VALID COMPONENTS -------------------") for menu_item in valid_components["menu"]: menu_name = menu_item["name"] valid_menu[menu_name] = {} @@ -339,12 +342,14 @@ def build_valid_menu(valid_components): component_extractor = CustomComponent(code=component_code) component_extractor.is_check_valid() + component_template = build_langchain_template_custom_component( component_extractor ) component_template["output_types"] = component_output_types - valid_menu[menu_name][component_name] = component_template + valid_menu[menu_name][component.get("file")] = component_template + logger.debug(f"Added {component_name} to valid menu to {menu_name}") except Exception as exc: logger.error(f"Error loading Component: {component['output_types']}") @@ -357,6 +362,8 @@ def build_valid_menu(valid_components): def build_invalid_menu(invalid_components): """Build the invalid menu""" + if invalid_components.get("menu"): + logger.debug("------------------- INVALID COMPONENTS -------------------") invalid_menu = {} for menu_item in invalid_components["menu"]: menu_name = menu_item["name"] @@ -377,12 +384,16 @@ def build_invalid_menu(invalid_components): ) component_template["error"] = component.get("error", None) + logger.debug(component) + logger.debug(f"Component Path: {component.get('path', None)}") + logger.debug(f"Component Error: {component.get('error', None)}") component_template.get("template").get("code")["value"] = component_code invalid_menu[menu_name][component_name] = component_template + logger.debug(f"Added {component_name} to invalid menu to {menu_name}") except Exception as exc: - logger.error( + logger.exception( f"Error while creating custom component [{component_name}]: {str(exc)}" ) From 2f776cc882577257eca83beab3a02ae9a1566704 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:53:50 -0300 Subject: [PATCH 32/45] =?UTF-8?q?=F0=9F=94=A7=20chore(component.py):=20add?= =?UTF-8?q?=20missing=20import=20for=20'Any'=20type=20in=20typing=20module?= =?UTF-8?q?=20to=20fix=20type=20hinting=20=F0=9F=9A=80=20feat(component.py?= =?UTF-8?q?):=20add=20'build'=20method=20to=20Component=20class=20to=20enf?= =?UTF-8?q?orce=20implementation=20in=20subclasses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/component.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/custom/component.py b/src/backend/langflow/interface/custom/component.py index 0ba90650f..d122eb6da 100644 --- a/src/backend/langflow/interface/custom/component.py +++ b/src/backend/langflow/interface/custom/component.py @@ -1,5 +1,5 @@ import ast -from typing import Optional +from typing import Any, Optional from pydantic import BaseModel from fastapi import HTTPException @@ -67,3 +67,6 @@ class Component(BaseModel): template_config["beta"] = ast.literal_eval(item_value) return template_config + + def build(self, *args: Any, **kwargs: Any) -> Any: + raise NotImplementedError From e08d62e6e9a5f55239de89a62e0ae45eaa5c7f6f Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:55:10 -0300 Subject: [PATCH 33/45] =?UTF-8?q?=F0=9F=94=A7=20fix(directory=5Freader.py)?= =?UTF-8?q?:=20fix=20typo=20in=20variable=20name=20'filtered'=20to=20impro?= =?UTF-8?q?ve=20code=20readability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interface/custom/directory_reader.py | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/backend/langflow/interface/custom/directory_reader.py b/src/backend/langflow/interface/custom/directory_reader.py index 3613de5d4..57bb3ca95 100644 --- a/src/backend/langflow/interface/custom/directory_reader.py +++ b/src/backend/langflow/interface/custom/directory_reader.py @@ -1,6 +1,7 @@ import os import ast import zlib +from langflow.utils.logger import logger class CustomComponentPathValueError(ValueError): @@ -74,8 +75,11 @@ class DirectoryReader: } for menu in data["menu"] ] - filtred = [menu for menu in items if menu["components"]] - return {"menu": filtred} + filtered = [menu for menu in items if menu["components"]] + logger.debug( + f'Filtered components {"with errors" if with_errors else ""}: {filtered}' + ) + return {"menu": filtered} def validate_code(self, file_content): """ @@ -116,7 +120,7 @@ class DirectoryReader: file_list.extend( os.path.join(root, filename) for filename in files - if filename.endswith(".py") + if filename.endswith(".py") and not filename.startswith("__") ) return file_list @@ -213,11 +217,16 @@ class DirectoryReader: from the .py files in the directory. """ response = {"menu": []} + logger.debug( + "-------------------- Building component menu list --------------------" + ) for file_path in file_paths: menu_name = os.path.basename(os.path.dirname(file_path)) + logger.debug(f"Menu name: {menu_name}") filename = os.path.basename(file_path) validation_result, result_content = self.process_file(file_path) + logger.debug(f"Validation result: {validation_result}") menu_result = self.find_menu(response, menu_name) or { "name": menu_name, @@ -227,9 +236,14 @@ class DirectoryReader: component_name = filename.split(".")[0] # This is the name of the file which will be displayed in the UI # We need to change it from snake_case to CamelCase - component_name_camelcase = " ".join( - word.title() for word in component_name.split("_") - ) + + # first check if it's already CamelCase + if "_" in component_name: + component_name_camelcase = " ".join( + word.title() for word in component_name.split("_") + ) + else: + component_name_camelcase = component_name component_info = { "name": "CustomComponent", @@ -240,7 +254,10 @@ class DirectoryReader: } menu_result["components"].append(component_info) + logger.debug(f"Component info: {component_info}") if menu_result not in response["menu"]: response["menu"].append(menu_result) - + logger.debug( + "-------------------- Component menu list built --------------------" + ) return response From e23e58f7f7e0a4c0caf06a3cbdfd4f324cf6c35a Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:55:32 -0300 Subject: [PATCH 34/45] =?UTF-8?q?=F0=9F=90=9B=20fix(utils.py):=20simplify?= =?UTF-8?q?=20import=5Fcustom=5Fcomponent=20function=20by=20directly=20imp?= =?UTF-8?q?orting=20the=20CustomComponent=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/importing/utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/backend/langflow/interface/importing/utils.py b/src/backend/langflow/interface/importing/utils.py index 0acb2cff5..d07222dd1 100644 --- a/src/backend/langflow/interface/importing/utils.py +++ b/src/backend/langflow/interface/importing/utils.py @@ -61,9 +61,7 @@ def import_by_type(_type: str, name: str) -> Any: def import_custom_component(custom_component: str) -> CustomComponent: """Import custom component from custom component name""" - return import_class( - f"langflow.interface.custom.custom_component.{custom_component}" - ) + return import_class("langflow.interface.custom.custom_component.CustomComponent") def import_output_parser(output_parser: str) -> Any: From 1a02e6170103fc071e32c054fa58bea6b9bd48e9 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 09:55:55 -0300 Subject: [PATCH 35/45] =?UTF-8?q?=F0=9F=94=A7=20chore(loading.py):=20add?= =?UTF-8?q?=20debug=20log=20to=20show=20instantiation=20of=20node=5Ftype?= =?UTF-8?q?=20and=20base=5Ftype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/initialize/loading.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/initialize/loading.py b/src/backend/langflow/interface/initialize/loading.py index 974b9c454..e72e5091b 100644 --- a/src/backend/langflow/interface/initialize/loading.py +++ b/src/backend/langflow/interface/initialize/loading.py @@ -33,6 +33,7 @@ from langflow.utils import validate from langchain.chains.base import Chain from langchain.vectorstores.base import VectorStore from langchain.document_loaders.base import BaseLoader +from langflow.utils.logger import logger def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any: @@ -44,7 +45,7 @@ def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any: if hasattr(custom_node, "initialize"): return custom_node.initialize(**params) return custom_node(**params) - + logger.debug(f"Instantiating {node_type} of type {base_type}") class_object = import_by_type(_type=base_type, name=node_type) return instantiate_based_on_type(class_object, base_type, node_type, params) From 47fe4481f3ee500abaed3f71449755b1be7aa247 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 10:45:28 -0300 Subject: [PATCH 36/45] =?UTF-8?q?=F0=9F=90=9B=20fix(types.py):=20fix=20syn?= =?UTF-8?q?tax=20error=20in=20adding=20component=5Ftemplate=20to=20valid?= =?UTF-8?q?=5Fmenu=20=E2=9C=A8=20feat(types.py):=20improve=20component=20n?= =?UTF-8?q?ame=20generation=20logic=20based=20on=20component=5Foutput=5Fty?= =?UTF-8?q?pes=20and=20file=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/types.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index ad91bc596..9a95b24f4 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -347,8 +347,23 @@ def build_valid_menu(valid_components): component_extractor ) component_template["output_types"] = component_output_types + if len(component_output_types) == 1: + component_name = component_output_types[0] + else: + file_name = component.get("file").split(".")[0] + if "_" in file_name: + # turn .py file into camelcase + component_name = "".join( + [ + word.capitalize() + for word in file_name.split("_") + ] + ) + else: + component_name = file_name - valid_menu[menu_name][component.get("file")] = component_template + + valid_menu[menu_name][] = component_template logger.debug(f"Added {component_name} to valid menu to {menu_name}") except Exception as exc: From b25098e24be61856c9dcfd3b9772bf7f986197c3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 11:10:29 -0300 Subject: [PATCH 37/45] =?UTF-8?q?=F0=9F=90=9B=20fix(custom=5Fcomponent.py)?= =?UTF-8?q?:=20handle=20case=20when=20repr=5Fvalue=20is=20a=20string=20in?= =?UTF-8?q?=20custom=5Frepr=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/custom/custom_component.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/langflow/interface/custom/custom_component.py b/src/backend/langflow/interface/custom/custom_component.py index b1d7a5e76..200625be5 100644 --- a/src/backend/langflow/interface/custom/custom_component.py +++ b/src/backend/langflow/interface/custom/custom_component.py @@ -24,6 +24,8 @@ class CustomComponent(Component, extra=Extra.allow): super().__init__(**data) def custom_repr(self): + if isinstance(self.repr_value, str): + return self.repr_value return str(self.repr_value) def build_config(self): From 06e8dd626f3ab45d7b58a8346d3d4697fe0d4db1 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 11:11:03 -0300 Subject: [PATCH 38/45] =?UTF-8?q?=F0=9F=90=9B=20fix(chat.py):=20fix=20debu?= =?UTF-8?q?g=20log=20message=20to=20include=20vertex=20type=20and=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/chat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index 4248bcebd..d407a9142 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -124,10 +124,10 @@ async def stream_build(flow_id: str): yield str(StreamData(event="log", data=log_dict)) vertex.build() params = vertex._built_object_repr() + vertex.vertex_type valid = True - logger.debug( - f"Building node {str(params)[:50]}{'...' if len(str(params)) > 50 else ''}" - ) + logger.debug(f"Building node {str(vertex.vertex_type)}") + logger.debug(f"Output: {params}") if vertex.artifacts: # The artifacts will be prompt variables # passed to build_input_keys_response From 791b1b4266b82694625caaf9f4c76e7a317098a3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 11:11:23 -0300 Subject: [PATCH 39/45] =?UTF-8?q?=F0=9F=94=92=20chore(poetry.lock):=20upda?= =?UTF-8?q?te=20cohere=20package=20version=20from=204.17.0=20to=204.19.2?= =?UTF-8?q?=20=F0=9F=94=92=20chore(poetry.lock):=20update=20debugpy=20pack?= =?UTF-8?q?age=20version=20from=201.6.8=20to=201.6.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🔀 chore: update dependencies 🔄 refactor: update debugpy package to version 1.6.7 🔒 chore(poetry.lock): update google-cloud-resource-manager to version 1.10.3 🔒 chore(poetry.lock): update jcloud to version 0.2.16 🔒 chore(poetry.lock): update more-itertools to version 10.1.0 --- poetry.lock | 61 +++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7d0da2cbc..809dab71e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -739,18 +739,19 @@ sqlalchemy = ["sqlalchemy (>1.3.21,<2.0)"] [[package]] name = "cohere" -version = "4.17.0" +version = "4.19.2" description = "" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "cohere-4.17.0-py3-none-any.whl", hash = "sha256:44e0bdb0a2d9467506d27b285f542177b98f92647f27e17ea921a01006fe2f33"}, - {file = "cohere-4.17.0.tar.gz", hash = "sha256:9f479543b50490b4cb6385468d7571ad891a09cde7bd6b028171596bac6ce6ff"}, + {file = "cohere-4.19.2-py3-none-any.whl", hash = "sha256:0b6a4fe04380a481a8e975ebcc9bb6433febe4d3eb583b6d6e04342a5e998345"}, + {file = "cohere-4.19.2.tar.gz", hash = "sha256:a0b0fa698b3d3983fb328bb90d68fcf08faaa2268f3772ebc6bfea6ba55acf27"}, ] [package.dependencies] aiohttp = ">=3.0,<4.0" backoff = ">=2.0,<3.0" +fastavro = {version = "1.8.2", markers = "python_version >= \"3.8\""} importlib_metadata = ">=6.0,<7.0" requests = ">=2.25.0,<3.0.0" urllib3 = ">=1.26,<3" @@ -958,29 +959,29 @@ typing-inspect = ">=0.4.0,<1" [[package]] name = "debugpy" -version = "1.6.8" +version = "1.6.7" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.7" files = [ - {file = "debugpy-1.6.8-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:8c1f5a3286fb633f691c594649e9d2e8e30292c9eaf49e38d7da525151b33a83"}, - {file = "debugpy-1.6.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406b3a6cb7548d73260f69a511178ec9196779cafda68e563488c6f94cc88670"}, - {file = "debugpy-1.6.8-cp310-cp310-win32.whl", hash = "sha256:6830947f68b41cd6abe20941ec3303a8452c40ff5fe3637c6efe233e395ecebc"}, - {file = "debugpy-1.6.8-cp310-cp310-win_amd64.whl", hash = "sha256:1fe3baa28f5a14d8d2a60dded9ea088e27b33f1854ae9a0a1faa1ba03a8b7e47"}, - {file = "debugpy-1.6.8-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:5502e14de6b7241ecf7c4fa4ec6dd61d0824da7a09020c7ffe7be4cd09d36f24"}, - {file = "debugpy-1.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4a7193cec3f1e188963f6e8699e1187f758a0a4bbce511b3ad40caf618fc888"}, - {file = "debugpy-1.6.8-cp37-cp37m-win32.whl", hash = "sha256:591aac0e69bc75102d9f9294f1228e5d9ff9aa17b8c88e48b1bbb3dab8a54dcc"}, - {file = "debugpy-1.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:bb27b8e08f8e60705de6cf05b5da4c21e5a0bc2ca73f06fc36646f456df18ff5"}, - {file = "debugpy-1.6.8-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:6ca1c92e30e2aaeca156d5bd76e1587c23e332474a7b12e1900dd632b31ce05e"}, - {file = "debugpy-1.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959f9b8181a4c544b067daff8d881cd3ac4c7aec1a3a4f41f81c529795b3d864"}, - {file = "debugpy-1.6.8-cp38-cp38-win32.whl", hash = "sha256:4172383b961a2334d29168c7f7b24f2f99d29291a945016986c78a5683fba915"}, - {file = "debugpy-1.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:05d1b288167ce3bfc8e1912ebed036207a27b9569ae4476f18287902501689c6"}, - {file = "debugpy-1.6.8-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:95f7ce92450b72abcf0c479539a7d00c20e68f1f1fb447eef0b08d2a635d96d7"}, - {file = "debugpy-1.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f16bb157b6018ce6a23b64653a6b1892f046cc2b0576df1794c6b22f9fd82118"}, - {file = "debugpy-1.6.8-cp39-cp39-win32.whl", hash = "sha256:f7a80c50b89d8fb49c9e5b6ee28c0bfb822fbd33fef0f2f9843724d0d1984e4e"}, - {file = "debugpy-1.6.8-cp39-cp39-win_amd64.whl", hash = "sha256:2345beced3e79fd8ac4158e839a1604d5cccd19beb45561a1ffe2e5b33465f28"}, - {file = "debugpy-1.6.8-py2.py3-none-any.whl", hash = "sha256:1ca76d3ebb0e6368e107cf2e005e848d3c7705a5b513fdf65470a6f4e49a2de7"}, - {file = "debugpy-1.6.8.zip", hash = "sha256:3b7091d908dec70022b8966c32b1e9eaf183ff05291edf1d147fee153f4cb9f8"}, + {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"}, + {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"}, + {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"}, + {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"}, + {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"}, + {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"}, + {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"}, + {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"}, + {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"}, + {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"}, + {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"}, + {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"}, + {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"}, + {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"}, + {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"}, + {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"}, + {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"}, + {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"}, ] [[package]] @@ -1729,13 +1730,13 @@ grpc = ["grpcio (>=1.38.0,<2.0dev)"] [[package]] name = "google-cloud-resource-manager" -version = "1.10.2" +version = "1.10.3" description = "Google Cloud Resource Manager API client library" optional = false python-versions = ">=3.7" files = [ - {file = "google-cloud-resource-manager-1.10.2.tar.gz", hash = "sha256:9a7bdd0347ad553376cc66ad317c5223d1ae04bdcf74edcbfcd12605cff7b510"}, - {file = "google_cloud_resource_manager-1.10.2-py2.py3-none-any.whl", hash = "sha256:9e074c28326bd1632f1a270c20cfea1ffe98f49cf821033e65bdac55661ffbd5"}, + {file = "google-cloud-resource-manager-1.10.3.tar.gz", hash = "sha256:f80efcea36f10c5a81889afe93910926e3978b4b1ceeb82f563a2fc863072d14"}, + {file = "google_cloud_resource_manager-1.10.3-py2.py3-none-any.whl", hash = "sha256:1381a4b0f522248ebe0ebd1289d8822b99c54f4e1fe03924a6e723b2ed93dd7f"}, ] [package.dependencies] @@ -2562,12 +2563,12 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", [[package]] name = "jcloud" -version = "0.2.15" +version = "0.2.16" description = "Simplify deploying and managing Jina projects on Jina Cloud" optional = false python-versions = "*" files = [ - {file = "jcloud-0.2.15.tar.gz", hash = "sha256:be3af2d8c9c7746bc5e2d4a77a383b0401848bcb1a8d590ed0205d0c3baa230f"}, + {file = "jcloud-0.2.16.tar.gz", hash = "sha256:abf39a70fc5852574a05e03dac5e5cc364df87ae1f8476cbd441178f14adb578"}, ] [package.dependencies] @@ -3326,13 +3327,13 @@ files = [ [[package]] name = "more-itertools" -version = "10.0.0" +version = "10.1.0" description = "More routines for operating on iterables, beyond itertools" optional = false python-versions = ">=3.8" files = [ - {file = "more-itertools-10.0.0.tar.gz", hash = "sha256:cd65437d7c4b615ab81c0640c0480bc29a550ea032891977681efd28344d51e1"}, - {file = "more_itertools-10.0.0-py3-none-any.whl", hash = "sha256:928d514ffd22b5b0a8fce326d57f423a55d2ff783b093bab217eda71e732330f"}, + {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"}, + {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"}, ] [[package]] From 19c6dc5ca7efc5ff341f1271124176dd5a8df592 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 11:35:48 -0300 Subject: [PATCH 40/45] =?UTF-8?q?=F0=9F=90=9B=20fix(types.py):=20fix=20syn?= =?UTF-8?q?tax=20error=20in=20adding=20component=20to=20valid=20menu=20dic?= =?UTF-8?q?tionary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/interface/types.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/backend/langflow/interface/types.py b/src/backend/langflow/interface/types.py index 9a95b24f4..3b4c09b32 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/langflow/interface/types.py @@ -354,16 +354,12 @@ def build_valid_menu(valid_components): if "_" in file_name: # turn .py file into camelcase component_name = "".join( - [ - word.capitalize() - for word in file_name.split("_") - ] + [word.capitalize() for word in file_name.split("_")] ) else: component_name = file_name - - valid_menu[menu_name][] = component_template + valid_menu[menu_name][component_name] = component_template logger.debug(f"Added {component_name} to valid menu to {menu_name}") except Exception as exc: From b9d433b37c825d8fca7f464be22d35068d342898 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 4 Aug 2023 12:34:25 -0300 Subject: [PATCH 41/45] Fixed break words on all code --- .../components/parameterComponent/index.tsx | 2 +- .../components/singleAlertComponent/index.tsx | 4 ++-- src/frontend/src/alerts/notice/index.tsx | 4 +++- src/frontend/src/modals/codeAreaModal/index.tsx | 4 ++-- .../src/modals/formModal/chatMessage/index.tsx | 4 ++-- .../src/modals/importModal/buttonBox/index.tsx | 2 +- src/frontend/src/style/applies.css | 12 ++++++------ src/frontend/tailwind.config.js | 4 +++- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index e91d65a3e..72c2a8e4d 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -87,7 +87,7 @@ export default function ParameterComponent({ useEffect(() => { if (name === "openai_api_base") console.log(info); infoHtml.current = ( -
+
{info.split("\n").map((line, i) => (

{line} diff --git a/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx b/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx index 9a94db7d5..ca15abc86 100644 --- a/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx @@ -36,14 +36,14 @@ export default function SingleAlert({ />

-

+

{dropItem.title}

{dropItem.list ? (
    {dropItem.list.map((item, idx) => ( -
  • +
  • {item}
  • ))} diff --git a/src/frontend/src/alerts/notice/index.tsx b/src/frontend/src/alerts/notice/index.tsx index 494d9d4dc..1acd5c898 100644 --- a/src/frontend/src/alerts/notice/index.tsx +++ b/src/frontend/src/alerts/notice/index.tsx @@ -47,7 +47,9 @@ export default function NoticeAlert({ />
-

{title}

+

+ {title} +

{link !== "" ? ( {error?.detail?.error} -

-
+              
+
                   {error?.detail?.traceback}
                 
diff --git a/src/frontend/src/modals/formModal/chatMessage/index.tsx b/src/frontend/src/modals/formModal/chatMessage/index.tsx index 08cc2d22b..e9de65d0f 100644 --- a/src/frontend/src/modals/formModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/formModal/chatMessage/index.tsx @@ -88,7 +88,7 @@ export default function ChatMessage({ - + {promptOpen ? template?.split("\n")?.map((line, index) => { const regex = /{([^}]+)}/g; diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index 0a998d56e..68759c8be 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -96,7 +96,7 @@ export default function ButtonBox({

Date: Fri, 4 Aug 2023 12:47:21 -0300 Subject: [PATCH 42/45] Fixed chat message size --- .../components/codeTabsComponent/index.tsx | 32 +++++++++++-------- .../modals/formModal/chatMessage/index.tsx | 6 ++-- src/frontend/src/style/applies.css | 12 +++---- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/frontend/src/components/codeTabsComponent/index.tsx b/src/frontend/src/components/codeTabsComponent/index.tsx index bc9ca3a5a..27653fbd7 100644 --- a/src/frontend/src/components/codeTabsComponent/index.tsx +++ b/src/frontend/src/components/codeTabsComponent/index.tsx @@ -132,21 +132,25 @@ export default function CodeTabsComponent({ }} >
- - {tabs.map((tab, index) => ( - - {tab.name} - - ))} - + {tabs.length > 0 && tabs[0].name !== "" ? ( + + {tabs.map((tab, index) => ( + + {tab.name} + + ))} + + ) : ( +
+ )} {Number(activeTab) < 4 && ( -
+
- + {promptOpen ? template?.split("\n")?.map((line, index) => { const regex = /{([^}]+)}/g; diff --git a/src/frontend/src/style/applies.css b/src/frontend/src/style/applies.css index b40614bd6..0281df7c2 100644 --- a/src/frontend/src/style/applies.css +++ b/src/frontend/src/style/applies.css @@ -336,7 +336,7 @@ @apply flex h-7 w-7 items-center justify-center rounded-full text-2xl; } .card-component-title-size { - @apply inline-block w-full flex-1 word-break-break-word truncate-doubleline; + @apply w-full flex-1 word-break-break-word truncate-doubleline; } .card-component-delete-button { @apply flex self-start; @@ -544,7 +544,7 @@ @apply focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1; } .toggle-component-span { - @apply pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out; + @apply pointer-events-none relative h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out; } .toggle-component-second-span { @apply absolute inset-0 flex h-full w-full items-center justify-center transition-opacity; @@ -590,13 +590,13 @@ @apply flex-max-width items-center text-start; } .chat-message-modal-text { - @apply relative inline-block w-full text-start text-sm font-normal text-muted-foreground; + @apply relative w-full text-start text-sm font-normal text-muted-foreground; } .chat-message-modal-icon-div { @apply absolute -left-2 -top-1 cursor-pointer; } .chat-message-modal-thought { - @apply chat-message-modal-thought-cursor ml-3 inline-block h-full w-[95%] rounded-md border border-ring bg-muted px-2 pb-3 pt-3 text-start text-muted-foreground; + @apply chat-message-modal-thought-cursor ml-3 h-full w-[95%] rounded-md border border-ring bg-muted px-2 pb-3 pt-3 text-start text-muted-foreground; } .chat-message-modal-thought-cursor { @apply cursor-pointer overflow-scroll scrollbar-hide; @@ -608,7 +608,7 @@ @apply mt-1 animate-pulse cursor-default; } .chat-message-modal-alert { - @apply inline-block px-3 text-start text-muted-foreground; + @apply px-3 text-start text-muted-foreground; } .file-card-modal-image-div { @@ -913,7 +913,7 @@ @apply rounded-md border border-ring/60; } .form-modal-chat-thought-size { - @apply inline-block h-full w-[95%]; + @apply h-full w-[95%]; } .form-modal-chat-thought { @apply form-modal-chat-thought-border form-modal-chat-thought-size cursor-pointer overflow-scroll bg-background px-2 py-2 text-start text-primary scrollbar-hide; From aac7e9283225c9617f2fe6c5128c013930c526d2 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 13:48:33 -0300 Subject: [PATCH 43/45] =?UTF-8?q?=F0=9F=93=9D=20docs(custom-component.mdx)?= =?UTF-8?q?:=20update=20guidelines=20for=20loading=20custom=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🔧 fix(custom-component.mdx): correct the recommended way to load custom components by setting LANGFLOW_COMPONENTS_PATH environment variable instead of using --components-path argument 💡 docs(custom-component.mdx): provide an alternative method to specify the path to custom components using --components-path argument --- docs/docs/guidelines/custom-component.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/docs/guidelines/custom-component.mdx b/docs/docs/guidelines/custom-component.mdx index bcd637222..e649ef6e9 100644 --- a/docs/docs/guidelines/custom-component.mdx +++ b/docs/docs/guidelines/custom-component.mdx @@ -385,19 +385,19 @@ Your structure should look something like this: ### Loading Custom Components -You can specify the path to your custom components using the _`--components-path`_ argument when running the Langflow CLI, as shown below: - -```bash -langflow --components-path /path/to/components -``` - -Alternatively, you can set the `LANGFLOW_COMPONENTS_PATH` environment variable: +The recommended way to load custom components is to set the _`LANGFLOW_COMPONENTS_PATH`_ environment variable to the path of your custom components directory. Then, run the Langflow CLI as usual. ```bash export LANGFLOW_COMPONENTS_PATH=/path/to/components langflow ``` +Alternatively, you can specify the path to your custom components using the _`--components-path`_ argument when running the Langflow CLI, as shown below: + +```bash +langflow --components-path /path/to/components +``` + Langflow will attempt to load all of the components found in the specified directory. If a component fails to load due to errors in the component's code, Langflow will print an error message to the console but will continue loading the rest of the components. ### Interacting with Custom Components From bb3be161bde067deb930531713c60d3947007fed Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 13:49:19 -0300 Subject: [PATCH 44/45] =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20fix=20typo?= =?UTF-8?q?=20in=20"successfully"=20in=20the=20built=20object=20representa?= =?UTF-8?q?tion=20message=20=F0=9F=90=9B=20fix(custom=5Fcomponent.py):=20a?= =?UTF-8?q?dd=20support=20for=20custom=20representation=20of=20repr=5Fvalu?= =?UTF-8?q?e=20if=20it=20is=20a=20dictionary=20by=20using=20yaml.dump()=20?= =?UTF-8?q?function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/graph/vertex/base.py | 6 +++++- src/backend/langflow/interface/custom/custom_component.py | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/graph/vertex/base.py b/src/backend/langflow/graph/vertex/base.py index 5139b6e90..cb7dc4905 100644 --- a/src/backend/langflow/graph/vertex/base.py +++ b/src/backend/langflow/graph/vertex/base.py @@ -269,4 +269,8 @@ class Vertex: def _built_object_repr(self): # Add a message with an emoji, stars for sucess, - return "Built sucessfully ✨" if self._built_object else "Failed to build 😵‍💫" + return ( + "Built sucessfully ✨" + if self._built_object is not None + else "Failed to build 😵‍💫" + ) diff --git a/src/backend/langflow/interface/custom/custom_component.py b/src/backend/langflow/interface/custom/custom_component.py index 200625be5..ce8956660 100644 --- a/src/backend/langflow/interface/custom/custom_component.py +++ b/src/backend/langflow/interface/custom/custom_component.py @@ -9,6 +9,7 @@ from langflow.utils import validate from langflow.database.base import session_getter from langflow.database.models.flow import Flow from pydantic import Extra +import yaml class CustomComponent(Component, extra=Extra.allow): @@ -24,6 +25,8 @@ class CustomComponent(Component, extra=Extra.allow): super().__init__(**data) def custom_repr(self): + if isinstance(self.repr_value, dict): + return yaml.dump(self.repr_value) if isinstance(self.repr_value, str): return self.repr_value return str(self.repr_value) From 520bbc35b00d401a29c6a105ca3232665520bc16 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 4 Aug 2023 15:13:09 -0300 Subject: [PATCH 45/45] =?UTF-8?q?=F0=9F=94=A5=20refactor(chat.py):=20remov?= =?UTF-8?q?e=20unused=20code=20line=20that=20accessed=20vertex=5Ftype=20at?= =?UTF-8?q?tribute=20of=20a=20vertex=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/chat.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index d407a9142..dd3407d1b 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -124,7 +124,6 @@ async def stream_build(flow_id: str): yield str(StreamData(event="log", data=log_dict)) vertex.build() params = vertex._built_object_repr() - vertex.vertex_type valid = True logger.debug(f"Building node {str(vertex.vertex_type)}") logger.debug(f"Output: {params}")