diff --git a/Dockerfile b/Dockerfile index f4c29d4be..1b713c3a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,4 +11,4 @@ WORKDIR $HOME/app COPY --chown=user . $HOME/app RUN pip install langflow>==0.0.71 -U --user -CMD ["langflow", "--host", "0.0.0.0", "--port", "7860"] \ No newline at end of file +CMD ["langflow", "--host", "0.0.0.0", "--port", "7860"] diff --git a/GCP_DEPLOYMENT.md b/GCP_DEPLOYMENT.md index edb7e043c..36c81e19f 100644 --- a/GCP_DEPLOYMENT.md +++ b/GCP_DEPLOYMENT.md @@ -6,14 +6,14 @@ This guide will help you set up a Langflow development VM in a Google Cloud Plat ## Standard VM -[![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/genome21/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial.md) +[![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/logspace-ai/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial.md) This script sets up a Debian-based VM with the Langflow package, Nginx, and the necessary configurations to run the Langflow Dev environment.
## Spot/Preemptible Instance -[![Open in Cloud Shell - Spot Instance](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/genome21/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial.md) +[![Open in Cloud Shell - Spot Instance](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/genome21/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial_spot.md) When running as a [spot (preemptible) instance](https://cloud.google.com/compute/docs/instances/preemptible), the code and VM will behave the same way as in a regular instance, executing the startup script to configure the environment, install necessary dependencies, and run the Langflow application. However, **due to the nature of spot instances, the VM may be terminated at any time if Google Cloud needs to reclaim the resources**. This makes spot instances suitable for fault-tolerant, stateless, or interruptible workloads that can handle unexpected terminations and restarts. diff --git a/README.md b/README.md index 9b0a0cb3a..de98f87a1 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,15 @@ or langflow ``` +### Deploy Langflow on Google Cloud Platform + +Follow our step-by-step guide to deploy Langflow on Google Cloud Platform (GCP) using Google Cloud Shell. The guide is available in the [**Langflow in Google Cloud Platform**](GCP_DEPLOYMENT.md) document. + +Alternatively, click the **"Open in Cloud Shell"** button below to launch Google Cloud Shell, clone the Langflow repository, and start an **interactive tutorial** that will guide you through the process of setting up the necessary resources and deploying Langflow on your GCP project. + +[![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/logspace-ai/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial_spot.md) + + ### Deploy Langflow on Google Cloud Platform Follow our step-by-step guide to deploy Langflow on Google Cloud Platform (GCP) using Google Cloud Shell. The guide is available in the [**Langflow in Google Cloud Platform**](GCP_DEPLOYMENT.md) document. diff --git a/docker-compose.yml b/docker-compose.yml index d9ba84030..755d0794d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,8 @@ services: dockerfile: ./dev.Dockerfile args: - BACKEND_URL=http://backend:7860 + environment: + - VITE_PROXY_TARGET=http://backend:7860 ports: - "3000:3000" volumes: diff --git a/poetry.lock b/poetry.lock index 2f42ef3ff..be596cd0a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -511,14 +511,14 @@ files = [ [[package]] name = "chromadb" -version = "0.3.22" +version = "0.3.23" description = "Chroma." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "chromadb-0.3.22-py3-none-any.whl", hash = "sha256:54b58e562ab8a63194ce3b453633ce351475193de2184845f0577db969f1cf49"}, - {file = "chromadb-0.3.22.tar.gz", hash = "sha256:41acb262c2c7bb41afecd50737f440dce3fdaa3d3fe1749d0e4be1ffc8699e63"}, + {file = "chromadb-0.3.23-py3-none-any.whl", hash = "sha256:c1e04fddff0916243895bedeffc1977745328f62404d70981eb1a0cb9dcdfaf3"}, + {file = "chromadb-0.3.23.tar.gz", hash = "sha256:87fa922c92e2e90fb48234b435e9d4f0c61646fbd1526062f53f63326fc21228"}, ] [package.dependencies] @@ -1180,20 +1180,19 @@ grpc = ["grpcio (>=1.44.0,<2.0.0dev)"] [[package]] name = "gptcache" -version = "0.1.23" +version = "0.1.24" description = "GPTCache, a powerful caching library that can be used to speed up and lower the cost of chat applications that rely on the LLM service. GPTCache works as a memcache for AIGC applications, similar to how Redis works for traditional applications." category = "main" optional = false python-versions = ">=3.8.1" files = [ - {file = "gptcache-0.1.23-py3-none-any.whl", hash = "sha256:8bcd366e1dd5de432e113831afdea97493f090372a752a42b9ff16cb8c818635"}, - {file = "gptcache-0.1.23.tar.gz", hash = "sha256:5b5e3ef6f5df35f948bd203d1e33f3985459e60be436547529ff8b31f245238d"}, + {file = "gptcache-0.1.24-py3-none-any.whl", hash = "sha256:070aad4867ab915a7b5db3a886e9f0289e52d1cb92a407c984b0241298079750"}, + {file = "gptcache-0.1.24.tar.gz", hash = "sha256:aa591cb00898d457a50a5e0cd137d0119e86819c110ce6c7bce2adafeae0a467"}, ] [package.dependencies] cachetools = "*" numpy = "*" -openai = "*" requests = "*" [[package]] @@ -1528,14 +1527,14 @@ files = [ [[package]] name = "ipykernel" -version = "6.23.0" +version = "6.23.1" description = "IPython Kernel for Jupyter" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.23.0-py3-none-any.whl", hash = "sha256:fc886f1dcdc0ec17f277e4d21fd071c857d381adcb04f3f3735d25325ca323c6"}, - {file = "ipykernel-6.23.0.tar.gz", hash = "sha256:bd6f487d9e2744c84f6e667d46462d7647a4c862e70e08282f05a52b9d4b705f"}, + {file = "ipykernel-6.23.1-py3-none-any.whl", hash = "sha256:77aeffab056c21d16f1edccdc9e5ccbf7d96eb401bd6703610a21be8b068aadc"}, + {file = "ipykernel-6.23.1.tar.gz", hash = "sha256:1aba0ae8453e15e9bc6b24e497ef6840114afcdb832ae597f32137fa19d42a6f"}, ] [package.dependencies] @@ -1735,13 +1734,13 @@ qdrant = ["qdrant-client (>=1.1.2,<2.0.0)"] [[package]] name = "llama-cpp-python" -version = "0.1.23" +version = "0.1.50" description = "A Python wrapper for llama.cpp" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "llama_cpp_python-0.1.23.tar.gz", hash = "sha256:323a937e68e04251b5ad1804922e05d15c8b6bfbcf7c3e683a7b39a20e165ebf"}, + {file = "llama_cpp_python-0.1.50.tar.gz", hash = "sha256:e305ae1b9f135f94afd8dd227701e6a1cd36db9c28f736b830ec364127c00bb9"}, ] [package.dependencies] @@ -4143,23 +4142,23 @@ scipy = ["scipy"] [[package]] name = "tornado" -version = "6.3.1" +version = "6.3.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." category = "dev" optional = false python-versions = ">= 3.8" files = [ - {file = "tornado-6.3.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:db181eb3df8738613ff0a26f49e1b394aade05034b01200a63e9662f347d4415"}, - {file = "tornado-6.3.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b4e7b956f9b5e6f9feb643ea04f07e7c6b49301e03e0023eedb01fa8cf52f579"}, - {file = "tornado-6.3.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9661aa8bc0e9d83d757cd95b6f6d1ece8ca9fd1ccdd34db2de381e25bf818233"}, - {file = "tornado-6.3.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81c17e0cc396908a5e25dc8e9c5e4936e6dfd544c9290be48bd054c79bcad51e"}, - {file = "tornado-6.3.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a27a1cfa9997923f80bdd962b3aab048ac486ad8cfb2f237964f8ab7f7eb824b"}, - {file = "tornado-6.3.1-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d7117f3c7ba5d05813b17a1f04efc8e108a1b811ccfddd9134cc68553c414864"}, - {file = "tornado-6.3.1-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:ffdce65a281fd708da5a9def3bfb8f364766847fa7ed806821a69094c9629e8a"}, - {file = "tornado-6.3.1-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:90f569a35a8ec19bde53aa596952071f445da678ec8596af763b9b9ce07605e6"}, - {file = "tornado-6.3.1-cp38-abi3-win32.whl", hash = "sha256:3455133b9ff262fd0a75630af0a8ee13564f25fb4fd3d9ce239b8a7d3d027bf8"}, - {file = "tornado-6.3.1-cp38-abi3-win_amd64.whl", hash = "sha256:1285f0691143f7ab97150831455d4db17a267b59649f7bd9700282cba3d5e771"}, - {file = "tornado-6.3.1.tar.gz", hash = "sha256:5e2f49ad371595957c50e42dd7e5c14d64a6843a3cf27352b69c706d1b5918af"}, + {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"}, + {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"}, + {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"}, + {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"}, + {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"}, + {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"}, + {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"}, + {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"}, + {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"}, + {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"}, + {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"}, ] [[package]] @@ -4840,4 +4839,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "d914f734f4ff1bcbe8e678d46b20b73c3565b3af6f5dd0ac0359fae800c6bf2e" +content-hash = "be5c3e25247d4a0c313de54d07f4a027253877a5b8fbbf7830030a43a02c2911" diff --git a/pyproject.toml b/pyproject.toml index 1fd786902..224606d5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.0.71" +version = "0.0.73" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [ @@ -37,7 +37,7 @@ pandas = "^1.5.3" chromadb = "^0.3.21" huggingface-hub = "^0.13.3" rich = "^13.3.3" -llama-cpp-python = "0.1.23" +llama-cpp-python = "0.1.50" networkx = "^3.1" unstructured = "^0.5.11" pypdf = "^3.7.1" diff --git a/scripts/deploy_langflow_gcp.sh b/scripts/deploy_langflow_gcp.sh index 2c3dc0420..fbf87099a 100644 --- a/scripts/deploy_langflow_gcp.sh +++ b/scripts/deploy_langflow_gcp.sh @@ -26,16 +26,16 @@ if [[ -z "$subnet_exists" ]]; then gcloud compute networks subnets create $SUBNET_NAME --network=$VPC_NAME --region=$REGION --range=$SUBNET_RANGE fi -# Create a firewall rule to allow TCP port 8080 for all instances in the VPC -firewall_8080_exists=$(gcloud compute firewall-rules list --filter="name=allow-tcp-8080" --format="value(name)") -if [[ -z "$firewall_8080_exists" ]]; then - gcloud compute firewall-rules create allow-tcp-8080 --network $VPC_NAME --allow tcp:8080 --source-ranges 0.0.0.0/0 --direction INGRESS +# Create a firewall rule to allow TCP port 7860 for all instances in the VPC +firewall_7860_exists=$(gcloud compute firewall-rules list --filter="name=allow-tcp-7860" --format="value(name)") +if [[ -z "$firewall_7860_exists" ]]; then + gcloud compute firewall-rules create allow-tcp-7860 --network $VPC_NAME --allow tcp:7860 --source-ranges 0.0.0.0/0 --direction INGRESS fi # Create a firewall rule to allow IAP traffic firewall_iap_exists=$(gcloud compute firewall-rules list --filter="name=allow-iap" --format="value(name)") if [[ -z "$firewall_iap_exists" ]]; then - gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443 --source-ranges 35.235.240.0/20 --direction INGRESS + gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443,tcp:22,:tcp:3389 --source-ranges 35.235.240.0/20 --direction INGRESS fi # Define the startup script as a multiline Bash here-doc @@ -49,24 +49,7 @@ apt -y upgrade # Install Python 3 pip, Langflow, and Nginx apt -y install python3-pip pip install langflow -apt-get -y install nginx - -# Configure Nginx for Langflow -touch /etc/nginx/sites-available/langflow-app -echo "server { - listen 0.0.0.0:8080; - - location / { - proxy_pass http://127.0.0.1:7860; - proxy_set_header Host "\$host"; - proxy_set_header X-Real-IP "\$remote_addr"; - proxy_set_header X-Forwarded-For "\$proxy_add_x_forwarded_for"; - } -}" >> /etc/nginx/sites-available/langflow-app -ln -s /etc/nginx/sites-available/langflow-app /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl restart nginx -langflow +langflow --host 0.0.0.0 --port 7860 EOF ) diff --git a/scripts/deploy_langflow_gcp_spot.sh b/scripts/deploy_langflow_gcp_spot.sh index 065b6013f..9291ddcc3 100644 --- a/scripts/deploy_langflow_gcp_spot.sh +++ b/scripts/deploy_langflow_gcp_spot.sh @@ -26,16 +26,16 @@ if [[ -z "$subnet_exists" ]]; then gcloud compute networks subnets create $SUBNET_NAME --network=$VPC_NAME --region=$REGION --range=$SUBNET_RANGE fi -# Create a firewall rule to allow TCP port 8080 for all instances in the VPC -firewall_8080_exists=$(gcloud compute firewall-rules list --filter="name=allow-tcp-8080" --format="value(name)") -if [[ -z "$firewall_8080_exists" ]]; then - gcloud compute firewall-rules create allow-tcp-8080 --network $VPC_NAME --allow tcp:8080 --source-ranges 0.0.0.0/0 --direction INGRESS +# Create a firewall rule to allow TCP port 7860 for all instances in the VPC +firewall_7860_exists=$(gcloud compute firewall-rules list --filter="name=allow-tcp-7860" --format="value(name)") +if [[ -z "$firewall_7860_exists" ]]; then + gcloud compute firewall-rules create allow-tcp-7860 --network $VPC_NAME --allow tcp:7860 --source-ranges 0.0.0.0/0 --direction INGRESS fi # Create a firewall rule to allow IAP traffic firewall_iap_exists=$(gcloud compute firewall-rules list --filter="name=allow-iap" --format="value(name)") if [[ -z "$firewall_iap_exists" ]]; then - gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443 --source-ranges 35.235.240.0/20 --direction INGRESS + gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443,tcp:22,:tcp:3389 --source-ranges 35.235.240.0/20 --direction INGRESS fi # Define the startup script as a multiline Bash here-doc @@ -49,24 +49,7 @@ apt -y upgrade # Install Python 3 pip, Langflow, and Nginx apt -y install python3-pip pip install langflow -apt-get -y install nginx - -# Configure Nginx for Langflow -touch /etc/nginx/sites-available/langflow-app -echo "server { - listen 0.0.0.0:8080; - - location / { - proxy_pass http://127.0.0.1:7860; - proxy_set_header Host "\$host"; - proxy_set_header X-Real-IP "\$remote_addr"; - proxy_set_header X-Forwarded-For "\$proxy_add_x_forwarded_for"; - } -}" >> /etc/nginx/sites-available/langflow-app -ln -s /etc/nginx/sites-available/langflow-app /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl restart nginx -langflow +langflow --host 0.0.0.0 --port 7860 EOF ) @@ -84,7 +67,7 @@ gcloud compute instances create $VM_NAME \ --zone $ZONE \ --network $VPC_NAME \ --subnet $SUBNET_NAME \ - -preemptible + --preemptible # Remove the temporary file after the VM is created rm $tempfile diff --git a/scripts/walkthroughtutorial.md b/scripts/walkthroughtutorial.md index fa6e3c11d..83ea3086a 100644 --- a/scripts/walkthroughtutorial.md +++ b/scripts/walkthroughtutorial.md @@ -37,7 +37,7 @@ The script will: 1. Check if the required resources (VPC, subnet, firewall rules, and Cloud Router) exist and create them if needed 2. Create a startup script to install Python, Langflow, and Nginx 3. Create a Compute Engine VM instance with the specified configuration and startup script -4. Configure Nginx to serve Langflow on TCP port 8080 +4. Run Langflow to serve content on TCP port 7860 > The process may take approximately 30 minutes to complete. Rest assured that progress is being made, and you'll be able to proceed once the process is finished. @@ -47,13 +47,13 @@ In the next step, you'll learn how to connect to the Langflow VM. ## Connect to the Langflow VM To connect to your new Langflow VM, follow these steps: -1. Navigate to the [VM instances](https://console.cloud.google.com/compute/instances) page and click on the external IP for your VM. Make sure to use HTTP and set the port to 8080 +1. Navigate to the [VM instances](https://console.cloud.google.com/compute/instances) page and click on the external IP for your VM. Make sure to use HTTP and set the port to 7860
**or** 3. Run the following command to display the URL for your Langflow environment: ```bash export LANGFLOW_IP=$(gcloud compute instances list --filter="NAME=langflow-dev" --format="value(EXTERNAL_IP)") -echo http://$LANGFLOW_IP:8080 +echo http://$LANGFLOW_IP:7860 ``` 4. Click on the Langflow URL in cloudshell to be greeted by the Langflow Dev environment @@ -76,7 +76,7 @@ However, if you decide to remove them after completing the walkthrough, you can > These commands will delete the firewall rules and network configurations created during the walkthrough. Make sure to run them only if you no longer need these settings. ``` -gcloud compute firewall-rules delete allow-tcp-8080 --quiet +gcloud compute firewall-rules delete allow-tcp-7860 --quiet gcloud compute firewall-rules delete allow-iap --quiet diff --git a/scripts/walkthroughtutorial_spot.md b/scripts/walkthroughtutorial_spot.md index 751f03d78..3792bc1ca 100644 --- a/scripts/walkthroughtutorial_spot.md +++ b/scripts/walkthroughtutorial_spot.md @@ -29,7 +29,7 @@ Run the deploy_langflow_gcp_spot.sh script to configure the GCP environment and ```sh gcloud config set project -bash ./deploy_langflow_gcp.sh +bash ./deploy_langflow_gcp_spot.sh ``` The script will: @@ -37,7 +37,7 @@ The script will: 1. Check if the required resources (VPC, subnet, firewall rules, and Cloud Router) exist and create them if needed 2. Create a startup script to install Python, Langflow, and Nginx 3. Create a Compute Engine VM instance with the specified configuration and startup script -4. Configure Nginx to serve Langflow on TCP port 8080 +4. Run Langflow to serve content on TCP port 7860 > The process may take approximately 30 minutes to complete. Rest assured that progress is being made, and you'll be able to proceed once the process is finished. @@ -46,13 +46,13 @@ In the next step, you'll learn how to connect to the Langflow VM. ## Connect to the Langflow VM To connect to your new Langflow VM, follow these steps: -1. Navigate to the [VM instances](https://console.cloud.google.com/compute/instances) page and click on the external IP for your VM. Make sure to use HTTP and set the port to 8080 +1. Navigate to the [VM instances](https://console.cloud.google.com/compute/instances) page and click on the external IP for your VM. Make sure to use HTTP and set the port to 7860
**or** 3. Run the following command to display the URL for your Langflow environment: ```bash export LANGFLOW_IP=$(gcloud compute instances list --filter="NAME=langflow-dev" --format="value(EXTERNAL_IP)") -echo http://$LANGFLOW_IP:8080 +echo http://$LANGFLOW_IP:7860 ``` 4. Click on the Langflow URL in cloudshell to be greeted by the Langflow Dev environment @@ -73,7 +73,7 @@ However, if you decide to remove them after completing the walkthrough, you can > These commands will delete the firewall rules and network configurations created during the walkthrough. Make sure to run them only if you no longer need these settings. ``` -gcloud compute firewall-rules delete allow-tcp-8080 --quiet +gcloud compute firewall-rules delete allow-tcp-7860 --quiet gcloud compute firewall-rules delete allow-iap --quiet diff --git a/src/backend/langflow/interface/loading.py b/src/backend/langflow/interface/loading.py index 148efd5b7..6cd9246b8 100644 --- a/src/backend/langflow/interface/loading.py +++ b/src/backend/langflow/interface/loading.py @@ -54,7 +54,7 @@ def instantiate_based_on_type(class_object, base_type, node_type, params): if base_type == "agents": return instantiate_agent(class_object, params) elif base_type == "prompts": - return instantiate_prompt(class_object, node_type, params) + return instantiate_prompt(node_type, class_object, params) elif base_type == "tools": return instantiate_tool(node_type, class_object, params) elif base_type == "toolkits": @@ -77,7 +77,7 @@ def instantiate_agent(class_object, params): return load_agent_executor(class_object, params) -def instantiate_prompt(class_object, node_type, params): +def instantiate_prompt(node_type, class_object, params): if node_type == "ZeroShotPrompt": if "tools" not in params: params["tools"] = [] @@ -96,7 +96,7 @@ def instantiate_tool(node_type, class_object, params): raise ValueError("Function should be a string") elif node_type.lower() == "tool": return class_object(**params) - return None # Or some other default action + return class_object(**params) def instantiate_toolkit(node_type, class_object, params): diff --git a/src/frontend/dev.Dockerfile b/src/frontend/dev.Dockerfile index 4773fc2b9..8678b02dd 100644 --- a/src/frontend/dev.Dockerfile +++ b/src/frontend/dev.Dockerfile @@ -23,4 +23,4 @@ RUN chmod +x set_proxy.sh && \ USER node RUN npm install --loglevel warn -CMD ["npm", "start"] \ No newline at end of file +CMD ["npm", "run", "dev:docker"] \ No newline at end of file diff --git a/src/frontend/package.json b/src/frontend/package.json index fd8cc02db..6315deb05 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -35,6 +35,7 @@ "web-vitals": "^2.1.4" }, "scripts": { + "dev:docker": "vite --host 0.0.0.0", "start": "vite", "build": "vite build", "serve": "vite preview" @@ -76,4 +77,4 @@ "typescript": "^5.0.2", "vite": "^4.3.5" } -} +} \ No newline at end of file diff --git a/src/frontend/src/components/chatComponent/chatMessage/index.tsx b/src/frontend/src/components/chatComponent/chatMessage/index.tsx index 6c9e24407..9e3586d23 100644 --- a/src/frontend/src/components/chatComponent/chatMessage/index.tsx +++ b/src/frontend/src/components/chatComponent/chatMessage/index.tsx @@ -7,7 +7,7 @@ import { useState } from "react"; import { ChatMessageType } from "../../../types/chat"; import { nodeColors } from "../../../utils"; import Convert from "ansi-to-html"; -var convert = new Convert({newline:true}); +const convert = new Convert({ newline: true }); export default function ChatMessage({ chat }: { chat: ChatMessageType }) { const [hidden, setHidden] = useState(true); diff --git a/src/frontend/src/contexts/tabsContext.tsx b/src/frontend/src/contexts/tabsContext.tsx index 735f93eaf..6479e330e 100644 --- a/src/frontend/src/contexts/tabsContext.tsx +++ b/src/frontend/src/contexts/tabsContext.tsx @@ -38,7 +38,7 @@ export function TabsProvider({ children }: { children: ReactNode }) { const { setNoticeData } = useContext(alertContext); const [tabIndex, setTabIndex] = useState(0); const [flows, setFlows] = useState>([]); - const [id, setId] = useState(""); + const [id, setId] = useState(uuidv4()); const { templates } = useContext(typesContext); const newNodeId = useRef(0); @@ -47,46 +47,50 @@ export function TabsProvider({ children }: { children: ReactNode }) { return newNodeId.current; } function save() { - if (flows.length !== 0) - window.localStorage.setItem( - "tabsData", - JSON.stringify({ tabIndex, flows, id, nodeId: newNodeId.current }) - ); + //disabled until flows can be saved on local storage again without bugs + // if (flows.length !== 0) + // window.localStorage.setItem( + // "tabsData", + // JSON.stringify({ tabIndex, flows, id, nodeId: newNodeId.current }) + // ); } useEffect(() => { + //disabled until flows can be saved on local storage again without bugs //save tabs locally - save(); + // save(); + }, [flows, id, tabIndex, newNodeId]); - useEffect(() => { - //get tabs locally saved - let cookie = window.localStorage.getItem("tabsData"); - if (cookie && Object.keys(templates).length > 0) { - let cookieObject: LangFlowState = JSON.parse(cookie); - cookieObject.flows.forEach((flow) => { - flow.data.nodes.forEach((node) => { - if (Object.keys(templates[node.data.type]["template"]).length > 0) { - node.data.node.template = updateTemplate( - templates[node.data.type][ - "template" - ] as unknown as APITemplateType, + // useEffect(() => { + // //get tabs locally saved + // let cookie = window.localStorage.getItem("tabsData"); + // if (cookie && Object.keys(templates).length > 0) { + // let cookieObject: LangFlowState = JSON.parse(cookie); + // cookieObject.flows.forEach((flow) => { + // flow.data.nodes.forEach((node) => { + // if (Object.keys(templates[node.data.type]["template"]).length > 0) { + // node.data.node.template = updateTemplate( + // templates[node.data.type][ + // "template" + // ] as unknown as APITemplateType, + + // node.data.node.template as APITemplateType + // ); + // } + // }); + // }); + // setTabIndex(cookieObject.tabIndex); + // setFlows(cookieObject.flows); + // setId(cookieObject.id); + // newNodeId.current = cookieObject.nodeId; + // } + // }, [templates]); - node.data.node.template as APITemplateType - ); - } - }); - }); - setTabIndex(cookieObject.tabIndex); - setFlows(cookieObject.flows); - setId(cookieObject.id); - newNodeId.current = cookieObject.nodeId; - } - }, [templates]); function hardReset() { newNodeId.current = 0; setTabIndex(0); setFlows([]); - setId(""); + setId(uuidv4()); } /** @@ -182,7 +186,7 @@ export function TabsProvider({ children }: { children: ReactNode }) { let newFlow: FlowType = { description, name: flow?.name ?? "New Flow", - id: id.toString(), + id: uuidv4(), data, }; diff --git a/src/frontend/src/modals/ApiModal/index.tsx b/src/frontend/src/modals/ApiModal/index.tsx index 6fc788253..f14b190f5 100644 --- a/src/frontend/src/modals/ApiModal/index.tsx +++ b/src/frontend/src/modals/ApiModal/index.tsx @@ -45,6 +45,7 @@ export default function ApiModal({ flowName }) { } const pythonApiCode = `import requests +import json API_URL = "${window.location.protocol}//${window.location.host}/predict" @@ -57,7 +58,7 @@ def predict(message): print(predict("Your message"))`; -const pythonCode = `from langflow import load_flow_from_json + const pythonCode = `from langflow import load_flow_from_json flow = load_flow_from_json("${flowName}.json") # Now you can use it like any chain @@ -165,7 +166,7 @@ flow("Hey, have you heard of LangFlow?")`; { @@ -35,9 +36,9 @@ export default function ChatMessage({ chat, lockChat }: { chat: ChatMessageType, )} > {!chat.isSend &&
- - -
} + + + } {chat.isSend && } {!chat.isSend ? ( diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index 33d1f7c9c..7f6c61cde 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -30,10 +30,16 @@ export default function ChatModal({ const ws = useRef(null); const [lockChat, setLockChat] = useState(false); const isOpen = useRef(open); + const id = useRef(flow.id); useEffect(() => { isOpen.current = open; }, [open]); + useEffect(() => { + id.current = flow.id; + },[flow.id]) + + var isStream = false; const addChatHistory = ( @@ -164,10 +170,9 @@ export default function ChatModal({ try { const urlWs = process.env.NODE_ENV === "development" - ? `ws://localhost:7860/chat/${flow.id}` + ? `ws://localhost:7860/chat/${id.current}` : `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host - }/chat/${flow.id}`; - + }/chat/${id.current}`; const newWs = new WebSocket(urlWs); newWs.onopen = () => { console.log("WebSocket connection established!"); @@ -184,6 +189,26 @@ export default function ChatModal({ }; newWs.onerror = (ev) => { console.log(ev, "error"); + if(flow.id===""){ + connectWS(); + } + else{ + setErrorData({ + title: "There was an error on web connection, please: ", + list: [ + "Refresh the page", + "Use a new flow tab", + "Check if the backend is up", + ], + }); + } + }; + ws.current = newWs; + } catch { + if(flow.id===""){ + connectWS(); + } + else{ setErrorData({ title: "There was an error on web connection, please: ", list: [ @@ -192,17 +217,7 @@ export default function ChatModal({ "Check if the backend is up", ], }); - }; - ws.current = newWs; - } catch { - setErrorData({ - title: "There was an error on web connection, please: ", - list: [ - "Refresh the page", - "Use a new flow tab", - "Check if the backend is up", - ], - }); + } } } diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index 1eec534d6..f715e4e5b 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -1,34 +1,32 @@ -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react-swc'; +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; -const apiRoutes = [ - '/all', - '/predict', - '^/validate/*', - '^/chat/*', -]; +const apiRoutes = ["/all", "/predict", "^/validate/*", "^/chat/*"]; + +// Use environment variable to determine the target. +const target = process.env.VITE_PROXY_TARGET || "http://127.0.0.1:7860"; const proxyTargets = apiRoutes.reduce((proxyObj, route) => { - proxyObj[route] = { - target: 'http://127.0.0.1:7860', - changeOrigin: true, - secure: false, - ws: true, - }; - return proxyObj; + proxyObj[route] = { + target: target, + changeOrigin: true, + secure: false, + ws: true, + }; + return proxyObj; }, {}); export default defineConfig(() => { - return { - build: { - outDir: 'build', - }, - plugins: [react()], - server: { - port: 3000, - proxy: { - ...proxyTargets - } - }, - }; -}); \ No newline at end of file + return { + build: { + outDir: "build", + }, + plugins: [react()], + server: { + port: 3000, + proxy: { + ...proxyTargets, + }, + }, + }; +});