merge dev into two_edges

This commit is contained in:
cristhianzl 2024-06-17 10:01:28 -03:00
commit fcf4512210
133 changed files with 2534 additions and 1507 deletions

View file

@ -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:

View file

@ -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'

View file

@ -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 }}

View file

@ -42,4 +42,4 @@ jobs:
poetry install
- name: Run unit tests
run: |
make tests args="-n auto"
make unit_tests args="-n auto"

View file

@ -13,6 +13,7 @@ env:
jobs:
lint:
name: Ruff Style Check
runs-on: ubuntu-latest
strategy:
matrix:

2
.gitignore vendored
View file

@ -271,4 +271,4 @@ prof/*
src/frontend/temp
*.db-shm
*.db-wal
*.db-wal

View file

@ -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

View file

@ -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:

View file

@ -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.
<div
style={{ marginBottom: "20px", display: "flex", justifyContent: "center" }}
@ -92,6 +92,10 @@ Langflow components can be edited by clicking the component settings button. Hid
<ReactPlayer playing controls url="/videos/langflow_parameters.mp4" />
</div>
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.

View file

@ -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**

View file

@ -14,7 +14,7 @@ In this guide, we will use Astra DB as a vector store to store and retrieve the
<Admonition type="tip">
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.
</Admonition>
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.
<ZoomableImage
alt="Docusaurus themed image"
sources={{
light: "img/astra-rag-flow-run.png",
dark: "img/astra-rag-flow-run.png",
dark: "img/astra-rag-flow-run.png"
}}
style={{ width: "80%", margin: "20px auto" }}
/>
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";

96
poetry.lock generated
View file

@ -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)"]

View file

@ -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 <contact@langflow.org>"]
maintainers = [

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -89,6 +89,7 @@ class AstraDBMessageWriterComponent(BaseMemoryComponent):
sender_name=sender_name,
metadata=metadata,
session_id=session_id,
type=sender,
)
]

View file

@ -164,4 +164,3 @@ class AstraDBVectorStoreComponent(CustomComponent):
)
return vector_store
return vector_store

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -73,6 +73,7 @@ INPUT_COMPONENTS = [
OUTPUT_COMPONENTS = [
InterfaceComponentTypes.ChatOutput,
InterfaceComponentTypes.TextOutput,
InterfaceComponentTypes.DataOutput,
]

View file

@ -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)"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -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(

View file

@ -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"

View file

@ -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 <contact@langflow.org>"]
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]

View file

@ -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"
}

View file

@ -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",

View file

@ -1,3 +1,3 @@
module.exports = {
plugins: [require("prettier-plugin-tailwindcss")],
plugins: ["prettier-plugin-tailwindcss"],
};

View file

@ -19,7 +19,7 @@ export default function OutputModal({
<SwitchOutputView nodeId={nodeId} outputName={outputName} />
</BaseModal.Content>
<BaseModal.Footer>
<div className="flex w-full justify-end pt-2">
<div className="flex w-full justify-end pt-2">
<Button className="flex gap-2 px-3" onClick={() => setOpen(false)}>
Close
</Button>

View file

@ -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<void> => {
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!)
);
}}
></Handle>
@ -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 ? (
<IconComponent
className={classNames(
"h-5 w-5 rounded-md text-status-red",
"h-5 w-5 rounded-md text-status-red"
)}
name={"X"}
/>
@ -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({
</div>
</Case>
<Case condition={data.node?.template[name]?.multiline}>
<div className="mt-2 flex w-full flex-col ">
<div className="mt-2 flex w-full flex-col">
<div className="flex-grow">
<TextAreaComponent
disabled={disabled}

View file

@ -376,14 +376,14 @@ export default function GenericNode({
className={
"generic-node-div-title " +
(!showNode
? " relative h-24 w-24 rounded-full "
: " justify-between rounded-t-lg ")
? " relative h-24 w-24 rounded-full"
: " justify-between rounded-t-lg")
}
>
<div
className={
"generic-node-title-arrangement rounded-full" +
(!showNode && " justify-center ")
(!showNode && " justify-center")
}
data-testid="generic-node-title-arrangement"
>
@ -714,10 +714,7 @@ export default function GenericNode({
nameEditable ? (
"Double Click to Edit Description"
) : (
<Markdown
className="markdown prose flex flex-col text-primary word-break-break-word
dark:prose-invert"
>
<Markdown className="markdown prose flex flex-col text-primary word-break-break-word dark:prose-invert">
{String(data.node?.description)}
</Markdown>
)}

View file

@ -83,7 +83,7 @@ export default function SingleAlert({
<div className="flex-shrink-0 cursor-help">
<IconComponent
name="Info"
className="h-5 w-5 text-status-blue "
className="h-5 w-5 text-status-blue"
aria-hidden="true"
/>
</div>

View file

@ -39,7 +39,7 @@ export default function AlertDropdown({
<PopoverContent className="nocopy nowheel nopan nodelete nodrag noundo flex h-[500px] w-[500px] flex-col">
<div className="text-md flex flex-row justify-between pl-3 font-medium text-foreground">
Notifications
<div className="flex gap-3 pr-3 ">
<div className="flex gap-3 pr-3">
<button
className="text-foreground hover:text-status-red"
onClick={() => {

View file

@ -42,7 +42,7 @@ export default function NoticeAlert({
<div className="flex-shrink-0 cursor-help">
<IconComponent
name="Info"
className="h-5 w-5 text-status-blue "
className="h-5 w-5 text-status-blue"
aria-hidden="true"
/>
</div>

View file

@ -81,8 +81,8 @@ export default function ImageViewer({ image }) {
}
return image === "" ? (
<div className="align-center flex h-full w-full flex-col justify-center gap-5 rounded-md border border-border bg-muted">
<div className="align-center flex justify-center gap-2 ">
<div className="align-center flex h-full w-full flex-col justify-center gap-5 rounded-md border border-border bg-muted">
<div className="align-center flex justify-center gap-2">
<ForwardedIconComponent name="Image" />
{IMGViewErrorTitle}
</div>
@ -95,10 +95,10 @@ export default function ImageViewer({ image }) {
) : (
<>
<div className="align-center my-2 mb-4 flex w-full justify-center">
<div className="shadow-round-btn-shadow hover:shadow-round-btn-shadow flex w-[50%] items-center justify-center rounded-sm border bg-muted shadow-md transition-all">
<div className="shadow-round-btn-shadow hover:shadow-round-btn-shadow flex w-[50%] items-center justify-center rounded-sm border bg-muted shadow-md transition-all">
<button
id="zoom-in-button"
className="relative inline-flex w-full w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover"
>
<ForwardedIconComponent
name="ZoomIn"
@ -110,7 +110,7 @@ export default function ImageViewer({ image }) {
</div>
<button
id="zoom-out-button"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover"
>
<ForwardedIconComponent
name="ZoomOut"
@ -122,7 +122,7 @@ export default function ImageViewer({ image }) {
</div>
<button
id="home-button"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover"
>
<ForwardedIconComponent
name="RotateCcw"
@ -134,7 +134,7 @@ export default function ImageViewer({ image }) {
</div>
<button
id="full-page-button"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover"
>
<ForwardedIconComponent
name="Maximize2"
@ -147,7 +147,7 @@ export default function ImageViewer({ image }) {
<button
onClick={download}
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover"
>
<ForwardedIconComponent
name="ArrowDownToLine"
@ -156,7 +156,7 @@ export default function ImageViewer({ image }) {
</button>
</div>
</div>
<div id="canvas" ref={viewerRef} className={`h-[90%] w-full `} />
<div id="canvas" ref={viewerRef} className={`h-[90%] w-full`} />
</>
);
}

View file

@ -92,7 +92,7 @@ export default function AddNewVariableButton({
<span className="pr-2"> Create Variable </span>
<ForwardedIconComponent
name="Globe"
className="h-6 w-6 pl-1 text-primary "
className="h-6 w-6 pl-1 text-primary"
aria-hidden="true"
/>
</BaseModal.Header>

View file

@ -262,10 +262,7 @@ export default function CollectionCardComponent({
)}
<ShadTooltip content="Likes">
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconComponent
name="Heart"
className={cn("h-4 w-4 ")}
/>
<IconComponent name="Heart" className={cn("h-4 w-4")} />
<span data-testid={`likes-${data.name}`}>
{likes_count ?? 0}
</span>
@ -428,7 +425,7 @@ export default function CollectionCardComponent({
name="Trash2"
className={cn(
"h-5 w-5",
!authorized ? " text-ring" : ""
!authorized ? "text-ring" : ""
)}
/>
</Button>
@ -463,7 +460,7 @@ export default function CollectionCardComponent({
liked_by_user
? "fill-destructive stroke-destructive"
: "",
!authorized ? " text-ring" : ""
!authorized ? "text-ring" : ""
)}
/>
</Button>
@ -501,7 +498,7 @@ export default function CollectionCardComponent({
}
className={cn(
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
!authorized ? " text-ring" : ""
!authorized ? "text-ring" : ""
)}
/>
</Button>

View file

@ -62,9 +62,9 @@ export default function FlowToolbar(): JSX.Element {
<button
disabled={!hasApiKey || !validApiKey || !hasStore}
className={classNames(
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover ",
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover",
!hasApiKey || !validApiKey || !hasStore
? " button-disable text-muted-foreground "
? "button-disable text-muted-foreground"
: ""
)}
>
@ -105,28 +105,28 @@ export default function FlowToolbar(): JSX.Element {
>
<div
className={
"shadow-round-btn-shadow hover:shadow-round-btn-shadow message-button-position flex items-center justify-center gap-7 rounded-sm border bg-muted shadow-md transition-all"
"shadow-round-btn-shadow hover:shadow-round-btn-shadow message-button-position flex items-center justify-center gap-7 rounded-sm border bg-muted shadow-md transition-all"
}
>
<div className="flex">
<div className="flex h-full w-full gap-1 rounded-sm transition-all">
<div className="flex h-full w-full gap-1 rounded-sm transition-all">
{hasIO ? (
<IOModal open={open} setOpen={setOpen} disable={!hasIO}>
<div className="relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover">
<div className="relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold transition-all duration-500 ease-in-out hover:bg-hover">
<ForwardedIconComponent
name="BotMessageSquareIcon"
className={" h-5 w-5 transition-all"}
className={"h-5 w-5 transition-all"}
/>
Playground
</div>
</IOModal>
) : (
<div
className={`relative inline-flex w-full cursor-not-allowed items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-muted-foreground transition-all duration-150 ease-in-out ease-in-out`}
className={`relative inline-flex w-full cursor-not-allowed items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-muted-foreground transition-all duration-150 ease-in-out`}
>
<ForwardedIconComponent
name="BotMessageSquareIcon"
className={" h-5 w-5 transition-all"}
className={"h-5 w-5 transition-all"}
/>
Playground
</div>
@ -149,7 +149,7 @@ export default function FlowToolbar(): JSX.Element {
>
<ForwardedIconComponent
name="Code2"
className={" h-5 w-5"}
className={"h-5 w-5"}
/>
API
</div>
@ -163,8 +163,8 @@ export default function FlowToolbar(): JSX.Element {
<div
className={`side-bar-button ${
!hasApiKey || !validApiKey || !hasStore
? " cursor-not-allowed"
: " cursor-pointer"
? "cursor-not-allowed"
: "cursor-pointer"
}`}
>
{ModalMemo}

View file

@ -32,7 +32,7 @@ export default function CodeAreaComponent({
}, [value]);
return (
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
<div className={disabled ? "pointer-events-none w-full" : "w-full"}>
<CodeAreaModal
open={open}
setOpen={setOpen}
@ -53,8 +53,8 @@ export default function CodeAreaComponent({
className={
editNode
? "input-edit-node input-dialog"
: (disabled ? " input-disable input-ring " : "") +
" primary-input text-muted-foreground "
: (disabled ? "input-disable input-ring " : "") +
" primary-input text-muted-foreground"
}
>
{myValue !== "" ? myValue : "Type something..."}

View file

@ -98,7 +98,7 @@ export default function CodeTabsComponent({
value={activeTab}
className={
"api-modal-tabs inset-0 m-0 " +
(isMessage ? "dark " : "") +
(isMessage ? "dark" : "") +
(dark && isMessage ? "bg-background" : "")
}
onValueChange={(value) => {

View file

@ -9,7 +9,7 @@ export default function CrashErrorComponent({
}: crashComponentPropsType): JSX.Element {
return (
<div className="z-50 flex h-screen w-screen items-center justify-center bg-foreground bg-opacity-50">
<div className="flex h-screen w-screen flex-col bg-background text-start shadow-lg">
<div className="flex h-screen w-screen flex-col bg-background text-start shadow-lg">
<div className="m-auto grid w-1/2 justify-center gap-5 text-center">
<Card className="p-8">
<CardHeader>
@ -31,7 +31,7 @@ export default function CrashErrorComponent({
href="https://github.com/langflow-ai/langflow/issues"
target="_blank"
rel="noopener noreferrer"
className="font-medium hover:underline "
className="font-medium hover:underline"
>
GitHub Issues
</a>{" "}

View file

@ -32,7 +32,7 @@ function CsvOutputComponent({
if (!file) {
return (
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex w-full justify-center gap-2">
<ForwardedIconComponent name="Table" />
{CSVViewErrorTitle}
@ -81,9 +81,9 @@ function CsvOutputComponent({
}, [separator]);
return (
<div className=" h-full rounded-md border bg-muted">
<div className="h-full rounded-md border bg-muted">
{status === "nodata" && (
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex w-full justify-center gap-2">
<ForwardedIconComponent name="Table" />
{CSVViewErrorTitle}
@ -96,7 +96,7 @@ function CsvOutputComponent({
</div>
)}
{status === "error" && (
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex w-full justify-center gap-2">
<ForwardedIconComponent name="Table" />
{CSVViewErrorTitle}
@ -125,7 +125,7 @@ function CsvOutputComponent({
</div>
)}
{status === "loading" && (
<div className=" flex h-full w-full items-center justify-center align-middle">
<div className="flex h-full w-full items-center justify-center align-middle">
<Loading />
</div>
)}

View file

@ -26,7 +26,7 @@ export default function DropdownButton({
id="new-project-btn"
variant="primary"
className={
"relative" + dropdownOptions ? " pl-[12px]" : " pl-[12px] pr-10"
"relative" + dropdownOptions ? "pl-[12px]" : "pl-[12px] pr-10"
}
onClick={(event) => {
event.stopPropagation();

View file

@ -78,7 +78,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
</Label>
<Label>
<div className="edit-flow-arrangement mt-3">
<span className="font-medium ">
<span className="font-medium">
Description{setDescription ? " (optional)" : ":"}
</span>
</div>

View file

@ -84,7 +84,7 @@ export default function CollectionCardComponent({
tabIndex={-1}
variant="outline"
size="sm"
className="whitespace-nowrap "
className="whitespace-nowrap"
>
<IconComponent
name="ExternalLink"

View file

@ -9,10 +9,11 @@ import {
import { useNavigate } from "react-router-dom";
import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants";
import { IS_MAC, SAVED_HOVER } from "../../../../constants/constants";
import { SAVED_HOVER } from "../../../../constants/constants";
import ExportModal from "../../../../modals/exportModal";
import FlowLogsModal from "../../../../modals/flowLogsModal";
import FlowSettingsModal from "../../../../modals/flowSettingsModal";
import ToolbarSelectItem from "../../../../pages/FlowPage/components/nodeToolbarComponent/toolbarSelectItem";
import useAlertStore from "../../../../stores/alertStore";
import useFlowStore from "../../../../stores/flowStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
@ -96,10 +97,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
}}
className="cursor-pointer"
>
<IconComponent
name="Settings2"
className="header-menu-options "
/>
<IconComponent name="Settings2" className="header-menu-options" />
Settings
</DropdownMenuItem>
<DropdownMenuItem
@ -110,7 +108,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
>
<IconComponent
name="ScrollText"
className="header-menu-options "
className="header-menu-options"
/>
Logs
</DropdownMenuItem>
@ -127,7 +125,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
);
}}
>
<IconComponent name="FileUp" className="header-menu-options " />
<IconComponent name="FileUp" className="header-menu-options" />
Import
</DropdownMenuItem>
<ExportModal>
@ -145,21 +143,15 @@ export const MenuBar = ({}: {}): JSX.Element => {
}}
className="cursor-pointer"
>
<IconComponent name="Undo" className="header-menu-options " />
Undo
{IS_MAC ? (
<IconComponent
name="Command"
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
/>
) : (
<span className="absolute right-[1.15rem] top-[0.40em] stroke-2">
{
shortcuts.find((s) => s.name.toLowerCase() === "undo")
?.shortcut
}
</span>
)}
<ToolbarSelectItem
value="Undo"
icon="Undo"
dataTestId=""
shortcut={
shortcuts.find((s) => s.name.toLowerCase() === "undo")
?.shortcut!
}
/>
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
@ -167,21 +159,15 @@ export const MenuBar = ({}: {}): JSX.Element => {
}}
className="cursor-pointer"
>
<IconComponent name="Redo" className="header-menu-options " />
Redo
{IS_MAC ? (
<IconComponent
name="Command"
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
/>
) : (
<span className="absolute right-[1.15rem] top-[0.40em] stroke-2">
{
shortcuts.find((s) => s.name.toLowerCase() === "redo")
?.shortcut
}
</span>
)}
<ToolbarSelectItem
value="Redo"
icon="Redo"
dataTestId=""
shortcut={
shortcuts.find((s) => s.name.toLowerCase() === "redo")
?.shortcut!
}
/>
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {

View file

@ -230,7 +230,7 @@ export default function Header(): JSX.Element {
userData?.profile_image ?? "Space/046-rocket.svg"
}` ?? profileCircle
}
className="h-5 w-5 focus-visible:outline-0 "
className="h-5 w-5 focus-visible:outline-0"
/>
{userData?.username ?? "User"}

View file

@ -93,9 +93,9 @@ const CustomInputPopover = ({
(!setSelectedOption || selectedOption === "") &&
!pwdVisible &&
value !== ""
? " text-clip password "
? "text-clip password"
: "",
editNode ? " input-edit-node " : "",
editNode ? "input-edit-node" : "",
password && (setSelectedOption || setSelectedOptions)
? "pr-[62.9px]"
: "",

View file

@ -67,9 +67,9 @@ export default function InputComponent({
required={required}
className={classNames(
password && !pwdVisible && value !== ""
? " text-clip password "
? "text-clip password"
: "",
editNode ? " input-edit-node " : "",
editNode ? "input-edit-node" : "",
password && editNode ? "pr-8" : "",
password && !editNode ? "pr-10" : "",
className!

View file

@ -117,7 +117,7 @@ export default function InputFileComponent({
name="FileSearch2"
className={
"icons-parameters-comp" +
(disabled ? " text-ring " : " hover:text-accent-foreground")
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>
)}

View file

@ -34,8 +34,8 @@ export default function PaginatorComponent({
<div
className={
storeComponent
? "flex items-center lg:space-x-8 "
: "flex items-center space-x-6 lg:space-x-8 "
? "flex items-center lg:space-x-8"
: "flex items-center space-x-6 lg:space-x-8"
}
>
<div className="flex items-center space-x-2">

View file

@ -110,7 +110,7 @@ export default function PdfViewer({ pdf }: { pdf: string }): JSX.Element {
"absolute z-50 pb-5 " + (showControl && numPages > 0 ? "" : " hidden")
}
>
<div className=" flex w-min items-center justify-center gap-0.5 rounded-xl bg-secondary px-2 align-middle">
<div className="flex w-min items-center justify-center gap-0.5 rounded-xl bg-secondary px-2 align-middle">
<button
type="button"
disabled={pageNumber <= 1}

View file

@ -23,7 +23,7 @@ export default function PromptAreaComponent({
}, [disabled]);
return (
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
<div className={disabled ? "pointer-events-none w-full" : "w-full"}>
<GenericModal
id={id}
field_name={field_name}
@ -43,8 +43,8 @@ export default function PromptAreaComponent({
className={
editNode
? "input-edit-node input-dialog"
: (disabled ? " input-disable text-ring " : "") +
" primary-input text-muted-foreground "
: (disabled ? "input-disable text-ring " : "") +
" primary-input text-muted-foreground"
}
>
{value !== "" ? value : "Type your prompt here..."}

View file

@ -12,21 +12,22 @@ export default function RenderIcons({
shortcutWPlus: string[];
}): JSX.Element {
return hasShift ? (
<span className="flex gap-0.5 text-xs">
<span className="flex items-center justify-center gap-0.5 text-xs">
{isMac ? (
<ForwardedIconComponent name="Command" className="h-3 w-3" />
) : (
filteredShortcut[0]
)}
<ForwardedIconComponent name="ArrowBigUp" className=" h-4 w-4" />
<ForwardedIconComponent name="ArrowBigUp" className="h-4 w-4" />
{filteredShortcut.map((key, idx) => {
if (idx > 0) {
return <span className=""> {key.toUpperCase()} </span>;
return key.toUpperCase();
}
return null;
})}
</span>
) : (
<span className="flex gap-1 text-xs">
<span className="flex items-center justify-center gap-0.5 text-xs">
{shortcutWPlus[0].toLowerCase() === "space" ? (
"Space"
) : shortcutWPlus[0].length <= 1 ? (
@ -34,12 +35,17 @@ export default function RenderIcons({
) : isMac ? (
<ForwardedIconComponent name="Command" className="h-3 w-3" />
) : (
shortcutWPlus[0]
<span className="flex items-center">{shortcutWPlus[0]}</span>
)}
{shortcutWPlus.map((key, idx) => {
if (idx > 0) {
return <span className=""> {key.toUpperCase()} </span>;
return (
<span key={idx} className="flex items-center">
{key.toUpperCase()}
</span>
);
}
return null;
})}
</span>
);

View file

@ -10,7 +10,7 @@ export default function ShadTooltip({
styleClasses,
delayDuration = 500,
}: ShadToolTipType): JSX.Element {
return (
return content ? (
<Tooltip defaultOpen={!children} delayDuration={delayDuration}>
<TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>
<TooltipContent
@ -22,5 +22,7 @@ export default function ShadTooltip({
{content}
</TooltipContent>
</Tooltip>
) : (
<>{children}</>
);
}

View file

@ -293,7 +293,7 @@ const SideBarFoldersButtonsComponent = ({
>
<IconComponent
name={"trash"}
className=" w-4 stroke-[1.5]"
className="w-4 stroke-[1.5]"
/>
</Button>
)}
@ -309,7 +309,7 @@ const SideBarFoldersButtonsComponent = ({
>
<IconComponent
name={"Download"}
className=" w-4 stroke-[1.5] text-white "
className="w-4 stroke-[1.5] text-white"
/>
</Button>
</div>

View file

@ -84,8 +84,8 @@ export default function TableOptions({
<IconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-primary transition-all",
!hasSelection ? "" : "hover:text-status-red "
"h-5 w-5 text-primary transition-all",
!hasSelection ? "" : "hover:text-status-red"
)}
/>
</Button>

View file

@ -2,7 +2,7 @@ import Loading from "../../../ui/loading";
export default function LoadingOverlay() {
return (
<div className=" flex h-full w-full items-center justify-center bg-background align-middle">
<div className="flex h-full w-full items-center justify-center bg-background align-middle">
<Loading />
</div>
);

View file

@ -45,7 +45,19 @@ export default function TableAutoCellRender({
"min-w-min bg-error-background text-error-foreground hover:bg-error-background",
)}
>
{value}
Success
</Badge>
);
} else if (value === "failure") {
return (
<Badge
variant="outline"
size="sq"
className={cn(
"min-w-min bg-error-background text-error-foreground hover:bg-error-background"
)}
>
Failure
</Badge>
);
} else {

View file

@ -33,7 +33,7 @@ export function TagsSelector({
className={
disabled
? "cursor-not-allowed"
: " overflow-hidden whitespace-nowrap"
: "overflow-hidden whitespace-nowrap"
}
onClick={() => {
updateTags(tag.name);

View file

@ -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);

View file

@ -34,7 +34,7 @@ const AccordionTrigger = React.forwardRef<
<div
className={cn(
"flex flex-1 cursor-pointer items-center justify-between py-4 text-sm font-medium transition-all [&[data-state=open]>svg]:rotate-180",
className,
className
)}
>
{children}
@ -46,7 +46,7 @@ const AccordionTrigger = React.forwardRef<
<ChevronDownIcon
className={cn(
"h-4 w-4 font-bold transition-transform duration-200",
disabled ? "text-muted-foreground" : "text-primary",
disabled ? "text-muted-foreground" : "text-primary"
)}
/>
</ShadTooltip>
@ -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}
>

View file

@ -69,7 +69,7 @@ const CardFooter = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(" flex items-center p-4 pt-0", className)}
className={cn("flex items-center p-4 pt-0", className)}
{...props}
/>
));

View file

@ -23,7 +23,7 @@ const AccordionTrigger = React.forwardRef<
<AccordionPrimitive.Trigger asChild ref={ref} {...props}>
<div
className={cn(
" 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",
"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
)}
>

View file

@ -64,7 +64,7 @@ const DialogHeader = ({
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left",
"flex flex-col space-y-1 text-center sm:text-left",
className
)}
{...props}

View file

@ -48,7 +48,7 @@ export default function FoldersModal({
</span>
<ForwardedIconComponent
name="Plus"
className="h-6 w-6 pl-1 text-primary "
className="h-6 w-6 pl-1 text-primary"
aria-hidden="true"
/>
</BaseModal.Header>

View file

@ -136,7 +136,7 @@ export default function IOFileInput({ field, updateValue }: IOFileInputProps) {
</>
) : image ? (
<img
className="order-last h-12 w-12 rounded-full object-cover "
className="order-last h-12 w-12 rounded-full object-cover"
src={image ?? ""}
/>
) : (

View file

@ -58,7 +58,7 @@ export default function IOFieldView({
return (
<Textarea
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
left ? "min-h-32" : "h-full"
}`}
placeholder={"Enter text..."}
value={node.data.node!.template["input_value"].value}
@ -142,7 +142,7 @@ export default function IOFieldView({
return (
<Textarea
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
left ? "min-h-32" : "h-full"
}`}
placeholder={"Enter text..."}
value={node.data.node!.template["input_value"]}
@ -266,7 +266,7 @@ export default function IOFieldView({
return (
<Textarea
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
left ? "min-h-32" : "h-full"
}`}
placeholder={"Empty"}
// update to real value on flowPool

View file

@ -27,7 +27,7 @@ const ButtonSendWrapper = ({
"form-modal-send-button",
noInput
? "bg-high-indigo text-background"
: chatValue === ""
: chatValue
? "text-primary"
: "bg-chat-send text-background"
)}
@ -64,7 +64,7 @@ const ButtonSendWrapper = ({
>
<IconComponent
name="LucideSend"
className="form-modal-send-icon "
className="form-modal-send-icon"
aria-hidden="true"
/>
</Case>

View file

@ -162,7 +162,7 @@ export default function ChatMessage({
)}
{chat.thought && chat.thought !== "" && !hidden && (
<SanitizedHTMLWrapper
className=" form-modal-chat-thought"
className="form-modal-chat-thought"
content={convert.toHtml(chat.thought)}
onClick={() => setHidden((prev) => !prev)}
/>
@ -187,8 +187,7 @@ export default function ChatMessage({
<Markdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeMathjax]}
className="markdown prose flex flex-col text-primary word-break-break-word
dark:prose-invert"
className="markdown prose flex flex-col text-primary word-break-break-word dark:prose-invert"
components={{
pre({ node, ...props }) {
return <>{props.children}</>;
@ -319,7 +318,7 @@ dark:prose-invert"
{chatMessage}
</span>
{chat.files && (
<div className="my-2 flex flex-col gap-5">
<div className="my-2 flex flex-col gap-5">
{chat.files.map((file, index) => {
return (
<FileCardWrapper

View file

@ -11,7 +11,7 @@ export default function DownloadButton({
if (isHovered) {
return (
<div
className={`absolute right-1 top-1 rounded-md bg-muted text-sm font-bold text-foreground `}
className={`absolute right-1 top-1 rounded-md bg-muted text-sm font-bold text-foreground`}
>
<Button
variant={"none"}

View file

@ -45,7 +45,7 @@ export default function FileCard({
<img
src={imgSrc}
alt="generated image"
className="m-0 h-auto w-auto rounded-lg border border-border p-0 transition-all"
className="m-0 h-auto w-auto rounded-lg border border-border p-0 transition-all"
/>
<DownloadButton
isHovered={isHovered}

View file

@ -27,10 +27,10 @@ export default function FilePreview({
<div className="relative inline-block">
{loading ? (
isImage ? (
<div className="flex h-20 w-20 items-center justify-center rounded-md border border-ring bg-background ">
<div className="flex h-20 w-20 items-center justify-center rounded-md border border-ring bg-background">
<svg
aria-hidden="true"
className={`h-10 w-10 animate-spin fill-black text-muted`}
className={`h-10 w-10 animate-spin fill-black text-muted`}
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
@ -49,7 +49,7 @@ export default function FilePreview({
<div
className={`relative ${
isImage ? "h-20 w-20" : "h-20 w-80"
} cursor-wait rounded-lg border border-ring bg-background transition duration-300 ${
} cursor-wait rounded-lg border border-ring bg-background transition duration-300 ${
isHovered ? "shadow-md" : ""
}`}
>
@ -68,7 +68,7 @@ export default function FilePreview({
<div
className={`relative mt-2 ${
isImage ? "h-20 w-20" : "h-20 w-80"
} cursor-pointer rounded-lg border border-ring bg-background transition duration-300 ${
} cursor-pointer rounded-lg border border-ring bg-background transition duration-300 ${
isHovered ? "shadow-md" : ""
}`}
onMouseEnter={() => setIsHovered(true)}
@ -93,7 +93,7 @@ export default function FilePreview({
<div
className={`absolute ${
isImage ? "bottom-16 left-16" : "bottom-16 left-[19em]"
} flex h-5 w-5 items-center justify-center`}
} flex h-5 w-5 items-center justify-center`}
>
<div
className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-gray-200 p-2 transition-all"

View file

@ -58,7 +58,7 @@ export default function ChatView({
//
.filter(
(output) =>
output.data.message || (!output.data.message && output.artifacts),
output.data.message || (!output.data.message && output.artifacts)
)
.map((output, index) => {
try {
@ -78,7 +78,10 @@ export default function ChatView({
sender === "Machine" || sender === null || sender === undefined;
return {
isSend: !is_ai,
message: message,
message:
message === "" || !message
? "No input message provided."
: message,
sender_name,
componentId: output.id,
stream_url: stream_url,
@ -138,7 +141,7 @@ export default function ChatView({
function updateChat(
chat: ChatMessageType,
message: string,
stream_url?: string,
stream_url?: string
) {
chat.message = message;
updateFlowPool(chat.componentId, {
@ -154,7 +157,7 @@ export default function ChatView({
setIsDragging,
setFiles,
currentFlowId,
setErrorData,
setErrorData
);
return (
@ -205,7 +208,7 @@ export default function ChatView({
<span>
<IconComponent
name="MessageSquareMore"
className="mx-1 inline h-5 w-5 animate-bounce "
className="mx-1 inline h-5 w-5 animate-bounce"
/>
</span>{" "}
{CHAT_SECOND_INITIAL_TEXT}

View file

@ -68,7 +68,7 @@ const Header: React.FC<{
}> = ({ children, description }: modalHeaderType): JSX.Element => {
return (
<DialogHeader>
<DialogTitle className="line-clamp-1 flex items-center">
<DialogTitle className="line-clamp-1 flex items-center pb-0.5">
{children}
</DialogTitle>
<DialogDescription className="line-clamp-2">

View file

@ -153,7 +153,7 @@ export default function CodeAreaModal({
<span className="pr-2"> {EDIT_CODE_TITLE} </span>
<IconComponent
name="prompts"
className="h-6 w-6 pl-1 text-primary "
className="h-6 w-6 pl-1 text-primary"
aria-hidden="true"
/>
</BaseModal.Header>

View file

@ -54,12 +54,12 @@ export default function DictAreaModal({
</span>
<IconComponent
name="BookMarked"
className="h-6 w-6 pl-1 text-primary "
className="h-6 w-6 pl-1 text-primary"
aria-hidden="true"
/>
</BaseModal.Header>
<BaseModal.Content>
<div className="flex h-full w-full flex-col transition-all ">
<div className="flex h-full w-full flex-col transition-all">
<JsonView
theme="vscode"
dark={isDark}

View file

@ -92,11 +92,11 @@ const ExportModal = forwardRef(
setChecked(event);
}}
/>
<label htmlFor="terms" className="export-modal-save-api text-sm ">
<label htmlFor="terms" className="export-modal-save-api text-sm">
{SAVE_WITH_API_CHECKBOX}
</label>
</div>
<span className="mt-1 text-xs text-destructive ">
<span className="mt-1 text-xs text-destructive">
{ALERT_SAVE_WITH_API}
</span>
</BaseModal.Content>

View file

@ -63,7 +63,7 @@ export default function FlowSettingsModal({
>
<BaseModal.Header description={SETTINGS_DIALOG_SUBTITLE}>
<span className="pr-2">Settings</span>
<IconComponent name="Settings2" className="mr-2 h-4 w-4 " />
<IconComponent name="Settings2" className="mr-2 h-4 w-4" />
</BaseModal.Header>
<BaseModal.Content>
<EditFlowSettings

View file

@ -48,7 +48,7 @@ export default function FoldersModal({
</span>
<ForwardedIconComponent
name={folderToEdit ? "Pencil" : "Plus"}
className="h-6 w-6 pl-1 text-primary "
className="h-6 w-6 pl-1 text-primary"
aria-hidden="true"
/>
</BaseModal.Header>

View file

@ -83,7 +83,7 @@ export default function GenericModal({
}
const filteredWordsHighlight = new Set(
matches.filter((word) => !invalid_chars.includes(word)),
matches.filter((word) => !invalid_chars.includes(word))
);
setWordsHighlight(filteredWordsHighlight);
@ -134,7 +134,7 @@ export default function GenericModal({
// to the first key of the custom_fields object
if (field_name === "") {
field_name = Array.isArray(
apiReturn.data?.frontend_node?.custom_fields?.[""],
apiReturn.data?.frontend_node?.custom_fields?.[""]
)
? apiReturn.data?.frontend_node?.custom_fields?.[""][0] ?? ""
: apiReturn.data?.frontend_node?.custom_fields?.[""] ?? "";
@ -200,7 +200,7 @@ export default function GenericModal({
</span>
<IconComponent
name={myModalTitle === "Edit Prompt" ? "TerminalSquare" : "FileText"}
className="h-6 w-6 pl-1 text-primary "
className="h-6 w-6 pl-1 text-primary"
aria-hidden="true"
/>
</BaseModal.Header>
@ -208,7 +208,7 @@ export default function GenericModal({
<div
className={classNames(
!isEdit ? "rounded-lg border" : "",
"flex h-full w-full",
"flex h-full w-full"
)}
>
{type === TypeModal.PROMPT && isEdit && !readonly ? (
@ -265,15 +265,15 @@ export default function GenericModal({
<div className="flex w-full shrink-0 items-end justify-between">
<div className="mb-auto flex-1">
{type === TypeModal.PROMPT && (
<div className=" mr-2">
<div className="mr-2">
<div
ref={divRef}
className="max-h-20 overflow-y-auto custom-scroll"
>
<div className="flex flex-wrap items-center">
<div className="flex flex-wrap items-center gap-2">
<IconComponent
name="Braces"
className=" -ml-px mr-1 flex h-4 w-4 text-primary"
className="flex h-4 w-4 text-primary"
/>
<span className="text-md font-semibold text-primary">
Prompt Variables:
@ -289,7 +289,7 @@ export default function GenericModal({
key={index}
variant="gray"
size="md"
className="m-1 max-w-[40vw] cursor-default truncate p-2.5 text-sm"
className="max-w-[40vw] cursor-default truncate p-1 text-sm"
>
<div className="relative bottom-[1px]">
<span id={"badge" + index.toString()}>

View file

@ -24,7 +24,7 @@ export default function NewFlowModal({
</span>
</BaseModal.Header>
<BaseModal.Content>
<div className=" mb-5 grid h-fit w-full grid-cols-3 gap-4 overflow-auto pb-6 custom-scroll">
<div className="mb-5 grid h-fit w-full grid-cols-3 gap-4 overflow-auto pb-6 custom-scroll">
<NewFlowCardComponent />
{examples.find((e) => e.name == "Basic Prompting (Hello, World)") && (

View file

@ -182,7 +182,7 @@ export default function ShareModal({
current?
</span>
<br></br>
<span className=" text-xs text-destructive ">
<span className="text-xs text-destructive">
Note: This action is irreversible.
</span>
</ConfirmationModal.Content>
@ -253,11 +253,11 @@ export default function ShareModal({
}}
data-testid="public-checkbox"
/>
<label htmlFor="public" className="export-modal-save-api text-sm ">
<label htmlFor="public" className="export-modal-save-api text-sm">
Set {nameComponent} status to public
</label>
</div>
<span className=" text-xs text-destructive ">
<span className="text-xs text-destructive">
<b>Attention:</b> API keys in specified fields are automatically
removed upon sharing.
</span>

View file

@ -284,7 +284,7 @@ export default function AdminPage() {
(loadingUsers ? " border-0" : "")
}
>
<Table className={"table-fixed outline-1 "}>
<Table className={"table-fixed outline-1"}>
<TableHeader
className={
loadingUsers ? "hidden" : "table-fixed bg-muted outline-1"
@ -297,7 +297,7 @@ export default function AdminPage() {
<TableHead className="h-10">Superuser</TableHead>
<TableHead className="h-10">Created At</TableHead>
<TableHead className="h-10">Updated At</TableHead>
<TableHead className="h-10 w-[100px] text-right"></TableHead>
<TableHead className="h-10 w-[100px] text-right"></TableHead>
</TableRow>
</TableHeader>
{!loadingUsers && (
@ -380,7 +380,7 @@ export default function AdminPage() {
</ConfirmationModal.Trigger>
</ConfirmationModal>
</TableCell>
<TableCell className="truncate py-2 ">
<TableCell className="truncate py-2">
{
new Date(user.create_at!)
.toISOString()

View file

@ -13,7 +13,7 @@ const ConnectionLineComponent = ({
fill="none"
// ! Replace hash # colors here
strokeWidth={1.5}
className="animated stroke-connection "
className="animated stroke-connection"
d={`M${fromX},${fromY} C ${fromX} ${toY} ${fromX} ${toY} ${toX},${toY}`}
style={connectionLineStyle}
/>

View file

@ -495,10 +495,7 @@ export default function Page({
>
<Background className="" />
{!view && (
<Controls
className="fill-foreground stroke-foreground text-primary [&>button]:border-b-border
[&>button]:bg-muted hover:[&>button]:bg-border"
></Controls>
<Controls className="fill-foreground stroke-foreground text-primary [&>button]:border-b-border [&>button]:bg-muted hover:[&>button]:bg-border"></Controls>
)}
<SelectionMenu
lastSelection={lastSelection}

View file

@ -18,7 +18,7 @@ export default function ParentDisclosureComponent({
data-testid={testId}
>
<div className="flex gap-4">
<span className="parent-disclosure-title ">{title}</span>
<span className="parent-disclosure-title">{title}</span>
</div>
<div className="components-disclosure-div">
{buttons.map((btn, index) => (

View file

@ -58,7 +58,7 @@ export default function SelectionMenu({
<div
className={
"duration-400 h-10 w-24 rounded-md border border-indigo-300 bg-background px-2.5 text-primary shadow-inner transition-all ease-in-out" +
(isTransitioning ? " opacity-100" : " opacity-0 ")
(isTransitioning ? " opacity-100" : " opacity-0")
}
>
<button

View file

@ -199,7 +199,7 @@ export default function ExtraSidebar(): JSX.Element {
className={classNames(
"extra-side-bar-buttons gap-[4px] text-sm font-semibold",
!hasApiKey || !validApiKey || !hasStore
? "button-disable cursor-default text-muted-foreground"
? "button-disable cursor-default text-muted-foreground"
: ""
)}
>
@ -262,7 +262,7 @@ export default function ExtraSidebar(): JSX.Element {
}}
/>
<div
className="search-icon "
className="search-icon"
onClick={() => {
if (search) {
setFilterData(data);

View file

@ -117,7 +117,7 @@ export const SidebarDraggableComponent = forwardRef(
<div ref={popoverRef}>
<IconComponent
name="Menu"
className="side-bar-components-icon "
className="side-bar-components-icon"
/>
<SelectTrigger></SelectTrigger>
<SelectContent

View file

@ -455,7 +455,7 @@ export default function NodeToolbarComponent({
<button
className={`${
isGroup ? "rounded-l-md" : ""
} relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10`}
} relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10`}
onClick={() => {
setShowModalAdvanced(true);
}}
@ -494,7 +494,7 @@ export default function NodeToolbarComponent({
>
<button
className={classNames(
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
)}
onClick={(event) => {
event.preventDefault();
@ -543,7 +543,7 @@ export default function NodeToolbarComponent({
<div
data-testid="more-options-modal"
className={classNames(
"relative -ml-px inline-flex h-8 w-[31px] items-center rounded-r-md bg-background text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
"relative -ml-px inline-flex h-8 w-[31px] items-center rounded-r-md bg-background text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
)}
>
<IconComponent
@ -710,11 +710,11 @@ export default function NodeToolbarComponent({
<div className="font-red flex text-status-red">
<IconComponent
name="Trash2"
className="relative top-0.5 mr-2 h-4 w-4 "
className="relative top-0.5 mr-2 h-4 w-4"
/>{" "}
<span className="">Delete</span>{" "}
<span
className={` absolute right-2 top-2 flex items-center justify-center rounded-sm px-1 py-[0.2] ${
className={`absolute right-2 top-2 flex items-center justify-center rounded-sm px-1 py-[0.2] ${
deleteIsFocus ? " " : "bg-muted"
}`}
>

View file

@ -1,5 +1,6 @@
import ForwardedIconComponent from "../../../../../components/genericIconComponent";
import RenderIcons from "../../../../../components/renderIconComponent";
import { IS_MAC } from "../../../../../constants/constants";
import { toolbarSelectItemProps } from "../../../../../types/components";
export default function ToolbarSelectItem({
@ -10,7 +11,6 @@ export default function ToolbarSelectItem({
ping,
shortcut,
}: toolbarSelectItemProps) {
const isMac = navigator.platform.toUpperCase().includes("MAC");
let hasShift = false;
const fixedShortcut = shortcut?.split("+");
fixedShortcut.forEach((key) => {
@ -28,20 +28,20 @@ export default function ToolbarSelectItem({
<div className={`flex ${style}`} data-testid={dataTestId}>
<ForwardedIconComponent
name={icon}
className={` mr-2 ${
className={`mr-2 ${
icon === "Share3"
? "absolute left-2 top-[0.25em] h-6 w-6"
? "absolute left-2 top-[0.25em] h-6 w-6"
: "mt-[0.15em] h-4 w-4"
} ${ping && "animate-pulse text-green-500"}`}
} ${ping && "animate-pulse text-green-500"}`}
/>
<span className={`${icon === "Share3" ? "ml-[1.8em]" : " "}`}>
{value}
</span>
<span
className={`absolute right-2 top-[0.43em] flex items-center rounded-sm bg-muted px-1.5 py-[0.1em] text-muted-foreground `}
className={`absolute right-2 top-[0.43em] flex items-center rounded-sm bg-muted px-1.5 py-[0.1em] text-muted-foreground`}
>
<RenderIcons
isMac={isMac}
isMac={IS_MAC}
hasShift={hasShift}
filteredShortcut={filteredShortcut}
shortcutWPlus={shortcutWPlus}

View file

@ -15,7 +15,7 @@ const EmptyComponent = ({}: EmptyComponentProps) => {
<>
<div className="mt-2 flex w-full items-center justify-center text-center">
<div className="flex-max-width h-full flex-col">
<div className="align-center flex w-full justify-center gap-1 ">
<div className="align-center flex w-full justify-center gap-1">
<span className="text-muted-foreground">
This folder is empty. New?
</span>

Some files were not shown because too many files have changed in this diff Show more