diff --git a/.github/workflows/docker_test.yml b/.github/workflows/docker_test.yml index 9be7beb00..07b826c58 100644 --- a/.github/workflows/docker_test.yml +++ b/.github/workflows/docker_test.yml @@ -24,6 +24,7 @@ env: jobs: test-docker: runs-on: ubuntu-latest + name: Test docker images steps: - uses: actions/checkout@v4 - name: Build image @@ -61,20 +62,3 @@ jobs: docker build -t langflowai/langflow-frontend:latest-dev \ -f docker/frontend/build_and_push_frontend.Dockerfile \ . - test-multi-arch-build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - id: qemu - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - push: false - file: ./docker/build_and_push.Dockerfile - platforms: "linux/amd64,linux/arm64/v8" - tags: langflowai/langflow:latest-dev diff --git a/.gitignore b/.gitignore index c81ff34d3..749eff4d3 100644 --- a/.gitignore +++ b/.gitignore @@ -180,6 +180,8 @@ coverage.xml local_settings.py db.sqlite3 db.sqlite3-journal +*.db-shm +*.db-wal # Flask stuff: instance/ diff --git a/Makefile b/Makefile index 4592caf9b..88487d312 100644 --- a/Makefile +++ b/Makefile @@ -9,17 +9,21 @@ open_browser ?= true path = src/backend/base/langflow/frontend workers ?= 1 + codespell: @poetry install --with spelling poetry run codespell --toml pyproject.toml + fix_codespell: @poetry install --with spelling poetry run codespell --toml pyproject.toml --write + setup_poetry: pipx install poetry + add: @echo 'Adding dependencies' ifdef devel @@ -34,45 +38,54 @@ ifdef base cd src/backend/base && poetry add $(base) endif + init: @echo 'Installing backend dependencies' make install_backend @echo 'Installing frontend dependencies' make install_frontend -coverage: + +coverage: ## run the tests and generate a coverage report poetry run pytest --cov \ --cov-config=.coveragerc \ --cov-report xml \ --cov-report term-missing:skip-covered \ --cov-report lcov:coverage/lcov-pytest.info + # allow passing arguments to pytest -tests: +tests: ## run the tests poetry run pytest tests --instafail -ra -n auto -m "not api_key_required" $(args) -format: +format: ## run code formatters poetry run ruff check . --fix poetry run ruff format . cd src/frontend && npm run format -lint: + +lint: ## run linters poetry run mypy --namespace-packages -p "langflow" -install_frontend: + +install_frontend: ## install the frontend dependencies cd src/frontend && npm install + install_frontendci: cd src/frontend && npm ci + install_frontendc: cd src/frontend && rm -rf node_modules package-lock.json && npm install + run_frontend: @-kill -9 `lsof -t -i:3000` cd src/frontend && npm start + tests_frontend: ifeq ($(UI), true) cd src/frontend && npx playwright test --ui --project=chromium @@ -80,6 +93,7 @@ else cd src/frontend && npx playwright test --project=chromium endif + run_cli: @echo 'Running the CLI' @make install_frontend > /dev/null @@ -93,6 +107,7 @@ else @make start host=$(host) port=$(port) log_level=$(log_level) endif + run_cli_debug: @echo 'Running the CLI in debug mode' @make install_frontend > /dev/null @@ -106,6 +121,7 @@ else @make start host=$(host) port=$(port) log_level=debug endif + start: @echo 'Running the CLI' @@ -116,30 +132,34 @@ else endif - setup_devcontainer: make init make build_frontend poetry run langflow --path src/frontend/build + setup_env: @sh ./scripts/setup/update_poetry.sh 1.8.2 @sh ./scripts/setup/setup_env.sh -frontend: + +frontend: ## run the frontend in development mode make install_frontend make run_frontend + frontendc: make install_frontendc make run_frontend + install_backend: @echo 'Installing backend dependencies' @poetry install @poetry run pre-commit install -backend: + +backend: ## run the backend in development mode @echo 'Setting up the environment' @make setup_env make install_backend @@ -152,6 +172,7 @@ else poetry run uvicorn --factory langflow.main:create_app --host 0.0.0.0 --port 7860 --reload --env-file .env --loop asyncio --workers $(workers) endif + build_and_run: @echo 'Removing dist folder' @make setup_env @@ -161,18 +182,21 @@ build_and_run: poetry run pip install dist/*.tar.gz poetry run langflow run + build_and_install: @echo 'Removing dist folder' rm -rf dist rm -rf src/backend/base/dist make build && poetry run pip install dist/*.whl && pip install src/backend/base/dist/*.whl --force-reinstall -build_frontend: + +build_frontend: ## build the frontend static files cd src/frontend && CI='' npm run build rm -rf src/backend/base/langflow/frontend cp -r src/frontend/build src/backend/base/langflow/frontend -build: + +build: ## build the frontend static files and package the project @echo 'Building the project' @make setup_env ifdef base @@ -185,13 +209,16 @@ ifdef main make build_langflow endif + build_langflow_base: cd src/backend/base && poetry build rm -rf src/backend/base/langflow/frontend + build_langflow_backup: poetry lock && poetry build + build_langflow: cd ./scripts && poetry run python update_dependencies.py poetry lock @@ -201,7 +228,8 @@ ifdef restore mv poetry.lock.bak poetry.lock endif -dev: + +dev: ## run the project in development mode with docker compose make install_frontend ifeq ($(build),1) @echo 'Running docker compose up with build' @@ -211,25 +239,30 @@ else docker compose $(if $(debug),-f docker-compose.debug.yml) up endif + lock_base: cd src/backend/base && poetry lock lock_langflow: poetry lock + lock: # Run both in parallel @echo 'Locking dependencies' cd src/backend/base && poetry lock poetry lock + publish_base: cd src/backend/base && poetry publish + publish_langflow: poetry publish -publish: + +publish: ## build the frontend static files and package the project and publish it to PyPI @echo 'Publishing the project' ifdef base make publish_base @@ -239,17 +272,11 @@ ifdef main make publish_langflow endif -help: + +help: ## show this help message @echo '----' - @echo 'format - run code formatters' - @echo 'lint - run linters' - @echo 'install_frontend - install the frontend dependencies' - @echo 'build_frontend - build the frontend static files' - @echo 'run_frontend - run the frontend in development mode' - @echo 'run_backend - run the backend in development mode' - @echo 'build - build the frontend static files and package the project' - @echo 'publish - build the frontend static files and package the project and publish it to PyPI' - @echo 'dev - run the project in development mode with docker compose' - @echo 'tests - run the tests' - @echo 'coverage - run the tests and generate a coverage report' + @echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | \ + sed -e 's/:.*##\s*/:/' \ + -e 's/^\(.\+\):\(.*\)/\\x1b[36mmake \1\\x1b[m:\2/' | \ + column -c2 -t -s :']]')" @echo '----' diff --git a/docker/build_and_push.Dockerfile b/docker/build_and_push.Dockerfile index 43d9a0272..79f6ac8d7 100644 --- a/docker/build_and_push.Dockerfile +++ b/docker/build_and_push.Dockerfile @@ -7,8 +7,9 @@ # Used to build deps + create our virtual environment ################################ -# force platform to the current architecture to increase build speed time on multi-platform builds -FROM --platform=$BUILDPLATFORM python:3.12-slim as builder-base +# 1. use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved +# 2. do not add --platform=$BUILDPLATFORM because the pydantic binaries must be resolved for the final architecture +FROM python:3.12.3-slim as builder-base ENV PYTHONDONTWRITEBYTECODE=1 \ \ @@ -51,15 +52,27 @@ COPY pyproject.toml poetry.lock README.md ./ COPY src/ ./src COPY scripts/ ./scripts RUN python -m pip install requests --user && cd ./scripts && python update_dependencies.py + +# 1. Install the dependencies using the current poetry.lock file to create reproducible builds +# 2. Do not install dev dependencies +# 3. Install all the extras to ensure all optionals are installed as well +# 4. --sync to ensure nothing else is in the environment +# 5. Build the wheel and install "langflow" package (mainly for version) + +# Note: moving to build and installing the wheel will make the docker images not reproducible. RUN $POETRY_HOME/bin/poetry lock --no-update \ + # install current lock file with fixed dependencies versions \ + # do not install dev dependencies \ + && $POETRY_HOME/bin/poetry install --without dev --sync -E deploy -E couchbase -E cassio \ && $POETRY_HOME/bin/poetry build -f wheel \ - && $POETRY_HOME/bin/poetry run pip install dist/*.whl --force-reinstall + && $POETRY_HOME/bin/poetry run pip install dist/*.whl ################################ # RUNTIME # Setup user, utilities and copy the virtual environment only ################################ -FROM python:3.12-slim as runtime +# 1. use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved +FROM python:3.12.3-slim as runtime RUN apt-get -y update \ && apt-get install --no-install-recommends -y \ diff --git a/docker/build_and_push_base.Dockerfile b/docker/build_and_push_base.Dockerfile index f70a517da..916531df2 100644 --- a/docker/build_and_push_base.Dockerfile +++ b/docker/build_and_push_base.Dockerfile @@ -10,7 +10,9 @@ # PYTHON-BASE # Sets up all our shared environment variables ################################ -FROM python:3.12-slim as python-base + +# use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved +FROM python:3.12.3-slim as python-base # python ENV PYTHONUNBUFFERED=1 \ diff --git a/docker/frontend/build_and_push_frontend.Dockerfile b/docker/frontend/build_and_push_frontend.Dockerfile index 46c5ffdeb..55f570187 100644 --- a/docker/frontend/build_and_push_frontend.Dockerfile +++ b/docker/frontend/build_and_push_frontend.Dockerfile @@ -5,7 +5,7 @@ # BUILDER-BASE ################################ -# force platform to the current architecture to increase build speed time on multi-platform builds +# 1. force platform to the current architecture to increase build speed time on multi-platform builds FROM --platform=$BUILDPLATFORM node:lts-bookworm-slim as builder-base COPY src/frontend /frontend diff --git a/docker/frontend/nginx.conf b/docker/frontend/nginx.conf index d5ecfce43..593b1dcc8 100644 --- a/docker/frontend/nginx.conf +++ b/docker/frontend/nginx.conf @@ -7,7 +7,7 @@ server { gzip_vary on; gzip_disable "MSIE [4-6] \."; - listen 80; + listen __FRONTEND_PORT__; location / { root /usr/share/nginx/html; diff --git a/docker/frontend/start-nginx.sh b/docker/frontend/start-nginx.sh index 3607adf7d..6ef09745c 100644 --- a/docker/frontend/start-nginx.sh +++ b/docker/frontend/start-nginx.sh @@ -4,11 +4,20 @@ trap 'kill -TERM $PID' TERM INT if [ -z "$BACKEND_URL" ]; then BACKEND_URL="$1" fi +if [ -z "$FRONTEND_PORT" ]; then + FRONTEND_PORT="$2" +fi +if [ -z "$FRONTEND_PORT" ]; then + FRONTEND_PORT="80" +fi if [ -z "$BACKEND_URL" ]; then echo "BACKEND_URL must be set as an environment variable or as first parameter. (e.g. http://localhost:7860)" exit 1 fi +echo "BACKEND_URL: $BACKEND_URL" +echo "FRONTEND_PORT: $FRONTEND_PORT" sed -i "s|__BACKEND_URL__|$BACKEND_URL|g" /etc/nginx/conf.d/default.conf +sed -i "s|__FRONTEND_PORT__|$FRONTEND_PORT|g" /etc/nginx/conf.d/default.conf cat /etc/nginx/conf.d/default.conf diff --git a/poetry.lock b/poetry.lock index 91afed2ff..e0e4f8392 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4409,7 +4409,7 @@ six = "*" [[package]] name = "langflow-base" -version = "0.0.63" +version = "0.0.66" description = "A Python package with a built-in web application" optional = false python-versions = ">=3.10,<3.13" diff --git a/pyproject.toml b/pyproject.toml index ee7630b6d..47316552c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "1.0.0a52" +version = "1.0.0a55" description = "A Python package with a built-in web application" authors = ["Langflow "] maintainers = [ diff --git a/src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py b/src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py index dd40d64d5..4fca09762 100644 --- a/src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py @@ -1,3 +1,4 @@ +from typing import Optional from langchain_core.embeddings import Embeddings from langchain_openai import AzureOpenAIEmbeddings from pydantic.v1 import SecretStr @@ -44,6 +45,11 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent): "password": True, }, "code": {"show": False}, + "dimensions": { + "display_name": "Dimensions", + "info": "The number of dimensions the resulting output embeddings should have. Only supported by certain models.", + "advanced": True, + }, } def build( @@ -52,6 +58,7 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent): azure_deployment: str, api_version: str, api_key: str, + dimensions: Optional[int] = None, ) -> Embeddings: if api_key: azure_api_key = SecretStr(api_key) @@ -63,6 +70,7 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent): azure_deployment=azure_deployment, api_version=api_version, api_key=azure_api_key, + dimensions=dimensions, ) except Exception as e: diff --git a/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py b/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py index 2ff78d562..4813fc793 100644 --- a/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py @@ -84,6 +84,11 @@ class OpenAIEmbeddingsComponent(CustomComponent): "advanced": True, }, "tiktoken_enable": {"display_name": "TikToken Enable", "advanced": True}, + "dimensions": { + "display_name": "Dimensions", + "info": "The number of dimensions the resulting output embeddings should have. Only supported by certain models.", + "advanced": True, + }, } def build( @@ -109,6 +114,7 @@ class OpenAIEmbeddingsComponent(CustomComponent): skip_empty: bool = False, tiktoken_enable: bool = True, tiktoken_model_name: Optional[str] = None, + dimensions: Optional[int] = None, ) -> Embeddings: # This is to avoid errors with Vector Stores (e.g Chroma) if disallowed_special == ["all"]: @@ -140,4 +146,5 @@ class OpenAIEmbeddingsComponent(CustomComponent): show_progress_bar=show_progress_bar, skip_empty=skip_empty, tiktoken_model_name=tiktoken_model_name, + dimensions=dimensions, ) diff --git a/src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py b/src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py index 7358762bc..76974a00f 100644 --- a/src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py +++ b/src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py @@ -53,7 +53,7 @@ class ChatOpenAIComponent(CustomComponent): self, max_tokens: Optional[int] = 0, model_kwargs: NestedDict = {}, - model_name: str = "gpt-4o", + model_name: str = "gpt-3.5-turbo", openai_api_base: Optional[str] = None, openai_api_key: Optional[str] = None, temperature: float = 0.7, diff --git a/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py b/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py index dfa4311da..3ea0c30c9 100644 --- a/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py +++ b/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py @@ -28,7 +28,7 @@ class AstraDBSearchComponent(LCVectorStoreComponent): "info": "The name of the collection within Astra DB where the vectors will be stored.", }, "token": { - "display_name": "Token", + "display_name": "Astra DB Application Token", "info": "Authentication token for accessing Astra DB.", "password": True, }, diff --git a/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py b/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py index 6ea230a1d..475d67a17 100644 --- a/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py +++ b/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py @@ -3,7 +3,6 @@ from typing import List, Optional import chromadb from chromadb.config import Settings from langchain_chroma import Chroma - from langflow.components.vectorstores.base.model import LCVectorStoreComponent from langflow.field_typing import Embeddings, Text from langflow.schema import Data @@ -104,10 +103,11 @@ class ChromaSearchComponent(LCVectorStoreComponent): client = chromadb.HttpClient(settings=chroma_settings) if index_directory: index_directory = self.resolve_path(index_directory) + vector_store = Chroma( embedding_function=embedding, collection_name=collection_name, - persist_directory=index_directory, + persist_directory=index_directory or None, client=client, ) diff --git a/src/backend/base/langflow/components/vectorstores/AstraDB.py b/src/backend/base/langflow/components/vectorstores/AstraDB.py index 1a97297c8..3b1df1d38 100644 --- a/src/backend/base/langflow/components/vectorstores/AstraDB.py +++ b/src/backend/base/langflow/components/vectorstores/AstraDB.py @@ -25,7 +25,7 @@ class AstraDBVectorStoreComponent(CustomComponent): "info": "The name of the collection within Astra DB where the vectors will be stored.", }, "token": { - "display_name": "Token", + "display_name": "Astra DB Application Token", "info": "Authentication token for accessing Astra DB.", "password": True, }, diff --git a/src/backend/base/langflow/graph/utils.py b/src/backend/base/langflow/graph/utils.py index 83e2177b1..332545caf 100644 --- a/src/backend/base/langflow/graph/utils.py +++ b/src/backend/base/langflow/graph/utils.py @@ -1,9 +1,11 @@ -from typing import Any, Union +from enum import Enum +from typing import Any, Generator, Union from langchain_core.documents import Document from pydantic import BaseModel from langflow.interface.utils import extract_input_variables_from_prompt +from langflow.schema.message import Message class UnbuiltObject: @@ -14,6 +16,16 @@ class UnbuiltResult: pass +class ArtifactType(str, Enum): + TEXT = "text" + RECORD = "record" + OBJECT = "object" + ARRAY = "array" + STREAM = "stream" + UNKNOWN = "unknown" + MESSAGE = "message" + + def validate_prompt(prompt: str): """Validate prompt.""" if extract_input_variables_from_prompt(prompt): @@ -50,3 +62,37 @@ def serialize_field(value): elif isinstance(value, str): return {"result": value} return value + + +def get_artifact_type(value, build_result) -> str: + result = ArtifactType.UNKNOWN + match value: + case Record(): + result = ArtifactType.RECORD + + case str(): + result = ArtifactType.TEXT + + case dict(): + result = ArtifactType.OBJECT + + case list(): + result = ArtifactType.ARRAY + + case Message(): + result = ArtifactType.MESSAGE + + if result == ArtifactType.UNKNOWN: + if isinstance(build_result, Generator): + result = ArtifactType.STREAM + elif isinstance(value, Message) and isinstance(value.text, Generator): + result = ArtifactType.STREAM + + return result.value + + +def post_process_raw(raw, artifact_type: str): + if artifact_type == ArtifactType.STREAM.value: + raw = "" + + return raw diff --git a/src/backend/base/langflow/initial_setup/setup.py b/src/backend/base/langflow/initial_setup/setup.py index 359bd2f21..1b956f71d 100644 --- a/src/backend/base/langflow/initial_setup/setup.py +++ b/src/backend/base/langflow/initial_setup/setup.py @@ -181,6 +181,9 @@ def update_new_output(data): } ) deduplicated_outputs = [] + if source_node is None: + source_node = {"data": {"node": {"outputs": []}}} + for output in source_node["data"]["node"]["outputs"]: if output["name"] not in [d["name"] for d in deduplicated_outputs]: deduplicated_outputs.append(output) diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json b/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json index 6814f9c30..a27880ebf 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json @@ -2,97 +2,73 @@ "data": { "edges": [ { - "className": "stroke-gray-900 stroke-connection", + "className": "", "data": { "sourceHandle": { + "baseClasses": ["object", "Text", "str"], "dataType": "OpenAIModel", - "id": "OpenAIModel-k39HS", - "name": "text_output", - "output_types": [ - "Text" - ] + "id": "OpenAIModel-NDBjF" }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-njtka", - "inputTypes": [ - "Text", - "Message" - ], + "id": "ChatOutput-JkVmc", + "inputTypes": ["Text"], "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-k39HS{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-k39HSœ}-ChatOutput-njtka{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-njtkaœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-k39HS", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-k39HSœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", + "id": "reactflow__edge-OpenAIModel-NDBjF{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-NDBjFœ}-ChatOutput-JkVmc{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-JkVmcœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "source": "OpenAIModel-NDBjF", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œTextœ, œstrœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-NDBjFœ}", "style": { "stroke": "#555" }, - "target": "ChatOutput-njtka", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-njtkaœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "target": "ChatOutput-JkVmc", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-JkVmcœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { - "className": "stroke-gray-900 stroke-connection", + "className": "", "data": { "sourceHandle": { + "baseClasses": ["object", "str", "Text"], "dataType": "Prompt", - "id": "Prompt-uxBqP", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-WSII4" }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-k39HS", - "inputTypes": [ - "Text", - "Data", - "Prompt" - ], + "id": "OpenAIModel-NDBjF", + "inputTypes": ["Text", "Record", "Prompt"], "type": "str" } }, - "id": "reactflow__edge-Prompt-uxBqP{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-uxBqPœ}-OpenAIModel-k39HS{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-k39HSœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", - "source": "Prompt-uxBqP", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-uxBqPœ, œoutput_typesœ: [œPromptœ], œnameœ: œpromptœ}", + "id": "reactflow__edge-Prompt-WSII4{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-WSII4œ}-OpenAIModel-NDBjF{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-NDBjFœ,œinputTypesœ:[œTextœ,œRecordœ,œPromptœ],œtypeœ:œstrœ}", + "source": "Prompt-WSII4", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-WSII4œ}", "style": { "stroke": "#555" }, - "target": "OpenAIModel-k39HS", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-k39HSœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "target": "OpenAIModel-NDBjF", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-NDBjFœ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": ["Message", "object", "str", "Text"], "dataType": "ChatInput", - "id": "ChatInput-P3fgL", - "name": "message", - "output_types": [ - "Message" - ] + "id": "ChatInput-kltLA" }, "targetHandle": { "fieldName": "user_input", - "id": "Prompt-uxBqP", - "inputTypes": [ - "Document", - "Message", - "Record", - "Text" - ], + "id": "Prompt-WSII4", + "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], "type": "str" } }, - "id": "reactflow__edge-ChatInput-P3fgL{œbaseClassesœ:[œobjectœ,œRecordœ,œstrœ,œTextœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-P3fgLœ}-Prompt-uxBqP{œfieldNameœ:œuser_inputœ,œidœ:œPrompt-uxBqPœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", - "source": "ChatInput-P3fgL", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-P3fgLœ, œoutput_typesœ: [œMessageœ], œnameœ: œmessageœ}", - "style": { - "stroke": "#555" - }, - "target": "Prompt-uxBqP", - "targetHandle": "{œfieldNameœ: œuser_inputœ, œidœ: œPrompt-uxBqPœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-ChatInput-kltLA{œbaseClassesœ:[œMessageœ,œobjectœ,œstrœ,œTextœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-kltLAœ}-Prompt-WSII4{œfieldNameœ:œuser_inputœ,œidœ:œPrompt-WSII4œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "source": "ChatInput-kltLA", + "sourceHandle": "{œbaseClassesœ: [œMessageœ, œobjectœ, œstrœ, œTextœ], œdataTypeœ: œChatInputœ, œidœ: œChatInput-kltLAœ}", + "target": "Prompt-WSII4", + "targetHandle": "{œfieldNameœ: œuser_inputœ, œidœ: œPrompt-WSII4œ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -100,18 +76,12 @@ "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-uxBqP", + "id": "Prompt-WSII4", "node": { - "base_classes": [ - "object", - "str", - "Text" - ], + "base_classes": ["object", "str", "Text"], "beta": false, "custom_fields": { - "template": [ - "user_input" - ] + "template": ["user_input"] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -126,33 +96,9 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } - ], + "output_types": ["Prompt"], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -169,7 +115,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" }, "template": { "advanced": false, @@ -178,9 +124,7 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -203,7 +147,7 @@ "info": "", "input_types": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -224,17 +168,17 @@ "type": "Prompt" }, "dragging": false, - "height": 383, - "id": "Prompt-uxBqP", + "height": 419, + "id": "Prompt-WSII4", "position": { - "x": 53.588791333410654, - "y": -107.07318910019967 + "x": 18.562420355453696, + "y": -284.15095348876025 }, "positionAbsolute": { - "x": 53.588791333410654, - "y": -107.07318910019967 + "x": 18.562420355453696, + "y": -284.15095348876025 }, - "selected": true, + "selected": false, "type": "genericNode", "width": 384 }, @@ -242,13 +186,9 @@ "data": { "description": "Generates text using OpenAI LLMs.", "display_name": "OpenAI", - "id": "OpenAIModel-k39HS", + "id": "OpenAIModel-NDBjF", "node": { - "base_classes": [ - "object", - "Text", - "str" - ], + "base_classes": ["object", "Text", "str"], "beta": false, "custom_fields": { "input_value": null, @@ -278,33 +218,9 @@ ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } - ], + "output_types": ["Text"], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -321,7 +237,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, @@ -330,22 +246,17 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text", - "Data", - "Prompt" - ], + "input_types": ["Text", "Record", "Prompt"], "list": false, "load_from_db": false, "multiline": false, "name": "input_value", "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, @@ -354,9 +265,6 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -366,8 +274,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "int", + "value": 256 }, "model_kwargs": { "advanced": true, @@ -376,9 +284,6 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -388,8 +293,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, @@ -398,9 +303,7 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], + "input_types": ["Text"], "list": true, "load_from_db": false, "multiline": false, @@ -418,7 +321,7 @@ "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-3.5-turbo" }, "openai_api_base": { "advanced": true, @@ -427,9 +330,7 @@ "fileTypes": [], "file_path": "", "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", - "input_types": [ - "Text" - ], + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -439,8 +340,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, @@ -449,20 +349,18 @@ "fileTypes": [], "file_path": "", "info": "The OpenAI API Key to use for the OpenAI model.", - "input_types": [ - "Text" - ], + "input_types": ["Text"], "list": false, - "load_from_db": true, + "load_from_db": false, "multiline": false, "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "stream": { "advanced": true, @@ -471,9 +369,6 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -483,7 +378,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", + "type": "bool", "value": false }, "system_message": { @@ -493,9 +388,7 @@ "fileTypes": [], "file_path": "", "info": "System message to pass to the model.", - "input_types": [ - "Text" - ], + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -505,8 +398,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, @@ -515,19 +407,22 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, "name": "temperature", "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, - "type": "str", + "type": "float", "value": 0.1 } } @@ -535,8 +430,8 @@ "type": "OpenAIModel" }, "dragging": false, - "height": 563, - "id": "OpenAIModel-k39HS", + "height": 571, + "id": "OpenAIModel-NDBjF", "position": { "x": 634.8148772766217, "y": 27.035057029045305 @@ -551,14 +446,9 @@ }, { "data": { - "id": "ChatOutput-njtka", + "id": "ChatOutput-JkVmc", "node": { - "base_classes": [ - "Record", - "Text", - "str", - "object" - ], + "base_classes": ["Record", "Text", "str", "object"], "beta": false, "custom_fields": { "input_value": null, @@ -575,22 +465,9 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } - ], + "output_types": ["Message", "Text"], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -607,7 +484,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -615,11 +492,8 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", - "input_types": [ - "Text", - "Message" - ], + "info": "", + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": true, @@ -629,8 +503,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -638,18 +511,13 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", - "input_types": [ - "Text" - ], + "info": "", + "input_types": ["Text"], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": [ - "Machine", - "User" - ], + "options": ["Machine", "User"], "password": false, "placeholder": "", "required": false, @@ -659,15 +527,13 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", - "input_types": [ - "Text" - ], + "info": "", + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -686,10 +552,8 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", - "input_types": [ - "Text" - ], + "info": "If provided, the message will be stored in the memory.", + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -699,23 +563,22 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, "type": "ChatOutput" }, "dragging": false, - "height": 383, - "id": "ChatOutput-njtka", + "height": 391, + "id": "ChatOutput-JkVmc", "position": { - "x": 1193.250417197867, - "y": 71.88476890163852 + "x": 1183.52086970399, + "y": -21.518887039580306 }, "positionAbsolute": { - "x": 1193.250417197867, - "y": 71.88476890163852 + "x": 1183.52086970399, + "y": -21.518887039580306 }, "selected": false, "type": "genericNode", @@ -723,18 +586,14 @@ }, { "data": { - "id": "ChatInput-P3fgL", + "id": "ChatInput-kltLA", "node": { - "base_classes": [ - "object", - "Record", - "str", - "Text" - ], + "base_classes": ["Message", "object", "str", "Text"], "beta": false, "custom_fields": { + "files": null, "input_value": null, - "return_record": null, + "return_message": null, "sender": null, "sender_name": null, "session_id": null @@ -746,22 +605,9 @@ "field_order": [], "frozen": false, "icon": "ChatInput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } - ], + "output_types": ["Message", "Text"], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -778,7 +624,49 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n input_types=[],\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"User\",\n info=\"Type of sender.\",\n advanced=True,\n ),\n StrInput(\n name=\"sender_name\",\n type=str,\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=\"User\",\n advanced=True,\n ),\n StrInput(\n name=\"session_id\", type=str, display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, (Message, str)) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.schema.message import Message\nfrom langflow.field_typing import Text\nfrom typing import Union\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Text\",\n \"multiline\": True,\n }\n build_config[\"return_message\"] = {\n \"display_name\": \"Return Record\",\n \"advanced\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n files: Optional[list[str]] = None,\n session_id: Optional[str] = None,\n return_message: Optional[bool] = True,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n files=files,\n session_id=session_id,\n return_message=return_message,\n )\n" + }, + "files": { + "advanced": true, + "display_name": "Files", + "dynamic": false, + "fileTypes": [ + ".txt", + ".md", + ".mdx", + ".csv", + ".json", + ".yaml", + ".yml", + ".xml", + ".html", + ".htm", + ".pdf", + ".docx", + ".py", + ".sh", + ".sql", + ".js", + ".ts", + ".tsx", + ".jpg", + ".jpeg", + ".png", + ".bmp" + ], + "file_path": "", + "info": "Files to be sent with the message.", + "list": false, + "load_from_db": false, + "multiline": false, + "name": "files", + "password": false, + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "file", + "value": "" }, "input_value": { "advanced": false, @@ -786,7 +674,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as input.", + "info": "", "input_types": [], "list": false, "load_from_db": false, @@ -798,7 +686,26 @@ "show": true, "title_case": false, "type": "str", - "value": "" + "value": "what do you see?" + }, + "return_message": { + "advanced": true, + "display_name": "Return Record", + "dynamic": false, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": false, + "name": "return_message", + "password": false, + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "bool", + "value": true }, "sender": { "advanced": true, @@ -806,18 +713,13 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", - "input_types": [ - "Text" - ], + "info": "", + "input_types": ["Text"], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": [ - "Machine", - "User" - ], + "options": ["Machine", "User"], "password": false, "placeholder": "", "required": false, @@ -832,10 +734,8 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", - "input_types": [ - "Text" - ], + "info": "", + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -854,10 +754,8 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", - "input_types": [ - "Text" - ], + "info": "If provided, the message will be stored in the memory.", + "input_types": ["Text"], "list": false, "load_from_db": false, "multiline": false, @@ -867,38 +765,37 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, "type": "ChatInput" }, "dragging": false, - "height": 375, - "id": "ChatInput-P3fgL", + "height": 289, + "id": "ChatInput-kltLA", "position": { - "x": -495.2223093083827, - "y": -232.56998443685862 + "x": -560.3246254009209, + "y": -435.0506368105706 }, "positionAbsolute": { - "x": -495.2223093083827, - "y": -232.56998443685862 + "x": -560.3246254009209, + "y": -435.0506368105706 }, - "selected": false, + "selected": true, "type": "genericNode", "width": 384 } ], "viewport": { - "x": 260.58251815500563, - "y": 318.2261172111936, - "zoom": 0.43514115784696294 + "x": 223.38563623650703, + "y": 271.96191180648566, + "zoom": 0.5138985141032123 } }, "description": "This flow will get you experimenting with the basics of the UI, the Chat and the Prompt component. \n\nTry changing the Template in it to see how the model behaves. \nYou can change it to this and a Text Input into the `type_of_person` variable : \"Answer the user as if you were a pirate.\n\nUser: {user_input}\n\nAnswer: \" ", - "id": "c091a57f-43a7-4a5e-b352-035ae8d8379c", + "id": "ad43b14f-6ec7-496f-9564-aad928603084", "is_component": false, - "last_tested_version": "1.0.0a4", + "last_tested_version": "1.0.0a52", "name": "Basic Prompting (Hello, World)" -} \ No newline at end of file +} diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json index 7e92c3d0b..200e625c5 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json @@ -5,10 +5,11 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Record" + ], "dataType": "URL", - "id": "URL-HYPkR", - "name": "record", - "output_types": [] + "id": "URL-HYPkR" }, "targetHandle": { "fieldName": "reference_2", @@ -25,7 +26,7 @@ "id": "reactflow__edge-URL-HYPkR{œbaseClassesœ:[œRecordœ],œdataTypeœ:œURLœ,œidœ:œURL-HYPkRœ}-Prompt-Rse03{œfieldNameœ:œreference_2œ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "URL-HYPkR", - "sourceHandle": "{œdataTypeœ: œURLœ, œidœ: œURL-HYPkRœ, œoutput_typesœ: [], œnameœ: œrecordœ}", + "sourceHandle": "{œbaseClassesœ: [œRecordœ], œdataTypeœ: œURLœ, œidœ: œURL-HYPkRœ}", "style": { "stroke": "#555" }, @@ -36,40 +37,41 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], "dataType": "OpenAIModel", - "id": "OpenAIModel-gi29P", - "name": "text_output", - "output_types": [ - "Text" - ] + "id": "OpenAIModel-gi29P" }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-JPlxl", "inputTypes": [ - "Text", - "Message" + "Text" ], "type": "str" } }, "id": "reactflow__edge-OpenAIModel-gi29P{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-gi29Pœ}-ChatOutput-JPlxl{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-JPlxlœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "source": "OpenAIModel-gi29P", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-gi29Pœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œTextœ, œobjectœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-gi29Pœ}", "style": { "stroke": "#555" }, "target": "ChatOutput-JPlxl", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-JPlxlœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-JPlxlœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Record" + ], "dataType": "URL", - "id": "URL-2cX90", - "name": "record", - "output_types": [] + "id": "URL-2cX90" }, "targetHandle": { "fieldName": "reference_1", @@ -85,7 +87,7 @@ }, "id": "reactflow__edge-URL-2cX90{œbaseClassesœ:[œRecordœ],œdataTypeœ:œURLœ,œidœ:œURL-2cX90œ}-Prompt-Rse03{œfieldNameœ:œreference_1œ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "URL-2cX90", - "sourceHandle": "{œdataTypeœ: œURLœ, œidœ: œURL-2cX90œ, œoutput_typesœ: [], œnameœ: œrecordœ}", + "sourceHandle": "{œbaseClassesœ: [œRecordœ], œdataTypeœ: œURLœ, œidœ: œURL-2cX90œ}", "style": { "stroke": "#555" }, @@ -96,12 +98,13 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], "dataType": "TextInput", - "id": "TextInput-og8Or", - "name": "Text", - "output_types": [ - "Text" - ] + "id": "TextInput-og8Or" }, "targetHandle": { "fieldName": "instructions", @@ -117,7 +120,7 @@ }, "id": "reactflow__edge-TextInput-og8Or{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-og8Orœ}-Prompt-Rse03{œfieldNameœ:œinstructionsœ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "TextInput-og8Or", - "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-og8Orœ, œoutput_typesœ: [œTextœ], œnameœ: œTextœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œTextœ, œstrœ], œdataTypeœ: œTextInputœ, œidœ: œTextInput-og8Orœ}", "style": { "stroke": "#555" }, @@ -128,19 +131,20 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], "dataType": "Prompt", - "id": "Prompt-Rse03", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-Rse03" }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-gi29P", "inputTypes": [ "Text", - "Data", + "Record", "Prompt" ], "type": "str" @@ -149,12 +153,12 @@ "id": "reactflow__edge-Prompt-Rse03{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-Rse03œ}-OpenAIModel-gi29P{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-gi29Pœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "Prompt-Rse03", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-Rse03œ, œoutput_typesœ: [œPromptœ], œnameœ: œpromptœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œTextœ, œstrœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-Rse03œ}", "style": { "stroke": "#555" }, "target": "OpenAIModel-gi29P", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-gi29Pœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-gi29Pœ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -190,33 +194,11 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Prompt" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -233,7 +215,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" }, "instructions": { "advanced": false, @@ -372,22 +354,11 @@ "field_order": [], "frozen": false, "icon": "layout-template", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "fetch_content", - "name": "data", - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Record" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -404,22 +375,31 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n inputs = [\n StrInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, separated by commas.\",\n value=\"\",\n is_list=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n ]\n\n def fetch_content(self) -> Data:\n urls = [url.strip() for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n data = [Data(content=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n" + "value": "from typing import Any, Dict\n\nfrom langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Record\n\n\nclass URLComponent(CustomComponent):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"urls\": {\"display_name\": \"URL\"},\n }\n\n def build(\n self,\n urls: list[str],\n ) -> list[Record]:\n loader = WebBaseLoader(web_paths=[url for url in urls if url])\n docs = loader.load()\n records = self.to_records(docs)\n self.status = records\n return records\n" }, "urls": { "advanced": false, - "display_name": "URLs", + "display_name": "URL", "dynamic": false, - "info": "Enter one or more URLs, separated by commas.", + "fileTypes": [], + "file_path": "", + "info": "", + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, + "multiline": false, "name": "urls", + "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", - "value": "" + "value": [ + "https://www.promptingguide.ai/techniques/prompt_chaining" + ] } } }, @@ -466,22 +446,12 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -498,7 +468,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -506,10 +476,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", + "info": "", "input_types": [ - "Text", - "Message" + "Text" ], "list": false, "load_from_db": false, @@ -520,8 +489,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -529,7 +497,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -550,12 +518,12 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -577,7 +545,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -590,8 +558,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, @@ -645,33 +612,11 @@ ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -688,7 +633,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, @@ -699,7 +644,7 @@ "info": "", "input_types": [ "Text", - "Data", + "Record", "Prompt" ], "list": false, @@ -708,11 +653,10 @@ "name": "input_value", "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, @@ -721,9 +665,6 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -733,8 +674,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "int", + "value": "1024" }, "model_kwargs": { "advanced": true, @@ -743,9 +684,6 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -755,8 +693,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, @@ -785,7 +723,7 @@ "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-3.5-turbo" }, "openai_api_base": { "advanced": true, @@ -806,8 +744,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, @@ -825,7 +762,7 @@ "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", @@ -838,9 +775,6 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -850,8 +784,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": false + "type": "bool", + "value": true }, "system_message": { "advanced": true, @@ -872,8 +806,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, @@ -882,20 +815,23 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, "name": "temperature", "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, - "type": "str", - "value": 0.1 + "type": "float", + "value": "0.1" } } }, @@ -934,22 +870,11 @@ "field_order": [], "frozen": false, "icon": "layout-template", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "fetch_content", - "name": "data", - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Record" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -966,22 +891,31 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n inputs = [\n StrInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, separated by commas.\",\n value=\"\",\n is_list=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n ]\n\n def fetch_content(self) -> Data:\n urls = [url.strip() for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n data = [Data(content=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n" + "value": "from typing import Any, Dict\n\nfrom langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Record\n\n\nclass URLComponent(CustomComponent):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"urls\": {\"display_name\": \"URL\"},\n }\n\n def build(\n self,\n urls: list[str],\n ) -> list[Record]:\n loader = WebBaseLoader(web_paths=[url for url in urls if url])\n docs = loader.load()\n records = self.to_records(docs)\n self.status = records\n return records\n" }, "urls": { "advanced": false, - "display_name": "URLs", + "display_name": "URL", "dynamic": false, - "info": "Enter one or more URLs, separated by commas.", + "fileTypes": [], + "file_path": "", + "info": "", + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, + "multiline": false, "name": "urls", + "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", - "value": "" + "value": [ + "https://www.promptingguide.ai/introduction/basics" + ] } } }, @@ -1026,15 +960,6 @@ "output_types": [ "Text" ], - "outputs": [ - { - "name": "Text", - "selected": "Text", - "types": [ - "Text" - ] - } - ], "template": { "_type": "CustomComponent", "code": { @@ -1131,4 +1056,4 @@ "is_component": false, "last_tested_version": "1.0.0a0", "name": "Blog Writer" -} \ No newline at end of file +} diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json index da9e2031d..97e56a5ba 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json @@ -2,121 +2,139 @@ "data": { "edges": [ { + "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { - "dataType": "File", - "id": "File-BzIs2", - "name": "data", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "Document", - "id": "Prompt-9DNZG", - "inputTypes": [ - "Document", - "Message", - "Data", - "Text" + "baseClasses": [ + "str", + "Record", + "Text", + "object" ], - "type": "str" - } - }, - "id": "reactflow__edge-File-BzIs2{œdataTypeœ:œFileœ,œidœ:œFile-BzIs2œ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-Prompt-9DNZG{œfieldNameœ:œDocumentœ,œidœ:œPrompt-9DNZGœ,œinputTypesœ:[œDocumentœ,œMessageœ,œDataœ,œTextœ],œtypeœ:œstrœ}", - "source": "File-BzIs2", - "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-BzIs2œ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "Prompt-9DNZG", - "targetHandle": "{œfieldNameœ: œDocumentœ, œidœ: œPrompt-9DNZGœ, œinputTypesœ: [œDocumentœ, œMessageœ, œDataœ, œTextœ], œtypeœ: œstrœ}" - }, - { - "data": { - "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-27Usy", - "name": "message", - "output_types": [ - "Message" - ] + "id": "ChatInput-MsSJ9" }, "targetHandle": { "fieldName": "Question", - "id": "Prompt-9DNZG", + "id": "Prompt-tHwPf", "inputTypes": [ "Document", - "Message", - "Data", + "BaseOutputParser", + "Record", "Text" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-27Usy{œdataTypeœ:œChatInputœ,œidœ:œChatInput-27Usyœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-9DNZG{œfieldNameœ:œQuestionœ,œidœ:œPrompt-9DNZGœ,œinputTypesœ:[œDocumentœ,œMessageœ,œDataœ,œTextœ],œtypeœ:œstrœ}", - "source": "ChatInput-27Usy", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-27Usyœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-9DNZG", - "targetHandle": "{œfieldNameœ: œQuestionœ, œidœ: œPrompt-9DNZGœ, œinputTypesœ: [œDocumentœ, œMessageœ, œDataœ, œTextœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-ChatInput-MsSJ9{œbaseClassesœ:[œstrœ,œRecordœ,œTextœ,œobjectœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-MsSJ9œ}-Prompt-tHwPf{œfieldNameœ:œQuestionœ,œidœ:œPrompt-tHwPfœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "source": "ChatInput-MsSJ9", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œRecordœ, œTextœ, œobjectœ], œdataTypeœ: œChatInputœ, œidœ: œChatInput-MsSJ9œ}", + "style": { + "stroke": "#555" + }, + "target": "Prompt-tHwPf", + "targetHandle": "{œfieldNameœ: œQuestionœ, œidœ: œPrompt-tHwPfœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" }, { + "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "File", + "id": "File-6TEsD" + }, + "targetHandle": { + "fieldName": "Document", + "id": "Prompt-tHwPf", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + } + }, + "id": "reactflow__edge-File-6TEsD{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-6TEsDœ}-Prompt-tHwPf{œfieldNameœ:œDocumentœ,œidœ:œPrompt-tHwPfœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "source": "File-6TEsD", + "sourceHandle": "{œbaseClassesœ: [œRecordœ], œdataTypeœ: œFileœ, œidœ: œFile-6TEsDœ}", + "style": { + "stroke": "#555" + }, + "target": "Prompt-tHwPf", + "targetHandle": "{œfieldNameœ: œDocumentœ, œidœ: œPrompt-tHwPfœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + }, + { + "className": "stroke-gray-900 stroke-connection", + "data": { + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], "dataType": "Prompt", - "id": "Prompt-9DNZG", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-tHwPf" }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-8b6nG", + "id": "OpenAIModel-Bt067", "inputTypes": [ "Text", - "Data", + "Record", "Prompt" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-9DNZG{œdataTypeœ:œPromptœ,œidœ:œPrompt-9DNZGœ,œnameœ:œpromptœ,œoutput_typesœ:[œPromptœ]}-OpenAIModel-8b6nG{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-8b6nGœ,œinputTypesœ:[œTextœ,œDataœ,œPromptœ],œtypeœ:œstrœ}", - "source": "Prompt-9DNZG", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-9DNZGœ, œnameœ: œpromptœ, œoutput_typesœ: [œPromptœ]}", - "target": "OpenAIModel-8b6nG", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-8b6nGœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-Prompt-tHwPf{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-tHwPfœ}-OpenAIModel-Bt067{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-Bt067œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "source": "Prompt-tHwPf", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-tHwPfœ}", + "style": { + "stroke": "#555" + }, + "target": "OpenAIModel-Bt067", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-Bt067œ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" }, { + "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-8b6nG", - "name": "text_output", - "output_types": [ + "baseClasses": [ + "object", + "str", "Text" - ] + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-Bt067" }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-y4SCS", + "id": "ChatOutput-F5Awj", "inputTypes": [ - "Text", - "Message" + "Text" ], "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-8b6nG{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-8b6nGœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œTextœ]}-ChatOutput-y4SCS{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-y4SCSœ,œinputTypesœ:[œTextœ,œMessageœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-8b6nG", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-8b6nGœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œTextœ]}", - "target": "ChatOutput-y4SCS", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-y4SCSœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-OpenAIModel-Bt067{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Bt067œ}-ChatOutput-F5Awj{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-F5Awjœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "source": "OpenAIModel-Bt067", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Bt067œ}", + "style": { + "stroke": "#555" + }, + "target": "ChatOutput-F5Awj", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-F5Awjœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "description": "Create a prompt template with dynamic variables.", + "description": "A component for creating prompt templates using dynamic variables.", "display_name": "Prompt", - "id": "Prompt-9DNZG", + "id": "Prompt-tHwPf", "node": { "base_classes": [ "object", @@ -124,7 +142,6 @@ "Text" ], "beta": false, - "conditional_paths": [], "custom_fields": { "template": [ "Document", @@ -135,6 +152,7 @@ "display_name": "Prompt", "documentation": "", "error": null, + "field_formatters": {}, "field_order": [], "frozen": false, "full_path": null, @@ -143,32 +161,9 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Prompt" ], - "pinned": false, "template": { "Document": { "advanced": false, @@ -180,8 +175,8 @@ "info": "", "input_types": [ "Document", - "Message", - "Data", + "BaseOutputParser", + "Record", "Text" ], "list": false, @@ -206,8 +201,8 @@ "info": "", "input_types": [ "Document", - "Message", - "Data", + "BaseOutputParser", + "Record", "Text" ], "list": false, @@ -222,7 +217,7 @@ "type": "str", "value": "" }, - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -239,7 +234,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" }, "template": { "advanced": false, @@ -268,8 +263,8 @@ "type": "Prompt" }, "dragging": false, - "height": 573, - "id": "Prompt-9DNZG", + "height": 479, + "id": "Prompt-tHwPf", "position": { "x": 585.7906101139403, "y": 117.52115876762832 @@ -284,7 +279,117 @@ }, { "data": { - "id": "ChatInput-27Usy", + "id": "File-6TEsD", + "node": { + "base_classes": [ + "Record" + ], + "beta": false, + "custom_fields": { + "path": null, + "silent_errors": null + }, + "description": "A generic file loader.", + "display_name": "Files", + "documentation": "", + "field_formatters": {}, + "field_order": [], + "frozen": false, + "output_types": [ + "Record" + ], + "template": { + "_type": "CustomComponent", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\n\n\nclass FileComponent(CustomComponent):\n display_name = \"Files\"\n description = \"A generic file loader.\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Record:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_record(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Record()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Record:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n" + }, + "path": { + "advanced": false, + "display_name": "Path", + "dynamic": false, + "fileTypes": [ + ".txt", + ".md", + ".mdx", + ".csv", + ".json", + ".yaml", + ".yml", + ".xml", + ".html", + ".htm", + ".pdf", + ".docx" + ], + "info": "Supported file types: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx", + "list": false, + "load_from_db": false, + "multiline": false, + "name": "path", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "file", + "value": "" + }, + "silent_errors": { + "advanced": true, + "display_name": "Silent Errors", + "dynamic": false, + "fileTypes": [], + "file_path": "", + "info": "If true, errors will not raise an exception.", + "list": false, + "load_from_db": false, + "multiline": false, + "name": "silent_errors", + "password": false, + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "bool", + "value": false + } + } + }, + "type": "File" + }, + "dragging": false, + "height": 282, + "id": "File-6TEsD", + "position": { + "x": -18.636536329280602, + "y": 3.951948774836353 + }, + "positionAbsolute": { + "x": -18.636536329280602, + "y": 3.951948774836353 + }, + "selected": false, + "type": "genericNode", + "width": 384 + }, + { + "data": { + "id": "ChatInput-MsSJ9", "node": { "base_classes": [ "str", @@ -307,22 +412,12 @@ "field_order": [], "frozen": false, "icon": "ChatInput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -339,7 +434,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n input_types=[],\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"User\",\n info=\"Type of sender.\",\n advanced=True,\n ),\n StrInput(\n name=\"sender_name\",\n type=str,\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=\"User\",\n advanced=True,\n ),\n StrInput(\n name=\"session_id\", type=str, display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, (Message, str)) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.schema.message import Message\nfrom langflow.field_typing import Text\nfrom typing import Union\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Text\",\n \"multiline\": True,\n }\n build_config[\"return_message\"] = {\n \"display_name\": \"Return Record\",\n \"advanced\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n files: Optional[list[str]] = None,\n session_id: Optional[str] = None,\n return_message: Optional[bool] = True,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n files=files,\n session_id=session_id,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -347,7 +442,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as input.", + "info": "", "input_types": [], "list": false, "load_from_db": false, @@ -367,7 +462,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -388,12 +483,12 @@ "value": "User" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -415,7 +510,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -428,31 +523,30 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, "type": "ChatInput" }, "dragging": false, - "height": 301, - "id": "ChatInput-27Usy", + "height": 377, + "id": "ChatInput-MsSJ9", "position": { - "x": -38.501719080514135, + "x": -28.80036300619821, "y": 379.81180230285355 }, "positionAbsolute": { - "x": -38.501719080514135, + "x": -28.80036300619821, "y": 379.81180230285355 }, - "selected": false, + "selected": true, "type": "genericNode", "width": 384 }, { "data": { - "id": "ChatOutput-y4SCS", + "id": "ChatOutput-F5Awj", "node": { "base_classes": [ "str", @@ -475,22 +569,12 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -507,7 +591,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -515,10 +599,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", + "info": "", "input_types": [ - "Text", - "Message" + "Text" ], "list": false, "load_from_db": false, @@ -529,8 +612,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -538,7 +620,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -559,12 +641,12 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -586,7 +668,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -599,16 +681,15 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, "type": "ChatOutput" }, "dragging": false, - "height": 309, - "id": "ChatOutput-y4SCS", + "height": 385, + "id": "ChatOutput-F5Awj", "position": { "x": 1733.3012915204283, "y": 168.76098809939327 @@ -623,184 +704,47 @@ }, { "data": { - "description": "A generic file loader.", - "display_name": "File", - "id": "File-BzIs2", + "id": "OpenAIModel-Bt067", "node": { "base_classes": [ - "Data" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "A generic file loader.", - "display_name": "File", - "documentation": "", - "edited": true, - "field_order": [ - "path", - "silent_errors" - ], - "frozen": false, - "icon": "file-text", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "load_file", - "name": "data", - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from pathlib import Path\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_data\nfrom langflow.custom import Component\nfrom langflow.inputs import BoolInput, FileInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\n\nclass FileComponent(Component):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n inputs = [\n FileInput(\n name=\"path\",\n display_name=\"Path\",\n file_types=TEXT_FILE_TYPES,\n info=f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n ),\n BoolInput(\n name=\"silent_errors\",\n display_name=\"Silent Errors\",\n advanced=True,\n info=\"If true, errors will not raise an exception.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"load_file\"),\n ]\n\n def load_file(self) -> Data:\n if not self.path:\n raise ValueError(\"Please, upload a file to use this component.\")\n resolved_path = self.resolve_path(self.path)\n silent_errors = self.silent_errors\n\n extension = Path(resolved_path).suffix[1:].lower()\n\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n\n data = parse_text_file_to_data(resolved_path, silent_errors)\n self.status = data if data else \"No data\"\n return data or Data()\n" - }, - "path": { - "advanced": false, - "display_name": "Path", - "dynamic": false, - "fileTypes": [ - "txt", - "md", - "mdx", - "csv", - "json", - "yaml", - "yml", - "xml", - "html", - "htm", - "pdf", - "docx", - "py", - "sh", - "sql", - "js", - "ts", - "tsx" - ], - "file_path": "cd558bbb-10b7-4c22-a7ad-3739f26b4bd7/Climate Prediction Updated.json", - "info": "Supported file types: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx, py, sh, sql, js, ts, tsx", - "list": false, - "name": "path", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "file", - "value": "" - }, - "silent_errors": { - "advanced": true, - "display_name": "Silent Errors", - "dynamic": false, - "info": "If true, errors will not raise an exception.", - "list": false, - "name": "silent_errors", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "bool", - "value": false - } - } - }, - "type": "File" - }, - "dragging": false, - "height": 301, - "id": "File-BzIs2", - "position": { - "x": -44.56084223565597, - "y": 39.0475820447775 - }, - "positionAbsolute": { - "x": -44.56084223565597, - "y": 39.0475820447775 - }, - "selected": true, - "type": "genericNode", - "width": 384 - }, - { - "data": { - "id": "OpenAIModel-8b6nG", - "node": { - "base_classes": [ - "BaseLanguageModel", + "object", + "str", "Text" ], "beta": false, - "conditional_paths": [], - "custom_fields": {}, + "custom_fields": { + "input_value": null, + "max_tokens": null, + "model_kwargs": null, + "model_name": null, + "openai_api_base": null, + "openai_api_key": null, + "stream": null, + "system_message": null, + "temperature": null + }, "description": "Generates text using OpenAI LLMs.", "display_name": "OpenAI", "documentation": "", + "field_formatters": {}, "field_order": [ - "input_value", "max_tokens", "model_kwargs", "model_name", "openai_api_base", "openai_api_key", "temperature", - "stream", - "system_message" + "input_value", + "system_message", + "stream" ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], - "pinned": false, "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -817,59 +761,82 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, "display_name": "Input", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "", "input_types": [ "Text", - "Data", + "Record", "Prompt" ], "list": false, "load_from_db": false, + "multiline": false, "name": "input_value", + "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, "display_name": "Max Tokens", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", "list": false, + "load_from_db": false, + "multiline": false, "name": "max_tokens", + "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "int" + "type": "int", + "value": 256 }, "model_kwargs": { "advanced": true, "display_name": "Model Kwargs", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "", "list": false, + "load_from_db": false, + "multiline": false, "name": "model_kwargs", + "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "dict" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, "display_name": "Model Name", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "", + "input_types": [ + "Text" + ], + "list": true, + "load_from_db": false, + "multiline": false, "name": "model_name", "options": [ "gpt-4o", @@ -878,83 +845,116 @@ "gpt-3.5-turbo", "gpt-3.5-turbo-0125" ], + "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-3.5-turbo" }, "openai_api_base": { "advanced": true, "display_name": "OpenAI API Base", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, + "multiline": false, "name": "openai_api_base", + "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, "display_name": "OpenAI API Key", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "The OpenAI API Key to use for the OpenAI model.", "input_types": [ "Text" ], + "list": false, "load_from_db": true, + "multiline": false, "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", "value": "OPENAI_API_KEY" }, "stream": { - "advanced": true, + "advanced": false, "display_name": "Stream", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", "list": false, + "load_from_db": false, + "multiline": false, "name": "stream", + "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "bool", - "value": false + "value": true }, "system_message": { "advanced": true, "display_name": "System Message", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "System message to pass to the model.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, + "multiline": false, "name": "system_message", + "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, "display_name": "Temperature", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "", "list": false, + "load_from_db": false, + "multiline": false, "name": "temperature", + "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, @@ -966,15 +966,15 @@ "type": "OpenAIModel" }, "dragging": false, - "height": 623, - "id": "OpenAIModel-8b6nG", + "height": 642, + "id": "OpenAIModel-Bt067", "position": { - "x": 1141.7303854551026, - "y": -51.19892217231286 + "x": 1137.6078582863759, + "y": -14.41920034020356 }, "positionAbsolute": { - "x": 1141.7303854551026, - "y": -51.19892217231286 + "x": 1137.6078582863759, + "y": -14.41920034020356 }, "selected": false, "type": "genericNode", @@ -982,14 +982,14 @@ } ], "viewport": { - "x": 198.5801484914205, - "y": 244.8736279905512, - "zoom": 0.5335671198494703 + "x": 352.20899206064655, + "y": 56.054900898593075, + "zoom": 0.9023391400011 } }, "description": "This flow integrates PDF reading with a language model to answer document-specific questions. Ideal for small-scale texts, it facilitates direct queries with immediate insights.", - "id": "cd558bbb-10b7-4c22-a7ad-3739f26b4bd7", + "id": "fecbce42-6f11-454c-8ab2-db6eddbbbb0f", "is_component": false, - "last_tested_version": "1.0.0a52", + "last_tested_version": "1.0.0a0", "name": "Document QA" -} \ No newline at end of file +} diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json index dc5fe03b8..6c5b563a5 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json @@ -2,56 +2,45 @@ "data": { "edges": [ { - "className": "stroke-gray-900 stroke-connection", + "className": "", "data": { "sourceHandle": { - "dataType": "MemoryComponent", - "id": "MemoryComponent-cdA1J", - "name": "text", - "output_types": [ + "baseClasses": [ + "str", + "object", "Text" - ] + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-Neuec" }, "targetHandle": { - "fieldName": "context", - "id": "Prompt-ODkUx", + "fieldName": "input_value", + "id": "ChatOutput-cVR7W", "inputTypes": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], "type": "str" } }, - "id": "reactflow__edge-MemoryComponent-cdA1J{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-cdA1Jœ}-Prompt-ODkUx{œfieldNameœ:œcontextœ,œidœ:œPrompt-ODkUxœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", - "selected": false, - "source": "MemoryComponent-cdA1J", - "sourceHandle": "{œdataTypeœ: œMemoryComponentœ, œidœ: œMemoryComponent-cdA1Jœ, œoutput_typesœ: [œTextœ], œnameœ: œtextœ}", + "id": "reactflow__edge-OpenAIModel-Neuec{œbaseClassesœ:[œstrœ,œobjectœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Neuecœ}-ChatOutput-cVR7W{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-cVR7Wœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "source": "OpenAIModel-Neuec", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œobjectœ, œTextœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Neuecœ}", "style": { "stroke": "#555" }, - "target": "Prompt-ODkUx", - "targetHandle": "{œfieldNameœ: œcontextœ, œidœ: œPrompt-ODkUxœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "target": "ChatOutput-cVR7W", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-cVR7Wœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { - "className": "stroke-gray-900 stroke-connection", + "className": "", "data": { "sourceHandle": { - "dataType": "ChatInput", - "id": "ChatInput-t7F8v", - "name": "message", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "user_message", - "id": "Prompt-ODkUx", - "inputTypes": [ - "Document", - "Message", - "Record", + "baseClasses": [ + "object", + "str", "Text" ], "type": "str" @@ -60,109 +49,108 @@ "id": "reactflow__edge-ChatInput-t7F8v{œbaseClassesœ:[œTextœ,œobjectœ,œRecordœ,œstrœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-t7F8vœ}-Prompt-ODkUx{œfieldNameœ:œuser_messageœ,œidœ:œPrompt-ODkUxœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "ChatInput-t7F8v", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-t7F8vœ, œoutput_typesœ: [œMessageœ], œnameœ: œmessageœ}", + "sourceHandle": "{œbaseClassesœ: [œTextœ, œobjectœ, œRecordœ, œstrœ], œdataTypeœ: œChatInputœ, œidœ: œChatInput-t7F8vœ}", "style": { "stroke": "#555" }, "target": "Prompt-ODkUx", - "targetHandle": "{œfieldNameœ: œuser_messageœ, œidœ: œPrompt-ODkUxœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œuser_messageœ, œidœ: œPrompt-ODkUxœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], "dataType": "Prompt", - "id": "Prompt-ODkUx", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-kykM2" }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-9RykF", + "id": "OpenAIModel-Neuec", "inputTypes": [ "Text", - "Data", + "Record", "Prompt" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-ODkUx{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-ODkUxœ}-OpenAIModel-9RykF{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-9RykFœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", - "source": "Prompt-ODkUx", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-ODkUxœ, œoutput_typesœ: [œPromptœ], œnameœ: œpromptœ}", - "style": { - "stroke": "#555" - }, - "target": "OpenAIModel-9RykF", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-9RykFœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-Prompt-kykM2{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-kykM2œ}-OpenAIModel-Neuec{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-Neuecœ,œinputTypesœ:[œTextœ,œRecordœ,œPromptœ],œtypeœ:œstrœ}", + "source": "Prompt-kykM2", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-kykM2œ}", + "target": "OpenAIModel-Neuec", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-Neuecœ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" }, { - "className": "stroke-gray-900 stroke-connection", + "className": "", "data": { "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-9RykF", - "name": "text_output", - "output_types": [ - "Text" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-P1jEe", - "inputTypes": [ + "baseClasses": [ "Text", - "Message" + "object", + "Record", + "str" ], - "type": "str" - } - }, - "id": "reactflow__edge-OpenAIModel-9RykF{œbaseClassesœ:[œstrœ,œobjectœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-9RykFœ}-ChatOutput-P1jEe{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-P1jEeœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-9RykF", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-9RykFœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", - "style": { - "stroke": "#555" - }, - "target": "ChatOutput-P1jEe", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-P1jEeœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" - }, - { - "className": "stroke-foreground stroke-connection", - "data": { - "sourceHandle": { - "dataType": "MemoryComponent", - "id": "MemoryComponent-cdA1J", - "name": "text", - "output_types": [ - "Text" - ] + "dataType": "ChatInput", + "id": "ChatInput-Z9Rn6" }, "targetHandle": { - "fieldName": "input_value", - "id": "TextOutput-vrs6T", + "fieldName": "UserMessage", + "id": "Prompt-kykM2", "inputTypes": [ + "Document", + "Message", "Record", "Text" ], "type": "str" } }, - "id": "reactflow__edge-MemoryComponent-cdA1J{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-cdA1Jœ}-TextOutput-vrs6T{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-vrs6Tœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", - "source": "MemoryComponent-cdA1J", - "sourceHandle": "{œdataTypeœ: œMemoryComponentœ, œidœ: œMemoryComponent-cdA1Jœ, œoutput_typesœ: [œTextœ], œnameœ: œtextœ}", - "style": { - "stroke": "#555" + "id": "reactflow__edge-ChatInput-Z9Rn6{œbaseClassesœ:[œTextœ,œobjectœ,œRecordœ,œstrœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-Z9Rn6œ}-Prompt-kykM2{œfieldNameœ:œUserMessageœ,œidœ:œPrompt-kykM2œ,œinputTypesœ:[œDocumentœ,œMessageœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "source": "ChatInput-Z9Rn6", + "sourceHandle": "{œbaseClassesœ: [œTextœ, œobjectœ, œRecordœ, œstrœ], œdataTypeœ: œChatInputœ, œidœ: œChatInput-Z9Rn6œ}", + "target": "Prompt-kykM2", + "targetHandle": "{œfieldNameœ: œUserMessageœ, œidœ: œPrompt-kykM2œ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + }, + { + "className": "", + "data": { + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "MemoryComponent", + "id": "MemoryComponent-u6m5G" + }, + "targetHandle": { + "fieldName": "Context", + "id": "Prompt-kykM2", + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], + "type": "str" + } }, - "target": "TextOutput-vrs6T", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œTextOutput-vrs6Tœ, œinputTypesœ: [œRecordœ, œTextœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-MemoryComponent-u6m5G{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-u6m5Gœ}-Prompt-kykM2{œfieldNameœ:œContextœ,œidœ:œPrompt-kykM2œ,œinputTypesœ:[œDocumentœ,œMessageœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "source": "MemoryComponent-u6m5G", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œTextœ, œobjectœ], œdataTypeœ: œMemoryComponentœ, œidœ: œMemoryComponent-u6m5Gœ}", + "target": "Prompt-kykM2", + "targetHandle": "{œfieldNameœ: œContextœ, œidœ: œPrompt-kykM2œ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "id": "ChatInput-t7F8v", + "id": "ChatInput-Z9Rn6", "node": { "base_classes": [ "Text", @@ -185,22 +173,12 @@ "field_order": [], "frozen": false, "icon": "ChatInput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -217,7 +195,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n input_types=[],\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"User\",\n info=\"Type of sender.\",\n advanced=True,\n ),\n StrInput(\n name=\"sender_name\",\n type=str,\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=\"User\",\n advanced=True,\n ),\n StrInput(\n name=\"session_id\", type=str, display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, (Message, str)) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.schema.message import Message\nfrom langflow.field_typing import Text\nfrom typing import Union\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Text\",\n \"multiline\": True,\n }\n build_config[\"return_message\"] = {\n \"display_name\": \"Return Record\",\n \"advanced\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n files: Optional[list[str]] = None,\n session_id: Optional[str] = None,\n return_message: Optional[bool] = True,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n files=files,\n session_id=session_id,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -225,7 +203,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as input.", + "info": "", "input_types": [], "list": false, "load_from_db": false, @@ -237,7 +215,7 @@ "show": true, "title_case": false, "type": "str", - "value": "" + "value": "do you know his name?" }, "sender": { "advanced": true, @@ -245,7 +223,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -266,12 +244,12 @@ "value": "User" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -288,12 +266,12 @@ "value": "User" }, "session_id": { - "advanced": true, + "advanced": false, "display_name": "Session ID", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -307,15 +285,15 @@ "show": true, "title_case": false, "type": "str", - "value": "" + "value": "MySessionID" } } }, "type": "ChatInput" }, "dragging": false, - "height": 469, - "id": "ChatInput-t7F8v", + "height": 477, + "id": "ChatInput-Z9Rn6", "position": { "x": 1283.2700598313072, "y": 982.5953650473145 @@ -330,7 +308,7 @@ }, { "data": { - "id": "ChatOutput-P1jEe", + "id": "ChatOutput-cVR7W", "node": { "base_classes": [ "Text", @@ -353,22 +331,12 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -385,7 +353,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -393,10 +361,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", + "info": "", "input_types": [ - "Text", - "Message" + "Text" ], "list": false, "load_from_db": false, @@ -407,8 +374,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -416,7 +382,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -437,12 +403,12 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -459,12 +425,12 @@ "value": "AI" }, "session_id": { - "advanced": true, + "advanced": false, "display_name": "Session ID", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -478,15 +444,15 @@ "show": true, "title_case": false, "type": "str", - "value": "" + "value": "MySessionID" } } }, "type": "ChatOutput" }, "dragging": false, - "height": 477, - "id": "ChatOutput-P1jEe", + "height": 485, + "id": "ChatOutput-cVR7W", "position": { "x": 3154.916355514023, "y": 851.051882666333 @@ -503,7 +469,7 @@ "data": { "description": "Retrieves stored chat messages given a specific Session ID.", "display_name": "Chat Memory", - "id": "MemoryComponent-cdA1J", + "id": "MemoryComponent-u6m5G", "node": { "base_classes": [ "str", @@ -529,20 +495,6 @@ "output_types": [ "Text" ], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "hidden": null, - "method": null, - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } - ], "template": { "_type": "CustomComponent", "code": { @@ -561,7 +513,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import Optional\n\nfrom langflow.base.memory.memory import BaseMemoryComponent\nfrom langflow.field_typing import Text\nfrom langflow.helpers.data import messages_to_text\nfrom langflow.memory import get_messages\nfrom langflow.schema.message import Message\n\n\nclass MemoryComponent(BaseMemoryComponent):\n display_name = \"Chat Memory\"\n description = \"Retrieves stored chat messages given a specific Session ID.\"\n beta: bool = True\n icon = \"history\"\n\n def build_config(self):\n return {\n \"sender\": {\n \"options\": [\"Machine\", \"User\", \"Machine and User\"],\n \"display_name\": \"Sender Type\",\n },\n \"sender_name\": {\"display_name\": \"Sender Name\", \"advanced\": True},\n \"n_messages\": {\n \"display_name\": \"Number of Messages\",\n \"info\": \"Number of messages to retrieve.\",\n },\n \"session_id\": {\n \"display_name\": \"Session ID\",\n \"info\": \"Session ID of the chat history.\",\n \"input_types\": [\"Text\"],\n },\n \"order\": {\n \"options\": [\"Ascending\", \"Descending\"],\n \"display_name\": \"Order\",\n \"info\": \"Order of the messages.\",\n \"advanced\": True,\n },\n \"data_template\": {\n \"display_name\": \"Data Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n \"advanced\": True,\n },\n }\n\n def get_messages(self, **kwargs) -> list[Message]:\n # Validate kwargs by checking if it contains the correct keys\n if \"sender\" not in kwargs:\n kwargs[\"sender\"] = None\n if \"sender_name\" not in kwargs:\n kwargs[\"sender_name\"] = None\n if \"session_id\" not in kwargs:\n kwargs[\"session_id\"] = None\n if \"limit\" not in kwargs:\n kwargs[\"limit\"] = 5\n if \"order\" not in kwargs:\n kwargs[\"order\"] = \"Descending\"\n\n kwargs[\"order\"] = \"DESC\" if kwargs[\"order\"] == \"Descending\" else \"ASC\"\n if kwargs[\"sender\"] == \"Machine and User\":\n kwargs[\"sender\"] = None\n return get_messages(**kwargs)\n\n def build(\n self,\n sender: Optional[str] = \"Machine and User\",\n sender_name: Optional[str] = None,\n session_id: Optional[str] = None,\n n_messages: int = 5,\n order: Optional[str] = \"Descending\",\n data_template: Optional[str] = \"{sender_name}: {text}\",\n ) -> Text:\n messages = self.get_messages(\n sender=sender,\n sender_name=sender_name,\n session_id=session_id,\n limit=n_messages,\n order=order,\n )\n messages_str = messages_to_text(template=data_template or \"\", messages=messages)\n self.status = messages_str\n return messages_str\n" + "value": "from typing import Optional\n\nfrom langflow.base.memory.memory import BaseMemoryComponent\nfrom langflow.field_typing import Text\nfrom langflow.helpers.record import messages_to_text\nfrom langflow.memory import get_messages\nfrom langflow.schema.message import Message\n\n\nclass MemoryComponent(BaseMemoryComponent):\n display_name = \"Chat Memory\"\n description = \"Retrieves stored chat messages given a specific Session ID.\"\n beta: bool = True\n icon = \"history\"\n\n def build_config(self):\n return {\n \"sender\": {\n \"options\": [\"Machine\", \"User\", \"Machine and User\"],\n \"display_name\": \"Sender Type\",\n },\n \"sender_name\": {\"display_name\": \"Sender Name\", \"advanced\": True},\n \"n_messages\": {\n \"display_name\": \"Number of Messages\",\n \"info\": \"Number of messages to retrieve.\",\n },\n \"session_id\": {\n \"display_name\": \"Session ID\",\n \"info\": \"Session ID of the chat history.\",\n \"input_types\": [\"Text\"],\n },\n \"order\": {\n \"options\": [\"Ascending\", \"Descending\"],\n \"display_name\": \"Order\",\n \"info\": \"Order of the messages.\",\n \"advanced\": True,\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def get_messages(self, **kwargs) -> list[Message]:\n # Validate kwargs by checking if it contains the correct keys\n if \"sender\" not in kwargs:\n kwargs[\"sender\"] = None\n if \"sender_name\" not in kwargs:\n kwargs[\"sender_name\"] = None\n if \"session_id\" not in kwargs:\n kwargs[\"session_id\"] = None\n if \"limit\" not in kwargs:\n kwargs[\"limit\"] = 5\n if \"order\" not in kwargs:\n kwargs[\"order\"] = \"Descending\"\n\n kwargs[\"order\"] = \"DESC\" if kwargs[\"order\"] == \"Descending\" else \"ASC\"\n if kwargs[\"sender\"] == \"Machine and User\":\n kwargs[\"sender\"] = None\n return get_messages(**kwargs)\n\n def build(\n self,\n sender: Optional[str] = \"Machine and User\",\n sender_name: Optional[str] = None,\n session_id: Optional[str] = None,\n n_messages: int = 5,\n order: Optional[str] = \"Descending\",\n record_template: Optional[str] = \"{sender_name}: {text}\",\n ) -> Text:\n messages = self.get_messages(\n sender=sender,\n sender_name=sender_name,\n session_id=session_id,\n limit=n_messages,\n order=order,\n )\n messages_str = messages_to_text(template=record_template or \"\", messages=messages)\n self.status = messages_str\n return messages_str\n" }, "n_messages": { "advanced": false, @@ -608,6 +560,28 @@ "type": "str", "value": "Descending" }, + "record_template": { + "advanced": true, + "display_name": "Record Template", + "dynamic": false, + "fileTypes": [], + "file_path": "", + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "input_types": [ + "Text" + ], + "list": false, + "load_from_db": false, + "multiline": true, + "name": "record_template", + "password": false, + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "str", + "value": "{sender_name}: {text}" + }, "sender": { "advanced": false, "display_name": "Sender Type", @@ -683,8 +657,8 @@ "type": "MemoryComponent" }, "dragging": false, - "height": 489, - "id": "MemoryComponent-cdA1J", + "height": 505, + "id": "MemoryComponent-u6m5G", "position": { "x": 1289.9606870058817, "y": 442.16804561053766 @@ -699,20 +673,20 @@ }, { "data": { - "description": "A component for creating prompt templates using dynamic variables.", + "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-ODkUx", + "id": "Prompt-kykM2", "node": { "base_classes": [ - "Text", + "object", "str", - "object" + "Text" ], "beta": false, "custom_fields": { "template": [ - "context", - "user_message" + "Context", + "UserMessage" ] }, "description": "Create a prompt template with dynamic variables.", @@ -728,54 +702,13 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Prompt" ], "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" - }, - "context": { + "Context": { "advanced": false, - "display_name": "context", + "display_name": "Context", "dynamic": false, "field_type": "str", "fileTypes": [], @@ -790,7 +723,7 @@ "list": false, "load_from_db": false, "multiline": true, - "name": "context", + "name": "Context", "password": false, "placeholder": "", "required": false, @@ -799,14 +732,66 @@ "type": "str", "value": "" }, - "template": { + "UserMessage": { "advanced": false, - "display_name": "Template", + "display_name": "UserMessage", "dynamic": false, + "field_type": "str", "fileTypes": [], "file_path": "", "info": "", "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], + "list": false, + "load_from_db": false, + "multiline": true, + "name": "UserMessage", + "password": false, + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "str", + "value": "" + }, + "_type": "CustomComponent", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "input_types": [ + "Text" + ], + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + }, + "template": { + "advanced": false, + "display_name": "Template", + "dynamic": false, + "field_type": "str", + "fileTypes": [], + "file_path": "", + "info": "", + "input_types": [ + "Document", + "BaseOutputParser", + "Record", "Text" ], "list": false, @@ -819,56 +804,30 @@ "show": true, "title_case": false, "type": "prompt", - "value": "{context}\n\nUser: {user_message}\nAI: " - }, - "user_message": { - "advanced": false, - "display_name": "user_message", - "dynamic": false, - "field_type": "str", - "fileTypes": [], - "file_path": "", - "info": "", - "input_types": [ - "Document", - "Message", - "Record", - "Text" - ], - "list": false, - "load_from_db": false, - "multiline": true, - "name": "user_message", - "password": false, - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "str", - "value": "" + "value": "Previous messages:\n{Context}\n\nUser: {UserMessage}\nAI: " } } }, "type": "Prompt" }, "dragging": false, - "height": 477, - "id": "Prompt-ODkUx", + "height": 513, + "id": "Prompt-kykM2", "position": { - "x": 1894.594426342426, + "x": 1890.2582485007167, "y": 753.3797365481901 }, "positionAbsolute": { - "x": 1894.594426342426, + "x": 1890.2582485007167, "y": 753.3797365481901 }, - "selected": false, + "selected": true, "type": "genericNode", "width": 384 }, { "data": { - "id": "OpenAIModel-9RykF", + "id": "OpenAIModel-Neuec", "node": { "base_classes": [ "str", @@ -904,33 +863,11 @@ ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -947,7 +884,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, @@ -958,7 +895,7 @@ "info": "", "input_types": [ "Text", - "Data", + "Record", "Prompt" ], "list": false, @@ -967,11 +904,10 @@ "name": "input_value", "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, @@ -980,9 +916,6 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -992,8 +925,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "int", + "value": 256 }, "model_kwargs": { "advanced": true, @@ -1002,9 +935,6 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1014,8 +944,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, @@ -1044,7 +974,7 @@ "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-3.5-turbo" }, "openai_api_base": { "advanced": true, @@ -1065,8 +995,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, @@ -1084,7 +1013,7 @@ "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", @@ -1097,9 +1026,6 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1109,7 +1035,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", + "type": "bool", "value": false }, "system_message": { @@ -1131,8 +1057,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, @@ -1141,28 +1066,31 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, "name": "temperature", "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, - "type": "str", - "value": 0.1 + "type": "float", + "value": "0.2" } } }, "type": "OpenAIModel" }, "dragging": false, - "height": 563, - "id": "OpenAIModel-9RykF", + "height": 571, + "id": "OpenAIModel-Neuec", "position": { "x": 2561.5850334731617, "y": 553.2745131130916 @@ -1285,16 +1213,14 @@ } ], "viewport": { - "x": -569.862554459756, - "y": -42.08339711050985, - "zoom": 0.4868590524514978 + "x": -511.79726701119625, + "y": 49.514712353620894, + "zoom": 0.4612356948928673 } }, "description": "This project can be used as a starting point for building a Chat experience with user specific memory. You can set a different Session ID to start a new message history.", - "icon": "🤖", - "icon_bg_color": "#FFD700", - "id": "08d5cccf-d098-4367-b14b-1078429c9ed9", + "id": "321b1bab-8691-42da-9689-1f12b5d2a48b", "is_component": false, - "last_tested_version": "1.0.0a0", + "last_tested_version": "1.0.0a54", "name": "Memory Chatbot" -} \ No newline at end of file +} diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json index 88a175a9e..4e0327636 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json @@ -5,19 +5,20 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], "dataType": "TextInput", - "id": "TextInput-sptaH", - "name": "text", - "output_types": [ - "Text" - ] + "id": "TextInput-sptaH" }, "targetHandle": { "fieldName": "document", "id": "Prompt-amqBu", "inputTypes": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -26,23 +27,24 @@ }, "id": "reactflow__edge-TextInput-sptaH{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-sptaHœ}-Prompt-amqBu{œfieldNameœ:œdocumentœ,œidœ:œPrompt-amqBuœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "TextInput-sptaH", - "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-sptaHœ, œoutput_typesœ: [œTextœ], œnameœ: œtextœ}", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œTextœ, œobjectœ], œdataTypeœ: œTextInputœ, œidœ: œTextInput-sptaHœ}", "style": { "stroke": "#555" }, "target": "Prompt-amqBu", - "targetHandle": "{œfieldNameœ: œdocumentœ, œidœ: œPrompt-amqBuœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œdocumentœ, œidœ: œPrompt-amqBuœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { - "dataType": "Prompt", - "id": "Prompt-amqBu", - "name": "text", - "output_types": [ + "baseClasses": [ + "object", + "str", "Text" - ] + ], + "dataType": "Prompt", + "id": "Prompt-amqBu" }, "targetHandle": { "fieldName": "input_value", @@ -56,7 +58,7 @@ }, "id": "reactflow__edge-Prompt-amqBu{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}-TextOutput-2MS4a{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-2MS4aœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "Prompt-amqBu", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-amqBuœ, œoutput_typesœ: [œTextœ], œnameœ: œtextœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-amqBuœ}", "style": { "stroke": "#555" }, @@ -67,19 +69,20 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], "dataType": "Prompt", - "id": "Prompt-amqBu", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-amqBu" }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-uYXZJ", "inputTypes": [ "Text", - "Data", + "Record", "Prompt" ], "type": "str" @@ -87,30 +90,31 @@ }, "id": "reactflow__edge-Prompt-amqBu{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}-OpenAIModel-uYXZJ{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-uYXZJœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "source": "Prompt-amqBu", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-amqBuœ, œoutput_typesœ: [œPromptœ], œnameœ: œpromptœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-amqBuœ}", "style": { "stroke": "#555" }, "target": "OpenAIModel-uYXZJ", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-uYXZJœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-uYXZJœ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], "dataType": "OpenAIModel", - "id": "OpenAIModel-uYXZJ", - "name": "text_output", - "output_types": [ - "Text" - ] + "id": "OpenAIModel-uYXZJ" }, "targetHandle": { "fieldName": "summary", "id": "Prompt-gTNiz", "inputTypes": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -119,53 +123,54 @@ }, "id": "reactflow__edge-OpenAIModel-uYXZJ{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}-Prompt-gTNiz{œfieldNameœ:œsummaryœ,œidœ:œPrompt-gTNizœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "OpenAIModel-uYXZJ", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-uYXZJœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œTextœ, œobjectœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-uYXZJœ}", "style": { "stroke": "#555" }, "target": "Prompt-gTNiz", - "targetHandle": "{œfieldNameœ: œsummaryœ, œidœ: œPrompt-gTNizœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œsummaryœ, œidœ: œPrompt-gTNizœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], "dataType": "OpenAIModel", - "id": "OpenAIModel-uYXZJ", - "name": "text_output", - "output_types": [ - "Text" - ] + "id": "OpenAIModel-uYXZJ" }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-EJkG3", "inputTypes": [ - "Text", - "Message" + "Text" ], "type": "str" } }, "id": "reactflow__edge-OpenAIModel-uYXZJ{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}-ChatOutput-EJkG3{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-EJkG3œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "source": "OpenAIModel-uYXZJ", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-uYXZJœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œTextœ, œobjectœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-uYXZJœ}", "style": { "stroke": "#555" }, "target": "ChatOutput-EJkG3", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-EJkG3œ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-EJkG3œ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { - "dataType": "Prompt", - "id": "Prompt-gTNiz", - "name": "text", - "output_types": [ + "baseClasses": [ + "object", + "str", "Text" - ] + ], + "dataType": "Prompt", + "id": "Prompt-gTNiz" }, "targetHandle": { "fieldName": "input_value", @@ -179,7 +184,7 @@ }, "id": "reactflow__edge-Prompt-gTNiz{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}-TextOutput-MUDOR{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-MUDORœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "Prompt-gTNiz", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-gTNizœ, œoutput_typesœ: [œTextœ], œnameœ: œtextœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-gTNizœ}", "style": { "stroke": "#555" }, @@ -190,19 +195,20 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], "dataType": "Prompt", - "id": "Prompt-gTNiz", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-gTNiz" }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-XawYB", "inputTypes": [ "Text", - "Data", + "Record", "Prompt" ], "type": "str" @@ -210,42 +216,42 @@ }, "id": "reactflow__edge-Prompt-gTNiz{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}-OpenAIModel-XawYB{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XawYBœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "source": "Prompt-gTNiz", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-gTNizœ, œoutput_typesœ: [œPromptœ], œnameœ: œpromptœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œstrœ, œTextœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-gTNizœ}", "style": { "stroke": "#555" }, "target": "OpenAIModel-XawYB", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-XawYBœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-XawYBœ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], "dataType": "OpenAIModel", - "id": "OpenAIModel-XawYB", - "name": "text_output", - "output_types": [ - "Text" - ] + "id": "OpenAIModel-XawYB" }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-DNmvg", "inputTypes": [ - "Text", - "Message" + "Text" ], "type": "str" } }, "id": "reactflow__edge-OpenAIModel-XawYB{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XawYBœ}-ChatOutput-DNmvg{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DNmvgœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "source": "OpenAIModel-XawYB", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-XawYBœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", + "sourceHandle": "{œbaseClassesœ: [œstrœ, œTextœ, œobjectœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-XawYBœ}", "style": { "stroke": "#555" }, "target": "ChatOutput-DNmvg", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-DNmvgœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-DNmvgœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -279,33 +285,11 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Prompt" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -322,7 +306,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" }, "document": { "advanced": false, @@ -334,7 +318,7 @@ "info": "", "input_types": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -421,33 +405,11 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Prompt" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -464,7 +426,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" }, "summary": { "advanced": false, @@ -476,7 +438,7 @@ "info": "", "input_types": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -555,22 +517,12 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -587,7 +539,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -595,10 +547,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", + "info": "", "input_types": [ - "Text", - "Message" + "Text" ], "list": false, "load_from_db": false, @@ -609,8 +560,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -618,7 +568,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -639,12 +589,12 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -658,7 +608,7 @@ "show": true, "title_case": false, "type": "str", - "value": "AI" + "value": "Summarizer" }, "session_id": { "advanced": true, @@ -666,7 +616,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -679,8 +629,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, @@ -723,22 +672,12 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -755,7 +694,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -763,10 +702,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", + "info": "", "input_types": [ - "Text", - "Message" + "Text" ], "list": false, "load_from_db": false, @@ -777,8 +715,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -786,7 +723,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -807,12 +744,12 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -826,7 +763,7 @@ "show": true, "title_case": false, "type": "str", - "value": "AI" + "value": "Question Generator" }, "session_id": { "advanced": true, @@ -834,7 +771,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -847,8 +784,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, @@ -885,22 +821,11 @@ "field_order": [], "frozen": false, "icon": "type", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -917,7 +842,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import MultilineInput, StrInput\nfrom langflow.template import Output\n\n\nclass TextInput(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Playground.\"\n icon = \"type\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Text to be passed as input.\",\n ),\n MultilineInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n advanced=True,\n value=\"{text}\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n ]\n\n def text_response(self) -> Text:\n return self.build(input_value=self.input_value, data_template=self.data_template)\n" + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextInput(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Playground.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Text\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as input.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Optional[Text] = \"\",\n record_template: Optional[str] = \"\",\n ) -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n" }, "input_value": { "advanced": false, @@ -925,9 +850,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Text to be passed as input.", + "info": "Text or Record to be passed as input.", "input_types": [ - "Data", + "Record", "Text" ], "list": false, @@ -940,6 +865,28 @@ "show": true, "title_case": false, "type": "str", + "value": "Revolutionary Nano-Battery Technology Unveiled In a groundbreaking announcement yesterday, researchers from the fictional Tech Innovations Institute revealed the development of a new nano-battery technology that promises to revolutionize energy storage. The new battery, dubbed the \"EnerGCell\", uses advanced nanomaterials to achieve unprecedented efficiency and storage capacities. According to lead researcher Dr. Ada Byron, the EnerGCell can store up to ten times more energy than the best lithium-ion batteries available today, while charging in just a fraction of the time. \"We're talking about charging your electric vehicle in just five minutes for a range of over 1,000 miles,\" Dr. Byron stated during the press conference. The technology behind the EnerGCell involves a complex arrangement of nanostructured electrodes that allow for rapid ion transfer and extremely high energy density. This breakthrough was achieved after a decade of research into nanomaterials and their applications in energy storage. The implications of this technology are vast, promising to accelerate the adoption of renewable energy by making it more practical and affordable to store wind and solar power. It could also lead to significant advancements in electric vehicles, mobile devices, and any other technology that relies on batteries. Despite the excitement, some experts are calling for patience, noting that the EnerGCell is still in its early stages of development and may take several years before it's commercially available. However, the potential impact of such a technology on the environment and the global economy is undeniable. Tech Innovations Institute plans to continue refining the EnerGCell and begin pilot projects with select partners in the coming year. If successful, this nano-battery technology could indeed be the breakthrough needed to usher in a new era of clean energy and technology." + }, + "record_template": { + "advanced": true, + "display_name": "Record Template", + "dynamic": false, + "fileTypes": [], + "file_path": "", + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "input_types": [ + "Text" + ], + "list": false, + "load_from_db": false, + "multiline": true, + "name": "record_template", + "password": false, + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "str", "value": "" } } @@ -1107,33 +1054,11 @@ ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -1150,7 +1075,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, @@ -1161,7 +1086,7 @@ "info": "", "input_types": [ "Text", - "Data", + "Record", "Prompt" ], "list": false, @@ -1170,11 +1095,10 @@ "name": "input_value", "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, @@ -1183,9 +1107,6 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1195,8 +1116,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "int", + "value": 256 }, "model_kwargs": { "advanced": true, @@ -1205,9 +1126,6 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1217,8 +1135,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, @@ -1247,7 +1165,7 @@ "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-3.5-turbo" }, "openai_api_base": { "advanced": true, @@ -1268,8 +1186,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, @@ -1287,7 +1204,7 @@ "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", @@ -1300,9 +1217,6 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1312,7 +1226,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", + "type": "bool", "value": false }, "system_message": { @@ -1334,8 +1248,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, @@ -1344,19 +1257,22 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, "name": "temperature", "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, - "type": "str", + "type": "float", "value": 0.1 } } @@ -1524,33 +1440,11 @@ ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -1567,7 +1461,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, @@ -1578,7 +1472,7 @@ "info": "", "input_types": [ "Text", - "Data", + "Record", "Prompt" ], "list": false, @@ -1587,11 +1481,10 @@ "name": "input_value", "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, @@ -1600,9 +1493,6 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1612,8 +1502,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "int", + "value": 256 }, "model_kwargs": { "advanced": true, @@ -1622,9 +1512,6 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1634,8 +1521,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, @@ -1664,7 +1551,7 @@ "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-4-turbo-preview" }, "openai_api_base": { "advanced": true, @@ -1685,8 +1572,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, @@ -1699,16 +1585,16 @@ "Text" ], "list": false, - "load_from_db": true, + "load_from_db": false, "multiline": false, "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "stream": { "advanced": true, @@ -1717,9 +1603,6 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1729,7 +1612,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", + "type": "bool", "value": false }, "system_message": { @@ -1751,8 +1634,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, @@ -1761,19 +1643,22 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, "name": "temperature", "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, - "type": "str", + "type": "float", "value": 0.1 } } @@ -1807,4 +1692,4 @@ "is_component": false, "last_tested_version": "1.0.0a0", "name": "Prompt Chaining" -} \ No newline at end of file +} diff --git a/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json b/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json index 7340fb242..97b21a559 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json @@ -5,19 +5,20 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], "dataType": "TextOutput", - "id": "TextOutput-BDknO", - "name": "Text", - "output_types": [ - "Text" - ] + "id": "TextOutput-BDknO" }, "targetHandle": { "fieldName": "context", "id": "Prompt-xeI6K", "inputTypes": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -27,30 +28,32 @@ "id": "reactflow__edge-TextOutput-BDknO{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextOutputœ,œidœ:œTextOutput-BDknOœ}-Prompt-xeI6K{œfieldNameœ:œcontextœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "TextOutput-BDknO", - "sourceHandle": "{œdataTypeœ: œTextOutputœ, œidœ: œTextOutput-BDknOœ, œoutput_typesœ: [œTextœ], œnameœ: œTextœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œTextœ, œstrœ], œdataTypeœ: œTextOutputœ, œidœ: œTextOutput-BDknOœ}", "style": { "stroke": "#555" }, "target": "Prompt-xeI6K", - "targetHandle": "{œfieldNameœ: œcontextœ, œidœ: œPrompt-xeI6Kœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œcontextœ, œidœ: œPrompt-xeI6Kœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object", + "Record" + ], "dataType": "ChatInput", - "id": "ChatInput-yxMKE", - "name": "message", - "output_types": [ - "Message" - ] + "id": "ChatInput-yxMKE" }, "targetHandle": { "fieldName": "question", "id": "Prompt-xeI6K", "inputTypes": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -60,30 +63,31 @@ "id": "reactflow__edge-ChatInput-yxMKE{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}-Prompt-xeI6K{œfieldNameœ:œquestionœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "ChatInput-yxMKE", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-yxMKEœ, œoutput_typesœ: [œMessageœ], œnameœ: œmessageœ}", + "sourceHandle": "{œbaseClassesœ: [œTextœ, œstrœ, œobjectœ, œRecordœ], œdataTypeœ: œChatInputœ, œidœ: œChatInput-yxMKEœ}", "style": { "stroke": "#555" }, "target": "Prompt-xeI6K", - "targetHandle": "{œfieldNameœ: œquestionœ, œidœ: œPrompt-xeI6Kœ, œinputTypesœ: [œDocumentœ, œMessageœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œquestionœ, œidœ: œPrompt-xeI6Kœ, œinputTypesœ: [œDocumentœ, œBaseOutputParserœ, œRecordœ, œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], "dataType": "Prompt", - "id": "Prompt-xeI6K", - "name": "prompt", - "output_types": [ - "Prompt" - ] + "id": "Prompt-xeI6K" }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-EjXlN", "inputTypes": [ "Text", - "Data", + "Record", "Prompt" ], "type": "str" @@ -92,30 +96,30 @@ "id": "reactflow__edge-Prompt-xeI6K{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-xeI6Kœ}-OpenAIModel-EjXlN{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-EjXlNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "Prompt-xeI6K", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-xeI6Kœ, œoutput_typesœ: [œPromptœ], œnameœ: œpromptœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œTextœ, œstrœ], œdataTypeœ: œPromptœ, œidœ: œPrompt-xeI6Kœ}", "style": { "stroke": "#555" }, "target": "OpenAIModel-EjXlN", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-EjXlNœ, œinputTypesœ: [œTextœ, œDataœ, œPromptœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-EjXlNœ, œinputTypesœ: [œTextœ, œRecordœ, œPromptœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], "dataType": "OpenAIModel", - "id": "OpenAIModel-EjXlN", - "name": "text_output", - "output_types": [ - "Text" - ] + "id": "OpenAIModel-EjXlN" }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-Q39I8", "inputTypes": [ - "Text", - "Message" + "Text" ], "type": "str" } @@ -123,28 +127,29 @@ "id": "reactflow__edge-OpenAIModel-EjXlN{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-EjXlNœ}-ChatOutput-Q39I8{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Q39I8œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "selected": false, "source": "OpenAIModel-EjXlN", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-EjXlNœ, œoutput_typesœ: [œTextœ], œnameœ: œtext_outputœ}", + "sourceHandle": "{œbaseClassesœ: [œobjectœ, œTextœ, œstrœ], œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-EjXlNœ}", "style": { "stroke": "#555" }, "target": "ChatOutput-Q39I8", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-Q39I8œ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-Q39I8œ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Record" + ], "dataType": "File", - "id": "File-t0a6a", - "name": "record", - "output_types": [] + "id": "File-t0a6a" }, "targetHandle": { "fieldName": "inputs", "id": "RecursiveCharacterTextSplitter-tR9QM", "inputTypes": [ "Document", - "Data" + "Record" ], "type": "Document" } @@ -152,23 +157,22 @@ "id": "reactflow__edge-File-t0a6a{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-t0a6aœ}-RecursiveCharacterTextSplitter-tR9QM{œfieldNameœ:œinputsœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ,œinputTypesœ:[œDocumentœ,œRecordœ],œtypeœ:œDocumentœ}", "selected": false, "source": "File-t0a6a", - "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-t0a6aœ, œoutput_typesœ: [], œnameœ: œrecordœ}", + "sourceHandle": "{œbaseClassesœ: [œRecordœ], œdataTypeœ: œFileœ, œidœ: œFile-t0a6aœ}", "style": { "stroke": "#555" }, "target": "RecursiveCharacterTextSplitter-tR9QM", - "targetHandle": "{œfieldNameœ: œinputsœ, œidœ: œRecursiveCharacterTextSplitter-tR9QMœ, œinputTypesœ: [œDocumentœ, œDataœ], œtypeœ: œDocumentœ}" + "targetHandle": "{œfieldNameœ: œinputsœ, œidœ: œRecursiveCharacterTextSplitter-tR9QMœ, œinputTypesœ: [œDocumentœ, œRecordœ], œtypeœ: œDocumentœ}" }, { "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { - "dataType": "OpenAIEmbeddings", - "id": "OpenAIEmbeddings-ZlOk1", - "name": "embeddings", - "output_types": [ + "baseClasses": [ "Embeddings" - ] + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-ZlOk1" }, "targetHandle": { "fieldName": "embedding", @@ -179,7 +183,7 @@ }, "id": "reactflow__edge-OpenAIEmbeddings-ZlOk1{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-ZlOk1œ}-AstraDBSearch-41nRz{œfieldNameœ:œembeddingœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", "source": "OpenAIEmbeddings-ZlOk1", - "sourceHandle": "{œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-ZlOk1œ, œoutput_typesœ: [œEmbeddingsœ], œnameœ: œembeddingsœ}", + "sourceHandle": "{œbaseClassesœ: [œEmbeddingsœ], œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-ZlOk1œ}", "style": { "stroke": "#555" }, @@ -190,12 +194,14 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object", + "Record" + ], "dataType": "ChatInput", - "id": "ChatInput-yxMKE", - "name": "message", - "output_types": [ - "Message" - ] + "id": "ChatInput-yxMKE" }, "targetHandle": { "fieldName": "input_value", @@ -208,7 +214,7 @@ }, "id": "reactflow__edge-ChatInput-yxMKE{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}-AstraDBSearch-41nRz{œfieldNameœ:œinput_valueœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", "source": "ChatInput-yxMKE", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-yxMKEœ, œoutput_typesœ: [œMessageœ], œnameœ: œmessageœ}", + "sourceHandle": "{œbaseClassesœ: [œTextœ, œstrœ, œobjectœ, œRecordœ], œdataTypeœ: œChatInputœ, œidœ: œChatInput-yxMKEœ}", "style": { "stroke": "#555" }, @@ -219,10 +225,11 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Record" + ], "dataType": "RecursiveCharacterTextSplitter", - "id": "RecursiveCharacterTextSplitter-tR9QM", - "name": "record", - "output_types": [] + "id": "RecursiveCharacterTextSplitter-tR9QM" }, "targetHandle": { "fieldName": "inputs", @@ -234,7 +241,7 @@ "id": "reactflow__edge-RecursiveCharacterTextSplitter-tR9QM{œbaseClassesœ:[œRecordœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ}-AstraDB-eUCSS{œfieldNameœ:œinputsœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œRecordœ}", "selected": false, "source": "RecursiveCharacterTextSplitter-tR9QM", - "sourceHandle": "{œdataTypeœ: œRecursiveCharacterTextSplitterœ, œidœ: œRecursiveCharacterTextSplitter-tR9QMœ, œoutput_typesœ: [], œnameœ: œrecordœ}", + "sourceHandle": "{œbaseClassesœ: [œRecordœ], œdataTypeœ: œRecursiveCharacterTextSplitterœ, œidœ: œRecursiveCharacterTextSplitter-tR9QMœ}", "style": { "stroke": "#555" }, @@ -245,12 +252,11 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { - "dataType": "OpenAIEmbeddings", - "id": "OpenAIEmbeddings-9TPjc", - "name": "embeddings", - "output_types": [ + "baseClasses": [ "Embeddings" - ] + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-9TPjc" }, "targetHandle": { "fieldName": "embedding", @@ -262,7 +268,7 @@ "id": "reactflow__edge-OpenAIEmbeddings-9TPjc{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9TPjcœ}-AstraDB-eUCSS{œfieldNameœ:œembeddingœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", "selected": false, "source": "OpenAIEmbeddings-9TPjc", - "sourceHandle": "{œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-9TPjcœ, œoutput_typesœ: [œEmbeddingsœ], œnameœ: œembeddingsœ}", + "sourceHandle": "{œbaseClassesœ: [œEmbeddingsœ], œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-9TPjcœ}", "style": { "stroke": "#555" }, @@ -273,10 +279,11 @@ "className": "stroke-gray-900 stroke-connection", "data": { "sourceHandle": { + "baseClasses": [ + "Record" + ], "dataType": "AstraDBSearch", - "id": "AstraDBSearch-41nRz", - "name": "record", - "output_types": [] + "id": "AstraDBSearch-41nRz" }, "targetHandle": { "fieldName": "input_value", @@ -290,7 +297,7 @@ }, "id": "reactflow__edge-AstraDBSearch-41nRz{œbaseClassesœ:[œRecordœ],œdataTypeœ:œAstraDBSearchœ,œidœ:œAstraDBSearch-41nRzœ}-TextOutput-BDknO{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-BDknOœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", "source": "AstraDBSearch-41nRz", - "sourceHandle": "{œdataTypeœ: œAstraDBSearchœ, œidœ: œAstraDBSearch-41nRzœ, œoutput_typesœ: [], œnameœ: œrecordœ}", + "sourceHandle": "{œbaseClassesœ: [œRecordœ], œdataTypeœ: œAstraDBSearchœ, œidœ: œAstraDBSearch-41nRzœ}", "style": { "stroke": "#555" }, @@ -324,22 +331,12 @@ "field_order": [], "frozen": false, "icon": "ChatInput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -356,7 +353,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n input_types=[],\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"User\",\n info=\"Type of sender.\",\n advanced=True,\n ),\n StrInput(\n name=\"sender_name\",\n type=str,\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=\"User\",\n advanced=True,\n ),\n StrInput(\n name=\"session_id\", type=str, display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, (Message, str)) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.schema.message import Message\nfrom langflow.field_typing import Text\nfrom typing import Union\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Text\",\n \"multiline\": True,\n }\n build_config[\"return_message\"] = {\n \"display_name\": \"Return Record\",\n \"advanced\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n files: Optional[list[str]] = None,\n session_id: Optional[str] = None,\n return_message: Optional[bool] = True,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n files=files,\n session_id=session_id,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -364,7 +361,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as input.", + "info": "", "input_types": [], "list": false, "load_from_db": false, @@ -376,7 +373,7 @@ "show": true, "title_case": false, "type": "str", - "value": "" + "value": "what is a line" }, "sender": { "advanced": true, @@ -384,7 +381,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -405,12 +402,12 @@ "value": "User" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -432,7 +429,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -445,8 +442,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, @@ -486,15 +482,6 @@ "output_types": [ "Text" ], - "outputs": [ - { - "name": "Text", - "selected": "Text", - "types": [ - "Text" - ] - } - ], "template": { "_type": "CustomComponent", "code": { @@ -620,20 +607,6 @@ "output_types": [ "Embeddings" ], - "outputs": [ - { - "cache": true, - "display_name": "Embeddings", - "hidden": null, - "method": null, - "name": "embeddings", - "selected": "Embeddings", - "types": [ - "Embeddings" - ], - "value": "__UNDEFINED__" - } - ], "template": { "_type": "CustomComponent", "allowed_special": { @@ -646,7 +619,7 @@ "input_types": [ "Text" ], - "list": true, + "list": false, "load_from_db": false, "multiline": false, "name": "allowed_special", @@ -693,7 +666,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, NestedDict\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n )\n" + "value": "from typing import Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, NestedDict\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n \"dimensions\": {\n \"display_name\": \"Dimensions\",\n \"info\": \"The number of dimensions the resulting output embeddings should have. Only supported by certain models.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n dimensions: Optional[int] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n dimensions=dimensions,\n )\n" }, "default_headers": { "advanced": true, @@ -764,7 +737,7 @@ "input_types": [ "Text" ], - "list": true, + "list": false, "load_from_db": false, "multiline": false, "name": "disallowed_special", @@ -894,7 +867,7 @@ "Text" ], "list": false, - "load_from_db": false, + "load_from_db": true, "multiline": false, "name": "openai_api_key", "password": true, @@ -1144,33 +1117,11 @@ ], "frozen": false, "icon": "OpenAI", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Text", - "method": "text_response", - "name": "text_output", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Language Model", - "method": "build_model", - "name": "model_output", - "selected": "BaseLanguageModel", - "types": [ - "BaseLanguageModel" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -1187,7 +1138,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import BaseLanguageModel, Text\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, FloatInput, SecretStrInput, StrInput\nfrom langflow.inputs.inputs import IntInput\nfrom langflow.template import Output\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n inputs = [\n StrInput(name=\"input_value\", display_name=\"Input\", input_types=[\"Text\", \"Data\", \"Prompt\"]),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text_output\", method=\"text_response\"),\n Output(display_name=\"Language Model\", name=\"model_output\", method=\"build_model\"),\n ]\n\n def text_response(self) -> Text:\n input_value = self.input_value\n stream = self.stream\n system_message = self.system_message\n output = self.build_model()\n result = self.get_chat_result(output, stream, input_value, system_message)\n self.status = result\n return result\n\n def build_model(self) -> BaseLanguageModel:\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs or {},\n model=model_name or None,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n return output\n" + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\", \"input_types\": [\"Text\", \"Record\", \"Prompt\"]},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n \"info\": \"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": MODEL_NAMES,\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float = 0.1,\n model_name: str = \"gpt-3.5-turbo\",\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n" }, "input_value": { "advanced": false, @@ -1198,7 +1149,7 @@ "info": "", "input_types": [ "Text", - "Data", + "Record", "Prompt" ], "list": false, @@ -1207,11 +1158,10 @@ "name": "input_value", "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "max_tokens": { "advanced": true, @@ -1220,9 +1170,6 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1232,8 +1179,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "int", + "value": 256 }, "model_kwargs": { "advanced": true, @@ -1242,9 +1189,6 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1254,8 +1198,8 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "NestedDict", + "value": {} }, "model_name": { "advanced": false, @@ -1284,7 +1228,7 @@ "show": true, "title_case": false, "type": "str", - "value": "gpt-4o" + "value": "gpt-3.5-turbo" }, "openai_api_base": { "advanced": true, @@ -1305,8 +1249,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "openai_api_key": { "advanced": false, @@ -1324,7 +1267,7 @@ "name": "openai_api_key", "password": true, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "type": "str", @@ -1337,9 +1280,6 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, @@ -1349,7 +1289,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", + "type": "bool", "value": false }, "system_message": { @@ -1371,8 +1311,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "temperature": { "advanced": false, @@ -1381,19 +1320,22 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": [ - "Text" - ], "list": false, "load_from_db": false, "multiline": false, "name": "temperature", "password": false, "placeholder": "", + "rangeSpec": { + "max": 1, + "min": -1, + "step": 0.1, + "step_type": "float" + }, "required": false, "show": true, "title_case": false, - "type": "str", + "type": "float", "value": 0.1 } } @@ -1446,33 +1388,11 @@ "is_input": null, "is_output": null, "name": "", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Prompt", - "method": "build_prompt", - "name": "prompt", - "selected": "Prompt", - "types": [ - "Prompt" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Text", - "method": "format_prompt", - "name": "text", - "selected": "Text", - "types": [ - "Text" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Prompt" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -1489,7 +1409,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.field_typing.prompt import Prompt\nfrom langflow.inputs import PromptInput\nfrom langflow.template import Output\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n Output(display_name=\"Text\", name=\"text\", method=\"format_prompt\"),\n ]\n\n async def format_prompt(self) -> str:\n prompt = await self.build_prompt()\n formatted_text = prompt.format_text()\n self.status = formatted_text\n return formatted_text\n\n async def build_prompt(\n self,\n ) -> Prompt:\n kwargs = {k: v for k, v in self._arguments.items() if k != \"template\"}\n prompt = await Prompt.from_template_and_variables(self.template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import TemplateField\nfrom langflow.field_typing.prompt import Prompt\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n async def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Prompt:\n prompt = await Prompt.from_template_and_variables(template, kwargs)\n self.status = prompt.format_text()\n return prompt\n" }, "context": { "advanced": false, @@ -1501,7 +1421,7 @@ "info": "", "input_types": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -1527,7 +1447,7 @@ "info": "", "input_types": [ "Document", - "Message", + "BaseOutputParser", "Record", "Text" ], @@ -1610,22 +1530,12 @@ "field_order": [], "frozen": false, "icon": "ChatOutput", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Message", - "method": "message_response", - "name": "message", - "selected": "Message", - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Message", + "Text" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -1642,7 +1552,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput, DropdownInput, MultilineInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n if isinstance(self.input_value, Message):\n message = self.input_value\n else:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.status = message\n return message\n" + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema.message import Message\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n files: Optional[list[str]] = None,\n return_message: Optional[bool] = False,\n ) -> Union[Message, Text]:\n return super().build_with_record(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n files=files,\n return_message=return_message,\n )\n" }, "input_value": { "advanced": false, @@ -1650,10 +1560,9 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Message to be passed as output.", + "info": "", "input_types": [ - "Text", - "Message" + "Text" ], "list": false, "load_from_db": false, @@ -1664,8 +1573,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" }, "sender": { "advanced": true, @@ -1673,7 +1581,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Type of sender.", + "info": "", "input_types": [ "Text" ], @@ -1694,12 +1602,12 @@ "value": "Machine" }, "sender_name": { - "advanced": true, + "advanced": false, "display_name": "Sender Name", "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Name of the sender.", + "info": "", "input_types": [ "Text" ], @@ -1721,7 +1629,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Session ID for the message.", + "info": "If provided, the message will be stored in the memory.", "input_types": [ "Text" ], @@ -1734,8 +1642,7 @@ "required": false, "show": true, "title_case": false, - "type": "str", - "value": "" + "type": "str" } } }, @@ -1775,22 +1682,11 @@ "field_order": [], "frozen": false, "icon": "file-text", - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "load_file", - "name": "data", - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } + "output_types": [ + "Record" ], "template": { - "_type": "Component", + "_type": "CustomComponent", "code": { "advanced": true, "dynamic": true, @@ -1807,49 +1703,58 @@ "show": true, "title_case": false, "type": "code", - "value": "from pathlib import Path\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_data\nfrom langflow.custom import Component\nfrom langflow.inputs import BoolInput, FileInput\nfrom langflow.schema import Data\nfrom langflow.template import Output\n\n\nclass FileComponent(Component):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n inputs = [\n FileInput(\n name=\"path\",\n display_name=\"Path\",\n file_types=TEXT_FILE_TYPES,\n info=f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n ),\n BoolInput(\n name=\"silent_errors\",\n display_name=\"Silent Errors\",\n advanced=True,\n info=\"If true, errors will not raise an exception.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"load_file\"),\n ]\n\n def load_file(self) -> Data:\n if not self.path:\n raise ValueError(\"Please, upload a file to use this component.\")\n resolved_path = self.resolve_path(self.path)\n silent_errors = self.silent_errors\n\n extension = Path(resolved_path).suffix[1:].lower()\n\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n\n data = parse_text_file_to_data(resolved_path, silent_errors)\n self.status = data if data else \"No data\"\n return data or Data()\n" + "value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Record\n\n\nclass FileComponent(CustomComponent):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Record:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_record(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Record()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Record:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n" }, "path": { "advanced": false, "display_name": "Path", "dynamic": false, "fileTypes": [ - "txt", - "md", - "mdx", - "csv", - "json", - "yaml", - "yml", - "xml", - "html", - "htm", - "pdf", - "docx", - "py", - "sh", - "sql", - "js", - "ts", - "tsx" + ".txt", + ".md", + ".mdx", + ".csv", + ".json", + ".yaml", + ".yml", + ".xml", + ".html", + ".htm", + ".pdf", + ".docx", + ".py", + ".sh", + ".sql", + ".js", + ".ts", + ".tsx" ], - "file_path": "", + "file_path": "51e2b78a-199b-4054-9f32-e288eef6924c/Langflow conversation.pdf", "info": "Supported file types: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx, py, sh, sql, js, ts, tsx", "list": false, + "load_from_db": false, + "multiline": false, "name": "path", + "password": false, "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "type": "file" + "type": "file", + "value": "" }, "silent_errors": { "advanced": true, "display_name": "Silent Errors", "dynamic": false, + "fileTypes": [], + "file_path": "", "info": "If true, errors will not raise an exception.", "list": false, + "load_from_db": false, + "multiline": false, "name": "silent_errors", + "password": false, "placeholder": "", "required": false, "show": true, @@ -1897,21 +1802,7 @@ "field_order": [], "frozen": false, "output_types": [ - "Data" - ], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "hidden": null, - "method": null, - "name": "data", - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } + "Record" ], "template": { "_type": "CustomComponent", @@ -1969,7 +1860,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import Optional\n\nfrom langchain_core.documents import Document\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\n\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Data\nfrom langflow.utils.util import build_loader_repr_from_data, unescape_string\n\n\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\n display_name: str = \"Recursive Character Text Splitter\"\n description: str = \"Split text into chunks of a specified length.\"\n documentation: str = \"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\"\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Input\",\n \"info\": \"The texts to split.\",\n \"input_types\": [\"Document\", \"Data\"],\n },\n \"separators\": {\n \"display_name\": \"Separators\",\n \"info\": 'The characters to split on.\\nIf left empty defaults to [\"\\\\n\\\\n\", \"\\\\n\", \" \", \"\"].',\n \"is_list\": True,\n },\n \"chunk_size\": {\n \"display_name\": \"Chunk Size\",\n \"info\": \"The maximum length of each chunk.\",\n \"field_type\": \"int\",\n \"value\": 1000,\n },\n \"chunk_overlap\": {\n \"display_name\": \"Chunk Overlap\",\n \"info\": \"The amount of overlap between chunks.\",\n \"field_type\": \"int\",\n \"value\": 200,\n },\n \"code\": {\"show\": False},\n }\n\n def build(\n self,\n inputs: list[Document],\n separators: Optional[list[str]] = None,\n chunk_size: Optional[int] = 1000,\n chunk_overlap: Optional[int] = 200,\n ) -> list[Data]:\n \"\"\"\n Split text into chunks of a specified length.\n\n Args:\n separators (list[str]): The characters to split on.\n chunk_size (int): The maximum length of each chunk.\n chunk_overlap (int): The amount of overlap between chunks.\n length_function (function): The function to use to calculate the length of the text.\n\n Returns:\n list[str]: The chunks of text.\n \"\"\"\n\n if separators == \"\":\n separators = None\n elif separators:\n # check if the separators list has escaped characters\n # if there are escaped characters, unescape them\n separators = [unescape_string(x) for x in separators]\n\n # Make sure chunk_size and chunk_overlap are ints\n if isinstance(chunk_size, str):\n chunk_size = int(chunk_size)\n if isinstance(chunk_overlap, str):\n chunk_overlap = int(chunk_overlap)\n splitter = RecursiveCharacterTextSplitter(\n separators=separators,\n chunk_size=chunk_size,\n chunk_overlap=chunk_overlap,\n )\n documents = []\n for _input in inputs:\n if isinstance(_input, Data):\n documents.append(_input.to_lc_document())\n else:\n documents.append(_input)\n docs = splitter.split_documents(documents)\n data = self.to_data(docs)\n self.repr_value = build_loader_repr_from_data(data)\n return data\n" + "value": "from typing import Optional\n\nfrom langchain_core.documents import Document\nfrom langchain_text_splitters import RecursiveCharacterTextSplitter\n\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Record\nfrom langflow.utils.util import build_loader_repr_from_records, unescape_string\n\n\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\n display_name: str = \"Recursive Character Text Splitter\"\n description: str = \"Split text into chunks of a specified length.\"\n documentation: str = \"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\"\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Input\",\n \"info\": \"The texts to split.\",\n \"input_types\": [\"Document\", \"Record\"],\n },\n \"separators\": {\n \"display_name\": \"Separators\",\n \"info\": 'The characters to split on.\\nIf left empty defaults to [\"\\\\n\\\\n\", \"\\\\n\", \" \", \"\"].',\n \"is_list\": True,\n },\n \"chunk_size\": {\n \"display_name\": \"Chunk Size\",\n \"info\": \"The maximum length of each chunk.\",\n \"field_type\": \"int\",\n \"value\": 1000,\n },\n \"chunk_overlap\": {\n \"display_name\": \"Chunk Overlap\",\n \"info\": \"The amount of overlap between chunks.\",\n \"field_type\": \"int\",\n \"value\": 200,\n },\n \"code\": {\"show\": False},\n }\n\n def build(\n self,\n inputs: list[Document],\n separators: Optional[list[str]] = None,\n chunk_size: Optional[int] = 1000,\n chunk_overlap: Optional[int] = 200,\n ) -> list[Record]:\n \"\"\"\n Split text into chunks of a specified length.\n\n Args:\n separators (list[str]): The characters to split on.\n chunk_size (int): The maximum length of each chunk.\n chunk_overlap (int): The amount of overlap between chunks.\n length_function (function): The function to use to calculate the length of the text.\n\n Returns:\n list[str]: The chunks of text.\n \"\"\"\n\n if separators == \"\":\n separators = None\n elif separators:\n # check if the separators list has escaped characters\n # if there are escaped characters, unescape them\n separators = [unescape_string(x) for x in separators]\n\n # Make sure chunk_size and chunk_overlap are ints\n if isinstance(chunk_size, str):\n chunk_size = int(chunk_size)\n if isinstance(chunk_overlap, str):\n chunk_overlap = int(chunk_overlap)\n splitter = RecursiveCharacterTextSplitter(\n separators=separators,\n chunk_size=chunk_size,\n chunk_overlap=chunk_overlap,\n )\n documents = []\n for _input in inputs:\n if isinstance(_input, Record):\n documents.append(_input.to_lc_document())\n else:\n documents.append(_input)\n docs = splitter.split_documents(documents)\n records = self.to_records(docs)\n self.repr_value = build_loader_repr_from_records(records)\n return records\n" }, "inputs": { "advanced": false, @@ -1980,7 +1871,7 @@ "info": "The texts to split.", "input_types": [ "Document", - "Data" + "Record" ], "list": true, "load_from_db": false, @@ -2078,21 +1969,7 @@ "frozen": false, "icon": "AstraDB", "output_types": [ - "Data" - ], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "hidden": null, - "method": null, - "name": "data", - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } + "Record" ], "template": { "_type": "CustomComponent", @@ -2107,7 +1984,7 @@ "Text" ], "list": false, - "load_from_db": false, + "load_from_db": true, "multiline": false, "name": "api_endpoint", "password": false, @@ -2124,7 +2001,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Optional number of data to process in a single batch.", + "info": "Optional number of records to process in a single batch.", "list": false, "load_from_db": false, "multiline": false, @@ -2178,7 +2055,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Optional concurrency level for bulk insert operations that overwrite existing data.", + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", "list": false, "load_from_db": false, "multiline": false, @@ -2206,7 +2083,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import List, Optional\n\nfrom langflow.components.vectorstores.AstraDB import AstraDBVectorStoreComponent\nfrom langflow.components.vectorstores.base.model import LCVectorStoreComponent\nfrom langflow.field_typing import Embeddings, Text\nfrom langflow.schema import Data\n\n\nclass AstraDBSearchComponent(LCVectorStoreComponent):\n display_name = \"Astra DB Search\"\n description = \"Searches an existing Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"input_value\", \"embedding\"]\n\n def build_config(self):\n return {\n \"search_type\": {\n \"display_name\": \"Search Type\",\n \"options\": [\"Similarity\", \"MMR\"],\n },\n \"input_value\": {\n \"display_name\": \"Input Value\",\n \"info\": \"Input value to search\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of data to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing data.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n \"number_of_results\": {\n \"display_name\": \"Number of Results\",\n \"info\": \"Number of results to return.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n collection_name: str,\n input_value: Text,\n token: str,\n api_endpoint: str,\n search_type: str = \"Similarity\",\n number_of_results: int = 4,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Sync\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> List[Data]:\n vector_store = AstraDBVectorStoreComponent().build(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n try:\n return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)\n except KeyError as e:\n if \"content\" in str(e):\n raise ValueError(\n \"You should ingest data through Langflow (or LangChain) to query it in Langflow. Your collection does not contain a field name 'content'.\"\n )\n else:\n raise e\n" + "value": "from typing import List, Optional\n\nfrom langflow.components.vectorstores.AstraDB import AstraDBVectorStoreComponent\nfrom langflow.components.vectorstores.base.model import LCVectorStoreComponent\nfrom langflow.field_typing import Embeddings, Text\nfrom langflow.schema import Record\n\n\nclass AstraDBSearchComponent(LCVectorStoreComponent):\n display_name = \"Astra DB Search\"\n description = \"Searches an existing Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"input_value\", \"embedding\"]\n\n def build_config(self):\n return {\n \"search_type\": {\n \"display_name\": \"Search Type\",\n \"options\": [\"Similarity\", \"MMR\"],\n },\n \"input_value\": {\n \"display_name\": \"Input Value\",\n \"info\": \"Input value to search\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Astra DB Application Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of records to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing records.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n \"number_of_results\": {\n \"display_name\": \"Number of Results\",\n \"info\": \"Number of results to return.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n collection_name: str,\n input_value: Text,\n token: str,\n api_endpoint: str,\n search_type: str = \"Similarity\",\n number_of_results: int = 4,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Sync\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> List[Record]:\n vector_store = AstraDBVectorStoreComponent().build(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n try:\n return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)\n except KeyError as e:\n if \"content\" in str(e):\n raise ValueError(\n \"You should ingest data through Langflow (or LangChain) to query it in Langflow. Your collection does not contain a field name 'content'.\"\n )\n else:\n raise e\n" }, "collection_indexing_policy": { "advanced": true, @@ -2464,7 +2341,7 @@ }, "token": { "advanced": false, - "display_name": "Token", + "display_name": "Astra DB Application Token", "dynamic": false, "fileTypes": [], "file_path": "", @@ -2473,7 +2350,7 @@ "Text" ], "list": false, - "load_from_db": false, + "load_from_db": true, "multiline": false, "name": "token", "password": true, @@ -2546,32 +2423,6 @@ "VectorStore", "BaseRetriever" ], - "outputs": [ - { - "cache": true, - "display_name": "VectorStore", - "hidden": null, - "method": null, - "name": "vectorstore", - "selected": "VectorStore", - "types": [ - "VectorStore" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "BaseRetriever", - "hidden": null, - "method": null, - "name": "baseretriever", - "selected": "BaseRetriever", - "types": [ - "BaseRetriever" - ], - "value": "__UNDEFINED__" - } - ], "template": { "_type": "CustomComponent", "api_endpoint": { @@ -2585,7 +2436,7 @@ "Text" ], "list": false, - "load_from_db": false, + "load_from_db": true, "multiline": false, "name": "api_endpoint", "password": false, @@ -2602,7 +2453,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Optional number of data to process in a single batch.", + "info": "Optional number of records to process in a single batch.", "list": false, "load_from_db": false, "multiline": false, @@ -2656,7 +2507,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Optional concurrency level for bulk insert operations that overwrite existing data.", + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", "list": false, "load_from_db": false, "multiline": false, @@ -2684,7 +2535,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import List, Optional, Union\n\nfrom langchain_core.retrievers import BaseRetriever\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, VectorStore\nfrom langflow.schema import Data\n\n\nclass AstraDBVectorStoreComponent(CustomComponent):\n display_name = \"Astra DB\"\n description = \"Builds or loads an Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"inputs\", \"embedding\"]\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Inputs\",\n \"info\": \"Optional list of data to be processed and stored in the vector store.\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of data to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing data.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n token: str,\n api_endpoint: str,\n collection_name: str,\n inputs: Optional[List[Data]] = None,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Sync\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> Union[VectorStore, BaseRetriever]:\n try:\n from langchain_astradb import AstraDBVectorStore\n from langchain_astradb.utils.astradb import SetupMode\n except ImportError:\n raise ImportError(\n \"Could not import langchain Astra DB integration package. \"\n \"Please install it with `pip install langchain-astradb`.\"\n )\n\n try:\n setup_mode_value = SetupMode[setup_mode.upper()]\n except KeyError:\n raise ValueError(f\"Invalid setup mode: {setup_mode}\")\n if inputs:\n documents = [_input.to_lc_document() for _input in inputs]\n\n vector_store = AstraDBVectorStore.from_documents(\n documents=documents,\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n else:\n vector_store = AstraDBVectorStore(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n\n return vector_store\n return vector_store\n" + "value": "from typing import List, Optional, Union\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, VectorStore\nfrom langflow.schema import Record\nfrom langchain_core.retrievers import BaseRetriever\n\n\nclass AstraDBVectorStoreComponent(CustomComponent):\n display_name = \"Astra DB\"\n description = \"Builds or loads an Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"inputs\", \"embedding\"]\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Inputs\",\n \"info\": \"Optional list of records to be processed and stored in the vector store.\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Astra DB Application Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of records to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing records.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n token: str,\n api_endpoint: str,\n collection_name: str,\n inputs: Optional[List[Record]] = None,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Sync\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> Union[VectorStore, BaseRetriever]:\n try:\n from langchain_astradb import AstraDBVectorStore\n from langchain_astradb.utils.astradb import SetupMode\n except ImportError:\n raise ImportError(\n \"Could not import langchain Astra DB integration package. \"\n \"Please install it with `pip install langchain-astradb`.\"\n )\n\n try:\n setup_mode_value = SetupMode[setup_mode.upper()]\n except KeyError:\n raise ValueError(f\"Invalid setup mode: {setup_mode}\")\n if inputs:\n documents = [_input.to_lc_document() for _input in inputs]\n\n vector_store = AstraDBVectorStore.from_documents(\n documents=documents,\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n else:\n vector_store = AstraDBVectorStore(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n\n return vector_store\n return vector_store\n" }, "collection_indexing_policy": { "advanced": true, @@ -2750,7 +2601,7 @@ "dynamic": false, "fileTypes": [], "file_path": "", - "info": "Optional list of data to be processed and stored in the vector store.", + "info": "Optional list of records to be processed and stored in the vector store.", "list": true, "load_from_db": false, "multiline": false, @@ -2894,7 +2745,7 @@ }, "token": { "advanced": false, - "display_name": "Token", + "display_name": "Astra DB Application Token", "dynamic": false, "fileTypes": [], "file_path": "", @@ -2903,7 +2754,7 @@ "Text" ], "list": false, - "load_from_db": false, + "load_from_db": true, "multiline": false, "name": "token", "password": true, @@ -2974,20 +2825,6 @@ "output_types": [ "Embeddings" ], - "outputs": [ - { - "cache": true, - "display_name": "Embeddings", - "hidden": null, - "method": null, - "name": "embeddings", - "selected": "Embeddings", - "types": [ - "Embeddings" - ], - "value": "__UNDEFINED__" - } - ], "template": { "_type": "CustomComponent", "allowed_special": { @@ -3000,7 +2837,7 @@ "input_types": [ "Text" ], - "list": true, + "list": false, "load_from_db": false, "multiline": false, "name": "allowed_special", @@ -3047,7 +2884,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, NestedDict\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n )\n" + "value": "from typing import Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, NestedDict\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n \"dimensions\": {\n \"display_name\": \"Dimensions\",\n \"info\": \"The number of dimensions the resulting output embeddings should have. Only supported by certain models.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n dimensions: Optional[int] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n dimensions=dimensions,\n )\n" }, "default_headers": { "advanced": true, @@ -3118,7 +2955,7 @@ "input_types": [ "Text" ], - "list": true, + "list": false, "load_from_db": false, "multiline": false, "name": "disallowed_special", @@ -3248,7 +3085,7 @@ "Text" ], "list": false, - "load_from_db": false, + "load_from_db": true, "multiline": false, "name": "openai_api_key", "password": true, @@ -3476,4 +3313,4 @@ "is_component": false, "last_tested_version": "1.0.0a0", "name": "Vector Store RAG" -} \ No newline at end of file +} diff --git a/src/backend/base/langflow/interface/initialize/loading.py b/src/backend/base/langflow/interface/initialize/loading.py index e0ecd5797..05329fcc1 100644 --- a/src/backend/base/langflow/interface/initialize/loading.py +++ b/src/backend/base/langflow/interface/initialize/loading.py @@ -160,7 +160,7 @@ async def build_custom_component(params: dict, custom_component: "CustomComponen if raw is None and isinstance(build_result, (dict, Data, str)): raw = build_result.data if isinstance(build_result, Data) else build_result - artifact_type = get_artifact_type(custom_component.repr_value or raw, build_result) + artifact_type = get_artifact_type(custom_component or raw, build_result) raw = post_process_raw(raw, artifact_type) artifact = {"repr": custom_repr, "raw": raw, "type": artifact_type} return custom_component, build_result, artifact diff --git a/src/backend/base/langflow/services/monitor/schema.py b/src/backend/base/langflow/services/monitor/schema.py index 363563873..69a1fc7ab 100644 --- a/src/backend/base/langflow/services/monitor/schema.py +++ b/src/backend/base/langflow/services/monitor/schema.py @@ -91,9 +91,17 @@ class MessageModel(DefaultModel): files: list[str] = [] @field_validator("files", mode="before") + @classmethod def validate_files(cls, v): if isinstance(v, str): - return json.loads(v) + v = json.loads(v) + return v + + @field_serializer("files") + @classmethod + def serialize_files(cls, v): + if isinstance(v, list): + return json.dumps(v) return v @classmethod diff --git a/src/backend/base/langflow/services/monitor/service.py b/src/backend/base/langflow/services/monitor/service.py index b9fdc028d..c7d898d11 100644 --- a/src/backend/base/langflow/services/monitor/service.py +++ b/src/backend/base/langflow/services/monitor/service.py @@ -3,12 +3,11 @@ from pathlib import Path from typing import TYPE_CHECKING, List, Optional, Union import duckdb -from loguru import logger -from platformdirs import user_cache_dir - from langflow.services.base import Service from langflow.services.monitor.schema import MessageModel, TransactionModel, VertexBuildModel from langflow.services.monitor.utils import add_row_to_table, drop_and_create_table_if_schema_mismatch +from loguru import logger +from platformdirs import user_cache_dir if TYPE_CHECKING: from langflow.services.settings.manager import SettingsService @@ -141,7 +140,7 @@ class MonitorService(Service): order: Optional[str] = "DESC", limit: Optional[int] = None, ): - query = "SELECT index, flow_id, sender_name, sender, session_id, text, timestamp FROM messages" + query = "SELECT index, flow_id, sender_name, sender, session_id, text, files, timestamp FROM messages" conditions = [] if sender: conditions.append(f"sender = '{sender}'") diff --git a/src/backend/base/pyproject.toml b/src/backend/base/pyproject.toml index 81e088c1c..03f3f70f1 100644 --- a/src/backend/base/pyproject.toml +++ b/src/backend/base/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow-base" -version = "0.0.63" +version = "0.0.66" description = "A Python package with a built-in web application" authors = ["Langflow "] maintainers = [ diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 7e7c3bbba..b4b86cfd1 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -105,7 +105,6 @@ "prettier": "^2.8.8", "prettier-plugin-organize-imports": "^3.2.3", "prettier-plugin-tailwindcss": "^0.3.0", - "pretty-quick": "^3.1.3", "simple-git-hooks": "^2.11.1", "tailwindcss": "^3.3.3", "tailwindcss-dotted-background": "^1.1.0", @@ -115,9 +114,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", - "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", "dev": true }, "node_modules/@alloc/quick-lru": { @@ -157,32 +156,12 @@ "nun": "bin/nun.mjs" } }, - "node_modules/@axiomhq/js": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@axiomhq/js/-/js-1.0.0-rc.3.tgz", - "integrity": "sha512-Zm10TczcMLounWqC42nMkXQ7XKLqjzLrd5ia022oBKDUZqAFVg2y9d1quQVNV4FlXyg9MKDdfMjpKQRmzEGaog==", - "dependencies": { - "fetch-retry": "^6.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@axiomhq/js/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.24.2", + "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { @@ -190,28 +169,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -227,11 +206,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", - "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dependencies": { - "@babel/types": "^7.24.5", + "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -241,12 +220,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -256,57 +235,61 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dependencies": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -316,70 +299,70 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dependencies": { - "@babel/types": "^7.24.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", - "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dependencies": { - "@babel/types": "^7.24.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", - "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", - "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -389,9 +372,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -400,9 +383,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -411,31 +394,31 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", - "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", "dependencies": { - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/types": "^7.24.5", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -444,52 +427,18 @@ } }, "node_modules/@babel/types": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", - "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dependencies": { - "@babel/helper-string-parser": "^7.24.1", - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@clack/core": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.4.tgz", - "integrity": "sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==", - "dependencies": { - "picocolors": "^1.0.0", - "sisteransi": "^1.0.5" - } - }, - "node_modules/@clack/prompts": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.7.0.tgz", - "integrity": "sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==", - "bundleDependencies": [ - "is-unicode-supported" - ], - "dependencies": { - "@clack/core": "^0.3.3", - "is-unicode-supported": "*", - "picocolors": "^1.0.0", - "sisteransi": "^1.0.5" - } - }, - "node_modules/@clack/prompts/node_modules/is-unicode-supported": { - "version": "1.3.0", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", @@ -851,9 +800,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -979,9 +928,9 @@ } }, "node_modules/@hookform/resolvers": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.4.2.tgz", - "integrity": "sha512-1m9uAVIO8wVf7VCDAGsuGA0t6Z3m6jVGAN50HkV9vYLl0yixKK/Z1lr01vaRvYCkIKGoy1noVRxMzQYb4y/j1Q==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.6.0.tgz", + "integrity": "sha512-UBcpyOX3+RR+dNnqBd0lchXpoL8p4xC21XP8H6Meb8uve5Br1GCnmg0PcBoKKqPKgGu9GHQ/oygcmPrQhetwqw==", "peerDependencies": { "react-hook-form": "^7.0.0" } @@ -990,6 +939,7 @@ "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", @@ -1039,6 +989,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, "node_modules/@isaacs/cliui": { @@ -1068,17 +1019,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1114,22 +1054,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -1205,25 +1129,6 @@ "node": ">=10" } }, - "node_modules/@million/install": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@million/install/-/install-0.0.3.tgz", - "integrity": "sha512-yK8NgP+73+Tby/bmQ12B96bJ7RjsLazLtFgBed1Fg1WfTCCpHTILq79yQMSD/OWgm1tt1NYV4ELaTRM6wZOeAg==", - "dependencies": { - "@antfu/ni": "^0.21.12", - "@axiomhq/js": "1.0.0-rc.3", - "@babel/core": "^7.24.5", - "@babel/types": "^7.23.6", - "@clack/prompts": "^0.7.0", - "cli-high": "^0.4.1", - "diff": "^5.1.0", - "posthog-node": "^3.6.3", - "xycolors": "^0.1.1" - }, - "bin": { - "install": "bin/index.js" - } - }, "node_modules/@million/lint": { "version": "0.0.73", "resolved": "https://registry.npmjs.org/@million/lint/-/lint-0.0.73.tgz", @@ -3372,14 +3277,14 @@ } }, "node_modules/@swc/core": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.7.tgz", - "integrity": "sha512-U4qJRBefIJNJDRCCiVtkfa/hpiZ7w0R6kASea+/KLp+vkus3zcLSB8Ub8SvKgTIxjWpwsKcZlPf5nrv4ls46SQ==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.28.tgz", + "integrity": "sha512-muCdNIqOTURUgYeyyOLYE3ShL8SZO6dw6bhRm6dCvxWzCZOncPc5fB0kjcPXTML+9KJoHL7ks5xg+vsQK+v6ig==", "dev": true, "hasInstallScript": true, "dependencies": { - "@swc/counter": "^0.1.2", - "@swc/types": "0.1.7" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.8" }, "engines": { "node": ">=10" @@ -3389,19 +3294,19 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.5.7", - "@swc/core-darwin-x64": "1.5.7", - "@swc/core-linux-arm-gnueabihf": "1.5.7", - "@swc/core-linux-arm64-gnu": "1.5.7", - "@swc/core-linux-arm64-musl": "1.5.7", - "@swc/core-linux-x64-gnu": "1.5.7", - "@swc/core-linux-x64-musl": "1.5.7", - "@swc/core-win32-arm64-msvc": "1.5.7", - "@swc/core-win32-ia32-msvc": "1.5.7", - "@swc/core-win32-x64-msvc": "1.5.7" + "@swc/core-darwin-arm64": "1.5.28", + "@swc/core-darwin-x64": "1.5.28", + "@swc/core-linux-arm-gnueabihf": "1.5.28", + "@swc/core-linux-arm64-gnu": "1.5.28", + "@swc/core-linux-arm64-musl": "1.5.28", + "@swc/core-linux-x64-gnu": "1.5.28", + "@swc/core-linux-x64-musl": "1.5.28", + "@swc/core-win32-arm64-msvc": "1.5.28", + "@swc/core-win32-ia32-msvc": "1.5.28", + "@swc/core-win32-x64-msvc": "1.5.28" }, "peerDependencies": { - "@swc/helpers": "^0.5.0" + "@swc/helpers": "*" }, "peerDependenciesMeta": { "@swc/helpers": { @@ -3410,9 +3315,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.7.tgz", - "integrity": "sha512-bZLVHPTpH3h6yhwVl395k0Mtx8v6CGhq5r4KQdAoPbADU974Mauz1b6ViHAJ74O0IVE5vyy7tD3OpkQxL/vMDQ==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.28.tgz", + "integrity": "sha512-sP6g63ybzIdOWNDbn51tyHN8EMt7Mb4RMeHQEsXB7wQfDvzhpWB+AbfK6Gs3Q8fwP/pmWIrWW9csKOc1K2Mmkg==", "cpu": [ "arm64" ], @@ -3426,9 +3331,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.7.tgz", - "integrity": "sha512-RpUyu2GsviwTc2qVajPL0l8nf2vKj5wzO3WkLSHAHEJbiUZk83NJrZd1RVbEknIMO7+Uyjh54hEh8R26jSByaw==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.28.tgz", + "integrity": "sha512-Bd/agp/g7QocQG5AuorOzSC78t8OzeN+pCN/QvJj1CvPhvppjJw6e1vAbOR8vO2vvGi2pvtf3polrYQStJtSiA==", "cpu": [ "x64" ], @@ -3442,9 +3347,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.7.tgz", - "integrity": "sha512-cTZWTnCXLABOuvWiv6nQQM0hP6ZWEkzdgDvztgHI/+u/MvtzJBN5lBQ2lue/9sSFYLMqzqff5EHKlFtrJCA9dQ==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.28.tgz", + "integrity": "sha512-Wr3TwPGIveS9/OBWm0r9VAL8wkCR0zQn46J8K01uYCmVhUNK3Muxjs0vQBZaOrGu94mqbj9OXY+gB3W7aDvGdA==", "cpu": [ "arm" ], @@ -3458,9 +3363,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.7.tgz", - "integrity": "sha512-hoeTJFBiE/IJP30Be7djWF8Q5KVgkbDtjySmvYLg9P94bHg9TJPSQoC72tXx/oXOgXvElDe/GMybru0UxhKx4g==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.28.tgz", + "integrity": "sha512-8G1ZwVTuLgTAVTMPD+M97eU6WeiRIlGHwKZ5fiJHPBcz1xqIC7jQcEh7XBkobkYoU5OILotls3gzjRt8CMNyDQ==", "cpu": [ "arm64" ], @@ -3474,9 +3379,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.7.tgz", - "integrity": "sha512-+NDhK+IFTiVK1/o7EXdCeF2hEzCiaRSrb9zD7X2Z7inwWlxAntcSuzZW7Y6BRqGQH89KA91qYgwbnjgTQ22PiQ==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.28.tgz", + "integrity": "sha512-0Ajdzb5Fzvz+XUbN5ESeHAz9aHHSYiQcm+vmsDi0TtPHmsalfnqEPZmnK0zPALPJPLQP2dDo4hELeDg3/c3xgA==", "cpu": [ "arm64" ], @@ -3490,9 +3395,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.7.tgz", - "integrity": "sha512-25GXpJmeFxKB+7pbY7YQLhWWjkYlR+kHz5I3j9WRl3Lp4v4UD67OGXwPe+DIcHqcouA1fhLhsgHJWtsaNOMBNg==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.28.tgz", + "integrity": "sha512-ueQ9VejnQUM2Pt+vT0IAKoF4vYBWUP6n1KHGdILpoGe3LuafQrqu7RoyQ15C7/AYii7hAeNhTFdf6gLbg8cjFg==", "cpu": [ "x64" ], @@ -3506,9 +3411,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.7.tgz", - "integrity": "sha512-0VN9Y5EAPBESmSPPsCJzplZHV26akC0sIgd3Hc/7S/1GkSMoeuVL+V9vt+F/cCuzr4VidzSkqftdP3qEIsXSpg==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.28.tgz", + "integrity": "sha512-G5th8Mg0az8CbY4GQt9/m5hg2Y0kGIwvQBeVACuLQB6q2Y4txzdiTpjmFqUUhEvvl7Klyx1IHvNhfXs3zpt7PA==", "cpu": [ "x64" ], @@ -3522,9 +3427,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.7.tgz", - "integrity": "sha512-RtoNnstBwy5VloNCvmvYNApkTmuCe4sNcoYWpmY7C1+bPR+6SOo8im1G6/FpNem8AR5fcZCmXHWQ+EUmRWJyuA==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.28.tgz", + "integrity": "sha512-JezwCGavZ7CkNXx4yInI4kpb71L0zxzxA9BFlmnsGKEEjVQcKc3hFpmIzfFVs+eotlBUwDNb0+Yo9m6Cb7lllA==", "cpu": [ "arm64" ], @@ -3538,9 +3443,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.7.tgz", - "integrity": "sha512-Xm0TfvcmmspvQg1s4+USL3x8D+YPAfX2JHygvxAnCJ0EHun8cm2zvfNBcsTlnwYb0ybFWXXY129aq1wgFC9TpQ==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.28.tgz", + "integrity": "sha512-q8tW5J4RkOkl7vYShnWS//VAb2Ngolfm9WOMaF2GRJUr2Y/Xeb/+cNjdsNOqea2BzW049D5vdP7XPmir3/zUZw==", "cpu": [ "ia32" ], @@ -3554,9 +3459,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.7.tgz", - "integrity": "sha512-tp43WfJLCsKLQKBmjmY/0vv1slVywR5Q4qKjF5OIY8QijaEW7/8VwPyUyVoJZEnDgv9jKtUTG5PzqtIYPZGnyg==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.28.tgz", + "integrity": "sha512-jap6EiB3wG1YE1hyhNr9KLPpH4PGm+5tVMfN0l7fgKtV0ikgpcEN/YF94tru+z5m2HovqYW009+Evq9dcVGmpg==", "cpu": [ "x64" ], @@ -3576,9 +3481,9 @@ "dev": true }, "node_modules/@swc/types": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.7.tgz", - "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.8.tgz", + "integrity": "sha512-RNFA3+7OJFNYY78x0FYwi1Ow+iF1eF5WvmfY1nXPOEH4R2p/D4Cr1vzje7dNAI2aLFqpv8Wyz4oKSWqIZArpQA==", "dev": true, "dependencies": { "@swc/counter": "^0.1.3" @@ -3656,11 +3561,11 @@ } }, "node_modules/@tanstack/react-virtual": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.0.tgz", - "integrity": "sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.1.tgz", + "integrity": "sha512-jIsuhfgy8GqA67PdWqg73ZB2LFE+HD9hjWL1L6ifEIZVyZVAKpYmgUG4WsKQ005aEyImJmbuimPiEvc57IY0Aw==", "dependencies": { - "@tanstack/virtual-core": "3.5.0" + "@tanstack/virtual-core": "3.5.1" }, "funding": { "type": "github", @@ -3672,9 +3577,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz", - "integrity": "sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.1.tgz", + "integrity": "sha512-046+AUSiDru/V9pajE1du8WayvBKeCvJ2NmKPy/mR8/SbKKrqmSbj7LJBfXE+nSq4f5TBXvnCzu0kcYebI9WdQ==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -4370,9 +4275,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==", + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==", "dev": true }, "node_modules/@types/mathjax": { @@ -4394,9 +4299,9 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "16.18.97", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.97.tgz", - "integrity": "sha512-4muilE1Lbfn57unR+/nT9AFjWk0MtWi5muwCEJqnOvfRQDbSfLCUdN7vCIg8TYuaANfhLOV85ve+FNpiUsbSRg==", + "version": "16.18.98", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.98.tgz", + "integrity": "sha512-fpiC20NvLpTLAzo3oVBKIqBGR6Fx/8oAK/SSf7G+fydnXMY1x4x9RZ6sBXhqKlCU21g2QapUsbLlhv3+a7wS+Q==", "devOptional": true }, "node_modules/@types/prop-types": { @@ -4405,9 +4310,9 @@ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", - "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4482,9 +4387,9 @@ "optional": true }, "node_modules/ace-builds": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.34.0.tgz", - "integrity": "sha512-ZQqoV76wl4guDE5zvEnxCDrvy9gzLAwu7eD4ikYj/Gdlb4+qRLbb+aOFVnweZZRsHh089V0WVaw2NMNuiiEdTw==" + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.35.0.tgz", + "integrity": "sha512-bwDKqjqNccC/MSujqnYTeAS5dIR8UmGLP0R90mvsJY0FRC8NUWBSTfj34+EIzo2NWc/gV8IZTqv4fXaiZJpCtA==" }, "node_modules/acorn": { "version": "8.11.3", @@ -4962,9 +4867,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "funding": [ { "type": "opencollective", @@ -4980,10 +4885,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -5104,9 +5009,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001621", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz", - "integrity": "sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA==", + "version": "1.0.30001632", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz", + "integrity": "sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg==", "funding": [ { "type": "opencollective", @@ -5259,24 +5164,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-high": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cli-high/-/cli-high-0.4.1.tgz", - "integrity": "sha512-fPbkILfCVG6mfxbsJbJZQsKE5JmfgJNlfBxap52XHXjLwPDhs/OMFVFrNR7bqiavZt2r5A80+wiRHzJyzWqwEQ==", - "hasInstallScript": true, - "dependencies": { - "@clack/prompts": "^0.7.0", - "sugar-high": "^0.6.1", - "xycolors": "^0.1.1", - "yargs": "^17.7.2" - }, - "bin": { - "cli-high": "bin/index.js" - }, - "funding": { - "url": "https://github.com/sponsors/xinyao27" - } - }, "node_modules/cli-spinners": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", @@ -5293,19 +5180,6 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -5637,9 +5511,9 @@ } }, "node_modules/daisyui": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.11.1.tgz", - "integrity": "sha512-obT9CUbQdW6eoHwSeT5VwaRrWlwrM4OT5qlfdJ0oQlSIEYhwnEl2+L2fwu5PioLbitwuMdYC2X8I1cyy8Pf6LQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.2.tgz", + "integrity": "sha512-ed3EFwPRLN+9+/MYPRB1pYjk6plRCBMobfBdSeB3voAS81KdL2pCKtbwJfUUpDdOnJ0F8T6oRdVX02P6UCD0Hg==", "dev": true, "dependencies": { "css-selector-tokenizer": "^0.8", @@ -5700,9 +5574,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -5959,9 +5833,9 @@ } }, "node_modules/dompurify": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.4.tgz", - "integrity": "sha512-2gnshi6OshmuKil8rMZuQCGiUF3cUxHY3NGDzUAdUx/NPEe5DVnO8BDoAQouvgwnx0R/+a6jUn36Z0FSdq8vww==" + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz", + "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==" }, "node_modules/dot-case": { "version": "3.0.4", @@ -5989,9 +5863,9 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.780", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.780.tgz", - "integrity": "sha512-NPtACGFe7vunRYzvYqVRhQvsDrTevxpgDKxG/Vcbe0BTNOY+5+/2mOXSw2ls7ToNbE5Bf/+uQbjTxcmwMozpCw==" + "version": "1.4.799", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.799.tgz", + "integrity": "sha512-3D3DwWkRTzrdEpntY0hMLYwj7SeBk1138CkPE8sBDSj3WzrzOiG2rHm3luw8jucpf+WiyLBCZyU9lMHyQI9M9Q==" }, "node_modules/emoji-regex": { "version": "10.3.0", @@ -6726,11 +6600,6 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/fetch-retry": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-6.0.0.tgz", - "integrity": "sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag==" - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -6885,9 +6754,9 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.0.tgz", + "integrity": "sha512-CrWQNaEl1/6WeZoarcM9LHupTo3RpZO2Pdk1vktwzPiQTsJnAKJmm3TACKeG5UZbWDfaH2AbvYxzP96y0MT7fA==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -6956,9 +6825,9 @@ } }, "node_modules/framer-motion": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.6.tgz", - "integrity": "sha512-XUrjjBt57e5YoHQtjwc3eNchFBuHvIgN/cS8SC4oIaAn2J/0+bLanUxXizidJKZVeHJam/JrmMnPRjYMglVn5g==", + "version": "11.2.10", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.10.tgz", + "integrity": "sha512-/gr3PLZUVFCc86a9MqCUboVrALscrdluzTb3yew+2/qKBU8CX6nzs918/SRBRCqaPbx0TZP10CB6yFgK2C5cYQ==", "dependencies": { "tslib": "^2.4.0" }, @@ -7087,14 +6956,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -7135,6 +6996,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "devOptional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -8072,9 +7934,9 @@ } }, "node_modules/jackspeak": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", - "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -8268,9 +8130,9 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "bin": { "jiti": "bin/jiti.js" } @@ -9508,20 +9370,19 @@ } }, "node_modules/million": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/million/-/million-3.1.1.tgz", - "integrity": "sha512-vmI3lyA3IN4QKiB0/M3uDef3lZZvgVUokWtLkc5NvxEnykY+TdSR6xatMMNDJmzMHTneayIOpc/eQu4d9Z/r2w==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/million/-/million-3.1.11.tgz", + "integrity": "sha512-6Vh1s0da0PzSqbbp9Zd8yMTIkOWnvBU4vNJCMHTZPXaY3fZ5h+N7s5croS/RBgjJIHz3WQZnvyNBQz7gQ6cqJg==", "dependencies": { "@babel/core": "^7.23.7", "@babel/types": "^7.23.6", - "@million/install": "^0.0.3", "@rollup/pluginutils": "^5.1.0", "kleur": "^4.1.5", "undici": "^6.3.0", "unplugin": "^1.6.0" }, "bin": { - "million": "packages/cli/dist/index.js" + "million": "cli.js" }, "funding": { "url": "https://github.com/sponsors/aidenybai" @@ -9690,9 +9551,9 @@ } }, "node_modules/nan": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", - "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", "optional": true }, "node_modules/nanoid": { @@ -10051,7 +9912,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-4.0.0.tgz", "integrity": "sha512-4Ispi9I9qYGO4lueiLDhe4q4iK5ERK8reLsuzH6BPaXn53EGaua8H66PXIFGrW897hwjXp+pVLrm/DLxN0RF0A==", - "license": "MIT", "engines": { "node": ">=12" } @@ -10095,15 +9955,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10437,9 +10288,9 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "engines": { "node": ">=14" }, @@ -10651,165 +10502,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pretty-quick": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.3.1.tgz", - "integrity": "sha512-3b36UXfYQ+IXXqex6mCca89jC8u0mYLqFAN5eTQKoXO6oCQYcIVYZEB/5AlBHI7JPYygReM2Vv6Vom/Gln7fBg==", - "dev": true, - "dependencies": { - "execa": "^4.1.0", - "find-up": "^4.1.0", - "ignore": "^5.3.0", - "mri": "^1.2.0", - "picocolors": "^1.0.0", - "picomatch": "^3.0.1", - "tslib": "^2.6.2" - }, - "bin": { - "pretty-quick": "dist/cli.js" - }, - "engines": { - "node": ">=10.13" - }, - "peerDependencies": { - "prettier": "^2.0.0" - } - }, - "node_modules/pretty-quick/node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/pretty-quick/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-quick/node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/pretty-quick/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-quick/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-quick/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/picomatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", - "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -11477,14 +11169,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -11560,6 +11244,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "devOptional": true, "dependencies": { "glob": "^7.1.3" @@ -12369,15 +12054,15 @@ } }, "node_modules/sucrase/node_modules/glob": { - "version": "10.3.16", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.16.tgz", - "integrity": "sha512-JDKXl1DiuuHJ6fVS2FXjownaavciiHNUU4mOvV/B793RLh05vZL1rcPnCSaOgv1hDT6RDlY7AB7ZUvFYAtPgAw==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.11.0" + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" @@ -12390,18 +12075,13 @@ } }, "node_modules/sucrase/node_modules/minipass": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", - "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "engines": { "node": ">=16 || 14 >=14.17" } }, - "node_modules/sugar-high": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/sugar-high/-/sugar-high-0.6.1.tgz", - "integrity": "sha512-kg1qMW7WwJcueXIlHkChL/p2EWY3gf8rQmP6n5nUq2TWVqatqDTMLvViS9WgAjgyTKH5/3/b8sRwWPOOAo1zMA==" - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -12444,9 +12124,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", - "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", + "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -12699,9 +12379,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/type-check": { "version": "0.4.0", @@ -12741,9 +12421,9 @@ } }, "node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", + "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", "dev": true, "funding": [ { @@ -12764,9 +12444,9 @@ } }, "node_modules/undici": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.1.tgz", - "integrity": "sha512-/0BWqR8rJNRysS5lqVmfc7eeOErcOP4tZpATVjJOojjHZ71gSYVAtFhEmadcIjwMIUehh5NFyKGsXCnXIajtbA==", + "version": "6.18.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.2.tgz", + "integrity": "sha512-o/MQLTwRm9IVhOqhZ0NQ9oXax1ygPjw6Vs+Vq/4QRjbOAC3B1GCHy7TYxxbExKlb7bzDRzt9vBWU6BDz0RFfYg==", "engines": { "node": ">=18.17" } @@ -13573,9 +13253,9 @@ } }, "node_modules/webpack-virtual-modules": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz", - "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==" }, "node_modules/whatwg-encoding": { "version": "2.0.0", @@ -13706,16 +13386,16 @@ } }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -13768,35 +13448,62 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { - "color-name": "~1.1.4" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, "node_modules/wrappy": { "version": "1.0.2", @@ -13853,32 +13560,15 @@ "node": ">=0.4" } }, - "node_modules/xycolors": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/xycolors/-/xycolors-0.1.1.tgz", - "integrity": "sha512-BbRKWpz/87nNH4lXp6TbBFUT0QipzmJI7ksQpSpBb3ny8mGJgkiKk36bIr8VqfyTEhasEBsfbp/Cum37fIHnjA==", - "hasInstallScript": true, - "funding": { - "url": "https://github.com/sponsors/xinyao27" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", - "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "bin": { "yaml": "bin.mjs" }, @@ -13886,31 +13576,6 @@ "node": ">= 14" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/src/frontend/package.json b/src/frontend/package.json index efcdd4b43..ca1717f26 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -85,9 +85,6 @@ "format": "npx prettier --write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore", "type-check": "tsc --noEmit --pretty --project tsconfig.json && vite" }, - "simple-git-hooks": { - "pre-commit": "npx pretty-quick --staged" - }, "eslintConfig": { "extends": [ "react-app", @@ -130,7 +127,6 @@ "prettier": "^2.8.8", "prettier-plugin-organize-imports": "^3.2.3", "prettier-plugin-tailwindcss": "^0.3.0", - "pretty-quick": "^3.1.3", "simple-git-hooks": "^2.11.1", "tailwindcss": "^3.3.3", "tailwindcss-dotted-background": "^1.1.0", @@ -138,4 +134,4 @@ "ua-parser-js": "^1.0.37", "vite": "^4.5.2" } -} +} \ No newline at end of file diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 36f2ad9f9..849244999 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -80,7 +80,6 @@ export default function App() { login(user["access_token"]); setUserData(user); setAutoLogin(true); - setLoading(false); fetchAllData(); } }) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 0f2bfbf6b..9a59fb5df 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -1,6 +1,5 @@ import { cloneDeep } from "lodash"; import { ReactNode, useEffect, useRef, useState } from "react"; -import { useHotkeys } from "react-hotkeys-hook"; import { Handle, Position, useUpdateNodeInternals } from "reactflow"; import CodeAreaComponent from "../../../../components/codeAreaComponent"; import DictComponent from "../../../../components/dictComponent"; @@ -18,7 +17,10 @@ import TextAreaComponent from "../../../../components/textAreaComponent"; import ToggleShadComponent from "../../../../components/toggleShadComponent"; import { Button } from "../../../../components/ui/button"; import { RefreshButton } from "../../../../components/ui/refreshButton"; -import { LANGFLOW_SUPPORTED_TYPES } from "../../../../constants/constants"; +import { + LANGFLOW_SUPPORTED_TYPES, + TOOLTIP_EMPTY, +} from "../../../../constants/constants"; import { Case } from "../../../../shared/components/caseComponent"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; @@ -49,8 +51,10 @@ import useHandleNodeClass from "../../../hooks/use-handle-node-class"; import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons"; import HandleTooltips from "../HandleTooltipComponent"; import OutputComponent from "../OutputComponent"; -import OutputModal from "../outputModal"; +import TooltipRenderComponent from "../tooltipRenderComponent"; import { TEXT_FIELD_TYPES } from "./constants"; +import OutputModal from "../outputModal"; +import { useHotkeys } from "react-hotkeys-hook"; export default function ParameterComponent({ left, @@ -71,6 +75,8 @@ export default function ParameterComponent({ selected, outputProxy, }: ParameterComponentType): JSX.Element { + const ref = useRef(null); + const refHtml = useRef(null); const infoHtml = useRef(null); const currentFlow = useFlowsManagerStore((state) => state.currentFlow); const nodes = useFlowStore((state) => state.nodes); @@ -81,13 +87,16 @@ export default function ParameterComponent({ const [isLoading, setIsLoading] = useState(false); const updateNodeInternals = useUpdateNodeInternals(); const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); + const flow = currentFlow?.data?.nodes ?? null; + const groupedEdge = useRef(null); const setFilterEdge = useFlowStore((state) => state.setFilterEdge); const [openOutputModal, setOpenOutputModal] = useState(false); const flowPool = useFlowStore((state) => state.flowPool); - const isValid = + const displayOutputPreview = !!flowPool[data.id] && - flowPool[data.id][flowPool[data.id].length - 1]?.valid; + flowPool[data.id][flowPool[data.id].length - 1]?.valid && + flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.message; const flowPoolNode = (flowPool[data.id] ?? [])[ (flowPool[data.id]?.length ?? 1) - 1 @@ -96,7 +105,6 @@ export default function ParameterComponent({ if (flowPoolNode?.data?.logs && outputName) { hasOutputs = flowPoolNode?.data?.logs[outputName] ?? null; } - const displayOutputPreview = isValid && hasOutputs; const unknownOutput = !!( flowPool[data.id] && flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.type === @@ -157,7 +165,7 @@ export default function ParameterComponent({ const handleOnNewValue = async ( newValue: string | string[] | boolean | Object[], - skipSnapshot: boolean | undefined = false + skipSnapshot: boolean | undefined = false, ): Promise => { handleOnNewValueHook(newValue, skipSnapshot); }; @@ -270,7 +278,7 @@ export default function ParameterComponent({ className={classNames( left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", "h-3 w-3 rounded-full border-2 bg-background", - !showNode ? "mt-0" : "" + !showNode ? "mt-0" : "", )} style={{ borderColor: color ?? nodeColors.unknown, @@ -287,6 +295,7 @@ export default function ParameterComponent({ ) ) : (
templateField.charAt(0) !== "_") .map( (templateField: string, idx) => - data.node!.template[templateField].show && - !data.node!.template[templateField].advanced && ( + data.node!.template[templateField]?.show && + !data.node!.template[templateField]?.advanced && ( 0 - ? data.node.output_types.join("|") + ? data.node.output_types.join(" | ") : data.type } tooltipTitle={data.node?.base_classes.join("\n")} @@ -718,10 +719,11 @@ export default function GenericNode({ .sort((a, b) => sortFields(a, b, data.node?.field_order ?? [])) .map((templateField: string, idx) => (
- {data.node!.template[templateField].show && - !data.node!.template[templateField].advanced ? ( + {data.node!.template[templateField]?.show && + !data.node!.template[templateField]?.advanced ? ( templateField.charAt(0) !== "_") .map((templateCamp) => { const { template } = data.node!; - if (template[templateCamp].input_types) return true; - if (!template[templateCamp].show) return false; - switch (template[templateCamp].type) { + if (template[templateCamp]?.input_types) return true; + if (!template[templateCamp]?.show) return false; + switch (template[templateCamp]?.type) { case "str": case "bool": case "float": diff --git a/src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx b/src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx index 34d41313b..3b5c8ce74 100644 --- a/src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx +++ b/src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx @@ -1,5 +1,9 @@ import { cloneDeep } from "lodash"; import { useEffect } from "react"; +import { + ERROR_UPDATING_COMPONENT, + TITLE_ERROR_UPDATING_COMPONENT, +} from "../../constants/constants"; import useAlertStore from "../../stores/alertStore"; import { ResponseErrorDetailAPI } from "../../types/api"; @@ -38,8 +42,10 @@ const useFetchDataOnMount = ( let responseError = error as ResponseErrorDetailAPI; setErrorData({ - title: "Error while updating the Component", - list: [responseError?.response?.data?.detail ?? "Unknown error"], + title: TITLE_ERROR_UPDATING_COMPONENT, + list: [ + responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT, + ], }); } setIsLoading(false); diff --git a/src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx b/src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx index 1a394cad3..22625d96d 100644 --- a/src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx +++ b/src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx @@ -1,4 +1,8 @@ import { cloneDeep } from "lodash"; +import { + ERROR_UPDATING_COMPONENT, + TITLE_ERROR_UPDATING_COMPONENT, +} from "../../constants/constants"; import useAlertStore from "../../stores/alertStore"; import { ResponseErrorTypeAPI } from "../../types/api"; @@ -42,9 +46,10 @@ const useHandleOnNewValue = ( } catch (error) { let responseError = error as ResponseErrorTypeAPI; setErrorData({ - title: "Error while updating the Component", + title: TITLE_ERROR_UPDATING_COMPONENT, list: [ - responseError?.response?.data?.detail.error ?? "Unknown error", + responseError?.response?.data?.detail.error ?? + ERROR_UPDATING_COMPONENT, ], }); } diff --git a/src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx b/src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx index 14e983ca1..e2ecb3f46 100644 --- a/src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx +++ b/src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx @@ -1,4 +1,8 @@ import { cloneDeep } from "lodash"; +import { + ERROR_UPDATING_COMPONENT, + TITLE_ERROR_UPDATING_COMPONENT, +} from "../../constants/constants"; import useAlertStore from "../../stores/alertStore"; import { ResponseErrorDetailAPI } from "../../types/api"; import { handleUpdateValues } from "../../utils/parameterUtils"; @@ -25,8 +29,10 @@ const useHandleRefreshButtonPress = (setIsLoading, setNode) => { let responseError = error as ResponseErrorDetailAPI; setErrorData({ - title: "Error while updating the Component", - list: [responseError?.response?.data?.detail ?? "Unknown error"], + title: TITLE_ERROR_UPDATING_COMPONENT, + list: [ + responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT, + ], }); } setIsLoading(false); diff --git a/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx b/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx index 682ddb498..d75bf625c 100644 --- a/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx +++ b/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx @@ -70,7 +70,10 @@ export default function AddNewVariableButton({ let responseError = error as ResponseErrorDetailAPI; setErrorData({ title: "Error creating variable", - list: [responseError?.response?.data?.detail ?? "Unknown error"], + list: [ + responseError?.response?.data?.detail ?? + "An unexpected error occurred while adding a new variable. Please try again.", + ], }); }); } diff --git a/src/frontend/src/components/headerComponent/index.tsx b/src/frontend/src/components/headerComponent/index.tsx index 9f927e59c..97ed41264 100644 --- a/src/frontend/src/components/headerComponent/index.tsx +++ b/src/frontend/src/components/headerComponent/index.tsx @@ -36,6 +36,7 @@ export default function Header(): JSX.Element { const location = useLocation(); const { logout, autoLogin, isAdmin, userData } = useContext(AuthContext); + const navigate = useNavigate(); const removeFlow = useFlowsManagerStore((store) => store.removeFlow); const hasStore = useStoreStore((state) => state.hasStore); @@ -208,7 +209,7 @@ export default function Header(): JSX.Element { 0, BACKEND_URL.length - 1 )}${BASE_URL_API}files/profile_pictures/${ - userData?.profile_image ?? "Space/046-rocket.png" + userData?.profile_image ?? "Space/046-rocket.svg" }` ?? profileCircle } className="h-7 w-7 shrink-0 focus-visible:outline-0" @@ -226,7 +227,7 @@ export default function Header(): JSX.Element { 0, BACKEND_URL.length - 1 )}${BASE_URL_API}files/profile_pictures/${ - userData?.profile_image + userData?.profile_image ?? "Space/046-rocket.svg" }` ?? profileCircle } className="h-5 w-5 focus-visible:outline-0 " diff --git a/src/frontend/src/components/inputListComponent/index.tsx b/src/frontend/src/components/inputListComponent/index.tsx index 7b5f87274..e89320dc9 100644 --- a/src/frontend/src/components/inputListComponent/index.tsx +++ b/src/frontend/src/components/inputListComponent/index.tsx @@ -31,7 +31,7 @@ export default function InputListComponent({
1 && editNode ? "my-1" : "", - "flex flex-col gap-3", + "flex flex-col gap-3" )} > {value.map((singleValue, idx) => { diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index fb675d37a..a2c23f3f4 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -853,3 +853,8 @@ export const ALLOWED_IMAGE_INPUT_EXTENSIONS = ["png", "jpg", "jpeg"]; export const FS_ERROR_TEXT = "Please ensure your file has one of the following extensions:"; export const SN_ERROR_TEXT = ALLOWED_IMAGE_INPUT_EXTENSIONS.join(", "); + +export const ERROR_UPDATING_COMPONENT = + "An unexpected error occurred while updating the Component. Please try again."; +export const TITLE_ERROR_UPDATING_COMPONENT = + "Error while updating the Component"; diff --git a/src/frontend/src/contexts/authContext.tsx b/src/frontend/src/contexts/authContext.tsx index 43416f373..1817447f1 100644 --- a/src/frontend/src/contexts/authContext.tsx +++ b/src/frontend/src/contexts/authContext.tsx @@ -42,6 +42,7 @@ export function AuthProvider({ children }): React.ReactElement { const [apiKey, setApiKey] = useState( cookies.get("apikey_tkn_lflw") ); + // const getFoldersApi = useFolderStore((state) => state.getFoldersApi); useEffect(() => { const storedAccessToken = cookies.get("access_token_lf"); @@ -59,11 +60,11 @@ export function AuthProvider({ children }): React.ReactElement { function getUser() { getLoggedUser() - .then((user) => { + .then(async (user) => { setUserData(user); - setLoading(false); const isSuperUser = user!.is_superuser; setIsAdmin(isSuperUser); + // await getFoldersApi(true); }) .catch((error) => { setLoading(false); diff --git a/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx b/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx index 491aaf8a6..3fd28ca4d 100644 --- a/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx +++ b/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx @@ -5,6 +5,7 @@ import CsvOutputComponent from "../../../../components/csvOutputComponent"; import DataOutputComponent from "../../../../components/dataOutputComponent"; import InputListComponent from "../../../../components/inputListComponent"; import PdfViewer from "../../../../components/pdfViewer"; +import RecordsOutputComponent from "../../../../components/recordsOutputComponent"; import { Textarea } from "../../../../components/ui/textarea"; import { PDFViewConstant } from "../../../../constants/constants"; import { InputOutput } from "../../../../constants/enums"; @@ -253,7 +254,7 @@ export default function IOFieldView({ rows={ Array.isArray(flowPoolNode?.data?.artifacts) ? flowPoolNode?.data?.artifacts?.map( - (artifact) => artifact.data + (artifact) => artifact.data, ) ?? [] : [flowPoolNode?.data?.artifacts] } diff --git a/src/frontend/src/modals/IOModal/components/SessionView/index.tsx b/src/frontend/src/modals/IOModal/components/SessionView/index.tsx index ef2c44d44..705e9245d 100644 --- a/src/frontend/src/modals/IOModal/components/SessionView/index.tsx +++ b/src/frontend/src/modals/IOModal/components/SessionView/index.tsx @@ -18,7 +18,7 @@ export default function SessionView({ rows }: { rows: Array }) { setSelectedRows, setSuccessData, setErrorData, - selectedRows, + selectedRows ); const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData); diff --git a/src/frontend/src/modals/IOModal/components/chatView/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/index.tsx index 2e57fb2cb..c6963fadc 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/index.tsx @@ -36,12 +36,6 @@ export default function ChatView({ const outputTypes = outputs.map((obj) => obj.type); const updateFlowPool = useFlowStore((state) => state.updateFlowPool); - // useEffect(() => { - // if (!outputTypes.includes("ChatOutput")) { - // setNoticeData({ title: NOCHATOUTPUT_NOTICE_ALERT }); - // } - // }, []); - //build chat history useEffect(() => { const chatOutputResponses: VertexBuildTypeAPI[] = []; @@ -62,14 +56,24 @@ export default function ChatView({ const chatMessages: ChatMessageType[] = chatOutputResponses .sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp)) // - .filter((output) => output.data.message) + .filter( + (output) => + output.data.message || (!output.data.message && output.artifacts) + ) .map((output, index) => { try { console.log("output:", output); + + const messageOutput = output.data.message; + const hasMessageValue = + messageOutput?.message || + messageOutput?.message === "" || + (messageOutput?.files ?? []).length > 0 || + messageOutput?.stream_url; + const { sender, message, sender_name, stream_url, files } = - output.data.message; - console.log("output.data.message:", output.data.message); - console.log("output.data.message.files:", output.data.message.files); + hasMessageValue ? output.data.message : output.artifacts; + const is_ai = sender === "Machine" || sender === null || sender === undefined; return { @@ -136,26 +140,12 @@ export default function ChatView({ message: string, stream_url?: string ) { - // if (message === "") return; chat.message = message; - // chat is one of the chatHistory updateFlowPool(chat.componentId, { message, sender_name: chat.sender_name ?? "Bot", sender: chat.isSend ? "User" : "Machine", }); - // setChatHistory((oldChatHistory) => { - // const index = oldChatHistory.findIndex((ch) => ch.id === chat.id); - // if (index === -1) return oldChatHistory; - // let newChatHistory = _.cloneDeep(oldChatHistory); - // newChatHistory = [ - // ...newChatHistory.slice(0, index), - // chat, - // ...newChatHistory.slice(index + 1), - // ]; - // console.log("newChatHistory:", newChatHistory); - // return newChatHistory; - // }); } const [files, setFiles] = useState([]); const [isDragging, setIsDragging] = useState(false); @@ -190,44 +180,6 @@ export default function ChatView({ aria-hidden="true" /> - {/* */}
{chatHistory?.length > 0 ? ( diff --git a/src/frontend/src/modals/apiModal/index.tsx b/src/frontend/src/modals/apiModal/index.tsx index 4d9379b0f..ead038ad2 100644 --- a/src/frontend/src/modals/apiModal/index.tsx +++ b/src/frontend/src/modals/apiModal/index.tsx @@ -10,7 +10,7 @@ import IconComponent from "../../components/genericIconComponent"; import { EXPORT_CODE_DIALOG } from "../../constants/constants"; import { AuthContext } from "../../contexts/authContext"; import { useTweaksStore } from "../../stores/tweaksStore"; -import { InputFieldType } from "../../types/api"; +import { TemplateVariableType } from "../../types/api"; import { uniqueTweakType } from "../../types/components"; import { FlowType } from "../../types/flow/index"; import BaseModal from "../baseModal"; @@ -39,7 +39,7 @@ const ApiModal = forwardRef( open?: boolean; setOpen?: (a: boolean | ((o?: boolean) => boolean)) => void; }, - ref + ref, ) => { const tweak = useTweaksStore((state) => state.tweak); const addTweaks = useTweaksStore((state) => state.setTweak); @@ -57,18 +57,18 @@ const ApiModal = forwardRef( flow?.id, autoLogin, tweak, - flow?.endpoint_name + flow?.endpoint_name, ); const curl_run_code = getCurlRunCode( flow?.id, autoLogin, tweak, - flow?.endpoint_name + flow?.endpoint_name, ); const curl_webhook_code = getCurlWebhookCode( flow?.id, autoLogin, - flow?.endpoint_name + flow?.endpoint_name, ); const pythonCode = getPythonCode(flow?.name, tweak); const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin); @@ -83,7 +83,7 @@ const ApiModal = forwardRef( pythonCode, ]; const [tabs, setTabs] = useState( - createTabsArray(codesArray, includeWebhook) + createTabsArray(codesArray, includeWebhook), ); const canShowTweaks = @@ -132,7 +132,7 @@ const ApiModal = forwardRef( buildTweakObject( nodeId, element.data.node.template[templateField].value, - element.data.node.template[templateField] + element.data.node.template[templateField], ); } }); @@ -149,7 +149,7 @@ const ApiModal = forwardRef( async function buildTweakObject( tw: string, changes: string | string[] | boolean | number | Object[] | Object, - template: InputFieldType + template: TemplateVariableType, ) { changes = getChangesType(changes, template); @@ -191,7 +191,7 @@ const ApiModal = forwardRef( flow?.id, autoLogin, cloneTweak, - flow?.endpoint_name + flow?.endpoint_name, ); const pythonCode = getPythonCode(flow?.name, cloneTweak); const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin); @@ -235,7 +235,7 @@ const ApiModal = forwardRef( ); - } + }, ); export default ApiModal; diff --git a/src/frontend/src/modals/apiModal/utils/get-changes-types.ts b/src/frontend/src/modals/apiModal/utils/get-changes-types.ts index 6a35446d5..e8e912ff3 100644 --- a/src/frontend/src/modals/apiModal/utils/get-changes-types.ts +++ b/src/frontend/src/modals/apiModal/utils/get-changes-types.ts @@ -1,9 +1,9 @@ -import { InputFieldType } from "../../../types/api"; +import { TemplateVariableType } from "../../../types/api"; import { convertArrayToObj } from "../../../utils/reactflowUtils"; export const getChangesType = ( changes: string | string[] | boolean | number | Object[] | Object, - template: InputFieldType + template: TemplateVariableType, ) => { if (typeof changes === "string" && template.type === "float") { changes = parseFloat(changes); diff --git a/src/frontend/src/modals/apiModal/utils/get-nodes-with-default-value.ts b/src/frontend/src/modals/apiModal/utils/get-nodes-with-default-value.ts index ea5887fda..dc4fbaffc 100644 --- a/src/frontend/src/modals/apiModal/utils/get-nodes-with-default-value.ts +++ b/src/frontend/src/modals/apiModal/utils/get-nodes-with-default-value.ts @@ -11,10 +11,10 @@ export const getNodesWithDefaultValue = (flow) => { .filter( (templateField) => templateField.charAt(0) !== "_" && - node.data.node.template[templateField].show && + node.data.node.template[templateField]?.show && LANGFLOW_SUPPORTED_TYPES.has( - node.data.node.template[templateField].type - ) + node.data.node.template[templateField].type, + ), ) .map((n, i) => { arrNodesWithValues.push(node["id"]); diff --git a/src/frontend/src/modals/apiModal/utils/get-value.ts b/src/frontend/src/modals/apiModal/utils/get-value.ts index 108ac09e3..df8e5bdde 100644 --- a/src/frontend/src/modals/apiModal/utils/get-value.ts +++ b/src/frontend/src/modals/apiModal/utils/get-value.ts @@ -1,11 +1,11 @@ -import { InputFieldType } from "../../../types/api"; +import { TemplateVariableType } from "../../../types/api"; import { NodeType } from "../../../types/flow"; export const getValue = ( value: string, node: NodeType, - template: InputFieldType, - tweak: Object[] + template: TemplateVariableType, + tweak: Object[], ) => { let returnValue = value ?? ""; diff --git a/src/frontend/src/modals/flowSettingsModal/index.tsx b/src/frontend/src/modals/flowSettingsModal/index.tsx index 022bd9aa0..912097a01 100644 --- a/src/frontend/src/modals/flowSettingsModal/index.tsx +++ b/src/frontend/src/modals/flowSettingsModal/index.tsx @@ -18,7 +18,7 @@ export default function FlowSettingsModal({ useEffect(() => { setName(currentFlow!.name); setDescription(currentFlow!.description); - }, [currentFlow!.name, currentFlow!.description, open]); + }, [currentFlow?.name, currentFlow?.description, open]); const [name, setName] = useState(currentFlow!.name); const [description, setDescription] = useState(currentFlow!.description); @@ -40,6 +40,7 @@ export default function FlowSettingsModal({ list: [err?.response?.data.detail ?? ""], }); console.error(err); + setIsSaving(false); }); } diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index 7c625a6fb..0961ef8e5 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -38,6 +38,7 @@ import { generateNodeFromFlow, getNodeId, isValidConnection, + reconnectEdges, scapeJSONParse, updateIds, validateSelection, @@ -61,19 +62,19 @@ export default function Page({ const preventDefault = true; const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow); const autoSaveCurrentFlow = useFlowsManagerStore( - (state) => state.autoSaveCurrentFlow + (state) => state.autoSaveCurrentFlow, ); const types = useTypesStore((state) => state.types); const templates = useTypesStore((state) => state.templates); const setFilterEdge = useFlowStore((state) => state.setFilterEdge); const reactFlowWrapper = useRef(null); const [showCanvas, setSHowCanvas] = useState( - Object.keys(templates).length > 0 && Object.keys(types).length > 0 + Object.keys(templates).length > 0 && Object.keys(types).length > 0, ); const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance); const setReactFlowInstance = useFlowStore( - (state) => state.setReactFlowInstance + (state) => state.setReactFlowInstance, ); const nodes = useFlowStore((state) => state.nodes); const edges = useFlowStore((state) => state.edges); @@ -90,10 +91,10 @@ export default function Page({ const paste = useFlowStore((state) => state.paste); const resetFlow = useFlowStore((state) => state.resetFlow); const lastCopiedSelection = useFlowStore( - (state) => state.lastCopiedSelection + (state) => state.lastCopiedSelection, ); const setLastCopiedSelection = useFlowStore( - (state) => state.setLastCopiedSelection + (state) => state.setLastCopiedSelection, ); const onConnect = useFlowStore((state) => state.onConnect); const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId); @@ -116,7 +117,7 @@ export default function Page({ clonedSelection!, clonedNodes, clonedEdges, - getRandomName() + getRandomName(), ); const newGroupNode = generateNodeFromFlow(newFlow, getNodeId); // const newEdges = reconnectEdges(newGroupNode, removedEdges); @@ -124,8 +125,8 @@ export default function Page({ ...clonedNodes.filter( (oldNodes) => !clonedSelection?.nodes.some( - (selectionNode) => selectionNode.id === oldNodes.id - ) + (selectionNode) => selectionNode.id === oldNodes.id, + ), ), newGroupNode, ]); @@ -212,7 +213,7 @@ export default function Page({ { x: position.current.x, y: position.current.y, - } + }, ); } } @@ -296,7 +297,7 @@ export default function Page({ useEffect(() => { setSHowCanvas( - Object.keys(templates).length > 0 && Object.keys(types).length > 0 + Object.keys(templates).length > 0 && Object.keys(types).length > 0, ); }, [templates, types]); @@ -305,7 +306,7 @@ export default function Page({ takeSnapshot(); onConnect(params); }, - [takeSnapshot, onConnect] + [takeSnapshot, onConnect], ); const onNodeDragStart: NodeDragHandler = useCallback(() => { @@ -346,7 +347,7 @@ export default function Page({ // Extract the data from the drag event and parse it as a JSON object const data: { type: string; node?: APIClassType } = JSON.parse( - event.dataTransfer.getData("nodedata") + event.dataTransfer.getData("nodedata"), ); const newId = getNodeId(data.type); @@ -362,7 +363,7 @@ export default function Page({ }; paste( { nodes: [newNode], edges: [] }, - { x: event.clientX, y: event.clientY } + { x: event.clientX, y: event.clientY }, ); } else if (event.dataTransfer.types.some((types) => types === "Files")) { takeSnapshot(); @@ -391,7 +392,7 @@ export default function Page({ } }, // Specify dependencies for useCallback - [getNodeId, setNodes, takeSnapshot, paste] + [getNodeId, setNodes, takeSnapshot, paste], ); const onEdgeUpdateStart = useCallback(() => { @@ -407,7 +408,7 @@ export default function Page({ setEdges((els) => updateEdge(oldEdge, newConnection, els)); } }, - [setEdges] + [setEdges], ); const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => { @@ -440,7 +441,7 @@ export default function Page({ (flow: OnSelectionChangeParams): void => { setLastSelection(flow); }, - [] + [], ); const onPaneClick = useCallback((flow) => { diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 8d3097344..8052984f8 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -57,17 +57,17 @@ export default function NodeToolbarComponent({ const nodeLength = Object.keys(data.node!.template).filter( (templateField) => templateField.charAt(0) !== "_" && - data.node?.template[templateField].show && - (data.node.template[templateField].type === "str" || - data.node.template[templateField].type === "bool" || - data.node.template[templateField].type === "float" || - data.node.template[templateField].type === "code" || - data.node.template[templateField].type === "prompt" || - data.node.template[templateField].type === "file" || - data.node.template[templateField].type === "Any" || - data.node.template[templateField].type === "int" || - data.node.template[templateField].type === "dict" || - data.node.template[templateField].type === "NestedDict") + data.node?.template[templateField]?.show && + (data.node.template[templateField]?.type === "str" || + data.node.template[templateField]?.type === "bool" || + data.node.template[templateField]?.type === "float" || + data.node.template[templateField]?.type === "code" || + data.node.template[templateField]?.type === "prompt" || + data.node.template[templateField]?.type === "file" || + data.node.template[templateField]?.type === "Any" || + data.node.template[templateField]?.type === "int" || + data.node.template[templateField]?.type === "dict" || + data.node.template[templateField]?.type === "NestedDict") ).length; const hasStore = useStoreStore((state) => state.hasStore); @@ -626,7 +626,7 @@ export default function NodeToolbarComponent({ /> )} - {(!hasStore || !hasApiKey || !validApiKey) && ( + {/* {(!hasStore || !hasApiKey || !validApiKey) && ( - )} + )} */} - - obj.name === "Download")?.shortcut! - } - value={"Download"} - icon={"Download"} - dataTestId="download-button-modal" - /> - + {(!hasStore || !hasApiKey || !validApiKey) && ( + + obj.name === "Download") + ?.shortcut! + } + value={"Download"} + icon={"Download"} + dataTestId="download-button-modal" + /> + + )} (CONTROL_LOGIN_STATE); const { password, username } = inputState; - const { login, isAuthenticated, setUserData, setIsAdmin } = - useContext(AuthContext); + const { login } = useContext(AuthContext); const navigate = useNavigate(); const setErrorData = useAlertStore((state) => state.setErrorData); diff --git a/src/frontend/src/pages/SettingsPage/pages/GeneralPage/components/ProfilePictureForm/index.tsx b/src/frontend/src/pages/SettingsPage/pages/GeneralPage/components/ProfilePictureForm/index.tsx index 908cea255..935d96c25 100644 --- a/src/frontend/src/pages/SettingsPage/pages/GeneralPage/components/ProfilePictureForm/index.tsx +++ b/src/frontend/src/pages/SettingsPage/pages/GeneralPage/components/ProfilePictureForm/index.tsx @@ -45,9 +45,9 @@ const ProfilePictureFormComponent = ({ } else { prev[folder] = [path]; } + setLoading(false); return prev; }); - setLoading(false); }); } }) diff --git a/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx b/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx index 84f1894dd..59ae0a17a 100644 --- a/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx +++ b/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx @@ -27,7 +27,7 @@ export default function MessagesPage() { setSelectedRows, setSuccessData, setErrorData, - selectedRows, + selectedRows ); const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData); @@ -61,7 +61,7 @@ export default function MessagesPage() { overlayNoRowsTemplate="No data available" onSelectionChanged={(event: SelectionChangedEvent) => { setSelectedRows( - event.api.getSelectedRows().map((row) => row.index), + event.api.getSelectedRows().map((row) => row.index) ); }} rowSelection="multiple" diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 49d94a350..1b6705097 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -177,6 +177,7 @@ export type VertexBuildTypeAPI = { timestamp: string; params: any; messages: ChatOutputType[] | ChatInputType[]; + artifacts: any | ChatOutputType | ChatInputType; }; export type LogType = { diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 5dbfd7b88..d362c7d75 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -75,7 +75,7 @@ export type ParameterComponentType = { info?: string; proxy?: { field: string; id: string }; showNode?: boolean; - index: number; + index?: string; onCloseModal?: (close: boolean) => void; outputName?: string; outputProxy?: OutputFieldProxyType; @@ -511,7 +511,7 @@ export type ChatInputType = { isDragging: boolean; files: FilePreviewType[]; setFiles: ( - files: FilePreviewType[] | ((prev: FilePreviewType[]) => FilePreviewType[]) + files: FilePreviewType[] | ((prev: FilePreviewType[]) => FilePreviewType[]), ) => void; chatValue: string; inputRef: { @@ -614,7 +614,7 @@ export type chatMessagePropsType = { updateChat: ( chat: ChatMessageType, message: string, - stream_url?: string + stream_url?: string, ) => void; }; diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts index f12d582a7..73eb4afce 100644 --- a/src/frontend/src/utils/buildUtils.ts +++ b/src/frontend/src/utils/buildUtils.ts @@ -17,7 +17,7 @@ type BuildVerticesParams = { onBuildUpdate?: ( data: VertexBuildTypeAPI, status: BuildStatus, - buildId: string + buildId: string, ) => void; // Replace any with the actual type if it's not any onBuildComplete?: (allNodesValid: boolean) => void; onBuildError?: (title, list, idList: VertexLayerElementType[]) => void; @@ -55,7 +55,7 @@ export async function updateVerticesOrder( startNodeId?: string | null, stopNodeId?: string | null, nodes?: Node[], - edges?: Edge[] + edges?: Edge[], ): Promise<{ verticesLayers: VertexLayerElementType[][]; verticesIds: string[]; @@ -71,7 +71,7 @@ export async function updateVerticesOrder( startNodeId, stopNodeId, nodes, - edges + edges, ); } catch (error: any) { setErrorData({ @@ -128,7 +128,7 @@ export async function buildVertices({ startNodeId, stopNodeId, nodes, - edges + edges, ); if (onValidateNodes) { try { @@ -162,7 +162,6 @@ export async function buildVertices({ const currentLayer = useFlowStore.getState().verticesBuild?.verticesLayers![currentLayerIndex]; // If there are no more layers, we are done - console.log("currentLayer", currentLayer); if (!currentLayer) { if (onBuildComplete) { const allNodesValid = buildResults.every((result) => result); @@ -191,14 +190,14 @@ export async function buildVertices({ onBuildUpdate( getInactiveVertexData(element.id), BuildStatus.INACTIVE, - runId + runId, ); } if (element.reference) { onBuildUpdate( getInactiveVertexData(element.reference), BuildStatus.INACTIVE, - runId + runId, ); } buildResults.push(false); @@ -224,7 +223,7 @@ export async function buildVertices({ if (stop) { return; } - }) + }), ); // Once the current layer is built, move to the next layer currentLayerIndex += 1; @@ -289,7 +288,10 @@ async function buildVertex({ console.error(error); onBuildError!( "Error Building Component", - [(error as AxiosError).response?.data?.detail ?? "Unknown Error"], + [ + (error as AxiosError).response?.data?.detail ?? + "An unexpected error occurred while building the Component. Please try again.", + ], verticesIds.map((id) => ({ id })) ); stopBuild(); diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index aaae69c7b..b16cb37ae 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -237,13 +237,13 @@ export function groupByFamily( const checkBaseClass = (template: InputFieldType) => { return ( - template.type && - template.show && + template?.type && + template?.show && ((!excludeTypes.has(template.type) && baseClassesSet.has(template.type)) || - (template.input_types && - template.input_types.some((inputType) => - baseClassesSet.has(inputType), + (template?.input_types && + template?.input_types.some((inputType) => + baseClassesSet.has(inputType) ))) ); }; diff --git a/src/frontend/tests/end-to-end/chatInputOutput.spec.ts b/src/frontend/tests/end-to-end/chatInputOutput.spec.ts index a1429ddec..bdba4ba50 100644 --- a/src/frontend/tests/end-to-end/chatInputOutput.spec.ts +++ b/src/frontend/tests/end-to-end/chatInputOutput.spec.ts @@ -24,31 +24,59 @@ test("chat_io_teste", async ({ page }) => { const jsonContent = readFileSync( "src/frontend/tests/end-to-end/assets/ChatTest.json", - "utf-8" + "utf-8", ); await page.getByTestId("blank-flow").click(); - await page.waitForTimeout(2000); + await page.waitForTimeout(3000); + await page.getByTestId("extended-disclosure").click(); + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("chat output"); + await page.waitForTimeout(1000); - // Create the DataTransfer and File - const dataTransfer = await page.evaluateHandle((data) => { - const dt = new DataTransfer(); - // Convert the buffer to a hex array - const file = new File([data], "ChatTest.json", { - type: "application/json", - }); - dt.items.add(file); - return dt; - }, jsonContent); + await page + .getByTestId("outputsChat Output") + .dragTo(page.locator('//*[@id="react-flow-id"]')); + await page.mouse.up(); + await page.mouse.down(); + + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("chat input"); + await page.waitForTimeout(1000); + + await page + .getByTestId("inputsChat Input") + .dragTo(page.locator('//*[@id="react-flow-id"]')); + await page.mouse.up(); + await page.mouse.down(); + + await page.getByTitle("fit view").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + await page.getByTitle("zoom out").click(); + + // Click and hold on the first element + await page + .locator( + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[10]/button/div/div' + ) + .hover(); + await page.mouse.down(); + + // Move to the second element + await page + .locator( + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[4]/div/button/div/div' + ) + .hover(); + + // Release the mouse + await page.mouse.up(); - // Now dispatch - await page.dispatchEvent( - '//*[@id="react-flow-id"]/div[1]/div[1]/div', - "drop", - { - dataTransfer, - } - ); await page.getByLabel("fit view").click(); await page.getByText("Playground", { exact: true }).click(); await page.getByPlaceholder("Send a message...").click(); diff --git a/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts b/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts index 1b27fa11f..89a066415 100644 --- a/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts +++ b/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts @@ -58,8 +58,13 @@ test("user must interact with chat with Input/Output", async ({ page }) => { .fill( "testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!" ); + await page.getByText("Playground", { exact: true }).last().click(); await page.getByTestId("icon-LucideSend").click(); await page.getByText("Close", { exact: true }).click(); + await page.getByText("Chat Input", { exact: true }).click(); + await page.getByTestId("advanced-button-modal").click(); + await page.getByTestId("showsender_name").click(); + await page.getByText("Save Changes", { exact: true }).click(); await page .getByTestId("popover-anchor-input-sender_name") diff --git a/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts b/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts index 577c138a3..6d9ac2d02 100644 --- a/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts +++ b/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts @@ -40,6 +40,7 @@ test("CodeAreaModalComponent", async ({ page }) => { await page.getByTitle("zoom out").click(); await page.getByTitle("zoom out").click(); await page.getByTestId("div-generic-node").click(); + await page.getByTestId("code-button-modal").click(); const wCode = diff --git a/src/frontend/tests/end-to-end/floatComponent.spec.ts b/src/frontend/tests/end-to-end/floatComponent.spec.ts index aacd7e1a2..66449c146 100644 --- a/src/frontend/tests/end-to-end/floatComponent.spec.ts +++ b/src/frontend/tests/end-to-end/floatComponent.spec.ts @@ -71,22 +71,12 @@ test("FloatComponent", async ({ page }) => { await page.getByTestId("showmirostat").click(); expect( - await page.locator('//*[@id="showmirostat"]').isChecked() + await page.locator('//*[@id="showmirostat"]').isChecked(), ).toBeTruthy(); await page.getByTestId("showmirostat_eta").click(); expect( - await page.locator('//*[@id="showmirostat"]').isChecked() - ).toBeTruthy(); - - await page.getByTestId("showmirostat_eta").click(); - expect( - await page.locator('//*[@id="showmirostat"]').isChecked() - ).toBeTruthy(); - - await page.getByTestId("showmirostat_eta").click(); - expect( - await page.locator('//*[@id="showmirostat_eta"]').isChecked() + await page.locator('//*[@id="showmirostat_eta"]').isChecked(), ).toBeTruthy(); await page.getByTestId("showmirostat_eta").click(); @@ -96,12 +86,12 @@ test("FloatComponent", async ({ page }) => { await page.getByTestId("showmirostat_tau").click(); expect( - await page.locator('//*[@id="showmirostat_tau"]').isChecked() + await page.locator('//*[@id="showmirostat_tau"]').isChecked(), ).toBeTruthy(); await page.getByTestId("showmirostat_tau").click(); expect( - await page.locator('//*[@id="showmirostat_tau"]').isChecked() + await page.locator('//*[@id="showmirostat_tau"]').isChecked(), ).toBeFalsy(); await page.getByTestId("showmodel").click(); @@ -124,22 +114,22 @@ test("FloatComponent", async ({ page }) => { await page.getByTestId("shownum_thread").click(); expect( - await page.locator('//*[@id="shownum_thread"]').isChecked() + await page.locator('//*[@id="shownum_thread"]').isChecked(), ).toBeTruthy(); await page.getByTestId("shownum_thread").click(); expect( - await page.locator('//*[@id="shownum_thread"]').isChecked() + await page.locator('//*[@id="shownum_thread"]').isChecked(), ).toBeFalsy(); await page.getByTestId("showrepeat_last_n").click(); expect( - await page.locator('//*[@id="showrepeat_last_n"]').isChecked() + await page.locator('//*[@id="showrepeat_last_n"]').isChecked(), ).toBeTruthy(); await page.getByTestId("showrepeat_last_n").click(); expect( - await page.locator('//*[@id="showrepeat_last_n"]').isChecked() + await page.locator('//*[@id="showrepeat_last_n"]').isChecked(), ).toBeFalsy(); await page.getByText("Save Changes", { exact: true }).click(); @@ -155,7 +145,7 @@ test("FloatComponent", async ({ page }) => { // showtemperature await page.locator('//*[@id="showtemperature"]').click(); expect( - await page.locator('//*[@id="showtemperature"]').isChecked() + await page.locator('//*[@id="showtemperature"]').isChecked(), ).toBeTruthy(); await page.getByText("Save Changes", { exact: true }).click();