diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index f84dead6b..bc7f9efb3 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -21,12 +21,14 @@ on: - main env: POETRY_VERSION: "1.8.2" + TEST_TAG: "langflowai/langflow:test" jobs: setup: runs-on: ubuntu-latest outputs: tags: ${{ steps.set-vars.outputs.tags }} + file: ${{ steps.set-vars.outputs.file }} steps: - uses: actions/checkout@v4 - name: Set Dockerfile and Tags @@ -34,16 +36,22 @@ jobs: run: | if [[ "${{ inputs.release_type }}" == "base" ]]; then echo "tags=langflowai/langflow:base-${{ inputs.version }}" >> $GITHUB_OUTPUT + echo "file=./docker/build_and_push_base.Dockerfile" >> $GITHUB_OUTPUT else echo "tags=langflowai/langflow:${{ inputs.version }},langflowai/langflow:1.0-alpha" >> $GITHUB_OUTPUT + echo "file=./docker/build_and_push.Dockerfile" >> $GITHUB_OUTPUT fi - build_base: + build: runs-on: ubuntu-latest needs: setup strategy: matrix: platform: [linux/amd64, linux/arm64/v8] - file: [./docker/build_and_push.Dockerfile, ./docker/build_and_push_base.Dockerfile] + file: + [ + ./docker/build_and_push.Dockerfile, + ./docker/build_and_push_base.Dockerfile + ] steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx @@ -53,19 +61,39 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push Base Image + # - name: Build Docker Image + # uses: docker/build-push-action@v5 + # id: docker_build + # with: + # context: . + # push: false # Do not push yet + # platforms: "linux/amd64,linux/arm64/v8" + # load: true + # file: ${{ matrix.file }} + # tags: ${{ env.TEST_TAG }} + # - name: Run Container + # run: | + # docker run -d --name test_container -p 8000:8000 ${{ needs.setup.outputs.tags }} + # - name: Wait for Container to Start and Check Health + # run: | + # timeout 40 bash -c 'until curl -f http://127.0.0.1:8000/health; do sleep 1; done' || (echo "Server did not start in time" && docker logs test_container && docker stop test_container && docker rm test_container && exit 1) + # - name: Stop and Remove Container + # run: | + # docker stop test_container + # docker rm test_container + - name: Build and Push Docker Image uses: docker/build-push-action@v5 with: context: . push: true - platforms: ${{ matrix.platform }} - file: ${{ matrix.file }} + platforms: "linux/amd64,linux/arm64/v8" + file: ${{ needs.setup.outputs.file }} tags: ${{ needs.setup.outputs.tags }} build_components: if: ${{ inputs.release_type == 'main' }} runs-on: ubuntu-latest - needs: build_base + needs: build strategy: matrix: component: [backend, frontend] @@ -85,6 +113,8 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Wait for Docker Hub to propagate (for backend) + run: sleep 120 - name: Build and push ${{ matrix.component }} uses: docker/build-push-action@v5 with: @@ -100,7 +130,7 @@ jobs: name: Restart HuggingFace Spaces if: ${{ inputs.release_type == 'main' }} runs-on: ubuntu-latest - needs: build_base + needs: build strategy: matrix: python-version: diff --git a/.github/workflows/lint-js.yml b/.github/workflows/lint-js.yml index 84823b885..300903288 100644 --- a/.github/workflows/lint-js.yml +++ b/.github/workflows/lint-js.yml @@ -35,7 +35,7 @@ jobs: - name: Install Node.js dependencies run: | cd src/frontend - npm ci + npm install if: ${{ steps.setup-node.outputs.cache-hit != 'true' }} - name: Run linters @@ -45,7 +45,9 @@ jobs: auto_fix: true git_email: "gabriel@langflow.org" # Enable linters - eslint: true + # eslint: true + # eslint_auto_fix: true prettier: true + prettier_auto_fix: true prettier_args: '--write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore' diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 286a7a921..85a12f978 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -62,6 +62,27 @@ jobs: else make build main=true fi + - name: Test CLI + run: | + if [ "${{ inputs.release_type }}" == "base" ]; then + python -m pip install src/backend/base/dist/*.whl + else + python -m pip install dist/*.whl + fi + python -m langflow run --host 127.0.0.1 --port 7860 & + SERVER_PID=$! + # Wait for the server to start + timeout 40 bash -c 'until curl -f http://127.0.0.1:7860/health; do sleep 1; done' || (echo "Server did not start in time" && kill $SERVER_PID && exit 1) + # Terminate the server + kill $SERVER_PID || (echo "Failed to terminate the server" && exit 1) + sleep 10 # give the server some time to terminate + # Check if the server is still running + if kill -0 $SERVER_PID 2>/dev/null; then + echo "Failed to terminate the server" + exit 1 + else + echo "Server terminated successfully" + fi - name: Publish to PyPI env: POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/python_test.yml b/.github/workflows/python_test.yml index dac1d4f6a..9a8ef15c8 100644 --- a/.github/workflows/python_test.yml +++ b/.github/workflows/python_test.yml @@ -42,4 +42,4 @@ jobs: poetry install - name: Run unit tests run: | - make tests args="-n auto" + make unit_tests args="-n auto" diff --git a/.github/workflows/style-check-py.yml b/.github/workflows/style-check-py.yml index 4063cd48d..217dc5aa8 100644 --- a/.github/workflows/style-check-py.yml +++ b/.github/workflows/style-check-py.yml @@ -13,6 +13,7 @@ env: jobs: lint: + name: Ruff Style Check runs-on: ubuntu-latest strategy: matrix: diff --git a/.gitignore b/.gitignore index 749eff4d3..243628fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -271,4 +271,4 @@ prof/* src/frontend/temp *.db-shm -*.db-wal \ No newline at end of file +*.db-wal diff --git a/Makefile b/Makefile index 88487d312..a305ed807 100644 --- a/Makefile +++ b/Makefile @@ -55,9 +55,11 @@ coverage: ## run the tests and generate a coverage report # allow passing arguments to pytest -tests: ## run the tests - poetry run pytest tests --instafail -ra -n auto -m "not api_key_required" $(args) +unit_tests: + poetry run pytest tests/unit --instafail -ra -n auto -m "not api_key_required" $(args) +integration_tests: + poetry run pytest tests/integration --instafail -ra -n auto $(args) format: ## run code formatters poetry run ruff check . --fix diff --git a/docs/docs/contributing/how-contribute.md b/docs/docs/contributing/how-contribute.md index ba9223fec..ff0df55a6 100644 --- a/docs/docs/contributing/how-contribute.md +++ b/docs/docs/contributing/how-contribute.md @@ -15,7 +15,7 @@ Please do not try to push directly to this repo unless you are a maintainer. You can develop Langflow using docker compose, or locally. -We provide a .vscode/launch.json file for debugging the backend in VSCode, which is a lot faster than using docker compose. +We provide a `.vscode/launch.json` file for debugging the backend in VSCode, which is a lot faster than using docker compose. Setting up hooks: diff --git a/docs/docs/getting-started/canvas.mdx b/docs/docs/getting-started/canvas.mdx index 5fe03715b..7771746a7 100644 --- a/docs/docs/getting-started/canvas.mdx +++ b/docs/docs/getting-started/canvas.mdx @@ -84,7 +84,7 @@ To debug, hover over the component status to see the outputs. ### Component Parameters -Langflow components can be edited by clicking the component settings button. Hide parameters to reduce complexity and keep the canvas clean and intuitive for experimentation. +Langflow components can be edited by clicking the component settings button.
+Hide parameters with the **SHOW** button to reduce complexity and keep the canvas clean and intuitive for experimentation. + +Double-click the component name to rename it. + ### Component menu Each component is a little unique, but they will all have a menu bar on top that looks something like this. diff --git a/docs/docs/migration/migrating-to-one-point-zero.mdx b/docs/docs/migration/migrating-to-one-point-zero.mdx index 6b608adcf..3d83c8d21 100644 --- a/docs/docs/migration/migrating-to-one-point-zero.mdx +++ b/docs/docs/migration/migrating-to-one-point-zero.mdx @@ -32,49 +32,49 @@ We have a special channel in our Discord server dedicated to Langflow 1.0 migrat Langflow 1.0 introduces adds the concept of Inputs and Outputs to flows, allowing a clear definition of the data flow between components. Discover how to use Inputs and Outputs to pass data between components and create more dynamic flows. -[Learn more about Inputs and Outputs of Components](../components/inputs-and-outputs) +[Learn more about Inputs and Outputs](../components/inputs-and-outputs.mdx) -## To Compose or Not to Compose: the choice is yours +## To Compose or Not to Compose: The Choice is Yours Even though composition is still possible in Langflow 1.0, the new standard is getting data moving through the flow. This allows for more flexibility and control over the data flow in your projects. -We will create guides on how to interweave LangChain components with our Core components soon. +[See our example components](../examples/create-record.mdx) for examples of interweaving LangChain components with our Core components. ## Continued Support for LangChain and Multiple Frameworks Langflow 1.0 continues to support LangChain while also introducing support for multiple frameworks. This is another important boon that adding the paradigm of data flow brings to the table. Find out how to leverage the power of different frameworks in your projects. -**Guide coming soon** +[Learn more about compatibility and updating existing flows](./compatibility.mdx) ## Sidebar Redesign and Customizable Playground We've expanded on the chat experience by creating a customizable interaction panel that allows you to design a panel that fits your needs and interact with it. The sidebar has also been redesigned to provide a more intuitive and user-friendly experience. Explore the new sidebar and interaction panel features to enhance your workflow. -**Guide coming soon** +[Learn more about the Playground](../administration/playground.mdx) ## New Native Categories and Components Langflow 1.0 introduces many new native categories, including Inputs, Outputs, Helpers, Experimental, Models, and more. Discover the new components available, such as Chat Input, Prompt, Files, API Request, and others. -**Guide coming soon** +[Learn more about new components](../components/inputs-and-outputs.mdx) ## New Way of Using Langflow: Text and Data (and more to come) With the introduction of Text and Data types connections between Components are more intuitive and easier to understand. This is the first step in a series of improvements to the way you interact with Langflow. Learn how to use Text, and Data and how they help you build better flows. -[Learn more about Text and Data](../components/text-and-record) +[Learn more about Text and Record](../components/text-and-record.mdx) ## CustomComponent for All Components Almost all components in Langflow 1.0 are now CustomComponents, allowing you to check and modify the code of each component. Discover how to leverage this feature to customize your components to your specific needs. -**Guide coming soon** +[Learn more about CustomComponents](../components/custom.mdx) ## Compatibility with Previous Versions To use flows built in previous versions of Langflow, you can utilize the experimental component Runnable Executor along with an Input and Output. **We'd love your feedback on this**. Learn how to adapt your existing flows to work seamlessly in the new version of Langflow. -[Learn more about Compatibility with Previous Versions](../migration/compatibility) +[Learn more about Compatibility with Previous Versions](./compatibility.mdx) ## Multiple Flows in the Canvas @@ -86,25 +86,25 @@ Langflow 1.0 allows you to have more than one flow in the canvas and run them se Each component now displays its status more clearly, allowing you to quickly identify any issues or errors. Explore how to use the new component status feature to troubleshoot and optimize your flows. -**Guide coming soon** +[Learn more about Component Status](../getting-started/canvas.mdx#component) ## Connecting Output Components You can now connect Output components to any other component (that has a Text output), providing a better understanding of the data flow. Explore the possibilities of connecting Output components and how it enhances your flow's functionality. -**Guide coming soon** +[Learn more about Inputs and Outputs](../components/inputs-and-outputs.mdx) ## Renaming and Editing Component Descriptions Langflow 1.0 allows you to rename and edit the description of each component, making it easier to understand and interact with the flow. Learn how to customize your component names and descriptions for improved clarity. -**Guide coming soon** +[Learn more about Component Descriptions](../getting-started/canvas.mdx#component-parameters) ## Passing Tweaks and Inputs in the API Things got a whole lot easier. You can now pass tweaks and inputs in the API by referencing the Display Name of the component. Discover how to leverage this feature to dynamically control your flow's behavior. -**Guide coming soon** +[Learn more about Tweaks and API inputs](../getting-started/canvas.mdx#tweaks) ## Global Variables for Text Fields @@ -116,11 +116,11 @@ Global Variables can be used in any Text Field across your projects. Learn how t Explore the experimental components available in Langflow 1.0, such as SubFlow, which allows you to load a flow as a component dynamically, and Flow as Tool, which enables you to use a flow as a tool for an Agent. -**Guide coming soon** +[Learn more about Experimental Components](../components/experimental.mdx) ## Experimental State Management System -We are experimenting with a State Management system for flows that allows components to trigger other components and pass messages between them using the Notify and Listen components. Discover how to leverage this system to create more dynamic and interactive flows. +We are experimenting with a State Management system for flows that allow components to trigger other components and pass messages between them using the Notify and Listen components. Discover how to leverage this system to create more dynamic and interactive flows. **Guide coming soon** diff --git a/docs/docs/tutorials/rag-with-astradb.mdx b/docs/docs/tutorials/rag-with-astradb.mdx index 181f5677c..867c32f53 100644 --- a/docs/docs/tutorials/rag-with-astradb.mdx +++ b/docs/docs/tutorials/rag-with-astradb.mdx @@ -14,7 +14,7 @@ In this guide, we will use Astra DB as a vector store to store and retrieve the This guide assumes that you have Langflow up and running. If you are new to Langflow, you can check out the [Getting - Started](../getting-started/install-langflow.mdx) guide. + Started](../getting-started/install-langflow) guide. TLDR; @@ -41,7 +41,7 @@ Once you have created an account, you will be taken to the Astra DB dashboard. C alt="Docusaurus themed image" sources={{ light: "img/astra-create-database.png", - dark: "img/astra-create-database.png", + dark: "img/astra-create-database.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -54,7 +54,7 @@ After you have configured your database, click on the **Create Database** button alt="Docusaurus themed image" sources={{ light: "img/astra-configure-deployment.png", - dark: "img/astra-configure-deployment.png", + dark: "img/astra-configure-deployment.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -65,7 +65,7 @@ Once your database is initialized, to the right of the page, you will see the _D alt="Docusaurus themed image" sources={{ light: "img/astra-generate-token.png", - dark: "img/astra-generate-token.png", + dark: "img/astra-generate-token.png" }} style={{ width: "50%", margin: "20px auto" }} /> @@ -97,7 +97,7 @@ The ingestion flow consists of: alt="Docusaurus themed image" sources={{ light: "img/astra-ingestion-flow.png", - dark: "img/astra-ingestion-flow.png", + dark: "img/astra-ingestion-flow.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -108,7 +108,7 @@ Now, let's update the **Astra DB** and **Astra DB Search** components with the * alt="Docusaurus themed image" sources={{ light: "img/astra-ingestion-fields.png", - dark: "img/astra-ingestion-fields.png", + dark: "img/astra-ingestion-fields.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -119,7 +119,7 @@ And run it! This will ingest the Text data from your file into the Astra DB data alt="Docusaurus themed image" sources={{ light: "img/astra-ingestion-run.png", - dark: "img/astra-ingestion-run.png", + dark: "img/astra-ingestion-run.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -141,23 +141,23 @@ The RAG flow is a bit more complex. It consists of: alt="Docusaurus themed image" sources={{ light: "img/astra-rag-flow.png", - dark: "img/astra-rag-flow.png", + dark: "img/astra-rag-flow.png" }} style={{ width: "80%", margin: "20px auto" }} /> -To run it all we have to do is click on the 🤖 _Playground_ button and start interacting with your RAG application. +To run it all we have to do is click on the **![Playground icon](/logos/botmessage.svg)Playground** button and start interacting with your RAG application. -This opens the Playground where you can chat your data. +This opens the Playground where you can chat with your data. Because this flow has a **Chat Input** and a **Text Output** component, the Panel displays a chat input at the bottom and the Extracted Chunks section on the left. @@ -165,7 +165,7 @@ Because this flow has a **Chat Input** and a **Text Output** component, the Pane alt="Docusaurus themed image" sources={{ light: "img/astra-rag-flow-interaction-panel.png", - dark: "img/astra-rag-flow-interaction-panel.png", + dark: "img/astra-rag-flow-interaction-panel.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -176,7 +176,7 @@ Once we interact with it we get a response and the Extracted Chunks section is u alt="Docusaurus themed image" sources={{ light: "img/astra-rag-flow-interaction-panel-interaction.png", - dark: "img/astra-rag-flow-interaction-panel-interaction.png", + dark: "img/astra-rag-flow-interaction-panel-interaction.png" }} style={{ width: "80%", margin: "20px auto" }} /> @@ -189,13 +189,4 @@ In this guide, we have learned how to run a RAG application using Astra DB and L We have seen how to create an Astra DB database, import the Astra DB RAG Flows project into Langflow, and run the ingestion and RAG flows.import ThemedImage from "@theme/ThemedImage"; import useBaseUrl from "@docusaurus/useBaseUrl"; import ZoomableImage from "/src/theme/ZoomableImage.js"; -import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; -import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; -import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; import Admonition from "@theme/Admonition"; diff --git a/poetry.lock b/poetry.lock index 187c62217..179e06ab6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -167,12 +167,13 @@ files = [ [[package]] name = "anthropic" -version = "0.28.0" +version = "0.28.1" description = "The official Python library for the anthropic API" optional = false python-versions = ">=3.7" files = [ - {file = "anthropic-0.28.0-py3-none-any.whl", hash = "sha256:2b620b21aee3d20c5d8005483c34df239d53ae895687113b26b8a36892a7e20f"}, + {file = "anthropic-0.28.1-py3-none-any.whl", hash = "sha256:c4773ae2b42951a6b747bed328b0d03fa412938c95c3a8b9dce70d69badb710b"}, + {file = "anthropic-0.28.1.tar.gz", hash = "sha256:e3a6d595bde241141bdc685edc393903ec95c7fa378013a71186cfb8f32b1793"}, ] [package.dependencies] @@ -471,17 +472,17 @@ files = [ [[package]] name = "boto3" -version = "1.34.126" +version = "1.34.127" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.126-py3-none-any.whl", hash = "sha256:7f676daef674fe74f34ce4063228eccc6e60c811f574720e31f230296c4bf29a"}, - {file = "boto3-1.34.126.tar.gz", hash = "sha256:7e8418b47dd43954a9088d504541bed8a42b6d06e712d02befba134c1c4d7c6d"}, + {file = "boto3-1.34.127-py3-none-any.whl", hash = "sha256:d370befe4fb7aea5bc383057d7dad18dda5d0cf3cd3295915bcc8c8c4191905c"}, + {file = "boto3-1.34.127.tar.gz", hash = "sha256:58ccdeae3a96811ecc9d5d866d8226faadbd0ee1891756e4a04d5186e9a57a64"}, ] [package.dependencies] -botocore = ">=1.34.126,<1.35.0" +botocore = ">=1.34.127,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -490,13 +491,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.126" +version = "1.34.127" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.126-py3-none-any.whl", hash = "sha256:7eff883c638fe30e0b036789df32d851e093d12544615a3b90062b42ac85bdbc"}, - {file = "botocore-1.34.126.tar.gz", hash = "sha256:7a8ccb6a7c02456757a984a3a44331b6f51c94cb8b9b287cd045122fd177a4b0"}, + {file = "botocore-1.34.127-py3-none-any.whl", hash = "sha256:e14fa28c8bb141de965e700f88b196d17c67a703c7f0f5c7e14f7dd1cf636011"}, + {file = "botocore-1.34.127.tar.gz", hash = "sha256:a377871742c40603d559103f19acb7bc93cfaf285e68f21b81637ec396099877"}, ] [package.dependencies] @@ -2437,8 +2438,8 @@ files = [ [package.dependencies] cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} greenlet = [ - {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}, {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""}, + {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}, ] "zope.event" = "*" "zope.interface" = "*" @@ -2597,12 +2598,12 @@ files = [ google-auth = ">=2.14.1,<3.0.dev0" googleapis-common-protos = ">=1.56.2,<2.0.dev0" grpcio = [ - {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, + {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, ] grpcio-status = [ - {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, + {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, ] proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" @@ -4113,19 +4114,19 @@ adal = ["adal (>=1.0.2)"] [[package]] name = "langchain" -version = "0.2.4" +version = "0.2.5" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.4-py3-none-any.whl", hash = "sha256:a04813215c30f944df006031e2febde872af8fab628dcee825d969e07b6cd621"}, - {file = "langchain-0.2.4.tar.gz", hash = "sha256:e704b5b06222d5eba2d02c76f891321d1bac8952ed54e093831b2bdabf99dcd5"}, + {file = "langchain-0.2.5-py3-none-any.whl", hash = "sha256:9aded9a65348254e1c93dcdaacffe4d1b6a5e7f74ef80c160c88ff78ad299228"}, + {file = "langchain-0.2.5.tar.gz", hash = "sha256:ffdbf4fcea46a10d461bcbda2402220fcfd72a0c70e9f4161ae0510067b9b3bd"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -langchain-core = ">=0.2.6,<0.3.0" +langchain-core = ">=0.2.7,<0.3.0" langchain-text-splitters = ">=0.2.0,<0.3.0" langsmith = ">=0.1.17,<0.2.0" numpy = [ @@ -4204,22 +4205,25 @@ langchain-core = ">=0.1.42,<0.3" [[package]] name = "langchain-community" -version = "0.2.4" +version = "0.2.5" description = "Community contributed LangChain integrations." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_community-0.2.4-py3-none-any.whl", hash = "sha256:8582e9800f4837660dc297cccd2ee1ddc1d8c440d0fe8b64edb07620f0373b0e"}, - {file = "langchain_community-0.2.4.tar.gz", hash = "sha256:2bb6a1a36b8500a564d25d76469c02457b1a7c3afea6d4a609a47c06b993e3e4"}, + {file = "langchain_community-0.2.5-py3-none-any.whl", hash = "sha256:bf37a334952e42c7676d083cf2d2c4cbfbb7de1949c4149fe19913e2b06c485f"}, + {file = "langchain_community-0.2.5.tar.gz", hash = "sha256:476787b8c8c213b67e7b0eceb53346e787f00fbae12d8e680985bd4f93b0bf64"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" dataclasses-json = ">=0.5.7,<0.7" -langchain = ">=0.2.0,<0.3.0" -langchain-core = ">=0.2.0,<0.3.0" +langchain = ">=0.2.5,<0.3.0" +langchain-core = ">=0.2.7,<0.3.0" langsmith = ">=0.1.0,<0.2.0" -numpy = ">=1,<2" +numpy = [ + {version = ">=1,<2", markers = "python_version < \"3.12\""}, + {version = ">=1.26.0,<2.0.0", markers = "python_version >= \"3.12\""}, +] PyYAML = ">=5.3" requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" @@ -4227,13 +4231,13 @@ tenacity = ">=8.1.0,<9.0.0" [[package]] name = "langchain-core" -version = "0.2.6" +version = "0.2.7" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.6-py3-none-any.whl", hash = "sha256:90521c9fc95d8f925e0d2e2d952382676aea6d3f8de611eda1b1810874c31e5d"}, - {file = "langchain_core-0.2.6.tar.gz", hash = "sha256:9f0e38da722a558a6e95b6d86de01bd92e84558c47ac8ba599f02eab70a1c873"}, + {file = "langchain_core-0.2.7-py3-none-any.whl", hash = "sha256:fd02e153c898486dd728d634684ffc64bc257ff2ba443dc7e53d017ac0bf4658"}, + {file = "langchain_core-0.2.7.tar.gz", hash = "sha256:b0b1b6dfbdedb39426fcb8bd3f07e40eec7964856e3fc384c420ca6dba61b34e"}, ] [package.dependencies] @@ -4246,21 +4250,18 @@ tenacity = ">=8.1.0,<9.0.0" [[package]] name = "langchain-experimental" -version = "0.0.60" +version = "0.0.61" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_experimental-0.0.60-py3-none-any.whl", hash = "sha256:ef3b6b6b84fe2bfe19eba6d1a98005e27d96576514c6415f5afe4ace5bf477d8"}, - {file = "langchain_experimental-0.0.60.tar.gz", hash = "sha256:a16cbcd18cda6b86be8f41fed7963c13569295def0d8b4c6324b806d878d442c"}, + {file = "langchain_experimental-0.0.61-py3-none-any.whl", hash = "sha256:f9c516f528f55919743bd56fe1689a53bf74ae7f8902d64b9d8aebc61249cbe2"}, + {file = "langchain_experimental-0.0.61.tar.gz", hash = "sha256:e9538efb994be5db3045cc582cddb9787c8299c86ffeee9d3779b7f58eef2226"}, ] [package.dependencies] -langchain-community = ">=0.2,<0.3" -langchain-core = ">=0.2,<0.3" - -[package.extras] -extended-testing = ["faker (>=19.3.1,<20.0.0)", "jinja2 (>=3,<4)", "pandas (>=2.0.1,<3.0.0)", "presidio-analyzer (>=2.2.352,<3.0.0)", "presidio-anonymizer (>=2.2.352,<3.0.0)", "sentence-transformers (>=2,<3)", "tabulate (>=0.9.0,<0.10.0)", "vowpal-wabbit-next (==0.6.0)"] +langchain-community = ">=0.2.5,<0.3.0" +langchain-core = ">=0.2.7,<0.3.0" [[package]] name = "langchain-google-genai" @@ -4412,7 +4413,7 @@ six = "*" [[package]] name = "langflow-base" -version = "0.0.68" +version = "0.0.70" description = "A Python package with a built-in web application" optional = false python-versions = ">=3.10,<3.13" @@ -4424,6 +4425,7 @@ alembic = "^1.13.0" asyncer = "^0.0.5" bcrypt = "4.0.1" cachetools = "^5.3.1" +chardet = "^5.2.0" cryptography = "^42.0.5" docstring-parser = "^0.15" duckdb = "^1.0.0" @@ -4510,13 +4512,13 @@ requests = ">=2,<3" [[package]] name = "litellm" -version = "1.40.12" +version = "1.40.14" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" files = [ - {file = "litellm-1.40.12-py3-none-any.whl", hash = "sha256:42f1648507f29c60543ba5fdf35d38fc161694da043b201508225bae50d3328c"}, - {file = "litellm-1.40.12.tar.gz", hash = "sha256:366bb9c3694b9ef59b3d073bb37ff9ca175ab4090dc187b0a11d2b21db3a6a5d"}, + {file = "litellm-1.40.14-py3-none-any.whl", hash = "sha256:5faf9e1ca7405ef7623d2fca521aee4e11e6aa4f761fcfcd3830dc485ce53af3"}, + {file = "litellm-1.40.14.tar.gz", hash = "sha256:22ecc4e54afb78eca7a1e17aebf3709260b33efb3a69d85882d4e6553d6e93fa"}, ] [package.dependencies] @@ -4525,6 +4527,7 @@ click = "*" importlib-metadata = ">=6.8.0" jinja2 = ">=3.1.2,<4.0.0" openai = ">=1.27.0" +pydantic = ">=2.0.0,<3.0.0" python-dotenv = ">=0.2.0" requests = ">=2.31.0,<3.0.0" tiktoken = ">=0.7.0" @@ -4579,8 +4582,8 @@ psutil = ">=5.9.1" pywin32 = {version = "*", markers = "platform_system == \"Windows\""} pyzmq = ">=25.0.0" requests = [ - {version = ">=2.26.0", markers = "python_version <= \"3.11\""}, {version = ">=2.32.2", markers = "python_version > \"3.11\""}, + {version = ">=2.26.0", markers = "python_version <= \"3.11\""}, ] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} Werkzeug = ">=2.0.0" @@ -6048,9 +6051,9 @@ files = [ [package.dependencies] numpy = [ + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, - {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -9548,13 +9551,13 @@ six = "*" [[package]] name = "unstructured" -version = "0.14.5" +version = "0.14.6" description = "A library that prepares raw documents for downstream ML tasks." optional = false python-versions = "<3.13,>=3.9.0" files = [ - {file = "unstructured-0.14.5-py3-none-any.whl", hash = "sha256:2286180ac089b691e1effb73c2ab17b7809011fbf7f751439301b12a4c984131"}, - {file = "unstructured-0.14.5.tar.gz", hash = "sha256:f37975273cdcf8f05768ef2f86abaf3d8f805992f6acb0441c2be00fa4ef6588"}, + {file = "unstructured-0.14.6-py3-none-any.whl", hash = "sha256:ab7d83016e46d3c221f6dae8b1040492ee69f7a97cb53c0f2109b54f0b764d19"}, + {file = "unstructured-0.14.6.tar.gz", hash = "sha256:5dddf44908faa0f5250c02f41768fd4ce3792496d3e00258fd33f68c24b902c1"}, ] [package.dependencies] @@ -9576,13 +9579,14 @@ python-pptx = {version = "<=0.6.23", optional = true, markers = "extra == \"pptx rapidfuzz = "*" requests = "*" tabulate = "*" +tqdm = "*" typing-extensions = "*" unstructured-client = "*" wrapt = "*" [package.extras] airtable = ["pyairtable"] -all-docs = ["effdet", "google-cloud-vision", "markdown", "networkx", "onnx", "openpyxl", "pandas", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypandoc", "pypdf", "pytesseract", "python-docx (>=1.1.2)", "python-oxmsg", "python-pptx (<=0.6.23)", "unstructured-inference (==0.7.33)", "unstructured.pytesseract (>=0.3.12)", "xlrd"] +all-docs = ["effdet", "google-cloud-vision", "markdown", "networkx", "onnx", "openpyxl", "pandas", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypandoc", "pypdf", "pytesseract", "python-docx (>=1.1.2)", "python-oxmsg", "python-pptx (<=0.6.23)", "unstructured-inference (==0.7.35)", "unstructured.pytesseract (>=0.3.12)", "xlrd"] astra = ["astrapy"] azure = ["adlfs", "fsspec"] azure-cognitive-search = ["azure-search-documents"] @@ -9611,9 +9615,9 @@ gitlab = ["python-gitlab"] google-drive = ["google-api-python-client"] hubspot = ["hubspot-api-client", "urllib3"] huggingface = ["langdetect", "sacremoses", "sentencepiece", "torch", "transformers"] -image = ["effdet", "google-cloud-vision", "onnx", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypdf", "pytesseract", "unstructured-inference (==0.7.33)", "unstructured.pytesseract (>=0.3.12)"] +image = ["effdet", "google-cloud-vision", "onnx", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypdf", "pytesseract", "unstructured-inference (==0.7.35)", "unstructured.pytesseract (>=0.3.12)"] jira = ["atlassian-python-api"] -local-inference = ["effdet", "google-cloud-vision", "markdown", "networkx", "onnx", "openpyxl", "pandas", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypandoc", "pypdf", "pytesseract", "python-docx (>=1.1.2)", "python-oxmsg", "python-pptx (<=0.6.23)", "unstructured-inference (==0.7.33)", "unstructured.pytesseract (>=0.3.12)", "xlrd"] +local-inference = ["effdet", "google-cloud-vision", "markdown", "networkx", "onnx", "openpyxl", "pandas", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypandoc", "pypdf", "pytesseract", "python-docx (>=1.1.2)", "python-oxmsg", "python-pptx (<=0.6.23)", "unstructured-inference (==0.7.35)", "unstructured.pytesseract (>=0.3.12)", "xlrd"] md = ["markdown"] mongodb = ["pymongo"] msg = ["python-oxmsg"] @@ -9625,7 +9629,7 @@ opensearch = ["opensearch-py"] org = ["pypandoc"] outlook = ["Office365-REST-Python-Client", "msal"] paddleocr = ["unstructured.paddleocr (==2.6.1.3)"] -pdf = ["effdet", "google-cloud-vision", "onnx", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypdf", "pytesseract", "unstructured-inference (==0.7.33)", "unstructured.pytesseract (>=0.3.12)"] +pdf = ["effdet", "google-cloud-vision", "onnx", "pdf2image", "pdfminer.six", "pikepdf", "pillow-heif", "pypdf", "pytesseract", "unstructured-inference (==0.7.35)", "unstructured.pytesseract (>=0.3.12)"] pinecone = ["pinecone-client (>=3.7.1)"] postgres = ["psycopg2-binary"] ppt = ["python-pptx (<=0.6.23)"] diff --git a/pyproject.toml b/pyproject.toml index 6435db14c..7c889b256 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "1.0.0a57" +version = "1.0.0a59" description = "A Python package with a built-in web application" authors = ["Langflow "] maintainers = [ diff --git a/src/backend/base/langflow/api/v1/chat.py b/src/backend/base/langflow/api/v1/chat.py index a01d2a223..fb20b8cd3 100644 --- a/src/backend/base/langflow/api/v1/chat.py +++ b/src/backend/base/langflow/api/v1/chat.py @@ -184,7 +184,7 @@ async def build_vertex( result_data_response = ResultDataResponse.model_validate(result_dict, from_attributes=True) except Exception as exc: - logger.exception(f"Error building vertex: {exc}") + logger.exception(f"Error building Component: {exc}") params = format_exception_message(exc) valid = False output_label = vertex.outputs[0]["name"] if vertex.outputs else "output" @@ -241,7 +241,7 @@ async def build_vertex( ) return build_response except Exception as exc: - logger.error(f"Error building vertex: {exc}") + logger.error(f"Error building Component: {exc}") logger.exception(exc) message = parse_exception(exc) raise HTTPException(status_code=500, detail=message) from exc @@ -336,7 +336,7 @@ async def build_vertex_stream( raise ValueError(f"No result found for vertex {vertex_id}") except Exception as exc: - logger.exception(f"Error building vertex: {exc}") + logger.exception(f"Error building Component: {exc}") exc_message = parse_exception(exc) if exc_message == "The message must be an iterator or an async iterator.": exc_message = "This stream has already been closed." @@ -347,4 +347,4 @@ async def build_vertex_stream( return StreamingResponse(stream_vertex(), media_type="text/event-stream") except Exception as exc: - raise HTTPException(status_code=500, detail="Error building vertex") from exc + raise HTTPException(status_code=500, detail="Error building Component") from exc diff --git a/src/backend/base/langflow/api/v1/endpoints.py b/src/backend/base/langflow/api/v1/endpoints.py index 018c5cdaa..5cf8a262b 100644 --- a/src/backend/base/langflow/api/v1/endpoints.py +++ b/src/backend/base/langflow/api/v1/endpoints.py @@ -5,9 +5,6 @@ from uuid import UUID import sqlalchemy as sa from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, Request, UploadFile, status -from loguru import logger -from sqlmodel import Session, select - from langflow.api.utils import update_frontend_node_with_template_values from langflow.api.v1.schemas import ( ConfigResponse, @@ -41,6 +38,8 @@ from langflow.services.deps import ( ) from langflow.services.session.service import SessionService from langflow.services.task.service import TaskService +from loguru import logger +from sqlmodel import Session, select if TYPE_CHECKING: from langflow.services.cache.base import CacheService @@ -71,29 +70,20 @@ async def get_all( async def simple_run_flow( - db: Session, flow: Flow, input_request: SimplifiedAPIRequest, - session_service: SessionService, stream: bool = False, api_key_user: Optional[User] = None, ): try: task_result: List[RunOutputs] = [] - artifacts = {} user_id = api_key_user.id if api_key_user else None flow_id_str = str(flow.id) - if input_request.session_id: - session_data = await session_service.load_session(input_request.session_id, flow_id=flow_id_str) - graph, artifacts = session_data if session_data else (None, None) - if graph is None: - raise ValueError(f"Session {input_request.session_id} not found") - else: - if flow.data is None: - raise ValueError(f"Flow {flow_id_str} has no data") - graph_data = flow.data - graph_data = process_tweaks(graph_data, input_request.tweaks or {}, stream=stream) - graph = Graph.from_payload(graph_data, flow_id=flow_id_str, user_id=str(user_id)) + if flow.data is None: + raise ValueError(f"Flow {flow_id_str} has no data") + graph_data = flow.data.copy() + graph_data = process_tweaks(graph_data, input_request.tweaks or {}, stream=stream) + graph = Graph.from_payload(graph_data, flow_id=flow_id_str, user_id=str(user_id)) inputs = [ InputValueRequest(components=[], input_value=input_request.input_value, type=input_request.input_type) ] @@ -115,8 +105,6 @@ async def simple_run_flow( session_id=input_request.session_id, inputs=inputs, outputs=outputs, - artifacts=artifacts, - session_service=session_service, stream=stream, ) @@ -189,10 +177,8 @@ async def simplified_run_flow( """ try: return await simple_run_flow( - db=db, flow=flow, input_request=input_request, - session_service=session_service, stream=stream, api_key_user=api_key_user, ) @@ -263,7 +249,6 @@ async def webhook_run_flow( db=db, flow=flow, input_request=input_request, - session_service=session_service, ) return {"message": "Task started in the background", "status": "in progress"} except Exception as exc: @@ -542,3 +527,4 @@ def get_config(): except Exception as exc: logger.exception(exc) raise HTTPException(status_code=500, detail=str(exc)) from exc + raise HTTPException(status_code=500, detail=str(exc)) from exc diff --git a/src/backend/base/langflow/base/flow_processing/utils.py b/src/backend/base/langflow/base/flow_processing/utils.py index 14420dac0..b2ec514c9 100644 --- a/src/backend/base/langflow/base/flow_processing/utils.py +++ b/src/backend/base/langflow/base/flow_processing/utils.py @@ -1,5 +1,7 @@ from typing import List +from loguru import logger + from langflow.graph.schema import ResultData, RunOutputs from langflow.schema import Data @@ -37,9 +39,32 @@ def build_data_from_result_data(result_data: ResultData, get_final_results_only: """ messages = result_data.messages + if not messages: return [] data = [] + + # Handle results without chat messages (calling flow) + if not messages: + # Result with a single record + if isinstance(result_data.artifacts, dict): + data.append(Data(data=result_data.artifacts)) + # List of artifacts + elif isinstance(result_data.artifacts, list): + for artifact in result_data.artifacts: + # If multiple records are found as artifacts, return as-is + if isinstance(artifact, Data): + data.append(artifact) + else: + # Warn about unknown output type + logger.warning(f"Unable to build record output from unknown ResultData.artifact: {str(artifact)}") + # Chat or text output + elif result_data.results: + data.append(Data(data={"result": result_data.results}, text_key="result")) + return data + else: + return [] + for message in messages: message_dict = message if isinstance(message, dict) else message.model_dump() if get_final_results_only: diff --git a/src/backend/base/langflow/components/memories/AstraDBMessageWriter.py b/src/backend/base/langflow/components/memories/AstraDBMessageWriter.py index 497104c9d..c929aca9e 100644 --- a/src/backend/base/langflow/components/memories/AstraDBMessageWriter.py +++ b/src/backend/base/langflow/components/memories/AstraDBMessageWriter.py @@ -89,6 +89,7 @@ class AstraDBMessageWriterComponent(BaseMemoryComponent): sender_name=sender_name, metadata=metadata, session_id=session_id, + type=sender, ) ] diff --git a/src/backend/base/langflow/components/vectorstores/AstraDB.py b/src/backend/base/langflow/components/vectorstores/AstraDB.py index 3b1df1d38..e912557c2 100644 --- a/src/backend/base/langflow/components/vectorstores/AstraDB.py +++ b/src/backend/base/langflow/components/vectorstores/AstraDB.py @@ -164,4 +164,3 @@ class AstraDBVectorStoreComponent(CustomComponent): ) return vector_store - return vector_store diff --git a/src/backend/base/langflow/custom/custom_component/custom_component.py b/src/backend/base/langflow/custom/custom_component/custom_component.py index 9eec57693..e324a442a 100644 --- a/src/backend/base/langflow/custom/custom_component/custom_component.py +++ b/src/backend/base/langflow/custom/custom_component/custom_component.py @@ -21,6 +21,7 @@ from langflow.type_extraction.type_extraction import ( extract_union_types_from_generic_alias, ) from langflow.utils import validate +from pydantic import BaseModel if TYPE_CHECKING: from langflow.graph.graph.base import Graph diff --git a/src/backend/base/langflow/graph/graph/base.py b/src/backend/base/langflow/graph/graph/base.py index 2ba9ae0d4..f541bb3e4 100644 --- a/src/backend/base/langflow/graph/graph/base.py +++ b/src/backend/base/langflow/graph/graph/base.py @@ -5,8 +5,6 @@ from functools import partial from itertools import chain from typing import TYPE_CHECKING, Callable, Coroutine, Dict, Generator, List, Optional, Tuple, Type, Union -from loguru import logger - from langflow.graph.edge.base import ContractEdge from langflow.graph.graph.constants import lazy_load_vertex_dict from langflow.graph.graph.runnable_vertices_manager import RunnableVerticesManager @@ -21,6 +19,7 @@ from langflow.services.cache.utils import CacheMiss from langflow.services.chat.service import ChatService from langflow.services.deps import get_chat_service from langflow.services.monitor.utils import log_transaction +from loguru import logger if TYPE_CHECKING: from langflow.graph.schema import ResultData @@ -729,6 +728,7 @@ class Graph: files: Optional[list[str]] = None, user_id: Optional[str] = None, fallback_to_env_vars: bool = False, + cache: bool = True, ): """ Builds a vertex in the graph. @@ -784,19 +784,23 @@ class Graph: raise ValueError(f"No result found for vertex {vertex_id}") set_cache_coro = partial(chat_service.set_cache, key=self.flow_id) next_runnable_vertices, top_level_vertices = await self.get_next_and_top_level_vertices( - lock, set_cache_coro, vertex + lock, set_cache_coro, vertex, cache=cache ) flow_id = self.flow_id log_transaction(flow_id, vertex, status="success") return next_runnable_vertices, top_level_vertices, result_dict, params, valid, artifacts, vertex except Exception as exc: - logger.exception(f"Error building vertex: {exc}") + logger.exception(f"Error building Component: {exc}") flow_id = self.flow_id log_transaction(flow_id, vertex, status="failure", error=str(exc)) raise exc async def get_next_and_top_level_vertices( - self, lock: asyncio.Lock, set_cache_coro: Callable[["Graph", asyncio.Lock], Coroutine], vertex: Vertex + self, + lock: asyncio.Lock, + set_cache_coro: Callable[["Graph", asyncio.Lock], Coroutine], + vertex: Vertex, + cache: bool = True, ): """ Retrieves the next runnable vertices and the top level vertices for a given vertex. @@ -809,7 +813,9 @@ class Graph: Returns: Tuple[List[Vertex], List[Vertex]]: A tuple containing the next runnable vertices and the top level vertices. """ - next_runnable_vertices = await self.run_manager.get_next_runnable_vertices(lock, set_cache_coro, self, vertex) + next_runnable_vertices = await self.run_manager.get_next_runnable_vertices( + lock, set_cache_coro, self, vertex, cache=cache + ) top_level_vertices = self.run_manager.get_top_level_vertices(self, next_runnable_vertices) return next_runnable_vertices, top_level_vertices @@ -850,13 +856,13 @@ class Graph: chat_service = get_chat_service() run_id = uuid.uuid4() self.set_run_id(run_id) + lock = chat_service._cache_locks[self.run_id] while to_process: current_batch = list(to_process) # Copy current deque items to a list to_process.clear() # Clear the deque for new items tasks = [] for vertex_id in current_batch: vertex = self.get_vertex(vertex_id) - lock = chat_service._cache_locks[self.run_id] task = asyncio.create_task( self.build_vertex( lock=lock, @@ -865,6 +871,7 @@ class Graph: user_id=self.user_id, inputs_dict={}, fallback_to_env_vars=fallback_to_env_vars, + cache=False, ), name=f"{vertex.display_name} Run {vertex_task_run_count.get(vertex_id, 0)}", ) @@ -872,8 +879,15 @@ class Graph: vertex_task_run_count[vertex_id] = vertex_task_run_count.get(vertex_id, 0) + 1 logger.debug(f"Running layer {layer_index} with {len(tasks)} tasks") - next_runnable_vertices = await self._execute_tasks(tasks) + try: + next_runnable_vertices = await self._execute_tasks(tasks) + except Exception as e: + logger.error(f"Error executing tasks in layer {layer_index}: {e}") + break + if not next_runnable_vertices: + break to_process.extend(next_runnable_vertices) + layer_index += 1 logger.debug("Graph processing complete") return self @@ -881,25 +895,23 @@ class Graph: async def _execute_tasks(self, tasks: List[asyncio.Task]) -> List[str]: """Executes tasks in parallel, handling exceptions for each task.""" results = [] - for i, task in enumerate(asyncio.as_completed(tasks)): - try: - result = await task - if isinstance(result, tuple) and len(result) == 7: - # Get the next runnable vertices - next_runnable_vertices = result[0] - results.extend(next_runnable_vertices) - else: - raise ValueError(f"Invalid result: {result}") - except Exception as e: - # Log the exception along with the task name for easier debugging - # task_name = task.get_name() - # coroutine has not attribute get_name - task_name = tasks[i].get_name() - logger.error(f"Task {task_name} failed with exception: {e}") + completed_tasks = await asyncio.gather(*tasks, return_exceptions=True) + + for i, result in enumerate(completed_tasks): + task_name = tasks[i].get_name() + if isinstance(result, Exception): + logger.error(f"Task {task_name} failed with exception: {result}") # Cancel all remaining tasks - for t in tasks[i:]: + for t in tasks[i + 1 :]: t.cancel() - raise e + raise result + elif isinstance(result, tuple) and len(result) == 7: + # Get the next runnable vertices + next_runnable_vertices = result[0] + results.extend(next_runnable_vertices) + else: + raise ValueError(f"Invalid result from task {task_name}: {result}") + return results def topological_sort(self) -> List[Vertex]: @@ -1377,3 +1389,5 @@ class Graph: predecessor_map[edge.target_id].append(edge.source_id) successor_map[edge.source_id].append(edge.target_id) return predecessor_map, successor_map + return predecessor_map, successor_map + return predecessor_map, successor_map diff --git a/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py b/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py index 713aead65..9dd7c346c 100644 --- a/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py +++ b/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py @@ -59,6 +59,7 @@ class RunnableVerticesManager: set_cache_coro: Callable[["Graph", asyncio.Lock], Awaitable[None]], graph: "Graph", vertex: "Vertex", + cache: bool = True, ): """ Retrieves the next runnable vertices in the graph for a given vertex. @@ -86,7 +87,8 @@ class RunnableVerticesManager: for v_id in set(next_runnable_vertices): # Use set to avoid duplicates self.update_vertex_run_state(v_id, is_runnable=False) self.remove_from_predecessors(v_id) - await set_cache_coro(data=graph, lock=lock) # type: ignore + if cache: + await set_cache_coro(data=graph, lock=lock) # type: ignore return next_runnable_vertices @staticmethod diff --git a/src/backend/base/langflow/graph/schema.py b/src/backend/base/langflow/graph/schema.py index 825379800..8f4b3249e 100644 --- a/src/backend/base/langflow/graph/schema.py +++ b/src/backend/base/langflow/graph/schema.py @@ -73,6 +73,7 @@ INPUT_COMPONENTS = [ OUTPUT_COMPONENTS = [ InterfaceComponentTypes.ChatOutput, InterfaceComponentTypes.TextOutput, + InterfaceComponentTypes.DataOutput, ] 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 283249015..aefb29594 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 @@ -8,12 +8,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-k39HS", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-njtka", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -24,7 +28,7 @@ "stroke": "#555" }, "target": "ChatOutput-njtka", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-njtkaœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-njtkaœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-gray-900 stroke-connection", @@ -33,12 +37,18 @@ "dataType": "Prompt", "id": "Prompt-uxBqP", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-k39HS", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -58,12 +68,19 @@ "dataType": "ChatInput", "id": "ChatInput-P3fgL", "name": "message", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "user_input", "id": "Prompt-uxBqP", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -84,10 +101,16 @@ "display_name": "Prompt", "id": "Prompt-uxBqP", "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", @@ -110,7 +133,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -119,7 +144,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -150,7 +177,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -171,7 +200,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -209,7 +243,11 @@ "display_name": "OpenAI", "id": "OpenAIModel-k39HS", "node": { - "base_classes": ["object", "Text", "str"], + "base_classes": [ + "object", + "Text", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -247,7 +285,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -256,7 +296,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -278,7 +320,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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, @@ -287,7 +329,11 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "multiline": false, @@ -307,7 +353,9 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -327,7 +375,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -347,7 +397,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -373,8 +425,10 @@ "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"], + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -394,7 +448,9 @@ "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, "multiline": false, @@ -414,7 +470,9 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -434,7 +492,9 @@ "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, @@ -454,7 +514,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -490,7 +552,12 @@ "data": { "id": "ChatOutput-njtka", "node": { - "base_classes": ["Record", "Text", "str", "object"], + "base_classes": [ + "Record", + "Text", + "str", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -515,7 +582,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -537,7 +617,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -546,7 +626,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -566,12 +648,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -587,7 +674,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -607,7 +696,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -643,7 +734,12 @@ "data": { "id": "ChatInput-P3fgL", "node": { - "base_classes": ["object", "Record", "str", "Text"], + "base_classes": [ + "object", + "Record", + "str", + "Text" + ], "beta": false, "custom_fields": { "input_value": null, @@ -667,7 +763,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -689,7 +798,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 langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\nfrom langflow.field_typing import Text\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -718,12 +827,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -739,7 +853,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -759,7 +875,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -803,4 +921,4 @@ "is_component": false, "last_tested_version": "1.0.0a4", "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 24b77b849..cbb648a64 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 @@ -13,7 +13,12 @@ "targetHandle": { "fieldName": "reference_2", "id": "Prompt-Rse03", - "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], "type": "str" } }, @@ -34,12 +39,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-gi29P", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-JPlxl", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -50,7 +59,7 @@ "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", @@ -64,7 +73,12 @@ "targetHandle": { "fieldName": "reference_1", "id": "Prompt-Rse03", - "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], "type": "str" } }, @@ -84,12 +98,19 @@ "dataType": "TextInput", "id": "TextInput-og8Or", "name": "Text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "instructions", "id": "Prompt-Rse03", - "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], "type": "str" } }, @@ -109,12 +130,18 @@ "dataType": "Prompt", "id": "Prompt-Rse03", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-gi29P", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -136,10 +163,18 @@ "display_name": "Prompt", "id": "Prompt-Rse03", "node": { - "base_classes": ["object", "Text", "str"], + "base_classes": [ + "object", + "Text", + "str" + ], "beta": false, "custom_fields": { - "template": ["reference_1", "reference_2", "instructions"] + "template": [ + "reference_1", + "reference_2", + "instructions" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -162,7 +197,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -171,7 +208,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -280,7 +319,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -316,7 +357,9 @@ "data": { "id": "URL-HYPkR", "node": { - "base_classes": ["Record"], + "base_classes": [ + "Record" + ], "beta": false, "custom_fields": { "urls": null @@ -336,7 +379,9 @@ "method": "fetch_content", "name": "data", "selected": "Data", - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" } ], @@ -358,7 +403,7 @@ "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\nimport re\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 ensure_url(self, string: str) -> str:\n \"\"\"\n Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(http://|https://)?\" # http:// or https://\n r\"(([a-zA-Z0-9\\.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,}))\" # top-level domain\n r\"(:[0-9]{1,5})?\" # optional port\n r\"(\\/.*)?$\" # optional path\n )\n\n if not re.match(url_regex, string):\n raise ValueError(f\"Invalid URL: {string}\")\n\n return string\n\n def fetch_content(self) -> Data:\n urls = [self.ensure_url(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 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\nimport re\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 ensure_url(self, string: str) -> str:\n \"\"\"\n Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(http://|https://)?\" # http:// or https://\n r\"(([a-zA-Z0-9\\.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,}))\" # top-level domain\n r\"(:[0-9]{1,5})?\" # optional port\n r\"(\\/.*)?$\" # optional path\n )\n\n if not re.match(url_regex, string):\n raise ValueError(f\"Invalid URL: {string}\")\n\n return string\n\n def fetch_content(self) -> Data:\n urls = [self.ensure_url(url.strip()) for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls, encoding=\"utf-8\")\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" }, "urls": { "advanced": false, @@ -398,7 +443,12 @@ "data": { "id": "ChatOutput-JPlxl", "node": { - "base_classes": ["Text", "Record", "object", "str"], + "base_classes": [ + "Text", + "Record", + "object", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -423,7 +473,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -445,7 +508,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -454,7 +517,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -474,12 +539,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -495,7 +565,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -515,7 +587,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -546,7 +620,11 @@ "data": { "id": "OpenAIModel-gi29P", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -584,7 +662,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -593,7 +673,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -615,7 +697,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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, @@ -624,7 +706,11 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "multiline": false, @@ -644,7 +730,9 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -664,7 +752,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -684,7 +774,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -710,8 +802,10 @@ "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"], + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -731,7 +825,9 @@ "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, "multiline": false, @@ -751,7 +847,9 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -771,7 +869,9 @@ "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, @@ -791,7 +891,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -827,7 +929,9 @@ "data": { "id": "URL-2cX90", "node": { - "base_classes": ["Record"], + "base_classes": [ + "Record" + ], "beta": false, "custom_fields": { "urls": null @@ -847,7 +951,9 @@ "method": "fetch_content", "name": "data", "selected": "Data", - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" } ], @@ -869,7 +975,7 @@ "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\nimport re\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 ensure_url(self, string: str) -> str:\n \"\"\"\n Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(http://|https://)?\" # http:// or https://\n r\"(([a-zA-Z0-9\\.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,}))\" # top-level domain\n r\"(:[0-9]{1,5})?\" # optional port\n r\"(\\/.*)?$\" # optional path\n )\n\n if not re.match(url_regex, string):\n raise ValueError(f\"Invalid URL: {string}\")\n\n return string\n\n def fetch_content(self) -> Data:\n urls = [self.ensure_url(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 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\nimport re\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 ensure_url(self, string: str) -> str:\n \"\"\"\n Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(http://|https://)?\" # http:// or https://\n r\"(([a-zA-Z0-9\\.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,}))\" # top-level domain\n r\"(:[0-9]{1,5})?\" # optional port\n r\"(\\/.*)?$\" # optional path\n )\n\n if not re.match(url_regex, string):\n raise ValueError(f\"Invalid URL: {string}\")\n\n return string\n\n def fetch_content(self) -> Data:\n urls = [self.ensure_url(url.strip()) for url in self.urls if url.strip()]\n loader = WebBaseLoader(web_paths=urls, encoding=\"utf-8\")\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" }, "urls": { "advanced": false, @@ -909,7 +1015,11 @@ "data": { "id": "TextInput-og8Or", "node": { - "base_classes": ["object", "Text", "str"], + "base_classes": [ + "object", + "Text", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -922,12 +1032,16 @@ "field_order": [], "frozen": false, "icon": "type", - "output_types": ["Text"], + "output_types": [ + "Text" + ], "outputs": [ { "name": "Text", "selected": "Text", - "types": ["Text"] + "types": [ + "Text" + ] } ], "template": { @@ -957,7 +1071,10 @@ "fileTypes": [], "file_path": "", "info": "Text or Record to be passed as input.", - "input_types": ["Record", "Text"], + "input_types": [ + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -977,7 +1094,9 @@ "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"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1021,4 +1140,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 48b474fc0..af8d4a88f 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 @@ -7,12 +7,19 @@ "dataType": "File", "id": "File-BzIs2", "name": "data", - "output_types": ["Data"] + "output_types": [ + "Data" + ] }, "targetHandle": { "fieldName": "Document", "id": "Prompt-9DNZG", - "inputTypes": ["Document", "Message", "Data", "Text"], + "inputTypes": [ + "Document", + "Message", + "Data", + "Text" + ], "type": "str" } }, @@ -28,12 +35,19 @@ "dataType": "ChatInput", "id": "ChatInput-27Usy", "name": "message", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "Question", "id": "Prompt-9DNZG", - "inputTypes": ["Document", "Message", "Data", "Text"], + "inputTypes": [ + "Document", + "Message", + "Data", + "Text" + ], "type": "str" } }, @@ -49,12 +63,18 @@ "dataType": "Prompt", "id": "Prompt-9DNZG", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-8b6nG", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -70,12 +90,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-8b6nG", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-y4SCS", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -83,7 +107,7 @@ "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œ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-y4SCSœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -93,11 +117,18 @@ "display_name": "Prompt", "id": "Prompt-9DNZG", "node": { - "base_classes": ["object", "str", "Text"], + "base_classes": [ + "object", + "str", + "Text" + ], "beta": false, "conditional_paths": [], "custom_fields": { - "template": ["Document", "Question"] + "template": [ + "Document", + "Question" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -119,7 +150,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -128,7 +161,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -142,7 +177,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Data", "Text"], + "input_types": [ + "Document", + "Message", + "Data", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -163,7 +203,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Data", "Text"], + "input_types": [ + "Document", + "Message", + "Data", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -202,7 +247,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -238,7 +285,12 @@ "data": { "id": "ChatInput-27Usy", "node": { - "base_classes": ["str", "Record", "Text", "object"], + "base_classes": [ + "str", + "Record", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -262,7 +314,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -284,7 +349,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 langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\nfrom langflow.field_typing import Text\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -313,12 +378,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -334,7 +404,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -354,7 +426,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -390,7 +464,12 @@ "data": { "id": "ChatOutput-y4SCS", "node": { - "base_classes": ["str", "Record", "Text", "object"], + "base_classes": [ + "str", + "Record", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -414,7 +493,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -436,7 +528,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -445,7 +537,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -465,12 +559,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -486,7 +585,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -506,7 +607,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -544,7 +647,9 @@ "display_name": "File", "id": "File-BzIs2", "node": { - "base_classes": ["Data"], + "base_classes": [ + "Data" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -552,7 +657,10 @@ "display_name": "File", "documentation": "", "edited": true, - "field_order": ["path", "silent_errors"], + "field_order": [ + "path", + "silent_errors" + ], "frozen": false, "icon": "file-text", "output_types": [], @@ -563,7 +671,9 @@ "method": "load_file", "name": "data", "selected": "Data", - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" } ], @@ -660,7 +770,10 @@ "data": { "id": "OpenAIModel-8b6nG", "node": { - "base_classes": ["BaseLanguageModel", "Text"], + "base_classes": [ + "BaseLanguageModel", + "Text" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -688,7 +801,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -697,7 +812,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -720,14 +837,18 @@ "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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, "display_name": "Input", "dynamic": false, "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "name": "input_value", @@ -788,7 +909,7 @@ "advanced": true, "display_name": "OpenAI API Base", "dynamic": false, - "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.", + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", "list": false, "load_from_db": false, "name": "openai_api_base", @@ -804,7 +925,9 @@ "display_name": "OpenAI API Key", "dynamic": false, "info": "The OpenAI API Key to use for the OpenAI model.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "load_from_db": true, "name": "openai_api_key", "password": true, @@ -889,4 +1012,4 @@ "is_component": false, "last_tested_version": "1.0.0a52", "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 f8617e1ae..05ad280a2 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 @@ -8,12 +8,19 @@ "dataType": "MemoryComponent", "id": "MemoryComponent-cdA1J", "name": "text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "context", "id": "Prompt-ODkUx", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -34,12 +41,19 @@ "dataType": "ChatInput", "id": "ChatInput-t7F8v", "name": "message", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "user_message", "id": "Prompt-ODkUx", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -60,12 +74,18 @@ "dataType": "Prompt", "id": "Prompt-ODkUx", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-9RykF", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -85,12 +105,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-9RykF", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-P1jEe", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -101,7 +125,7 @@ "stroke": "#555" }, "target": "ChatOutput-P1jEe", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-P1jEeœ, œinputTypesœ: [œTextœ, œMessageœ], œtypeœ: œstrœ}" + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-P1jEeœ, œinputTypesœ: [œTextœ], œtypeœ: œstrœ}" }, { "className": "stroke-foreground stroke-connection", @@ -110,12 +134,17 @@ "dataType": "MemoryComponent", "id": "MemoryComponent-cdA1J", "name": "text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "TextOutput-vrs6T", - "inputTypes": ["Record", "Text"], + "inputTypes": [ + "Record", + "Text" + ], "type": "str" } }, @@ -134,7 +163,12 @@ "data": { "id": "ChatInput-t7F8v", "node": { - "base_classes": ["Text", "object", "Record", "str"], + "base_classes": [ + "Text", + "object", + "Record", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -158,7 +192,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -180,7 +227,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 langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\nfrom langflow.field_typing import Text\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -209,12 +256,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -230,7 +282,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -250,7 +304,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -286,7 +342,12 @@ "data": { "id": "ChatOutput-P1jEe", "node": { - "base_classes": ["Text", "object", "Record", "str"], + "base_classes": [ + "Text", + "object", + "Record", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -310,7 +371,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -332,7 +406,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -341,7 +415,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -361,12 +437,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -382,7 +463,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -402,7 +485,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -440,7 +525,11 @@ "display_name": "Chat Memory", "id": "MemoryComponent-cdA1J", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": true, "custom_fields": { "n_messages": null, @@ -457,7 +546,9 @@ "field_order": [], "frozen": false, "icon": "history", - "output_types": ["Text"], + "output_types": [ + "Text" + ], "outputs": [ { "cache": true, @@ -466,7 +557,9 @@ "method": null, "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -516,12 +609,17 @@ "fileTypes": [], "file_path": "", "info": "Order of the messages.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "order", - "options": ["Ascending", "Descending"], + "options": [ + "Ascending", + "Descending" + ], "password": false, "placeholder": "", "required": false, @@ -537,12 +635,18 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User", "Machine and User"], + "options": [ + "Machine", + "User", + "Machine and User" + ], "password": false, "placeholder": "", "required": false, @@ -558,7 +662,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -577,7 +683,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID of the chat history.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -615,10 +723,17 @@ "display_name": "Prompt", "id": "Prompt-ODkUx", "node": { - "base_classes": ["Text", "str", "object"], + "base_classes": [ + "Text", + "str", + "object" + ], "beta": false, "custom_fields": { - "template": ["context", "user_message"] + "template": [ + "context", + "user_message" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -641,7 +756,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -650,7 +767,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -682,7 +801,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -702,7 +826,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -723,7 +849,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -759,7 +890,11 @@ "data": { "id": "OpenAIModel-9RykF", "node": { - "base_classes": ["str", "object", "Text"], + "base_classes": [ + "str", + "object", + "Text" + ], "beta": false, "custom_fields": { "input_value": null, @@ -797,7 +932,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -806,7 +943,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -828,7 +967,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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, @@ -837,7 +976,11 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "multiline": false, @@ -857,7 +1000,9 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -877,7 +1022,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -897,7 +1044,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -923,8 +1072,10 @@ "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"], + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -944,7 +1095,9 @@ "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, "multiline": false, @@ -964,7 +1117,9 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -984,7 +1139,9 @@ "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, @@ -1004,7 +1161,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1040,7 +1199,11 @@ "data": { "id": "TextOutput-vrs6T", "node": { - "base_classes": ["str", "object", "Text"], + "base_classes": [ + "str", + "object", + "Text" + ], "beta": false, "custom_fields": { "input_value": null, @@ -1053,7 +1216,9 @@ "field_order": [], "frozen": false, "icon": "type", - "output_types": ["Text"], + "output_types": [ + "Text" + ], "template": { "_type": "CustomComponent", "code": { @@ -1081,7 +1246,10 @@ "fileTypes": [], "file_path": "", "info": "Text or Record to be passed as output.", - "input_types": ["Record", "Text"], + "input_types": [ + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1101,7 +1269,9 @@ "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"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1147,4 +1317,4 @@ "is_component": false, "last_tested_version": "1.0.0a0", "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 8951eaa80..b739cdf0b 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 @@ -8,12 +8,19 @@ "dataType": "TextInput", "id": "TextInput-sptaH", "name": "text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "document", "id": "Prompt-amqBu", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -33,12 +40,17 @@ "dataType": "Prompt", "id": "Prompt-amqBu", "name": "text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "TextOutput-2MS4a", - "inputTypes": ["Record", "Text"], + "inputTypes": [ + "Record", + "Text" + ], "type": "str" } }, @@ -58,12 +70,18 @@ "dataType": "Prompt", "id": "Prompt-amqBu", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-uYXZJ", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -83,12 +101,19 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-uYXZJ", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "summary", "id": "Prompt-gTNiz", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -108,12 +133,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-uYXZJ", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-EJkG3", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -124,7 +153,7 @@ "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", @@ -133,12 +162,17 @@ "dataType": "Prompt", "id": "Prompt-gTNiz", "name": "text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "TextOutput-MUDOR", - "inputTypes": ["Record", "Text"], + "inputTypes": [ + "Record", + "Text" + ], "type": "str" } }, @@ -158,12 +192,18 @@ "dataType": "Prompt", "id": "Prompt-gTNiz", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-XawYB", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -183,12 +223,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-XawYB", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-DNmvg", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -199,7 +243,7 @@ "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": [ @@ -209,10 +253,16 @@ "display_name": "Prompt", "id": "Prompt-amqBu", "node": { - "base_classes": ["object", "str", "Text"], + "base_classes": [ + "object", + "str", + "Text" + ], "beta": false, "custom_fields": { - "template": ["document"] + "template": [ + "document" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -235,7 +285,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -244,7 +296,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -276,7 +330,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -296,7 +355,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -334,10 +395,16 @@ "display_name": "Prompt", "id": "Prompt-gTNiz", "node": { - "base_classes": ["object", "str", "Text"], + "base_classes": [ + "object", + "str", + "Text" + ], "beta": false, "custom_fields": { - "template": ["summary"] + "template": [ + "summary" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -360,7 +427,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -369,7 +438,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -401,7 +472,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -421,7 +497,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -453,7 +531,12 @@ "data": { "id": "ChatOutput-EJkG3", "node": { - "base_classes": ["object", "Record", "Text", "str"], + "base_classes": [ + "object", + "Record", + "Text", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -478,7 +561,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -500,7 +596,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -509,7 +605,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -529,12 +627,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -550,7 +653,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -570,7 +675,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -602,7 +709,12 @@ "data": { "id": "ChatOutput-DNmvg", "node": { - "base_classes": ["object", "Record", "Text", "str"], + "base_classes": [ + "object", + "Record", + "Text", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -627,7 +739,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -649,7 +774,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -658,7 +783,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -678,12 +805,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -699,7 +831,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -719,7 +853,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -750,7 +886,11 @@ "data": { "id": "TextInput-sptaH", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -771,7 +911,9 @@ "method": "text_response", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -793,7 +935,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 langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import StrInput\nfrom langflow.template import Output\n\n\nclass TextInputComponent(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 ]\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)\n" }, "input_value": { "advanced": false, @@ -802,7 +944,9 @@ "fileTypes": [], "file_path": "", "info": "Text to be passed as input.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -838,7 +982,11 @@ "data": { "id": "TextOutput-2MS4a", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -851,7 +999,9 @@ "field_order": [], "frozen": false, "icon": "type", - "output_types": ["Text"], + "output_types": [ + "Text" + ], "template": { "_type": "CustomComponent", "code": { @@ -879,7 +1029,10 @@ "fileTypes": [], "file_path": "", "info": "Text or Record to be passed as output.", - "input_types": ["Record", "Text"], + "input_types": [ + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -899,7 +1052,9 @@ "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"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -935,7 +1090,11 @@ "data": { "id": "OpenAIModel-uYXZJ", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -973,7 +1132,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -982,7 +1143,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -1004,7 +1167,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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, @@ -1013,7 +1176,11 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1033,7 +1200,9 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1053,7 +1222,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1073,7 +1244,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -1099,8 +1272,10 @@ "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"], + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1120,7 +1295,9 @@ "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, "multiline": false, @@ -1140,7 +1317,9 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1160,7 +1339,9 @@ "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, @@ -1180,7 +1361,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1216,7 +1399,11 @@ "data": { "id": "TextOutput-MUDOR", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -1229,7 +1416,9 @@ "field_order": [], "frozen": false, "icon": "type", - "output_types": ["Text"], + "output_types": [ + "Text" + ], "template": { "_type": "CustomComponent", "code": { @@ -1257,7 +1446,10 @@ "fileTypes": [], "file_path": "", "info": "Text or Record to be passed as output.", - "input_types": ["Record", "Text"], + "input_types": [ + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1277,7 +1469,9 @@ "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"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1313,7 +1507,11 @@ "data": { "id": "OpenAIModel-XawYB", "node": { - "base_classes": ["str", "Text", "object"], + "base_classes": [ + "str", + "Text", + "object" + ], "beta": false, "custom_fields": { "input_value": null, @@ -1351,7 +1549,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -1360,7 +1560,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -1382,7 +1584,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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, @@ -1391,7 +1593,11 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1411,7 +1617,9 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1431,7 +1639,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1451,7 +1661,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -1477,8 +1689,10 @@ "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"], + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1498,7 +1712,9 @@ "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, "multiline": false, @@ -1518,7 +1734,9 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1538,7 +1756,9 @@ "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, @@ -1558,7 +1778,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1602,4 +1824,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 088a13d24..0dae27634 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 @@ -8,12 +8,19 @@ "dataType": "TextOutput", "id": "TextOutput-BDknO", "name": "Text", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "context", "id": "Prompt-xeI6K", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -34,12 +41,19 @@ "dataType": "ChatInput", "id": "ChatInput-yxMKE", "name": "message", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "question", "id": "Prompt-xeI6K", - "inputTypes": ["Document", "Message", "Record", "Text"], + "inputTypes": [ + "Document", + "Message", + "Record", + "Text" + ], "type": "str" } }, @@ -60,12 +74,18 @@ "dataType": "Prompt", "id": "Prompt-xeI6K", "name": "prompt", - "output_types": ["Prompt"] + "output_types": [ + "Prompt" + ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-EjXlN", - "inputTypes": ["Text", "Data", "Prompt"], + "inputTypes": [ + "Text", + "Data", + "Prompt" + ], "type": "str" } }, @@ -86,12 +106,16 @@ "dataType": "OpenAIModel", "id": "OpenAIModel-EjXlN", "name": "text_output", - "output_types": ["Text"] + "output_types": [ + "Text" + ] }, "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-Q39I8", - "inputTypes": ["Text", "Message"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -103,7 +127,7 @@ "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", @@ -117,7 +141,10 @@ "targetHandle": { "fieldName": "inputs", "id": "RecursiveCharacterTextSplitter-tR9QM", - "inputTypes": ["Document", "Data"], + "inputTypes": [ + "Document", + "Data" + ], "type": "Document" } }, @@ -138,7 +165,9 @@ "dataType": "OpenAIEmbeddings", "id": "OpenAIEmbeddings-ZlOk1", "name": "embeddings", - "output_types": ["Embeddings"] + "output_types": [ + "Embeddings" + ] }, "targetHandle": { "fieldName": "embedding", @@ -163,12 +192,16 @@ "dataType": "ChatInput", "id": "ChatInput-yxMKE", "name": "message", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "input_value", "id": "AstraDBSearch-41nRz", - "inputTypes": ["Text"], + "inputTypes": [ + "Text" + ], "type": "str" } }, @@ -214,7 +247,9 @@ "dataType": "OpenAIEmbeddings", "id": "OpenAIEmbeddings-9TPjc", "name": "embeddings", - "output_types": ["Embeddings"] + "output_types": [ + "Embeddings" + ] }, "targetHandle": { "fieldName": "embedding", @@ -245,7 +280,10 @@ "targetHandle": { "fieldName": "input_value", "id": "TextOutput-BDknO", - "inputTypes": ["Record", "Text"], + "inputTypes": [ + "Record", + "Text" + ], "type": "str" } }, @@ -264,7 +302,12 @@ "data": { "id": "ChatInput-yxMKE", "node": { - "base_classes": ["Text", "str", "object", "Record"], + "base_classes": [ + "Text", + "str", + "object", + "Record" + ], "beta": false, "custom_fields": { "input_value": null, @@ -288,7 +331,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -310,7 +366,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 langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\nfrom langflow.field_typing import Text\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -339,12 +395,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -360,7 +421,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -380,7 +443,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -411,7 +476,11 @@ "data": { "id": "TextOutput-BDknO", "node": { - "base_classes": ["object", "Text", "str"], + "base_classes": [ + "object", + "Text", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -424,12 +493,16 @@ "field_order": [], "frozen": false, "icon": "type", - "output_types": ["Text"], + "output_types": [ + "Text" + ], "outputs": [ { "name": "Text", "selected": "Text", - "types": ["Text"] + "types": [ + "Text" + ] } ], "template": { @@ -459,7 +532,10 @@ "fileTypes": [], "file_path": "", "info": "Text or Record to be passed as output.", - "input_types": ["Record", "Text"], + "input_types": [ + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -479,7 +555,9 @@ "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"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -515,7 +593,9 @@ "data": { "id": "OpenAIEmbeddings-ZlOk1", "node": { - "base_classes": ["Embeddings"], + "base_classes": [ + "Embeddings" + ], "beta": false, "custom_fields": { "allowed_special": null, @@ -547,53 +627,30 @@ "field_formatters": {}, "field_order": [], "frozen": false, - "output_types": ["Embeddings"], + "icon": "OpenAI", + "output_types": [], "outputs": [ { "cache": true, "display_name": "Embeddings", - "hidden": null, - "method": null, + "method": "build_embeddings", "name": "embeddings", "selected": "Embeddings", - "types": ["Embeddings"], + "types": [ + "Embeddings" + ], "value": "__UNDEFINED__" } ], "template": { - "_type": "CustomComponent", - "allowed_special": { - "advanced": true, - "display_name": "Allowed Special", - "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", - "input_types": ["Text"], - "list": true, - "load_from_db": false, - "multiline": false, - "name": "allowed_special", - "password": false, - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "str", - "value": [] - }, + "_type": "Component", "chunk_size": { "advanced": true, "display_name": "Chunk Size", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "chunk_size", - "password": false, "placeholder": "", "required": false, "show": true, @@ -601,6 +658,24 @@ "type": "int", "value": 1000 }, + "client": { + "advanced": true, + "display_name": "Client", + "dynamic": false, + "info": "", + "input_types": [ + "Text" + ], + "list": false, + "load_from_db": false, + "name": "client", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "str", + "value": "" + }, "code": { "advanced": true, "dynamic": true, @@ -617,318 +692,243 @@ "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 \"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" + "value": "from langchain_openai.embeddings.base import OpenAIEmbeddings\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import Embeddings\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n FloatInput,\n IntInput,\n SecretStrInput,\n StrInput,\n DropdownInput\n)\nfrom langflow.template import Output\n\n\nclass OpenAIEmbeddingsComponent(LCModelComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n icon = \"OpenAI\"\n inputs = [\n DictInput(\n name=\"default_headers\",\n display_name=\"Default Headers\",\n advanced=True,\n info=\"Default headers to use for the API request.\",\n ),\n DictInput(\n name=\"default_query\",\n display_name=\"Default Query\",\n advanced=True,\n info=\"Default query parameters to use for the API request.\",\n ),\n IntInput(name=\"chunk_size\", display_name=\"Chunk Size\", advanced=True, value=1000),\n StrInput(name=\"client\", display_name=\"Client\", advanced=True),\n StrInput(name=\"deployment\", display_name=\"Deployment\", advanced=True),\n IntInput(\n name=\"embedding_ctx_length\",\n display_name=\"Embedding Context Length\",\n advanced=True,\n value=1536\n ),\n IntInput(name=\"max_retries\", display_name=\"Max Retries\", value=3, advanced=True),\n DropdownInput(\n name=\"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 value=\"text-embedding-3-small\"\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n SecretStrInput(\n name=\"openai_api_base\", display_name=\"OpenAI API Base\", advanced=True\n ),\n SecretStrInput(name=\"openai_api_key\", display_name=\"OpenAI API Key\"),\n SecretStrInput(\n name=\"openai_api_type\", display_name=\"OpenAI API Type\", advanced=True\n ),\n StrInput(\n name=\"openai_api_version\", display_name=\"OpenAI API Version\", advanced=True\n ),\n StrInput(\n name=\"openai_organization\",\n display_name=\"OpenAI Organization\",\n advanced=True,\n ),\n StrInput(name=\"openai_proxy\", display_name=\"OpenAI Proxy\", advanced=True),\n FloatInput(\n name=\"request_timeout\", display_name=\"Request Timeout\", advanced=True\n ),\n BoolInput(\n name=\"show_progress_bar\", display_name=\"Show Progress Bar\", advanced=True\n ),\n BoolInput(name=\"skip_empty\", display_name=\"Skip Empty\", advanced=True),\n StrInput(\n name=\"tiktoken_model_name\",\n display_name=\"TikToken Model Name\",\n advanced=True,\n ),\n BoolInput(\n name=\"tiktoken_enable\", display_name=\"TikToken Enable\", advanced=True\n ),\n ]\n\n outputs = [\n Output(display_name=\"Embeddings\", name=\"embeddings\", method=\"build_embeddings\"),\n ]\n\n def build_embeddings(self) -> Embeddings:\n return OpenAIEmbeddings(\n tiktoken_enabled=self.tiktoken_enable,\n default_headers=self.default_headers,\n default_query=self.default_query,\n allowed_special=\"all\",\n disallowed_special=\"all\",\n chunk_size=self.chunk_size,\n deployment=self.deployment,\n embedding_ctx_length=self.embedding_ctx_length,\n max_retries=self.max_retries,\n model=self.model,\n model_kwargs=self.model_kwargs,\n base_url=self.openai_api_base,\n api_key=self.openai_api_key,\n openai_api_type=self.openai_api_type,\n api_version=self.openai_api_version,\n organization=self.openai_organization,\n openai_proxy=self.openai_proxy,\n timeout=self.request_timeout,\n show_progress_bar=self.show_progress_bar,\n skip_empty=self.skip_empty,\n tiktoken_model_name=self.tiktoken_model_name,\n )\n" }, "default_headers": { "advanced": true, "display_name": "Default Headers", "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", + "info": "Default headers to use for the API request.", "list": false, - "load_from_db": false, - "multiline": false, "name": "default_headers", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "dict" + "type": "dict", + "value": {} }, "default_query": { "advanced": true, "display_name": "Default Query", "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", + "info": "Default query parameters to use for the API request.", "list": false, - "load_from_db": false, - "multiline": false, "name": "default_query", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "NestedDict", + "type": "dict", "value": {} }, "deployment": { "advanced": true, "display_name": "Deployment", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "deployment", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "str", - "value": "text-embedding-ada-002" - }, - "disallowed_special": { - "advanced": true, - "display_name": "Disallowed Special", - "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", - "input_types": ["Text"], - "list": true, - "load_from_db": false, - "multiline": false, - "name": "disallowed_special", - "password": false, - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "str", - "value": ["all"] + "value": "" }, "embedding_ctx_length": { "advanced": true, "display_name": "Embedding Context Length", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "embedding_ctx_length", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "int", - "value": 8191 + "value": 1536 }, "max_retries": { "advanced": true, "display_name": "Max Retries", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "max_retries", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "int", - "value": 6 + "value": 3 }, "model": { "advanced": false, "display_name": "Model", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": true, - "load_from_db": false, - "multiline": false, "name": "model", "options": [ "text-embedding-3-small", "text-embedding-3-large", "text-embedding-ada-002" ], - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "str", - "value": "text-embedding-ada-002" + "value": "text-embedding-3-small" }, "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": "NestedDict", + "type": "dict", "value": {} }, "openai_api_base": { "advanced": true, "display_name": "OpenAI API Base", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": false, - "load_from_db": false, - "multiline": false, + "input_types": [ + "Text" + ], + "load_from_db": true, "name": "openai_api_base", "password": true, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_api_key": { "advanced": false, "display_name": "OpenAI API Key", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": false, - "load_from_db": false, - "multiline": false, + "input_types": [ + "Text" + ], + "load_from_db": true, "name": "openai_api_key", "password": true, "placeholder": "", - "required": true, + "required": false, "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "openai_api_type": { "advanced": true, "display_name": "OpenAI API Type", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": false, - "load_from_db": false, - "multiline": false, + "input_types": [ + "Text" + ], + "load_from_db": true, "name": "openai_api_type", "password": true, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_api_version": { "advanced": true, "display_name": "OpenAI API Version", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "openai_api_version", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_organization": { "advanced": true, "display_name": "OpenAI Organization", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "openai_organization", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_proxy": { "advanced": true, "display_name": "OpenAI Proxy", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "openai_proxy", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "request_timeout": { "advanced": true, "display_name": "Request Timeout", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "request_timeout", - "password": false, "placeholder": "", - "rangeSpec": { - "max": 1, - "min": -1, - "step": 0.1, - "step_type": "float" - }, "required": false, "show": true, "title_case": false, - "type": "float" + "type": "float", + "value": "" }, "show_progress_bar": { "advanced": true, "display_name": "Show Progress Bar", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "show_progress_bar", - "password": false, "placeholder": "", "required": false, "show": true, @@ -940,14 +940,9 @@ "advanced": true, "display_name": "Skip Empty", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "skip_empty", - "password": false, "placeholder": "", "required": false, "show": true, @@ -959,39 +954,33 @@ "advanced": true, "display_name": "TikToken Enable", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "tiktoken_enable", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "bool", - "value": true + "value": false }, "tiktoken_model_name": { "advanced": true, "display_name": "TikToken Model Name", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "tiktoken_model_name", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" } } }, @@ -1012,7 +1001,11 @@ "data": { "id": "OpenAIModel-EjXlN", "node": { - "base_classes": ["object", "Text", "str"], + "base_classes": [ + "object", + "Text", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -1050,7 +1043,9 @@ "method": "text_response", "name": "text_output", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" }, { @@ -1059,7 +1054,9 @@ "method": "build_model", "name": "model_output", "selected": "BaseLanguageModel", - "types": ["BaseLanguageModel"], + "types": [ + "BaseLanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -1081,7 +1078,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 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, IntInput, SecretStrInput, StrInput\nfrom langflow.template import Output\n\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. You 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 BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n info=\"Enable JSON mode for the model output.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\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 json_mode = self.json_mode\n seed = self.seed\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n response_format = None\n if json_mode:\n response_format = {\"type\": \"json_object\"}\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 response_format=response_format,\n seed=seed,\n )\n\n return output\n" }, "input_value": { "advanced": false, @@ -1090,7 +1087,11 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text", "Data", "Prompt"], + "input_types": [ + "Text", + "Data", + "Prompt" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1110,7 +1111,9 @@ "fileTypes": [], "file_path": "", "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1130,7 +1133,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1150,7 +1155,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -1176,8 +1183,10 @@ "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"], + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1197,7 +1206,9 @@ "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, "multiline": false, @@ -1217,7 +1228,9 @@ "fileTypes": [], "file_path": "", "info": "Stream the response from the model. Streaming works only in Chat.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1237,7 +1250,9 @@ "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, @@ -1257,7 +1272,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1295,10 +1312,17 @@ "display_name": "Prompt", "id": "Prompt-xeI6K", "node": { - "base_classes": ["object", "Text", "str"], + "base_classes": [ + "object", + "Text", + "str" + ], "beta": false, "custom_fields": { - "template": ["context", "question"] + "template": [ + "context", + "question" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", @@ -1321,7 +1345,9 @@ "method": "build_prompt", "name": "prompt", "selected": "Prompt", - "types": ["Prompt"], + "types": [ + "Prompt" + ], "value": "__UNDEFINED__" }, { @@ -1330,7 +1356,9 @@ "method": "format_prompt", "name": "text", "selected": "Text", - "types": ["Text"], + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -1362,7 +1390,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1383,7 +1416,12 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Document", "Message", "Record", "Text"], + "input_types": [ + "Document", + "Message", + "Record", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1403,7 +1441,9 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1439,7 +1479,12 @@ "data": { "id": "ChatOutput-Q39I8", "node": { - "base_classes": ["object", "Text", "Record", "str"], + "base_classes": [ + "object", + "Text", + "Record", + "str" + ], "beta": false, "custom_fields": { "input_value": null, @@ -1464,7 +1509,20 @@ "method": "message_response", "name": "message", "selected": "Message", - "types": ["Message"], + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + }, + { + "cache": true, + "display_name": "Text", + "method": "text_response", + "name": "text", + "selected": "Text", + "types": [ + "Text" + ], "value": "__UNDEFINED__" } ], @@ -1486,7 +1544,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 langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, 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 StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 Output(display_name=\"Text\", name=\"text\", method=\"text_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) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n\n def text_response(self) -> Text:\n text = self.message_response().text\n return text\n" }, "input_value": { "advanced": false, @@ -1495,7 +1553,9 @@ "fileTypes": [], "file_path": "", "info": "Message to be passed as output.", - "input_types": ["Text", "Message"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1515,12 +1575,17 @@ "fileTypes": [], "file_path": "", "info": "Type of sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "password": false, "placeholder": "", "required": false, @@ -1536,7 +1601,9 @@ "fileTypes": [], "file_path": "", "info": "Name of the sender.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1556,7 +1623,9 @@ "fileTypes": [], "file_path": "", "info": "Session ID for the message.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -1592,7 +1661,9 @@ "data": { "id": "File-t0a6a", "node": { - "base_classes": ["Record"], + "base_classes": [ + "Record" + ], "beta": false, "custom_fields": { "path": null, @@ -1613,7 +1684,9 @@ "method": "load_file", "name": "data", "selected": "Data", - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" } ], @@ -1708,7 +1781,9 @@ "data": { "id": "RecursiveCharacterTextSplitter-tR9QM", "node": { - "base_classes": ["Record"], + "base_classes": [ + "Record" + ], "beta": false, "custom_fields": { "chunk_overlap": null, @@ -1722,7 +1797,9 @@ "field_formatters": {}, "field_order": [], "frozen": false, - "output_types": ["Data"], + "output_types": [ + "Data" + ], "outputs": [ { "cache": true, @@ -1731,7 +1808,9 @@ "method": null, "name": "data", "selected": "Data", - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" } ], @@ -1800,7 +1879,10 @@ "fileTypes": [], "file_path": "", "info": "The texts to split.", - "input_types": ["Document", "Data"], + "input_types": [ + "Document", + "Data" + ], "list": true, "load_from_db": false, "multiline": false, @@ -1819,7 +1901,9 @@ "fileTypes": [], "file_path": "", "info": "The characters to split on.\nIf left empty defaults to [\"\\n\\n\", \"\\n\", \" \", \"\"].", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -1830,7 +1914,9 @@ "show": true, "title_case": false, "type": "str", - "value": [""] + "value": [ + "" + ] } } }, @@ -1855,7 +1941,9 @@ "data": { "id": "AstraDBSearch-41nRz", "node": { - "base_classes": ["Record"], + "base_classes": [ + "Record" + ], "beta": false, "custom_fields": { "api_endpoint": null, @@ -1890,7 +1978,9 @@ ], "frozen": false, "icon": "AstraDB", - "output_types": ["Data"], + "output_types": [ + "Data" + ], "outputs": [ { "cache": true, @@ -1899,7 +1989,9 @@ "method": null, "name": "data", "selected": "Data", - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" } ], @@ -1912,7 +2004,9 @@ "fileTypes": [], "file_path": "", "info": "API endpoint URL for the Astra DB service.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2040,7 +2134,9 @@ "fileTypes": [], "file_path": "", "info": "The name of the collection within Astra DB where the vectors will be stored.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2078,7 +2174,9 @@ "fileTypes": [], "file_path": "", "info": "Input value to search", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2097,7 +2195,9 @@ "fileTypes": [], "file_path": "", "info": "Optional list of metadata fields to exclude from the indexing.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -2116,7 +2216,9 @@ "fileTypes": [], "file_path": "", "info": "Optional list of metadata fields to include in the indexing.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -2135,7 +2237,9 @@ "fileTypes": [], "file_path": "", "info": "Optional distance metric for vector comparisons in the vector store.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2154,7 +2258,9 @@ "fileTypes": [], "file_path": "", "info": "Optional namespace within Astra DB to use for the collection.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2211,12 +2317,17 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "search_type", - "options": ["Similarity", "MMR"], + "options": [ + "Similarity", + "MMR" + ], "password": false, "placeholder": "", "required": false, @@ -2232,12 +2343,18 @@ "fileTypes": [], "file_path": "", "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "setup_mode", - "options": ["Sync", "Async", "Off"], + "options": [ + "Sync", + "Async", + "Off" + ], "password": false, "placeholder": "", "required": false, @@ -2253,7 +2370,9 @@ "fileTypes": [], "file_path": "", "info": "Authentication token for accessing Astra DB.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2289,7 +2408,9 @@ "data": { "id": "AstraDB-eUCSS", "node": { - "base_classes": ["VectorStore"], + "base_classes": [ + "VectorStore" + ], "beta": false, "custom_fields": { "api_endpoint": null, @@ -2322,7 +2443,10 @@ ], "frozen": false, "icon": "AstraDB", - "output_types": ["VectorStore", "BaseRetriever"], + "output_types": [ + "VectorStore", + "BaseRetriever" + ], "outputs": [ { "cache": true, @@ -2331,7 +2455,9 @@ "method": null, "name": "vectorstore", "selected": "VectorStore", - "types": ["VectorStore"], + "types": [ + "VectorStore" + ], "value": "__UNDEFINED__" }, { @@ -2341,7 +2467,9 @@ "method": null, "name": "baseretriever", "selected": "BaseRetriever", - "types": ["BaseRetriever"], + "types": [ + "BaseRetriever" + ], "value": "__UNDEFINED__" } ], @@ -2354,7 +2482,9 @@ "fileTypes": [], "file_path": "", "info": "API endpoint URL for the Astra DB service.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2455,7 +2585,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\": \"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 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 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\": \"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 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" }, "collection_indexing_policy": { "advanced": true, @@ -2482,7 +2612,9 @@ "fileTypes": [], "file_path": "", "info": "The name of the collection within Astra DB where the vectors will be stored.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2538,7 +2670,9 @@ "fileTypes": [], "file_path": "", "info": "Optional list of metadata fields to exclude from the indexing.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -2557,7 +2691,9 @@ "fileTypes": [], "file_path": "", "info": "Optional list of metadata fields to include in the indexing.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, @@ -2576,7 +2712,9 @@ "fileTypes": [], "file_path": "", "info": "Optional distance metric for vector comparisons in the vector store.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2595,7 +2733,9 @@ "fileTypes": [], "file_path": "", "info": "Optional namespace within Astra DB to use for the collection.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2633,12 +2773,18 @@ "fileTypes": [], "file_path": "", "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": true, "load_from_db": false, "multiline": false, "name": "setup_mode", - "options": ["Sync", "Async", "Off"], + "options": [ + "Sync", + "Async", + "Off" + ], "password": false, "placeholder": "", "required": false, @@ -2654,7 +2800,9 @@ "fileTypes": [], "file_path": "", "info": "Authentication token for accessing Astra DB.", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, "multiline": false, @@ -2690,7 +2838,9 @@ "data": { "id": "OpenAIEmbeddings-9TPjc", "node": { - "base_classes": ["Embeddings"], + "base_classes": [ + "Embeddings" + ], "beta": false, "custom_fields": { "allowed_special": null, @@ -2722,53 +2872,30 @@ "field_formatters": {}, "field_order": [], "frozen": false, - "output_types": ["Embeddings"], + "icon": "OpenAI", + "output_types": [], "outputs": [ { "cache": true, "display_name": "Embeddings", - "hidden": null, - "method": null, + "method": "build_embeddings", "name": "embeddings", "selected": "Embeddings", - "types": ["Embeddings"], + "types": [ + "Embeddings" + ], "value": "__UNDEFINED__" } ], "template": { - "_type": "CustomComponent", - "allowed_special": { - "advanced": true, - "display_name": "Allowed Special", - "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", - "input_types": ["Text"], - "list": true, - "load_from_db": false, - "multiline": false, - "name": "allowed_special", - "password": false, - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "str", - "value": [] - }, + "_type": "Component", "chunk_size": { "advanced": true, "display_name": "Chunk Size", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "chunk_size", - "password": false, "placeholder": "", "required": false, "show": true, @@ -2776,6 +2903,24 @@ "type": "int", "value": 1000 }, + "client": { + "advanced": true, + "display_name": "Client", + "dynamic": false, + "info": "", + "input_types": [ + "Text" + ], + "list": false, + "load_from_db": false, + "name": "client", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "type": "str", + "value": "" + }, "code": { "advanced": true, "dynamic": true, @@ -2792,318 +2937,243 @@ "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 \"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" + "value": "from langchain_openai.embeddings.base import OpenAIEmbeddings\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import Embeddings\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n FloatInput,\n IntInput,\n SecretStrInput,\n StrInput,\n DropdownInput\n)\nfrom langflow.template import Output\n\n\nclass OpenAIEmbeddingsComponent(LCModelComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n icon = \"OpenAI\"\n inputs = [\n DictInput(\n name=\"default_headers\",\n display_name=\"Default Headers\",\n advanced=True,\n info=\"Default headers to use for the API request.\",\n ),\n DictInput(\n name=\"default_query\",\n display_name=\"Default Query\",\n advanced=True,\n info=\"Default query parameters to use for the API request.\",\n ),\n IntInput(name=\"chunk_size\", display_name=\"Chunk Size\", advanced=True, value=1000),\n StrInput(name=\"client\", display_name=\"Client\", advanced=True),\n StrInput(name=\"deployment\", display_name=\"Deployment\", advanced=True),\n IntInput(\n name=\"embedding_ctx_length\",\n display_name=\"Embedding Context Length\",\n advanced=True,\n value=1536\n ),\n IntInput(name=\"max_retries\", display_name=\"Max Retries\", value=3, advanced=True),\n DropdownInput(\n name=\"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 value=\"text-embedding-3-small\"\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n SecretStrInput(\n name=\"openai_api_base\", display_name=\"OpenAI API Base\", advanced=True\n ),\n SecretStrInput(name=\"openai_api_key\", display_name=\"OpenAI API Key\"),\n SecretStrInput(\n name=\"openai_api_type\", display_name=\"OpenAI API Type\", advanced=True\n ),\n StrInput(\n name=\"openai_api_version\", display_name=\"OpenAI API Version\", advanced=True\n ),\n StrInput(\n name=\"openai_organization\",\n display_name=\"OpenAI Organization\",\n advanced=True,\n ),\n StrInput(name=\"openai_proxy\", display_name=\"OpenAI Proxy\", advanced=True),\n FloatInput(\n name=\"request_timeout\", display_name=\"Request Timeout\", advanced=True\n ),\n BoolInput(\n name=\"show_progress_bar\", display_name=\"Show Progress Bar\", advanced=True\n ),\n BoolInput(name=\"skip_empty\", display_name=\"Skip Empty\", advanced=True),\n StrInput(\n name=\"tiktoken_model_name\",\n display_name=\"TikToken Model Name\",\n advanced=True,\n ),\n BoolInput(\n name=\"tiktoken_enable\", display_name=\"TikToken Enable\", advanced=True\n ),\n ]\n\n outputs = [\n Output(display_name=\"Embeddings\", name=\"embeddings\", method=\"build_embeddings\"),\n ]\n\n def build_embeddings(self) -> Embeddings:\n return OpenAIEmbeddings(\n tiktoken_enabled=self.tiktoken_enable,\n default_headers=self.default_headers,\n default_query=self.default_query,\n allowed_special=\"all\",\n disallowed_special=\"all\",\n chunk_size=self.chunk_size,\n deployment=self.deployment,\n embedding_ctx_length=self.embedding_ctx_length,\n max_retries=self.max_retries,\n model=self.model,\n model_kwargs=self.model_kwargs,\n base_url=self.openai_api_base,\n api_key=self.openai_api_key,\n openai_api_type=self.openai_api_type,\n api_version=self.openai_api_version,\n organization=self.openai_organization,\n openai_proxy=self.openai_proxy,\n timeout=self.request_timeout,\n show_progress_bar=self.show_progress_bar,\n skip_empty=self.skip_empty,\n tiktoken_model_name=self.tiktoken_model_name,\n )\n" }, "default_headers": { "advanced": true, "display_name": "Default Headers", "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", + "info": "Default headers to use for the API request.", "list": false, - "load_from_db": false, - "multiline": false, "name": "default_headers", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "dict" + "type": "dict", + "value": {} }, "default_query": { "advanced": true, "display_name": "Default Query", "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", + "info": "Default query parameters to use for the API request.", "list": false, - "load_from_db": false, - "multiline": false, "name": "default_query", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "NestedDict", + "type": "dict", "value": {} }, "deployment": { "advanced": true, "display_name": "Deployment", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "deployment", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "str", - "value": "text-embedding-ada-002" - }, - "disallowed_special": { - "advanced": true, - "display_name": "Disallowed Special", - "dynamic": false, - "fileTypes": [], - "file_path": "", - "info": "", - "input_types": ["Text"], - "list": true, - "load_from_db": false, - "multiline": false, - "name": "disallowed_special", - "password": false, - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "type": "str", - "value": ["all"] + "value": "" }, "embedding_ctx_length": { "advanced": true, "display_name": "Embedding Context Length", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "embedding_ctx_length", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "int", - "value": 8191 + "value": 1536 }, "max_retries": { "advanced": true, "display_name": "Max Retries", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "max_retries", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "int", - "value": 6 + "value": 3 }, "model": { "advanced": false, "display_name": "Model", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": true, - "load_from_db": false, - "multiline": false, "name": "model", "options": [ "text-embedding-3-small", "text-embedding-3-large", "text-embedding-ada-002" ], - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "str", - "value": "text-embedding-ada-002" + "value": "text-embedding-3-small" }, "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": "NestedDict", + "type": "dict", "value": {} }, "openai_api_base": { "advanced": true, "display_name": "OpenAI API Base", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": false, - "load_from_db": false, - "multiline": false, + "input_types": [ + "Text" + ], + "load_from_db": true, "name": "openai_api_base", "password": true, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_api_key": { "advanced": false, "display_name": "OpenAI API Key", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": false, - "load_from_db": false, - "multiline": false, + "input_types": [ + "Text" + ], + "load_from_db": true, "name": "openai_api_key", "password": true, "placeholder": "", - "required": true, + "required": false, "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "openai_api_type": { "advanced": true, "display_name": "OpenAI API Type", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], - "list": false, - "load_from_db": false, - "multiline": false, + "input_types": [ + "Text" + ], + "load_from_db": true, "name": "openai_api_type", "password": true, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_api_version": { "advanced": true, "display_name": "OpenAI API Version", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "openai_api_version", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_organization": { "advanced": true, "display_name": "OpenAI Organization", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "openai_organization", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "openai_proxy": { "advanced": true, "display_name": "OpenAI Proxy", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "openai_proxy", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" }, "request_timeout": { "advanced": true, "display_name": "Request Timeout", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "request_timeout", - "password": false, "placeholder": "", - "rangeSpec": { - "max": 1, - "min": -1, - "step": 0.1, - "step_type": "float" - }, "required": false, "show": true, "title_case": false, - "type": "float" + "type": "float", + "value": "" }, "show_progress_bar": { "advanced": true, "display_name": "Show Progress Bar", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "show_progress_bar", - "password": false, "placeholder": "", "required": false, "show": true, @@ -3115,14 +3185,9 @@ "advanced": true, "display_name": "Skip Empty", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "skip_empty", - "password": false, "placeholder": "", "required": false, "show": true, @@ -3134,39 +3199,33 @@ "advanced": true, "display_name": "TikToken Enable", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", "list": false, - "load_from_db": false, - "multiline": false, "name": "tiktoken_enable", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, "type": "bool", - "value": true + "value": false }, "tiktoken_model_name": { "advanced": true, "display_name": "TikToken Model Name", "dynamic": false, - "fileTypes": [], - "file_path": "", "info": "", - "input_types": ["Text"], + "input_types": [ + "Text" + ], "list": false, "load_from_db": false, - "multiline": false, "name": "tiktoken_model_name", - "password": false, "placeholder": "", "required": false, "show": true, "title_case": false, - "type": "str" + "type": "str", + "value": "" } } }, @@ -3199,4 +3258,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/processing/process.py b/src/backend/base/langflow/processing/process.py index 1b54d3f08..60f11b388 100644 --- a/src/backend/base/langflow/processing/process.py +++ b/src/backend/base/langflow/processing/process.py @@ -1,15 +1,13 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union -from loguru import logger -from pydantic import BaseModel - from langflow.graph.graph.base import Graph from langflow.graph.schema import RunOutputs from langflow.graph.vertex.base import Vertex from langflow.schema.graph import InputValue, Tweaks from langflow.schema.schema import INPUT_FIELD_NAME from langflow.services.deps import get_settings_service -from langflow.services.session.service import SessionService +from loguru import logger +from pydantic import BaseModel if TYPE_CHECKING: from langflow.api.v1.schemas import InputValueRequest @@ -27,18 +25,13 @@ async def run_graph_internal( session_id: Optional[str] = None, inputs: Optional[List["InputValueRequest"]] = None, outputs: Optional[List[str]] = None, - artifacts: Optional[Dict[str, Any]] = None, - session_service: Optional[SessionService] = None, ) -> tuple[List[RunOutputs], str]: """Run the graph and generate the result""" inputs = inputs or [] - graph_data = graph._graph_data - if session_id is None and session_service is not None: - session_id_str = session_service.generate_key(session_id=flow_id, data_graph=graph_data) - elif session_id is not None: - session_id_str = session_id + if session_id is None: + session_id_str = flow_id else: - raise ValueError("session_id or session_service must be provided") + session_id_str = session_id components = [] inputs_list = [] types = [] @@ -53,16 +46,14 @@ async def run_graph_internal( fallback_to_env_vars = get_settings_service().settings.fallback_to_env_var run_outputs = await graph.arun( - inputs_list, - components, - types, - outputs or [], + inputs=inputs_list, + inputs_components=components, + types=types, + outputs=outputs or [], stream=stream, session_id=session_id_str or "", fallback_to_env_vars=fallback_to_env_vars, ) - if session_id_str and session_service: - await session_service.update_session(session_id_str, (graph, artifacts)) return run_outputs, session_id_str diff --git a/src/backend/base/langflow/services/monitor/service.py b/src/backend/base/langflow/services/monitor/service.py index c7d898d11..d6e071881 100644 --- a/src/backend/base/langflow/services/monitor/service.py +++ b/src/backend/base/langflow/services/monitor/service.py @@ -4,19 +4,21 @@ from typing import TYPE_CHECKING, List, Optional, Union import duckdb 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 + from langflow.services.monitor.schema import MessageModel, TransactionModel, VertexBuildModel class MonitorService(Service): name = "monitor_service" def __init__(self, settings_service: "SettingsService"): + from langflow.services.monitor.schema import MessageModel, TransactionModel, VertexBuildModel + self.settings_service = settings_service self.base_cache_dir = Path(user_cache_dir("langflow")) self.db_path = self.base_cache_dir / "monitor.duckdb" @@ -45,7 +47,7 @@ class MonitorService(Service): def add_row( self, table_name: str, - data: Union[dict, TransactionModel, MessageModel, VertexBuildModel], + data: Union[dict, "TransactionModel", "MessageModel", "VertexBuildModel"], ): # Make sure the model passed matches the table @@ -127,7 +129,7 @@ class MonitorService(Service): return self.exec_query(query, read_only=False) - def add_message(self, message: MessageModel): + def add_message(self, message: "MessageModel"): self.add_row("messages", message) def get_messages( diff --git a/src/backend/base/poetry.lock b/src/backend/base/poetry.lock index b61c9fbe2..adf1ad968 100644 --- a/src/backend/base/poetry.lock +++ b/src/backend/base/poetry.lock @@ -337,6 +337,17 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + [[package]] name = "charset-normalizer" version = "3.3.2" @@ -1158,19 +1169,19 @@ files = [ [[package]] name = "langchain" -version = "0.2.4" +version = "0.2.5" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.4-py3-none-any.whl", hash = "sha256:a04813215c30f944df006031e2febde872af8fab628dcee825d969e07b6cd621"}, - {file = "langchain-0.2.4.tar.gz", hash = "sha256:e704b5b06222d5eba2d02c76f891321d1bac8952ed54e093831b2bdabf99dcd5"}, + {file = "langchain-0.2.5-py3-none-any.whl", hash = "sha256:9aded9a65348254e1c93dcdaacffe4d1b6a5e7f74ef80c160c88ff78ad299228"}, + {file = "langchain-0.2.5.tar.gz", hash = "sha256:ffdbf4fcea46a10d461bcbda2402220fcfd72a0c70e9f4161ae0510067b9b3bd"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -langchain-core = ">=0.2.6,<0.3.0" +langchain-core = ">=0.2.7,<0.3.0" langchain-text-splitters = ">=0.2.0,<0.3.0" langsmith = ">=0.1.17,<0.2.0" numpy = [ @@ -1185,22 +1196,25 @@ tenacity = ">=8.1.0,<9.0.0" [[package]] name = "langchain-community" -version = "0.2.4" +version = "0.2.5" description = "Community contributed LangChain integrations." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_community-0.2.4-py3-none-any.whl", hash = "sha256:8582e9800f4837660dc297cccd2ee1ddc1d8c440d0fe8b64edb07620f0373b0e"}, - {file = "langchain_community-0.2.4.tar.gz", hash = "sha256:2bb6a1a36b8500a564d25d76469c02457b1a7c3afea6d4a609a47c06b993e3e4"}, + {file = "langchain_community-0.2.5-py3-none-any.whl", hash = "sha256:bf37a334952e42c7676d083cf2d2c4cbfbb7de1949c4149fe19913e2b06c485f"}, + {file = "langchain_community-0.2.5.tar.gz", hash = "sha256:476787b8c8c213b67e7b0eceb53346e787f00fbae12d8e680985bd4f93b0bf64"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" dataclasses-json = ">=0.5.7,<0.7" -langchain = ">=0.2.0,<0.3.0" -langchain-core = ">=0.2.0,<0.3.0" +langchain = ">=0.2.5,<0.3.0" +langchain-core = ">=0.2.7,<0.3.0" langsmith = ">=0.1.0,<0.2.0" -numpy = ">=1,<2" +numpy = [ + {version = ">=1,<2", markers = "python_version < \"3.12\""}, + {version = ">=1.26.0,<2.0.0", markers = "python_version >= \"3.12\""}, +] PyYAML = ">=5.3" requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" @@ -1208,13 +1222,13 @@ tenacity = ">=8.1.0,<9.0.0" [[package]] name = "langchain-core" -version = "0.2.6" +version = "0.2.7" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.6-py3-none-any.whl", hash = "sha256:90521c9fc95d8f925e0d2e2d952382676aea6d3f8de611eda1b1810874c31e5d"}, - {file = "langchain_core-0.2.6.tar.gz", hash = "sha256:9f0e38da722a558a6e95b6d86de01bd92e84558c47ac8ba599f02eab70a1c873"}, + {file = "langchain_core-0.2.7-py3-none-any.whl", hash = "sha256:fd02e153c898486dd728d634684ffc64bc257ff2ba443dc7e53d017ac0bf4658"}, + {file = "langchain_core-0.2.7.tar.gz", hash = "sha256:b0b1b6dfbdedb39426fcb8bd3f07e40eec7964856e3fc384c420ca6dba61b34e"}, ] [package.dependencies] @@ -1227,21 +1241,18 @@ tenacity = ">=8.1.0,<9.0.0" [[package]] name = "langchain-experimental" -version = "0.0.60" +version = "0.0.61" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_experimental-0.0.60-py3-none-any.whl", hash = "sha256:ef3b6b6b84fe2bfe19eba6d1a98005e27d96576514c6415f5afe4ace5bf477d8"}, - {file = "langchain_experimental-0.0.60.tar.gz", hash = "sha256:a16cbcd18cda6b86be8f41fed7963c13569295def0d8b4c6324b806d878d442c"}, + {file = "langchain_experimental-0.0.61-py3-none-any.whl", hash = "sha256:f9c516f528f55919743bd56fe1689a53bf74ae7f8902d64b9d8aebc61249cbe2"}, + {file = "langchain_experimental-0.0.61.tar.gz", hash = "sha256:e9538efb994be5db3045cc582cddb9787c8299c86ffeee9d3779b7f58eef2226"}, ] [package.dependencies] -langchain-community = ">=0.2,<0.3" -langchain-core = ">=0.2,<0.3" - -[package.extras] -extended-testing = ["faker (>=19.3.1,<20.0.0)", "jinja2 (>=3,<4)", "pandas (>=2.0.1,<3.0.0)", "presidio-analyzer (>=2.2.352,<3.0.0)", "presidio-anonymizer (>=2.2.352,<3.0.0)", "sentence-transformers (>=2,<3)", "tabulate (>=0.9.0,<0.10.0)", "vowpal-wabbit-next (==0.6.0)"] +langchain-community = ">=0.2.5,<0.3.0" +langchain-core = ">=0.2.7,<0.3.0" [[package]] name = "langchain-text-splitters" @@ -3297,4 +3308,4 @@ local = [] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "72f05330f1e734596d160b45cb68ab2ebf7d0824314bec0566bddb5b2043f4e6" +content-hash = "73dc20fcd3c34d40dd31c9251efc8e2d8d3346f2f1bc18be516acf57c86ce460" diff --git a/src/backend/base/pyproject.toml b/src/backend/base/pyproject.toml index 1762b645d..e3e3630f5 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.68" +version = "0.0.70" description = "A Python package with a built-in web application" authors = ["Langflow "] maintainers = [ @@ -64,6 +64,7 @@ asyncer = "^0.0.5" pyperclip = "^1.8.2" uncurl = "^0.0.11" sentry-sdk = "^2.5.1" +chardet = "^5.2.0" [tool.poetry.extras] diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index b4b86cfd1..c2d3e3f03 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -99,12 +99,11 @@ "@vitejs/plugin-react-swc": "^3.3.2", "autoprefixer": "^10.4.15", "daisyui": "^4.0.4", - "eslint": "^8.57.0", - "eslint-plugin-node": "^11.1.0", + "eslint": "^9.5.0", "postcss": "^8.4.29", - "prettier": "^2.8.8", + "prettier": "^3.3.2", "prettier-plugin-organize-imports": "^3.2.3", - "prettier-plugin-tailwindcss": "^0.3.0", + "prettier-plugin-tailwindcss": "^0.6.4", "simple-git-hooks": "^2.11.1", "tailwindcss": "^3.3.3", "tailwindcss-dotted-background": "^1.1.0", @@ -799,6 +798,18 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", @@ -808,16 +819,52 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", + "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -825,7 +872,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -842,15 +889,12 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -869,12 +913,21 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", + "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@floating-ui/core": { @@ -935,43 +988,6 @@ "react-hook-form": "^7.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "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", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -985,12 +1001,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "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/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -3277,9 +3299,9 @@ } }, "node_modules/@swc/core": { - "version": "1.5.28", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.28.tgz", - "integrity": "sha512-muCdNIqOTURUgYeyyOLYE3ShL8SZO6dw6bhRm6dCvxWzCZOncPc5fB0kjcPXTML+9KJoHL7ks5xg+vsQK+v6ig==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.6.0.tgz", + "integrity": "sha512-Wynbo79uIVBgmq3TPcTMdtXUkqk69IPSVuzo7/Jl1OhR4msC7cUaoRB1216ZanWttrAZ4/g6u17w9XZG4fzp1A==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -3294,16 +3316,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@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" + "@swc/core-darwin-arm64": "1.6.0", + "@swc/core-darwin-x64": "1.6.0", + "@swc/core-linux-arm-gnueabihf": "1.6.0", + "@swc/core-linux-arm64-gnu": "1.6.0", + "@swc/core-linux-arm64-musl": "1.6.0", + "@swc/core-linux-x64-gnu": "1.6.0", + "@swc/core-linux-x64-musl": "1.6.0", + "@swc/core-win32-arm64-msvc": "1.6.0", + "@swc/core-win32-ia32-msvc": "1.6.0", + "@swc/core-win32-x64-msvc": "1.6.0" }, "peerDependencies": { "@swc/helpers": "*" @@ -3315,9 +3337,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.0.tgz", + "integrity": "sha512-W1Mwk0WRrJ5lAVkYRPxpxOmwu8p9ASXeOmiORhXvE7DYREyI30005xlqSOITU1pfSNKj7G9u3+9DjsOzPPPbBw==", "cpu": [ "arm64" ], @@ -3331,9 +3353,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.6.0.tgz", + "integrity": "sha512-EzxLnpPC1zgLb2Y0iVUG6b+/GUv43k6uJUIs52UzxOnBElYP/WeItI3RJ+LUMFzCpZMk/IxB10wofEoeQ1H/Xg==", "cpu": [ "x64" ], @@ -3347,9 +3369,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.0.tgz", + "integrity": "sha512-uP/STDjWZ5N6lc8mxJFsex4NXDaqhfzd8UOrI3LfdV97+4faE4/BC6bVqDNHFFzZi0PHuVBxD6md7IfPjugk6A==", "cpu": [ "arm" ], @@ -3363,9 +3385,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.0.tgz", + "integrity": "sha512-UgNz6anowcnYzJtZohzpii31FOgouBHJqluiq+p2geX/agbC+KfOKwVXdljn95+Qc4ygBuw/hjKjgF2msOLeVg==", "cpu": [ "arm64" ], @@ -3379,9 +3401,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.0.tgz", + "integrity": "sha512-xPV6qrnj4nFwXQbIv70C1Kn5z5Th53sirIY76aEonr78qeC6+ywaBZR4uLFNHsljVjyuvVQfTTcl2qraGhu6oQ==", "cpu": [ "arm64" ], @@ -3395,9 +3417,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.0.tgz", + "integrity": "sha512-xTeWn4OT5uQ+DxT2cy94ngK8tF1U/5fMC49/V6FhCS2Wh+Xa/O+OWcOyKvYtk3b0eGYS4iNIRKgzog7fLSFtvQ==", "cpu": [ "x64" ], @@ -3411,9 +3433,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.0.tgz", + "integrity": "sha512-3P01mYD5XbyaVLT0MGZmZE+ZdgmGSvuvIhSejRDBlEXqkFnH79nWds+KsE+91hzVU8XsgzX57Yzv4eO5dlIuPw==", "cpu": [ "x64" ], @@ -3427,9 +3449,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.0.tgz", + "integrity": "sha512-xFuook1efU0ctzMAEeol4eI7J6+k/c/pMJpp/NP/4JJDnhlHwAi2iyiZcID8YZS+ePHgXMLndGdIMHVv/wIPkQ==", "cpu": [ "arm64" ], @@ -3443,9 +3465,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.0.tgz", + "integrity": "sha512-VCJa5vTywxzASqvf9OEUM5SZBcNrWbuIkSGM5T9guuBzyrh/tSqVHjzOWL9qpP69uPVj5G/I5bJObLiUKErhvQ==", "cpu": [ "ia32" ], @@ -3459,9 +3481,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "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==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.0.tgz", + "integrity": "sha512-L7i8WBSIJTQiMONJGHnznDydZmlJIqHjZ3VhBHeTTms8cEAuwkAVgzPwgr5cD9GhmcwdeBI9iYdOuKr1pUx19Q==", "cpu": [ "x64" ], @@ -4356,12 +4378,6 @@ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.0.tgz", @@ -4392,9 +4408,9 @@ "integrity": "sha512-bwDKqjqNccC/MSujqnYTeAS5dIR8UmGLP0R90mvsJY0FRC8NUWBSTfj34+EIzo2NWc/gV8IZTqv4fXaiZJpCtA==" }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "bin": { "acorn": "bin/acorn" }, @@ -4421,9 +4437,12 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -5009,9 +5028,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001632", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz", - "integrity": "sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg==", + "version": "1.0.30001634", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001634.tgz", + "integrity": "sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA==", "funding": [ { "type": "opencollective", @@ -5802,18 +5821,6 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -5863,9 +5870,9 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.799", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.799.tgz", - "integrity": "sha512-3D3DwWkRTzrdEpntY0hMLYwj7SeBk1138CkPE8sBDSj3WzrzOiG2rHm3luw8jucpf+WiyLBCZyU9lMHyQI9M9Q==" + "version": "1.4.803", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.803.tgz", + "integrity": "sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==" }, "node_modules/emoji-regex": { "version": "10.3.0", @@ -6020,41 +6027,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", + "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/config-array": "^0.16.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.5.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.1", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -6068,120 +6071,35 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-node/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "url": "https://eslint.org/donate" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6258,21 +6176,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6315,17 +6218,17 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", + "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6601,15 +6504,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-saver": { @@ -6706,17 +6609,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -6754,9 +6656,9 @@ } }, "node_modules/foreground-child": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.0.tgz", - "integrity": "sha512-CrWQNaEl1/6WeZoarcM9LHupTo3RpZO2Pdk1vktwzPiQTsJnAKJmm3TACKeG5UZbWDfaH2AbvYxzP96y0MT7fA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -6895,7 +6797,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true + "optional": true }, "node_modules/fsevents": { "version": "2.3.2", @@ -6997,7 +6899,7 @@ "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, + "optional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7028,7 +6930,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "optional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7038,7 +6940,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "optional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7096,12 +6998,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -7482,7 +7378,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "devOptional": true, + "optional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -10040,7 +9936,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, + "optional": true, "engines": { "node": ">=0.10.0" } @@ -10368,15 +10264,15 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -10403,20 +10299,20 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.3.0.tgz", - "integrity": "sha512-009/Xqdy7UmkcTBpwlq7jsViDqXAYSOMLDrHAdTMlVZOrKfM2o9Ci7EMWTMZ7SkKBFTG04UM9F9iM2+4i6boDA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.4.tgz", + "integrity": "sha512-3vhbIvlKyAWPaw9bUr2cw6M1BGx2Oy9CCLJyv+nxEiBGCTcL69WcAz2IFMGqx8IXSzQCInGSo2ujAByg9poHLQ==", "dev": true, "engines": { - "node": ">=12.17.0" + "node": ">=14.21.3" }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", - "@shufo/prettier-plugin-blade": "*", "@trivago/prettier-plugin-sort-imports": "*", - "prettier": ">=2.2.0", + "@zackad/prettier-plugin-twig-melody": "*", + "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", @@ -10424,9 +10320,9 @@ "prettier-plugin-marko": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*", - "prettier-plugin-twig-melody": "*" + "prettier-plugin-svelte": "*" }, "peerDependenciesMeta": { "@ianvs/prettier-plugin-sort-imports": { @@ -10438,10 +10334,10 @@ "@shopify/prettier-plugin-liquid": { "optional": true }, - "@shufo/prettier-plugin-blade": { + "@trivago/prettier-plugin-sort-imports": { "optional": true }, - "@trivago/prettier-plugin-sort-imports": { + "@zackad/prettier-plugin-twig-melody": { "optional": true }, "prettier-plugin-astro": { @@ -10465,14 +10361,14 @@ "prettier-plugin-organize-imports": { "optional": true }, + "prettier-plugin-sort-imports": { + "optional": true + }, "prettier-plugin-style-order": { "optional": true }, "prettier-plugin-svelte": { "optional": true - }, - "prettier-plugin-twig-melody": { - "optional": true } } }, @@ -11079,18 +10975,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/rehype-mathjax": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/rehype-mathjax/-/rehype-mathjax-4.0.3.tgz", @@ -11245,7 +11129,7 @@ "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, + "optional": true, "dependencies": { "glob": "^7.1.3" }, @@ -12395,18 +12279,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -12444,9 +12316,9 @@ } }, "node_modules/undici": { - "version": "6.18.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.2.tgz", - "integrity": "sha512-o/MQLTwRm9IVhOqhZ0NQ9oXax1ygPjw6Vs+Vq/4QRjbOAC3B1GCHy7TYxxbExKlb7bzDRzt9vBWU6BDz0RFfYg==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.0.tgz", + "integrity": "sha512-9gGwbSLgYMjp4r6M5P9bhqhx1E+RyUIHqZE0r7BmrRoqroJUG6xlVu5TXH9DnwmCPLkcaVNrcYtxUE9d3InnyQ==", "engines": { "node": ">=18.17" } diff --git a/src/frontend/package.json b/src/frontend/package.json index ca1717f26..f3eb36409 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -121,12 +121,11 @@ "@vitejs/plugin-react-swc": "^3.3.2", "autoprefixer": "^10.4.15", "daisyui": "^4.0.4", - "eslint": "^8.57.0", - "eslint-plugin-node": "^11.1.0", + "eslint": "^9.5.0", "postcss": "^8.4.29", - "prettier": "^2.8.8", + "prettier": "^3.3.2", "prettier-plugin-organize-imports": "^3.2.3", - "prettier-plugin-tailwindcss": "^0.3.0", + "prettier-plugin-tailwindcss": "^0.6.4", "simple-git-hooks": "^2.11.1", "tailwindcss": "^3.3.3", "tailwindcss-dotted-background": "^1.1.0", diff --git a/src/frontend/prettier.config.js b/src/frontend/prettier.config.js index f01cc7a68..d57311886 100644 --- a/src/frontend/prettier.config.js +++ b/src/frontend/prettier.config.js @@ -1,3 +1,3 @@ module.exports = { - plugins: [require("prettier-plugin-tailwindcss")], + plugins: ["prettier-plugin-tailwindcss"], }; diff --git a/src/frontend/src/CustomNodes/GenericNode/components/outputModal/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/outputModal/index.tsx index 33485387f..e34ee6ec1 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/outputModal/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/outputModal/index.tsx @@ -19,7 +19,7 @@ export default function OutputModal({ -
+
diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 095cc5d84..aee1dbd33 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -114,7 +114,7 @@ export default function ParameterComponent({ const logs = (data?.logs[outputName] ?? [])[0]; if (Array.isArray(logs) && logs.length > 1) { return logs.some( - (log) => log.type === "error" || log.type === "ValueError", + (log) => log.type === "error" || log.type === "ValueError" ); } else { return logs?.type === "error" || logs?.type === "ValueError"; @@ -156,7 +156,7 @@ export default function ParameterComponent({ handleUpdateValues, debouncedHandleUpdateValues, setNode, - setIsLoading, + setIsLoading ); const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( @@ -164,7 +164,7 @@ export default function ParameterComponent({ name, takeSnapshot, setNode, - updateNodeInternals, + updateNodeInternals ); const { handleRefreshButtonPress: handleRefreshButtonPressHook } = @@ -173,13 +173,13 @@ export default function ParameterComponent({ let disabled = edges.some( (edge) => - edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id), + edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) ) ?? false; let disabledOutput = edges.some( (edge) => - edge.sourceHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id), + edge.sourceHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) ) ?? false; const handleRefreshButtonPress = async (name, data) => { @@ -190,7 +190,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); }; @@ -302,16 +302,16 @@ export default function ParameterComponent({ isValidConnection(connection, nodes, edges) } className={classNames( - left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", + 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, }} onClick={() => { setFilterEdge( - groupByFamily(myData, tooltipTitle!, left, nodes!), + groupByFamily(myData, tooltipTitle!, left, nodes!) ); }} > @@ -326,7 +326,7 @@ export default function ParameterComponent({ "relative mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2" + ((name === "code" && type === "code") || (name.includes("code") && proxy) - ? " hidden " + ? " hidden" : "") } > @@ -389,7 +389,7 @@ export default function ParameterComponent({ {errorOutput ? ( @@ -399,7 +399,7 @@ export default function ParameterComponent({ "h-5 w-5 rounded-md", displayOutputPreview && !unknownOutput ? " hover:text-medium-indigo" - : " cursor-not-allowed text-muted-foreground", + : " cursor-not-allowed text-muted-foreground" )} name={"ScanEye"} /> @@ -457,12 +457,12 @@ export default function ParameterComponent({ } className={classNames( left ? "-ml-0.5" : "-mr-0.5", - "h-3 w-3 rounded-full border-2 bg-background", + "h-3 w-3 rounded-full border-2 bg-background" )} style={{ borderColor: color ?? nodeColors.unknown }} onClick={() => { setFilterEdge( - groupByFamily(myData, tooltipTitle!, left, nodes!), + groupByFamily(myData, tooltipTitle!, left, nodes!) ); }} /> @@ -502,7 +502,7 @@ export default function ParameterComponent({
-
+
@@ -714,10 +714,7 @@ export default function GenericNode({ nameEditable ? ( "Double Click to Edit Description" ) : ( - + {String(data.node?.description)} )} diff --git a/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx b/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx index 953305c84..e3e562174 100644 --- a/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx @@ -83,7 +83,7 @@ export default function SingleAlert({
diff --git a/src/frontend/src/alerts/alertDropDown/index.tsx b/src/frontend/src/alerts/alertDropDown/index.tsx index 6eff32fe2..597431884 100644 --- a/src/frontend/src/alerts/alertDropDown/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/index.tsx @@ -39,7 +39,7 @@ export default function AlertDropdown({
Notifications -
+
-
+
); } diff --git a/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx b/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx index d75bf625c..d56a0e608 100644 --- a/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx +++ b/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx @@ -92,7 +92,7 @@ export default function AddNewVariableButton({ Create Variable
diff --git a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx index cbdb541b4..4b0ac5373 100644 --- a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx +++ b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx @@ -84,8 +84,8 @@ export default function TableOptions({ diff --git a/src/frontend/src/components/tableComponent/components/loadingOverlay/index.tsx b/src/frontend/src/components/tableComponent/components/loadingOverlay/index.tsx index 9df9144e0..3f5e8c1cd 100644 --- a/src/frontend/src/components/tableComponent/components/loadingOverlay/index.tsx +++ b/src/frontend/src/components/tableComponent/components/loadingOverlay/index.tsx @@ -2,7 +2,7 @@ import Loading from "../../../ui/loading"; export default function LoadingOverlay() { return ( -
+
); diff --git a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx index 6576fdecd..427eca50b 100644 --- a/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx +++ b/src/frontend/src/components/tableComponent/components/tableAutoCellRender/index.tsx @@ -45,7 +45,19 @@ export default function TableAutoCellRender({ "min-w-min bg-error-background text-error-foreground hover:bg-error-background", )} > - {value} + Success + + ); + } else if (value === "failure") { + return ( + + Failure ); } else { diff --git a/src/frontend/src/components/tagsSelectorComponent/index.tsx b/src/frontend/src/components/tagsSelectorComponent/index.tsx index 6f84ae7c3..6bf0c1d3c 100644 --- a/src/frontend/src/components/tagsSelectorComponent/index.tsx +++ b/src/frontend/src/components/tagsSelectorComponent/index.tsx @@ -33,7 +33,7 @@ export function TagsSelector({ className={ disabled ? "cursor-not-allowed" - : " overflow-hidden whitespace-nowrap" + : "overflow-hidden whitespace-nowrap" } onClick={() => { updateTags(tag.name); diff --git a/src/frontend/src/components/textAreaComponent/index.tsx b/src/frontend/src/components/textAreaComponent/index.tsx index 650700f21..7bd10153b 100644 --- a/src/frontend/src/components/textAreaComponent/index.tsx +++ b/src/frontend/src/components/textAreaComponent/index.tsx @@ -28,7 +28,7 @@ export default function TextAreaComponent({ data-testid={id} value={value} disabled={disabled} - className={editNode ? "input-edit-node w-full" : " w-full"} + className={editNode ? "input-edit-node w-full" : "w-full"} placeholder={"Type something..."} onChange={(event) => { onChange(event.target.value); diff --git a/src/frontend/src/components/ui/accordion.tsx b/src/frontend/src/components/ui/accordion.tsx index d7862e1e5..3efc7518a 100644 --- a/src/frontend/src/components/ui/accordion.tsx +++ b/src/frontend/src/components/ui/accordion.tsx @@ -34,7 +34,7 @@ const AccordionTrigger = React.forwardRef<
svg]:rotate-180", - className, + className )} > {children} @@ -46,7 +46,7 @@ const AccordionTrigger = React.forwardRef< @@ -64,7 +64,7 @@ const AccordionContent = React.forwardRef< ref={ref} className={cn( "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm", - className, + className )} {...props} > diff --git a/src/frontend/src/components/ui/card.tsx b/src/frontend/src/components/ui/card.tsx index d986c5530..eb9bd7b56 100644 --- a/src/frontend/src/components/ui/card.tsx +++ b/src/frontend/src/components/ui/card.tsx @@ -69,7 +69,7 @@ const CardFooter = React.forwardRef< >(({ className, ...props }, ref) => (
)); diff --git a/src/frontend/src/components/ui/custom-accordion.tsx b/src/frontend/src/components/ui/custom-accordion.tsx index 9ce39b8a7..b43c0f71c 100644 --- a/src/frontend/src/components/ui/custom-accordion.tsx +++ b/src/frontend/src/components/ui/custom-accordion.tsx @@ -23,7 +23,7 @@ const AccordionTrigger = React.forwardRef<
svg]:rotate-180", + "flex flex-1 cursor-pointer items-center justify-between border-[1px] py-2 text-sm font-medium data-[state=closed]:rounded-md data-[state=open]:rounded-t-md data-[state=open]:border-b-0 data-[state=open]:bg-muted [&[data-state=open]>svg]:rotate-180", className )} > diff --git a/src/frontend/src/components/ui/dialog.tsx b/src/frontend/src/components/ui/dialog.tsx index 5a0b1d587..76b86f592 100644 --- a/src/frontend/src/components/ui/dialog.tsx +++ b/src/frontend/src/components/ui/dialog.tsx @@ -64,7 +64,7 @@ const DialogHeader = ({ }: React.HTMLAttributes) => (