merge fix

This commit is contained in:
cristhianzl 2024-03-29 17:52:09 -03:00
commit 3a612c874c
89 changed files with 1296 additions and 1059 deletions

View file

@ -62,4 +62,6 @@ jobs:
context: .
push: true
file: ./build_and_push.Dockerfile
tags: logspace/langflow:${{ steps.check-version.outputs.version }}
tags: |
logspace/langflow:${{ steps.check-version.outputs.version }}
logspace/langflow:latest-dev

View file

@ -0,0 +1,98 @@
# A new chapter for Langflow
# First things first
Thank you all for being part of the Langflow community. The journey so far has been amazing and we are happy to have you with us.
We have some exciting news to share with you. Langflow is changing, and we want to tell you all about it.
## Where have we been?
We spent the last few months working on a new version of Langflow. We wanted to make it more powerful, more flexible, and easier to use.
We're moving from version 0.6 straight to 1.0 (preview). This is a big change, and we want to explain why we're doing it and what it means for you.
## Why?
In the past year, we learned a lot from the community and our users. We saw the potential of Langflow and the need for a more powerful and flexible tool for building conversational AI applications (and beyond).
We realized that Langflow was hiding things from you that would really help you build better and more complex conversational AI applications. So we decided to make a big change.
## The only way to go is forward
From all the people we talked to, we learned that the most important thing for (most of) them is to have a tool that is easy to use, but also powerful and controllable. They also told us that Langflow's transparency could be improved.
In those points, we saw an opportunity to make Langflow much more powerful and flexible, while also making it easier to use and understand.
One key change you'll notice is that projects now require you to define Inputs and Outputs.
This is a big change, but it's also a big improvement.
It allows you to define the structure of your conversation and the data that flows through it.
This makes it easier to understand and control your conversation.
This change comes with a new way of visualizing your projects. Before 1.0 you would connect Components to ultimately build one final Component that was processed behind the scenes.
Now, each step of the process is defined by you, is visible on the canvas, and can be monitored and controlled by you. This makes it so that Composition is now just another way of building in Langflow. **Now data flows through your project more transparently**.
The caveat is existing projects may need some new Components to get them back to their full functionality.
[We've made this as easy as possible](../migration/compatibility), and there will be improvements to it as we get feedback in our Discord server and on GitHub.
## Custom Interactions
The moment we decided to make this change, we saw the potential to make Langflow even more yours.
By having a clear definition of Inputs and Outputs, we could build the experience around that which led us to create the **Interaction Panel**.
When building a project testing and debugging is crucial. The Interaction Panel is a tool that changes dynamically based on the Inputs and Outputs you defined in your project.
For example, let's say you are building a simple RAG application. Generally, you have an Input, some references that come from a Vector Store Search, a Prompt and the answer.
Now, you could plug the output of your Prompt into a [Text Output](../components/outputs#Text-Output), rename that to "Prompt Result" and see the output of your Prompt in the Interaction Panel.
{/* Add image here of the described above */}
This is just one example of how the Interaction Panel can help you build and debug your projects.
We have many planned features for the Interaction Panel, and we're excited to see how you use it and what you think of it.
## An easier start
The experience for the first-time user is also something we wanted to improve.
Meet the new and improved **New Project** screen. It's now easier to start a new project, and you can choose from a list of starter projects to get you started.
{/* Add new project image */}
We wanted to create start projects that would help you learn about new features and also give you a head start on your projects.
For now, we have:
- **Basic Prompting**: A simple project that shows you how to use the Prompt Component.
- **Data Ingestion**: A project that shows you how to ingest files into a Vector Store.
- **RAG**: A project that shows you how to use a Vector Store Search and a Prompt to build a simple RAG application.
As always, your feedback is invaluable, so please let us know what you think of the new starter projects and what you would like to see in the future.
## Less is more
We added many new Components to Langflow and updated some of the existing ones, and we will deprecate some of them.
The idea is that Langflow has evolved, and we want to make sure that the Components you use are the best they can be.
Some of them don't work well with the others, and some of them are just not needed anymore.
We are working on a list of Components that will be deprecated.
In the preview stages of 1.0, we will have a smaller list of Components so that we make sure that the ones we have are the best they can be.
Regardless, community feedback is very important in this matter, so please let us know what you think of the new Components and which ones you miss.
We are aiming at having a more stable and reliable set of Components that helps you get quickly to useful results.
This also means that your contributions in the [Langflow Store](https://langflow.store) and throughout the community are more important than ever.
## What's next?
Langflow went through a big change, and we are excited to see how you use it and what you think of it.
We plan to add more types of Input and Output like Image and Audio, and we also plan to add more Components to help you build more complex projects.
We also have some experimental features like a State Management System (so cool!) and a new way of building Grouped Components that we are excited to show you.
## Reach out
One last time, we want to thank you for being part of the Langflow community. Your feedback is invaluable, and we want to hear from you.

360
poetry.lock generated
View file

@ -602,7 +602,7 @@ name = "build"
version = "1.1.1"
description = "A simple, correct Python build frontend"
optional = false
python-versions = ">= 3.7"
python-versions = ">=3.8"
files = [
{file = "build-1.1.1-py3-none-any.whl", hash = "sha256:8ed0851ee76e6e38adce47e4bee3b51c771d86c64cf578d0c2245567ee200e73"},
{file = "build-1.1.1.tar.gz", hash = "sha256:8eea65bb45b1aac2e734ba2cc8dad3a6d97d97901a395bd0ed3e7b46953d2a31"},
@ -617,8 +617,9 @@ tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[package.extras]
docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
typing = ["importlib-metadata (>=5.1)", "mypy (>=1.5.0,<1.6.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
uv = ["uv (>=0.1.18)"]
virtualenv = ["virtualenv (>=20.0.35)"]
[[package]]
@ -2584,9 +2585,9 @@ files = [
[package.dependencies]
google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0"
google-auth = ">=1.19.0,<3.0.0.dev0"
google-auth-httplib2 = ">=0.1.0"
httplib2 = ">=0.15.0,<1.dev0"
google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0"
google-auth-httplib2 = ">=0.2.0,<1.0.0"
httplib2 = ">=0.19.0,<1.dev0"
uritemplate = ">=3.0.1,<5"
[[package]]
@ -3338,13 +3339,13 @@ typer = ">=0.9.0,<0.10.0"
[[package]]
name = "ipykernel"
version = "6.29.3"
version = "6.29.4"
description = "IPython Kernel for Jupyter"
optional = false
python-versions = ">=3.8"
files = [
{file = "ipykernel-6.29.3-py3-none-any.whl", hash = "sha256:5aa086a4175b0229d4eca211e181fb473ea78ffd9869af36ba7694c947302a21"},
{file = "ipykernel-6.29.3.tar.gz", hash = "sha256:e14c250d1f9ea3989490225cc1a542781b095a18a19447fcf2b5eaf7d0ac5bd2"},
{file = "ipykernel-6.29.4-py3-none-any.whl", hash = "sha256:1181e653d95c6808039c509ef8e67c4126b3b3af7781496c7cbfb5ed938a27da"},
{file = "ipykernel-6.29.4.tar.gz", hash = "sha256:3d44070060f9475ac2092b760123fadf105d2e2493c24848b6691a7c4f42af5c"},
]
[package.dependencies]
@ -3884,6 +3885,23 @@ langchain-core = ">=0.1.28,<0.2.0"
[package.extras]
extended-testing = ["lxml (>=5.1.0,<6.0.0)"]
[[package]]
name = "langchain-text-splitters"
version = "0.0.1"
description = "LangChain text splitting utilities"
optional = false
python-versions = ">=3.8.1,<4.0"
files = [
{file = "langchain_text_splitters-0.0.1-py3-none-any.whl", hash = "sha256:f5b802f873f5ff6a8b9259ff34d53ed989666ef4e1582e6d1adb3b5520e3839a"},
{file = "langchain_text_splitters-0.0.1.tar.gz", hash = "sha256:ac459fa98799f5117ad5425a9330b21961321e30bc19a2a2f9f761ddadd62aa1"},
]
[package.dependencies]
langchain-core = ">=0.1.28,<0.2.0"
[package.extras]
extended-testing = ["lxml (>=5.1.0,<6.0.0)"]
[[package]]
name = "langdetect"
version = "1.0.9"
@ -5451,18 +5469,18 @@ datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
[[package]]
name = "opentelemetry-api"
version = "1.23.0"
version = "1.24.0"
description = "OpenTelemetry Python API"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_api-1.23.0-py3-none-any.whl", hash = "sha256:cc03ea4025353048aadb9c64919099663664672ea1c6be6ddd8fee8e4cd5e774"},
{file = "opentelemetry_api-1.23.0.tar.gz", hash = "sha256:14a766548c8dd2eb4dfc349739eb4c3893712a0daa996e5dbf945f9da665da9d"},
{file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"},
{file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"},
]
[package.dependencies]
deprecated = ">=1.2.6"
importlib-metadata = ">=6.0,<7.0"
importlib-metadata = ">=6.0,<=7.0"
[[package]]
name = "opentelemetry-exporter-otlp"
@ -5481,27 +5499,27 @@ opentelemetry-exporter-otlp-proto-http = "1.23.0"
[[package]]
name = "opentelemetry-exporter-otlp-proto-common"
version = "1.23.0"
version = "1.24.0"
description = "OpenTelemetry Protobuf encoding"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_exporter_otlp_proto_common-1.23.0-py3-none-any.whl", hash = "sha256:2a9e7e9d5a8b026b572684b6b24dcdefcaa58613d5ce3d644130b0c373c056c1"},
{file = "opentelemetry_exporter_otlp_proto_common-1.23.0.tar.gz", hash = "sha256:35e4ea909e7a0b24235bd0aaf17fba49676527feb1823b46565ff246d5a1ab18"},
{file = "opentelemetry_exporter_otlp_proto_common-1.24.0-py3-none-any.whl", hash = "sha256:e51f2c9735054d598ad2df5d3eca830fecfb5b0bda0a2fa742c9c7718e12f641"},
{file = "opentelemetry_exporter_otlp_proto_common-1.24.0.tar.gz", hash = "sha256:5d31fa1ff976cacc38be1ec4e3279a3f88435c75b38b1f7a099a1faffc302461"},
]
[package.dependencies]
opentelemetry-proto = "1.23.0"
opentelemetry-proto = "1.24.0"
[[package]]
name = "opentelemetry-exporter-otlp-proto-grpc"
version = "1.23.0"
version = "1.24.0"
description = "OpenTelemetry Collector Protobuf over gRPC Exporter"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_exporter_otlp_proto_grpc-1.23.0-py3-none-any.whl", hash = "sha256:40f9e3e7761eb34f2a1001f4543028783ac26e2db27e420d5374f2cca0182dad"},
{file = "opentelemetry_exporter_otlp_proto_grpc-1.23.0.tar.gz", hash = "sha256:aa1a012eea5342bfef51fcf3f7f22601dcb0f0984a07ffe6025b2fbb6d91a2a9"},
{file = "opentelemetry_exporter_otlp_proto_grpc-1.24.0-py3-none-any.whl", hash = "sha256:f40d62aa30a0a43cc1657428e59fcf82ad5f7ea8fff75de0f9d9cb6f739e0a3b"},
{file = "opentelemetry_exporter_otlp_proto_grpc-1.24.0.tar.gz", hash = "sha256:217c6e30634f2c9797999ea9da29f7300479a94a610139b9df17433f915e7baa"},
]
[package.dependencies]
@ -5509,9 +5527,9 @@ deprecated = ">=1.2.6"
googleapis-common-protos = ">=1.52,<2.0"
grpcio = ">=1.0.0,<2.0.0"
opentelemetry-api = ">=1.15,<2.0"
opentelemetry-exporter-otlp-proto-common = "1.23.0"
opentelemetry-proto = "1.23.0"
opentelemetry-sdk = ">=1.23.0,<1.24.0"
opentelemetry-exporter-otlp-proto-common = "1.24.0"
opentelemetry-proto = "1.24.0"
opentelemetry-sdk = ">=1.24.0,<1.25.0"
[package.extras]
test = ["pytest-grpc"]
@ -5541,13 +5559,13 @@ test = ["responses (>=0.22.0,<0.25)"]
[[package]]
name = "opentelemetry-instrumentation"
version = "0.44b0"
version = "0.45b0"
description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_instrumentation-0.44b0-py3-none-any.whl", hash = "sha256:79560f386425176bcc60c59190064597096114c4a8e5154f1cb281bb4e47d2fc"},
{file = "opentelemetry_instrumentation-0.44b0.tar.gz", hash = "sha256:8213d02d8c0987b9b26386ae3e091e0477d6331673123df736479322e1a50b48"},
{file = "opentelemetry_instrumentation-0.45b0-py3-none-any.whl", hash = "sha256:06c02e2c952c1b076e8eaedf1b82f715e2937ba7eeacab55913dd434fbcec258"},
{file = "opentelemetry_instrumentation-0.45b0.tar.gz", hash = "sha256:6c47120a7970bbeb458e6a73686ee9ba84b106329a79e4a4a66761f933709c7e"},
]
[package.dependencies]
@ -5557,47 +5575,45 @@ wrapt = ">=1.0.0,<2.0.0"
[[package]]
name = "opentelemetry-instrumentation-asgi"
version = "0.44b0"
version = "0.45b0"
description = "ASGI instrumentation for OpenTelemetry"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_instrumentation_asgi-0.44b0-py3-none-any.whl", hash = "sha256:0d95c84a8991008c8a8ac35e15d43cc7768a5bb46f95f129e802ad2990d7c366"},
{file = "opentelemetry_instrumentation_asgi-0.44b0.tar.gz", hash = "sha256:72d4d28ec7ccd551eac11edc5ae8cac3586c0a228467d6a95fad7b6d4edd597a"},
{file = "opentelemetry_instrumentation_asgi-0.45b0-py3-none-any.whl", hash = "sha256:8be1157ed62f0db24e45fdf7933c530c4338bd025c5d4af7830e903c0756021b"},
{file = "opentelemetry_instrumentation_asgi-0.45b0.tar.gz", hash = "sha256:97f55620f163fd3d20323e9fd8dc3aacc826c03397213ff36b877e0f4b6b08a6"},
]
[package.dependencies]
asgiref = ">=3.0,<4.0"
opentelemetry-api = ">=1.12,<2.0"
opentelemetry-instrumentation = "0.44b0"
opentelemetry-semantic-conventions = "0.44b0"
opentelemetry-util-http = "0.44b0"
opentelemetry-instrumentation = "0.45b0"
opentelemetry-semantic-conventions = "0.45b0"
opentelemetry-util-http = "0.45b0"
[package.extras]
instruments = ["asgiref (>=3.0,<4.0)"]
test = ["opentelemetry-instrumentation-asgi[instruments]", "opentelemetry-test-utils (==0.44b0)"]
[[package]]
name = "opentelemetry-instrumentation-fastapi"
version = "0.44b0"
version = "0.45b0"
description = "OpenTelemetry FastAPI Instrumentation"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_instrumentation_fastapi-0.44b0-py3-none-any.whl", hash = "sha256:4441482944bea6676816668d56deb94af990e8c6e9582c581047e5d84c91d3c9"},
{file = "opentelemetry_instrumentation_fastapi-0.44b0.tar.gz", hash = "sha256:67ed10b93ad9d35238ae0be73cf8acbbb65a4a61fb7444d0aee5b0c492e294db"},
{file = "opentelemetry_instrumentation_fastapi-0.45b0-py3-none-any.whl", hash = "sha256:77d9c123a363129148f5f66d44094f3d67aaaa2b201396d94782b4a7f9ce4314"},
{file = "opentelemetry_instrumentation_fastapi-0.45b0.tar.gz", hash = "sha256:5a6b91e1c08a01601845fcfcfdefd0a2aecdb3c356d4a436a3210cb58c21487e"},
]
[package.dependencies]
opentelemetry-api = ">=1.12,<2.0"
opentelemetry-instrumentation = "0.44b0"
opentelemetry-instrumentation-asgi = "0.44b0"
opentelemetry-semantic-conventions = "0.44b0"
opentelemetry-util-http = "0.44b0"
opentelemetry-instrumentation = "0.45b0"
opentelemetry-instrumentation-asgi = "0.45b0"
opentelemetry-semantic-conventions = "0.45b0"
opentelemetry-util-http = "0.45b0"
[package.extras]
instruments = ["fastapi (>=0.58,<1.0)"]
test = ["httpx (>=0.22,<1.0)", "opentelemetry-instrumentation-fastapi[instruments]", "opentelemetry-test-utils (==0.44b0)", "requests (>=2.23,<3.0)"]
[[package]]
name = "opentelemetry-instrumentation-httpx"
@ -5622,13 +5638,13 @@ test = ["opentelemetry-instrumentation-httpx[instruments]", "opentelemetry-sdk (
[[package]]
name = "opentelemetry-proto"
version = "1.23.0"
version = "1.24.0"
description = "OpenTelemetry Python Proto"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_proto-1.23.0-py3-none-any.whl", hash = "sha256:4c017deca052cb287a6003b7c989ed8b47af65baeb5d57ebf93dde0793f78509"},
{file = "opentelemetry_proto-1.23.0.tar.gz", hash = "sha256:e6aaf8b7ace8d021942d546161401b83eed90f9f2cc6f13275008cea730e4651"},
{file = "opentelemetry_proto-1.24.0-py3-none-any.whl", hash = "sha256:bcb80e1e78a003040db71ccf83f2ad2019273d1e0828089d183b18a1476527ce"},
{file = "opentelemetry_proto-1.24.0.tar.gz", hash = "sha256:ff551b8ad63c6cabb1845ce217a6709358dfaba0f75ea1fa21a61ceddc78cab8"},
]
[package.dependencies]
@ -5636,40 +5652,40 @@ protobuf = ">=3.19,<5.0"
[[package]]
name = "opentelemetry-sdk"
version = "1.23.0"
version = "1.24.0"
description = "OpenTelemetry Python SDK"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_sdk-1.23.0-py3-none-any.whl", hash = "sha256:a93c96990ac0f07c6d679e2f1015864ff7a4f5587122dd5af968034436efb1fd"},
{file = "opentelemetry_sdk-1.23.0.tar.gz", hash = "sha256:9ddf60195837b59e72fd2033d6a47e2b59a0f74f0ec37d89387d89e3da8cab7f"},
{file = "opentelemetry_sdk-1.24.0-py3-none-any.whl", hash = "sha256:fa731e24efe832e98bcd90902085b359dcfef7d9c9c00eb5b9a18587dae3eb59"},
{file = "opentelemetry_sdk-1.24.0.tar.gz", hash = "sha256:75bc0563affffa827700e0f4f4a68e1e257db0df13372344aebc6f8a64cde2e5"},
]
[package.dependencies]
opentelemetry-api = "1.23.0"
opentelemetry-semantic-conventions = "0.44b0"
opentelemetry-api = "1.24.0"
opentelemetry-semantic-conventions = "0.45b0"
typing-extensions = ">=3.7.4"
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.44b0"
version = "0.45b0"
description = "OpenTelemetry Semantic Conventions"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_semantic_conventions-0.44b0-py3-none-any.whl", hash = "sha256:7c434546c9cbd797ab980cc88bf9ff3f4a5a28f941117cad21694e43d5d92019"},
{file = "opentelemetry_semantic_conventions-0.44b0.tar.gz", hash = "sha256:2e997cb28cd4ca81a25a9a43365f593d0c2b76be0685015349a89abdf1aa4ffa"},
{file = "opentelemetry_semantic_conventions-0.45b0-py3-none-any.whl", hash = "sha256:a4a6fb9a7bacd9167c082aa4681009e9acdbfa28ffb2387af50c2fef3d30c864"},
{file = "opentelemetry_semantic_conventions-0.45b0.tar.gz", hash = "sha256:7c84215a44ac846bc4b8e32d5e78935c5c43482e491812a0bb8aaf87e4d92118"},
]
[[package]]
name = "opentelemetry-util-http"
version = "0.44b0"
version = "0.45b0"
description = "Web util for OpenTelemetry"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_util_http-0.44b0-py3-none-any.whl", hash = "sha256:ff018ab6a2fa349537ff21adcef99a294248b599be53843c44f367aef6bccea5"},
{file = "opentelemetry_util_http-0.44b0.tar.gz", hash = "sha256:75896dffcbbeb5df5429ad4526e22307fc041a27114e0c5bfd90bb219381e68f"},
{file = "opentelemetry_util_http-0.45b0-py3-none-any.whl", hash = "sha256:6628868b501b3004e1860f976f410eeb3d3499e009719d818000f24ce17b6e33"},
{file = "opentelemetry_util_http-0.45b0.tar.gz", hash = "sha256:4ce08b6a7d52dd7c96b7705b5b4f06fdb6aa3eac1233b3b0bfef8a0cab9a92cd"},
]
[[package]]
@ -6842,93 +6858,93 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pymongo"
version = "4.6.2"
version = "4.6.3"
description = "Python driver for MongoDB <http://www.mongodb.org>"
optional = false
python-versions = ">=3.7"
files = [
{file = "pymongo-4.6.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7640d176ee5b0afec76a1bda3684995cb731b2af7fcfd7c7ef8dc271c5d689af"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux1_i686.whl", hash = "sha256:4e2129ec8f72806751b621470ac5d26aaa18fae4194796621508fa0e6068278a"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:c43205e85cbcbdf03cff62ad8f50426dd9d20134a915cfb626d805bab89a1844"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:91ddf95cedca12f115fbc5f442b841e81197d85aa3cc30b82aee3635a5208af2"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:0fbdbf2fba1b4f5f1522e9f11e21c306e095b59a83340a69e908f8ed9b450070"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:097791d5a8d44e2444e0c8c4d6e14570ac11e22bcb833808885a5db081c3dc2a"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:e0b208ebec3b47ee78a5c836e2e885e8c1e10f8ffd101aaec3d63997a4bdcd04"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1849fd6f1917b4dc5dbf744b2f18e41e0538d08dd8e9ba9efa811c5149d665a3"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa0bbbfbd1f8ebbd5facaa10f9f333b20027b240af012748555148943616fdf3"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4522ad69a4ab0e1b46a8367d62ad3865b8cd54cf77518c157631dac1fdc97584"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397949a9cc85e4a1452f80b7f7f2175d557237177120954eff00bf79553e89d3"},
{file = "pymongo-4.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d511db310f43222bc58d811037b176b4b88dc2b4617478c5ef01fea404f8601"},
{file = "pymongo-4.6.2-cp310-cp310-win32.whl", hash = "sha256:991e406db5da4d89fb220a94d8caaf974ffe14ce6b095957bae9273c609784a0"},
{file = "pymongo-4.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:94637941fe343000f728e28d3fe04f1f52aec6376b67b85583026ff8dab2a0e0"},
{file = "pymongo-4.6.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:84593447a5c5fe7a59ba86b72c2c89d813fbac71c07757acdf162fbfd5d005b9"},
{file = "pymongo-4.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aebddb2ec2128d5fc2fe3aee6319afef8697e0374f8a1fcca3449d6f625e7b4"},
{file = "pymongo-4.6.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f706c1a644ed33eaea91df0a8fb687ce572b53eeb4ff9b89270cb0247e5d0e1"},
{file = "pymongo-4.6.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18c422e6b08fa370ed9d8670c67e78d01f50d6517cec4522aa8627014dfa38b6"},
{file = "pymongo-4.6.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d002ae456a15b1d790a78bb84f87af21af1cb716a63efb2c446ab6bcbbc48ca"},
{file = "pymongo-4.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f86ba0c781b497a3c9c886765d7b6402a0e3ae079dd517365044c89cd7abb06"},
{file = "pymongo-4.6.2-cp311-cp311-win32.whl", hash = "sha256:ac20dd0c7b42555837c86f5ea46505f35af20a08b9cf5770cd1834288d8bd1b4"},
{file = "pymongo-4.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:e78af59fd0eb262c2a5f7c7d7e3b95e8596a75480d31087ca5f02f2d4c6acd19"},
{file = "pymongo-4.6.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6125f73503407792c8b3f80165f8ab88a4e448d7d9234c762681a4d0b446fcb4"},
{file = "pymongo-4.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba052446a14bd714ec83ca4e77d0d97904f33cd046d7bb60712a6be25eb31dbb"},
{file = "pymongo-4.6.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b65433c90e07dc252b4a55dfd885ca0df94b1cf77c5b8709953ec1983aadc03"},
{file = "pymongo-4.6.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2160d9c8cd20ce1f76a893f0daf7c0d38af093f36f1b5c9f3dcf3e08f7142814"},
{file = "pymongo-4.6.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f251f287e6d42daa3654b686ce1fcb6d74bf13b3907c3ae25954978c70f2cd4"},
{file = "pymongo-4.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7d227a60b00925dd3aeae4675575af89c661a8e89a1f7d1677e57eba4a3693c"},
{file = "pymongo-4.6.2-cp312-cp312-win32.whl", hash = "sha256:311794ef3ccae374aaef95792c36b0e5c06e8d5cf04a1bdb1b2bf14619ac881f"},
{file = "pymongo-4.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:f673b64a0884edcc56073bda0b363428dc1bf4eb1b5e7d0b689f7ec6173edad6"},
{file = "pymongo-4.6.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:fe010154dfa9e428bd2fb3e9325eff2216ab20a69ccbd6b5cac6785ca2989161"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1f5f4cd2969197e25b67e24d5b8aa2452d381861d2791d06c493eaa0b9c9fcfe"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c9519c9d341983f3a1bd19628fecb1d72a48d8666cf344549879f2e63f54463b"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:c68bf4a399e37798f1b5aa4f6c02886188ef465f4ac0b305a607b7579413e366"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:a509db602462eb736666989739215b4b7d8f4bb8ac31d0bffd4be9eae96c63ef"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:362a5adf6f3f938a8ff220a4c4aaa93e84ef932a409abecd837c617d17a5990f"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:ee30a9d4c27a88042d0636aca0275788af09cc237ae365cd6ebb34524bddb9cc"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:477914e13501bb1d4608339ee5bb618be056d2d0e7267727623516cfa902e652"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd343ca44982d480f1e39372c48e8e263fc6f32e9af2be456298f146a3db715"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3797e0a628534e07a36544d2bfa69e251a578c6d013e975e9e3ed2ac41f2d95"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97d81d357e1a2a248b3494d52ebc8bf15d223ee89d59ee63becc434e07438a24"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed694c0d1977cb54281cb808bc2b247c17fb64b678a6352d3b77eb678ebe1bd9"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ceaaff4b812ae368cf9774989dea81b9bbb71e5bed666feca6a9f3087c03e49"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7dd63f7c2b3727541f7f37d0fb78d9942eb12a866180fbeb898714420aad74e2"},
{file = "pymongo-4.6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e571434633f99a81e081738721bb38e697345281ed2f79c2f290f809ba3fbb2f"},
{file = "pymongo-4.6.2-cp37-cp37m-win32.whl", hash = "sha256:3e9f6e2f3da0a6af854a3e959a6962b5f8b43bbb8113cd0bff0421c5059b3106"},
{file = "pymongo-4.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:3a5280f496297537301e78bde250c96fadf4945e7b2c397d8bb8921861dd236d"},
{file = "pymongo-4.6.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:5f6bcd2d012d82d25191a911a239fd05a8a72e8c5a7d81d056c0f3520cad14d1"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:4fa30494601a6271a8b416554bd7cde7b2a848230f0ec03e3f08d84565b4bf8c"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bea62f03a50f363265a7a651b4e2a4429b4f138c1864b2d83d4bf6f9851994be"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b2d445f1cf147331947cc35ec10342f898329f29dd1947a3f8aeaf7e0e6878d1"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:5db133d6ec7a4f7fc7e2bd098e4df23d7ad949f7be47b27b515c9fb9301c61e4"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:9eec7140cf7513aa770ea51505d312000c7416626a828de24318fdcc9ac3214c"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:5379ca6fd325387a34cda440aec2bd031b5ef0b0aa2e23b4981945cff1dab84c"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:579508536113dbd4c56e4738955a18847e8a6c41bf3c0b4ab18b51d81a6b7be8"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bae553ca39ed52db099d76acd5e8566096064dc7614c34c9359bb239ec4081"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0257e0eebb50f242ca28a92ef195889a6ad03dcdde5bf1c7ab9f38b7e810801"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbafe3a1df21eeadb003c38fc02c1abf567648b6477ec50c4a3c042dca205371"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaecfafb407feb6f562c7f2f5b91f22bfacba6dd739116b1912788cff7124c4a"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e942945e9112075a84d2e2d6e0d0c98833cdcdfe48eb8952b917f996025c7ffa"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f7b98f8d2cf3eeebde738d080ae9b4276d7250912d9751046a9ac1efc9b1ce2"},
{file = "pymongo-4.6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8110b78fc4b37dced85081d56795ecbee6a7937966e918e05e33a3900e8ea07d"},
{file = "pymongo-4.6.2-cp38-cp38-win32.whl", hash = "sha256:df813f0c2c02281720ccce225edf39dc37855bf72cdfde6f789a1d1cf32ffb4b"},
{file = "pymongo-4.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:64ec3e2dcab9af61bdbfcb1dd863c70d1b0c220b8e8ac11df8b57f80ee0402b3"},
{file = "pymongo-4.6.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bff601fbfcecd2166d9a2b70777c2985cb9689e2befb3278d91f7f93a0456cae"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f1febca6f79e91feafc572906871805bd9c271b6a2d98a8bb5499b6ace0befed"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d788cb5cc947d78934be26eef1623c78cec3729dc93a30c23f049b361aa6d835"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5c2f258489de12a65b81e1b803a531ee8cf633fa416ae84de65cd5f82d2ceb37"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:fb24abcd50501b25d33a074c1790a1389b6460d2509e4b240d03fd2e5c79f463"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:4d982c6db1da7cf3018183891883660ad085de97f21490d314385373f775915b"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:b2dd8c874927a27995f64a3b44c890e8a944c98dec1ba79eab50e07f1e3f801b"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:4993593de44c741d1e9f230f221fe623179f500765f9855936e4ff6f33571bad"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:658f6c028edaeb02761ebcaca8d44d519c22594b2a51dcbc9bd2432aa93319e3"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68109c13176749fbbbbbdb94dd4a58dcc604db6ea43ee300b2602154aebdd55f"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:707d28a822b918acf941cff590affaddb42a5d640614d71367c8956623a80cbc"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f251db26c239aec2a4d57fbe869e0a27b7f6b5384ec6bf54aeb4a6a5e7408234"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57c05f2e310701fc17ae358caafd99b1830014e316f0242d13ab6c01db0ab1c2"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b575fbe6396bbf21e4d0e5fd2e3cdb656dc90c930b6c5532192e9a89814f72d"},
{file = "pymongo-4.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ca5877754f3fa6e4fe5aacf5c404575f04c2d9efc8d22ed39576ed9098d555c8"},
{file = "pymongo-4.6.2-cp39-cp39-win32.whl", hash = "sha256:8caa73fb19070008e851a589b744aaa38edd1366e2487284c61158c77fdf72af"},
{file = "pymongo-4.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:3e03c732cb64b96849310e1d8688fb70d75e2571385485bf2f1e7ad1d309fa53"},
{file = "pymongo-4.6.2.tar.gz", hash = "sha256:ab7d01ac832a1663dad592ccbd92bb0f0775bc8f98a1923c5e1a7d7fead495af"},
{file = "pymongo-4.6.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e344d0afdd7c06c1f1e66a4736593293f432defc2191e6b411fc9c82fa8c5adc"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux1_i686.whl", hash = "sha256:731a92dfc4022db763bfa835c6bd160f2d2cba6ada75749c2ed500e13983414b"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:c4726e36a2f7e92f09f5b8e92ba4db7525daffe31a0dcbcf0533edc0ade8c7d8"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:00e6cfce111883ca63a3c12878286e0b89871f4b840290e61fb6f88ee0e687be"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:cc7a26edf79015c58eea46feb5b262cece55bc1d4929a8a9e0cbe7e6d6a9b0eb"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:4955be64d943b30f2a7ff98d818ca530f7cb37450bc6b32c37e0e74821907ef8"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:af039afc6d787502c02089759778b550cb2f25dbe2780f5b050a2e37031c3fbf"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccc15a7c7a99aed7d0831eaf78a607f1db0c7a255f96e3d18984231acd72f70c"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e97c138d811e9367723fcd07c4402a9211caae20479fdd6301d57762778a69f"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebcc145c74d06296ce0cad35992185064e5cb2aadef719586778c144f0cd4d37"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:664c64b6bdb31aceb80f0556951e5e2bf50d359270732268b4e7af00a1cf5d6c"},
{file = "pymongo-4.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4056bc421d4df2c61db4e584415f2b0f1eebb92cbf9222f7f38303467c37117"},
{file = "pymongo-4.6.3-cp310-cp310-win32.whl", hash = "sha256:cdbea2aac1a4caa66ee912af3601557d2bda2f9f69feec83601c78c7e53ece64"},
{file = "pymongo-4.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:6cec7279e5a1b74b257d0270a8c97943d745811066630a6bc6beb413c68c6a33"},
{file = "pymongo-4.6.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:138b9fa18d40401c217bc038a48bcde4160b02d36d8632015b1804971a2eaa2f"},
{file = "pymongo-4.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60931b0e07448afe8866ffff764cd5bf4b1a855dc84c7dcb3974c6aa6a377a59"},
{file = "pymongo-4.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b35f8bded43ff91475305445fedf0613f880ff7e25c75ae1028e1260a9b7a86"},
{file = "pymongo-4.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:872bad5c83f7eec9da11e1fef5f858c6a4c79fe4a83c7780e7b0fe95d560ae3f"},
{file = "pymongo-4.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2ad3e5bfcd345c0bfe9af69a82d720860b5b043c1657ffb513c18a0dee19c19"},
{file = "pymongo-4.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e208f2ab7b495eff8fd175022abfb0abce6307ac5aee3f4de51fc1a459b71c9"},
{file = "pymongo-4.6.3-cp311-cp311-win32.whl", hash = "sha256:4670edbb5ddd71a4d555668ef99b032a5f81b59e4145d66123aa0d831eac7883"},
{file = "pymongo-4.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:1c2761302b6cbfd12e239ce1b8061d4cf424a361d199dcb32da534985cae9350"},
{file = "pymongo-4.6.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:722f2b709b63311c0efda4fa4c603661faa4bec6bad24a6cc41a3bc6d841bf09"},
{file = "pymongo-4.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:994386a4d6ad39e18bcede6dc8d1d693ec3ed897b88f86b1841fbc37227406da"},
{file = "pymongo-4.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:391aea047bba928006114282f175bc8d09c53fe1b7d8920bf888325e229302fe"},
{file = "pymongo-4.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4330c022024e7994b630199cdae909123e4b0e9cf15335de71b146c0f6a2435"},
{file = "pymongo-4.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01277a7e183c59081368e4efbde2b8f577014431b257959ca98d3a4e8682dd51"},
{file = "pymongo-4.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d30d5d7963453b478016bf7b0d87d7089ca24d93dbdecfbc9aa32f1b4772160a"},
{file = "pymongo-4.6.3-cp312-cp312-win32.whl", hash = "sha256:a023804a3ac0f85d4510265b60978522368b5815772262e61e3a2222a8b315c9"},
{file = "pymongo-4.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2a6ae9a600bbc2dbff719c98bf5da584fb8a4f2bb23729a09be2e9c3dbc61c8a"},
{file = "pymongo-4.6.3-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:3b909e5b1864de01510079b39bbdc480720c37747be5552b354bc73f02c24a3c"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:48c60bd32ec141c0d45d8471179430003d9fb4490da181b8165fb1dce9cc255c"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36d7049fc183fe4edda3eae7f66ea14c660921429e082fe90b4b7f4dc6664a70"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:18e5c161b18660f1c9d1f78236de45520a436be65e42b7bb51f25f74ad22bdde"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:e458e6fc2b7dd40d15cda04898bd2d8c9ff7ae086c516bc261628d54eb4e3158"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:e420e74c6db4594a6d09f39b58c0772679006cb0b4fc40901ba608794d87dad2"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:9c9340c7161e112e36ebb97fbba1cdbe7db3dfacb694d2918b1f155a01f3d859"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:26d036e0f5de09d0b21d0fc30314fcf2ae6359e4d43ae109aa6cf27b4ce02d30"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7cf28d9c90e40d4e385b858e4095739829f466f23e08674085161d86bb4bb10"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9066dff9dc0a182478ca5885d0b8a2b820b462e19459ada109df7a3ced31b272"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1e1586ebdebe0447a24842480defac17c496430a218486c96e2da3f164c0f05"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b3853fb66bf34ce1b6e573e1bbb3cb28763be9d1f57758535757faf1ab2f24a"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:462684a6f5ce6f2661c30eab4d1d459231e0eed280f338e716e31a24fc09ccb3"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a4ea44e5a913bdb7c9abd34c69e9fcfac10dfaf49765463e0dc1ea922dd2a9d"},
{file = "pymongo-4.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:098d420a8214ad25f872de7e8b309441995d12ece0376218a04d9ed5d2222cf3"},
{file = "pymongo-4.6.3-cp37-cp37m-win32.whl", hash = "sha256:7330245253fbe2e09845069d2f4d35dd27f63e377034c94cb0ddac18bc8b0d82"},
{file = "pymongo-4.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:151361c101600a85cb1c1e0db4e4b28318b521fcafa9b62d389f7342faaaee80"},
{file = "pymongo-4.6.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:4d167d546352869125dc86f6fda6dffc627d8a9c8963eaee665825f2520d542b"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:eaf3d594ebfd5e1f3503d81e06a5d78e33cda27418b36c2491c3d4ad4fca5972"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7ee79e02a7c5ed34706ecb5dad19e6c7d267cf86d28c075ef3127c58f3081279"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af5c5112db04cf62a5d9d224a24f289aaecb47d152c08a457cca81cee061d5bd"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:6b5aec78aa4840e8d6c3881900259892ab5733a366696ca10d99d68c3d73eaaf"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:9757602fb45c8ecc1883fe6db7c59c19d87eb3c645ec9342d28a6026837da931"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:dde9fb6e105ce054339256a8b7a9775212ebb29596ef4e402d7bbc63b354d202"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:7df8b166d3db6cfead4cf55b481408d8f0935d8bd8d6dbf64507c49ef82c7200"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53451190b8628e1ce7d1fe105dc376c3f10705127bd3b51fe3e107b9ff1851e6"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75107a386d4ccf5291e75cce8ca3898430e7907f4cc1208a17c9efad33a1ea84"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4a0660ce32d8459b7f12dc3ca0141528fead62d3cce31b548f96f30902074cc0"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa310096450e9c461b7dfd66cbc1c41771fe36c06200440bb3e062b1d4a06b6e"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f465cca9b178e7bb782f952dd58e9e92f8ba056e585959465f2bb50feddef5f"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c67c19f653053ef2ebd7f1837c2978400058d6d7f66ec5760373a21eaf660158"},
{file = "pymongo-4.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c701de8e483fb5e53874aab642235361aac6de698146b02c644389eaa8c137b6"},
{file = "pymongo-4.6.3-cp38-cp38-win32.whl", hash = "sha256:90525454546536544307e6da9c81f331a71a1b144e2d038fec587cc9f9250285"},
{file = "pymongo-4.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:3e1ba5a037c526a3f4060c28f8d45d71ed9626e2bf954b0cd9a8dcc3b45172ee"},
{file = "pymongo-4.6.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:14a82593528cddc93cfea5ee78fac95ae763a3a4e124ca79ee0b24fbbc6da1c9"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:cd6c15242d9306ff1748681c3235284cbe9f807aeaa86cd17d85e72af626e9a7"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6de33f1b2eed91b802ec7abeb92ffb981d052f3604b45588309aae9e0f6e3c02"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0182899aafe830f25cf96c5976d724efeaaf7b6646c15424ad8dd25422b2efe1"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:8d0ea740a2faa56f930dc82c5976d96c017ece26b29a1cddafb58721c7aab960"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:5c8a4982f5eb767c6fbfb8fb378683d09bcab7c3251ba64357eef600d43f6c23"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:becfa816545a48c8e740ac2fd624c1c121e1362072d68ffcf37a6b1be8ea187e"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:ff7d1f449fcad23d9bc8e8dc2b9972be38bcd76d99ea5f7d29b2efa929c2a7ff"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e097f877de4d6af13a33ef938bf2a2350f424be5deabf8b857da95f5b080487a"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:705a9bfd619301ee7e985d6f91f68b15dfcb2f6f36b8cc225cc82d4260d2bce5"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ef1b4992ee1cb8bb16745e70afa0c02c5360220a7a8bb4775888721f052d0a6"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3d10bdd46cbc35a2109737d36ffbef32e7420569a87904738ad444ccb7ac2c5"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17c1c143ba77d6e21fc8b48e93f0a5ed982a23447434e9ee4fbb6d633402506b"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e51e30d67b468a2a634ade928b30cb3e420127f148a9aec60de33f39087bdc4"},
{file = "pymongo-4.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bec8e4e88984be157408f1923d25869e1b575c07711cdbdde596f66931800934"},
{file = "pymongo-4.6.3-cp39-cp39-win32.whl", hash = "sha256:98877a9c4ad42df8253a12d8d17a3265781d1feb5c91c767bd153f88feb0b670"},
{file = "pymongo-4.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:6d5b35da9e16cda630baed790ffc3d0d01029d269523a7cec34d2ec7e6823e75"},
{file = "pymongo-4.6.3.tar.gz", hash = "sha256:400074090b9a631f120b42c61b222fd743490c133a5d2f99c0208cefcccc964e"},
]
[package.dependencies]
@ -8791,36 +8807,36 @@ files = [
[[package]]
name = "torch"
version = "2.2.1"
version = "2.2.2"
description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration"
optional = true
python-versions = ">=3.8.0"
files = [
{file = "torch-2.2.1-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:8d3bad336dd2c93c6bcb3268e8e9876185bda50ebde325ef211fb565c7d15273"},
{file = "torch-2.2.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:5297f13370fdaca05959134b26a06a7f232ae254bf2e11a50eddec62525c9006"},
{file = "torch-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:5f5dee8433798888ca1415055f5e3faf28a3bad660e4c29e1014acd3275ab11a"},
{file = "torch-2.2.1-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:b6d78338acabf1fb2e88bf4559d837d30230cf9c3e4337261f4d83200df1fcbe"},
{file = "torch-2.2.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:6ab3ea2e29d1aac962e905142bbe50943758f55292f1b4fdfb6f4792aae3323e"},
{file = "torch-2.2.1-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:d86664ec85902967d902e78272e97d1aff1d331f7619d398d3ffab1c9b8e9157"},
{file = "torch-2.2.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d6227060f268894f92c61af0a44c0d8212e19cb98d05c20141c73312d923bc0a"},
{file = "torch-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:77e990af75fb1675490deb374d36e726f84732cd5677d16f19124934b2409ce9"},
{file = "torch-2.2.1-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:46085e328d9b738c261f470231e987930f4cc9472d9ffb7087c7a1343826ac51"},
{file = "torch-2.2.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:2d9e7e5ecbb002257cf98fae13003abbd620196c35f85c9e34c2adfb961321ec"},
{file = "torch-2.2.1-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:ada53aebede1c89570e56861b08d12ba4518a1f8b82d467c32665ec4d1f4b3c8"},
{file = "torch-2.2.1-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:be21d4c41ecebed9e99430dac87de1439a8c7882faf23bba7fea3fea7b906ac1"},
{file = "torch-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:79848f46196750367dcdf1d2132b722180b9d889571e14d579ae82d2f50596c5"},
{file = "torch-2.2.1-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:7ee804847be6be0032fbd2d1e6742fea2814c92bebccb177f0d3b8e92b2d2b18"},
{file = "torch-2.2.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:84b2fb322ab091039fdfe74e17442ff046b258eb5e513a28093152c5b07325a7"},
{file = "torch-2.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5c0c83aa7d94569997f1f474595e808072d80b04d34912ce6f1a0e1c24b0c12a"},
{file = "torch-2.2.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:91a1b598055ba06b2c386415d2e7f6ac818545e94c5def597a74754940188513"},
{file = "torch-2.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f93ddf3001ecec16568390b507652644a3a103baa72de3ad3b9c530e3277098"},
{file = "torch-2.2.1-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:0e8bdd4c77ac2584f33ee14c6cd3b12767b4da508ec4eed109520be7212d1069"},
{file = "torch-2.2.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:6a21bcd7076677c97ca7db7506d683e4e9db137e8420eb4a68fb67c3668232a7"},
{file = "torch-2.2.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f1b90ac61f862634039265cd0f746cc9879feee03ff962c803486301b778714b"},
{file = "torch-2.2.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:ed9e29eb94cd493b36bca9cb0b1fd7f06a0688215ad1e4b3ab4931726e0ec092"},
{file = "torch-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:c47bc25744c743f3835831a20efdcfd60aeb7c3f9804a213f61e45803d16c2a5"},
{file = "torch-2.2.1-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:0952549bcb43448c8d860d5e3e947dd18cbab491b14638e21750cb3090d5ad3e"},
{file = "torch-2.2.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:26bd2272ec46fc62dcf7d24b2fb284d44fcb7be9d529ebf336b9860350d674ed"},
{file = "torch-2.2.2-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:bc889d311a855dd2dfd164daf8cc903a6b7273a747189cebafdd89106e4ad585"},
{file = "torch-2.2.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:15dffa4cc3261fa73d02f0ed25f5fa49ecc9e12bf1ae0a4c1e7a88bbfaad9030"},
{file = "torch-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:11e8fe261233aeabd67696d6b993eeb0896faa175c6b41b9a6c9f0334bdad1c5"},
{file = "torch-2.2.2-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:b2e2200b245bd9f263a0d41b6a2dab69c4aca635a01b30cca78064b0ef5b109e"},
{file = "torch-2.2.2-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:877b3e6593b5e00b35bbe111b7057464e76a7dd186a287280d941b564b0563c2"},
{file = "torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb"},
{file = "torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf"},
{file = "torch-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c"},
{file = "torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059"},
{file = "torch-2.2.2-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1"},
{file = "torch-2.2.2-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:cf12cdb66c9c940227ad647bc9cf5dba7e8640772ae10dfe7569a0c1e2a28aca"},
{file = "torch-2.2.2-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:89ddac2a8c1fb6569b90890955de0c34e1724f87431cacff4c1979b5f769203c"},
{file = "torch-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:451331406b760f4b1ab298ddd536486ab3cfb1312614cfe0532133535be60bea"},
{file = "torch-2.2.2-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:eb4d6e9d3663e26cd27dc3ad266b34445a16b54908e74725adb241aa56987533"},
{file = "torch-2.2.2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:bf9558da7d2bf7463390b3b2a61a6a3dbb0b45b161ee1dd5ec640bf579d479fc"},
{file = "torch-2.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cd2bf7697c9e95fb5d97cc1d525486d8cf11a084c6af1345c2c2c22a6b0029d0"},
{file = "torch-2.2.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b421448d194496e1114d87a8b8d6506bce949544e513742b097e2ab8f7efef32"},
{file = "torch-2.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:3dbcd563a9b792161640c0cffe17e3270d85e8f4243b1f1ed19cca43d28d235b"},
{file = "torch-2.2.2-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:31f4310210e7dda49f1fb52b0ec9e59382cfcb938693f6d5378f25b43d7c1d29"},
{file = "torch-2.2.2-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:c795feb7e8ce2e0ef63f75f8e1ab52e7fd5e1a4d7d0c31367ade1e3de35c9e95"},
{file = "torch-2.2.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a6e5770d68158d07456bfcb5318b173886f579fdfbf747543901ce718ea94782"},
{file = "torch-2.2.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:67dcd726edff108e2cd6c51ff0e416fd260c869904de95750e80051358680d24"},
{file = "torch-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:539d5ef6c4ce15bd3bd47a7b4a6e7c10d49d4d21c0baaa87c7d2ef8698632dfb"},
{file = "torch-2.2.2-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:dff696de90d6f6d1e8200e9892861fd4677306d0ef604cb18f2134186f719f82"},
{file = "torch-2.2.2-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:3a4dd910663fd7a124c056c878a52c2b0be4a5a424188058fe97109d4436ee42"},
]
[package.dependencies]
@ -9631,22 +9647,24 @@ files = [
[[package]]
name = "weaviate-client"
version = "3.26.2"
version = "4.5.4"
description = "A python native Weaviate client"
optional = false
python-versions = ">=3.8"
files = [
{file = "weaviate-client-3.26.2.tar.gz", hash = "sha256:63ec70839b64909810a64aa7b3e5b85088462e93c7e2ed3c32ebefb702f36723"},
{file = "weaviate_client-3.26.2-py3-none-any.whl", hash = "sha256:ca43bfb9c06b8ae3fd938dc9158acd93d4cbf4622192e173333e1ff63cf97164"},
{file = "weaviate-client-4.5.4.tar.gz", hash = "sha256:fc53dc73cd53df453c5e6dc758e49a6a1549212d6670ddd013392107120692f8"},
{file = "weaviate_client-4.5.4-py3-none-any.whl", hash = "sha256:f6d3a6b759e5aa0d3350067490526ea38b9274ae4043b4a3ae0064c28d56883f"},
]
[package.dependencies]
authlib = ">=1.2.1,<2.0.0"
grpcio = ">=1.57.0,<2.0.0"
grpcio-health-checking = ">=1.57.0,<2.0.0"
grpcio-tools = ">=1.57.0,<2.0.0"
httpx = "0.27.0"
pydantic = ">=2.5.0,<3.0.0"
requests = ">=2.30.0,<3.0.0"
validators = ">=0.21.2,<1.0.0"
[package.extras]
grpc = ["grpcio (>=1.57.0,<2.0.0)", "grpcio-tools (>=1.57.0,<2.0.0)"]
validators = "0.22.0"
[[package]]
name = "websocket-client"

View file

@ -7,7 +7,6 @@ maintainers = [
"Carlos Coelho <carlos@logspace.ai>",
"Cristhian Zanforlin <cristhian.lousa@gmail.com>",
"Gabriel Almeida <gabriel@logspace.ai>",
"Gustavo Schaedler <gustavopoa@gmail.com>",
"Igor Carvalho <igorr.ackerman@gmail.com>",
"Lucas Eduoli <lucaseduoli@gmail.com>",
"Otávio Anovazzi <otavio2204@gmail.com>",

View file

@ -26,13 +26,13 @@ def upgrade() -> None:
flow_constraints = inspector.get_unique_constraints("flow")
user_constraints = inspector.get_unique_constraints("user")
try:
if not any(constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints):
if not any(constraint["column_names"] == ["id"] for constraint in api_key_constraints):
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.create_unique_constraint("uq_apikey_id", ["id"])
if not any(constraint["name"] == "uq_flow_id" for constraint in flow_constraints):
if not any(constraint["column_names"] == ["id"] for constraint in flow_constraints):
with op.batch_alter_table("flow", schema=None) as batch_op:
batch_op.create_unique_constraint("uq_flow_id", ["id"])
if not any(constraint["name"] == "uq_user_id" for constraint in user_constraints):
if not any(constraint["column_names"] == ["id"] for constraint in user_constraints):
with op.batch_alter_table("user", schema=None) as batch_op:
batch_op.create_unique_constraint("uq_user_id", ["id"])
except Exception as e:

View file

@ -2,6 +2,7 @@ import warnings
from typing import Optional, Union
from langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.memory import add_messages
from langflow.schema import Record
@ -21,6 +22,7 @@ class ChatComponent(CustomComponent):
"sender": {
"options": ["Machine", "User"],
"display_name": "Sender Type",
"advanced": True,
},
"sender_name": {"display_name": "Sender Name"},
"session_id": {
@ -31,6 +33,13 @@ class ChatComponent(CustomComponent):
"return_record": {
"display_name": "Return Record",
"info": "Return the message as a record containing the sender, sender_name, and session_id.",
"advanced": True,
},
"record_template": {
"display_name": "Record Template",
"multiline": True,
"info": "In case of Message being a Record, this template will be used to convert it to text.",
"advanced": True,
},
}
@ -74,9 +83,10 @@ class ChatComponent(CustomComponent):
self,
sender: Optional[str] = "User",
sender_name: Optional[str] = "User",
input_value: Optional[str] = None,
input_value: Optional[Union[str, Record]] = None,
session_id: Optional[str] = None,
return_record: Optional[bool] = False,
record_template: Optional[str] = "Text: {text}\nData: {data}",
) -> Union[Text, Record]:
input_value_record: Optional[Record] = None
if return_record:
@ -94,6 +104,8 @@ class ChatComponent(CustomComponent):
"session_id": session_id,
},
)
elif isinstance(input_value, Record):
input_value = records_to_text(template=record_template, records=input_value)
if not input_value:
input_value = ""
if return_record and input_value_record:

View file

@ -1,18 +1,28 @@
from typing import Optional
from typing import Optional, Union
from langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema.schema import Record
class TextComponent(CustomComponent):
display_name = "Text Component"
description = "Used to pass text to the next component."
field_config = {
"input_value": {"display_name": "Value", "multiline": True},
}
def build_config(self):
return {
"input_value": {"display_name": "Value", "input_types": ["Record"], "info": "Text or Record to be passed."},
"record_template": {"display_name": "Record Template", "multiline": True},
}
def build(self, input_value: Optional[str] = "") -> Text:
def build(
self,
input_value: Optional[Union[Text, Record]] = "",
record_template: Optional[str] = "Text: {text}\nData: {data}",
) -> Text:
if isinstance(input_value, Record):
input_value = records_to_text(template=record_template, records=input_value)
self.status = input_value
if not input_value:
input_value = ""

View file

@ -1,18 +1,17 @@
__all__ = [
"agents",
"chains",
"data",
"documentloaders",
"embeddings",
"experimental",
"helpers",
"inputs",
"memories",
"model_specs",
"models",
"outputs",
"retrievers",
"textsplitters",
"toolkits",
"tools",
"vectorsearch",
"vectorstores",
]

View file

@ -5,6 +5,7 @@ from .OpenAIConversationalAgent import ConversationalAgent
from .SQLAgent import SQLAgentComponent
from .VectorStoreAgent import VectorStoreAgentComponent
from .VectorStoreRouterAgent import VectorStoreRouterAgentComponent
from .XMLAgent import XMLAgentComponent
__all__ = [
"AgentInitializerComponent",
@ -14,4 +15,5 @@ __all__ = [
"SQLAgentComponent",
"VectorStoreAgentComponent",
"VectorStoreRouterAgentComponent",
"XMLAgentComponent",
]

View file

@ -10,11 +10,11 @@ from langflow.schema import Record
class APIRequest(CustomComponent):
display_name: str = "API Request"
description: str = "Make an HTTP request to the given URL."
description: str = "Make HTTP requests given one or more URLs."
output_types: list[str] = ["Record"]
documentation: str = "https://docs.langflow.org/components/utilities#api-request"
field_config = {
"urls": {"display_name": "URLs", "info": "The URLs to make the request to."},
"urls": {"display_name": "URLs", "info": "URLs to make requests to."},
"method": {
"display_name": "Method",
"info": "The HTTP method to use.",

View file

@ -7,7 +7,7 @@ from langflow.schema import Record
class DirectoryComponent(CustomComponent):
display_name = "Directory"
description = "Load Text Files from a Directory and Convert Them to Records."
description = "Recursively load files from a directory."
def build_config(self) -> Dict[str, Any]:
return {

View file

@ -1,4 +1,5 @@
from typing import Any, Dict, List
from pathlib import Path
from typing import Any, Dict
from langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record
from langflow.interface.custom.custom_component import CustomComponent
@ -7,12 +8,12 @@ from langflow.schema import Record
class FileComponent(CustomComponent):
display_name = "Files"
description = "Read Text Files"
description = "A generic file loader."
def build_config(self) -> Dict[str, Any]:
return {
"paths": {
"display_name": "Paths",
"path": {
"display_name": "Path",
"field_type": "file",
"file_types": TEXT_FILE_TYPES,
"info": f"Supported file types: {', '.join(TEXT_FILE_TYPES)}",
@ -26,7 +27,8 @@ class FileComponent(CustomComponent):
def load_file(self, path: str, silent_errors: bool = False) -> Record:
resolved_path = self.resolve_path(path)
extension = resolved_path.split(".")[-1]
path_obj = Path(resolved_path)
extension = path_obj.suffix[1:].lower()
if extension == "doc":
raise ValueError("doc files are not supported. Please save as .docx")
if extension not in TEXT_FILE_TYPES:
@ -37,9 +39,9 @@ class FileComponent(CustomComponent):
def build(
self,
paths: List[str],
path: str,
silent_errors: bool = False,
) -> List[Record]:
records = [self.load_file(path, silent_errors) for path in paths]
self.status = records
return records
) -> Record:
record = self.load_file(path, silent_errors)
self.status = record
return record

View file

@ -1,117 +0,0 @@
from typing import List
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
from langflow.utils.constants import LOADERS_INFO
class FileLoaderComponent(CustomComponent):
display_name: str = "File Loader"
description: str = "Generic File Loader"
def build_config(self):
loader_options = ["Automatic"] + [loader_info["name"] for loader_info in LOADERS_INFO]
file_types = []
suffixes = []
for loader_info in LOADERS_INFO:
if "allowedTypes" in loader_info:
file_types.extend(loader_info["allowedTypes"])
suffixes.extend([f".{ext}" for ext in loader_info["allowedTypes"]])
return {
"file_path": {
"display_name": "File Path",
"required": True,
"field_type": "file",
"file_types": [
"json",
"txt",
"csv",
"jsonl",
"html",
"htm",
"conllu",
"enex",
"msg",
"pdf",
"srt",
"eml",
"md",
"mdx",
"pptx",
"docx",
],
"suffixes": [
".json",
".txt",
".csv",
".jsonl",
".html",
".htm",
".conllu",
".enex",
".msg",
".pdf",
".srt",
".eml",
".md",
".mdx",
".pptx",
".docx",
],
# "file_types" : file_types,
# "suffixes": suffixes,
},
"loader": {
"display_name": "Loader",
"is_list": True,
"required": True,
"options": loader_options,
"value": "Automatic",
},
"code": {"show": False},
}
def build(self, file_path: str, loader: str) -> List[Record]:
file_type = file_path.split(".")[-1]
# Map the loader to the correct loader class
selected_loader_info = None
for loader_info in LOADERS_INFO:
if loader_info["name"] == loader:
selected_loader_info = loader_info
break
if selected_loader_info is None and loader != "Automatic":
raise ValueError(f"Loader {loader} not found in the loader info list")
if loader == "Automatic":
# Determine the loader based on the file type
default_loader_info = None
for info in LOADERS_INFO:
if "defaultFor" in info and file_type in info["defaultFor"]:
default_loader_info = info
break
if default_loader_info is None:
raise ValueError(f"No default loader found for file type: {file_type}")
selected_loader_info = default_loader_info
if isinstance(selected_loader_info, dict):
loader_import: str = selected_loader_info["import"]
else:
raise ValueError(f"Loader info for {loader} is not a dict\nLoader info:\n{selected_loader_info}")
module_name, class_name = loader_import.rsplit(".", 1)
try:
# Import the loader class
loader_module = __import__(module_name, fromlist=[class_name])
loader_instance = getattr(loader_module, class_name)
except ImportError as e:
raise ValueError(f"Loader {loader} could not be imported\nLoader info:\n{selected_loader_info}") from e
result = loader_instance(file_path=file_path)
docs = result.load()
return self.to_records(docs)

View file

@ -8,7 +8,7 @@ from langflow.schema import Record
class URLComponent(CustomComponent):
display_name = "URL"
description = "Load URLs and convert them to records."
description = "Fetch text content given one or more URLs."
def build_config(self) -> Dict[str, Any]:
return {
@ -22,4 +22,5 @@ class URLComponent(CustomComponent):
loader = WebBaseLoader(web_paths=urls)
docs = loader.load()
records = self.to_records(docs)
self.status = records
return records

View file

@ -1,7 +1,7 @@
from .APIRequest import APIRequest
from .Directory import DirectoryComponent
from .File import FileComponent
from .FileLoader import FileLoaderComponent
from .URL import URLComponent
__all__ = ["APIRequest", "DirectoryComponent", "FileComponent", "FileLoaderComponent", "URLComponent"]
__all__ = ["APIRequest", "DirectoryComponent", "FileComponent", "URLComponent"]

View file

@ -2,7 +2,7 @@ from typing import Optional
from langchain_community.embeddings.cohere import CohereEmbeddings
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class CohereEmbeddingsComponent(CustomComponent):

View file

@ -1,23 +1,27 @@
from .ClearMessageHistory import ClearMessageHistoryComponent
from .ExtractDataFromRecord import ExtractKeyFromRecordComponent
from .Listen import ListenComponent
from .FlowTool import FlowToolComponent
from .ListFlows import ListFlowsComponent
from .Listen import ListenComponent
from .MergeRecords import MergeRecordsComponent
from .Notify import NotifyComponent
from .PythonFunction import PythonFunctionComponent
from .RunFlow import RunFlowComponent
from .RunnableExecutor import RunnableExecComponent
from .SQLExecutor import SQLExecutorComponent
from .SubFlow import SubFlowComponent
__all__ = [
"ClearMessageHistoryComponent",
"ExtractKeyFromRecordComponent",
"ListenComponent",
"FlowToolComponent",
"ListFlowsComponent",
"ListenComponent",
"MergeRecordsComponent",
"MessageHistoryComponent",
"NotifyComponent",
"PythonFunctionComponent",
"RunFlowComponent",
"RunnableExecComponent",
"SQLExecutorComponent",
"TextToRecordComponent",
"SubFlowComponent",
]

View file

@ -2,16 +2,16 @@ from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
class TextToRecordComponent(CustomComponent):
display_name = "Text to Record"
description = "A component to create a record from Text."
class CreateRecordComponent(CustomComponent):
display_name = "Create Record"
description = "A component to create a record."
beta: bool = True
def build_config(self):
return {
"data": {
"display_name": "Data",
"info": "The data to convert to a record.",
"info": "Data to contruct the record.",
"input_types": ["Text"],
}
}

View file

@ -7,8 +7,8 @@ from langflow.schema import Record
class DocumentToRecordComponent(CustomComponent):
display_name = "Documents to Records"
description = "Convert documents to records."
display_name = "Documents To Records"
description = "Convert LangChain Documents into Records."
field_config = {
"documents": {"display_name": "Documents"},

View file

@ -6,7 +6,7 @@ from langflow.interface.custom.custom_component import CustomComponent
class UUIDGeneratorComponent(CustomComponent):
documentation: str = "http://docs.langflow.org/components/custom"
display_name = "Unique ID Generator"
display_name = "ID Generator"
description = "Generates a unique ID."
def update_build_config(

View file

@ -7,7 +7,7 @@ from langflow.schema import Record
class MessageHistoryComponent(CustomComponent):
display_name = "Message History"
description = "Used to retrieve stored messages."
description = "Used to retrieve stored chat messages."
beta: bool = True
def build_config(self):
@ -30,7 +30,7 @@ class MessageHistoryComponent(CustomComponent):
def build(
self,
sender: Optional[str] = None,
sender: Optional[str] = "Machine",
sender_name: Optional[str] = None,
session_id: Optional[str] = None,
n_messages: int = 5,

View file

@ -4,9 +4,9 @@ from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
class RecordsAsTextComponent(CustomComponent):
display_name = "Records to Text"
description = "Converts Records into single piece of text using a template."
class RecordsToTextComponent(CustomComponent):
display_name = "Records To Text"
description = "Convert Records into plain text using a pre-defined template."
def build_config(self):
return {

View file

@ -4,7 +4,7 @@ from langflow.schema import Record
class UpdateRecordComponent(CustomComponent):
display_name = "Update Record"
description = "Updates a record with new data."
description = "Updates a Record with new data. Akin to a Python dictionary update."
def build_config(self):
return {

View file

@ -2,8 +2,6 @@ from .CustomComponent import Component
from .DocumentToRecord import DocumentToRecordComponent
from .IDGenerator import UUIDGeneratorComponent
from .MessageHistory import MessageHistoryComponent
from .PythonFunction import PythonFunctionComponent
from .RecordsAsText import RecordsAsTextComponent
from .TextToRecord import TextToRecordComponent
from .UpdateRecord import UpdateRecordComponent
@ -13,7 +11,7 @@ __all__ = [
"DocumentToRecordComponent",
"UUIDGeneratorComponent",
"PythonFunctionComponent",
"RecordsAsTextComponent",
"RecordsToTextComponent",
"TextToRecordComponent",
"MessageHistoryComponent",
]

View file

@ -7,7 +7,7 @@ from langflow.schema import Record
class ChatInput(ChatComponent):
display_name = "Chat Input"
description = "Used to get user input from the chat."
description = "Capture user inputs from the chat interface."
icon = "ChatInput"
def build(

View file

@ -1,30 +0,0 @@
import ast
import json
from langflow.custom import CustomComponent
from langflow.schema import Record
class JSONInputComponent(CustomComponent):
display_name = "JSON Input"
description = "Load a JSON object as input."
def build_config(self):
return {
"json_str": {
"display_name": "JSON String",
"multiline": True,
"info": "The JSON string to load.",
}
}
def build(self, json_str: str) -> Record:
try:
data = json.loads(json_str)
except json.JSONDecodeError:
try:
data = ast.literal_eval(json_str)
except (SyntaxError, ValueError):
raise ValueError("Invalid JSON string.")
record = Record(data=data)
return record

View file

@ -6,7 +6,7 @@ from langflow.interface.custom.custom_component import CustomComponent
class PromptComponent(CustomComponent):
display_name: str = "Prompt"
description: str = "A component for creating prompts using templates"
description: str = "A component for creating prompt templates using dynamic variables."
icon = "terminal-square"
def build_config(self):

View file

@ -6,7 +6,21 @@ from langflow.field_typing import Text
class TextInput(TextComponent):
display_name = "Text Input"
description = "Used to pass text input to the next component."
description = "Capture Text or Record and send text inputs."
def build(self, input_value: Optional[str] = "") -> Text:
return super().build(input_value=input_value)
def build_config(self):
return {
"input_value": {
"display_name": "Value",
"input_types": ["Record"],
"info": "Text or Record to be passed as input.",
},
"record_template": {"display_name": "Record Template", "multiline": True},
}
def build(
self,
input_value: Optional[str] = "",
record_template: Optional[str] = "{text}",
) -> Text:
return super().build(input_value=input_value, record_template=record_template)

View file

@ -2,4 +2,4 @@ from .ChatInput import ChatInput
from .Prompt import PromptComponent
from .TextInput import TextInput
__all__ = ["ChatInput", "TextInput", "PromptComponent"]
__all__ = ["ChatInput", "PromptComponent", "TextInput"]

View file

@ -1,33 +0,0 @@
from typing import Dict, Optional
from langchain_community.llms.ctransformers import CTransformers
from langflow.interface.custom.custom_component import CustomComponent
class CTransformersComponent(CustomComponent):
display_name = "CTransformers"
description = "C Transformers LLM models"
documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers"
def build_config(self):
return {
"model": {"display_name": "Model", "required": True},
"model_file": {
"display_name": "Model File",
"required": False,
"field_type": "file",
"file_types": [".bin"],
},
"model_type": {"display_name": "Model Type", "required": True},
"config": {
"display_name": "Config",
"advanced": True,
"required": False,
"field_type": "dict",
"value": '{"top_k":40,"top_p":0.95,"temperature":0.8,"repetition_penalty":1.1,"last_n_tokens":64,"seed":-1,"max_new_tokens":256,"stop":"","stream":"False","reset":"True","batch_size":8,"threads":-1,"context_length":-1,"gpu_layers":0}',
},
}
def build(self, model: str, model_file: str, model_type: str, config: Optional[Dict] = None) -> CTransformers:
return CTransformers(model=model, model_file=model_file, model_type=model_type, config=config) # type: ignore

View file

@ -3,8 +3,8 @@ from typing import Callable, Optional, Union
from langchain_community.chat_models.anthropic import ChatAnthropic
from pydantic.v1.types import SecretStr
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class ChatAnthropicComponent(CustomComponent):
@ -20,31 +20,48 @@ class ChatAnthropicComponent(CustomComponent):
"field_type": "str",
"password": True,
},
"anthropic_api_url": {
"display_name": "Anthropic API URL",
"field_type": "str",
},
"model_kwargs": {
"display_name": "Model Kwargs",
"field_type": "dict",
"advanced": True,
},
"model_name": {
"display_name": "Model Name",
"field_type": "str",
"advanced": False,
"required": False,
"options": ["claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307"],
},
"temperature": {
"display_name": "Temperature",
"field_type": "float",
},
"max_tokens": {
"display_name": "Max Tokens",
"field_type": "int",
"advanced": False,
"required": False,
},
"top_k": {"display_name": "Top K", "field_type": "int", "advanced": True},
"top_p": {"display_name": "Top P", "field_type": "float", "advanced": True},
}
def build(
self,
anthropic_api_key: str,
anthropic_api_url: Optional[str] = None,
model_kwargs: dict = {},
model_name: str = "claude-3-opus-20240229",
temperature: Optional[float] = None,
max_tokens: Optional[int] = 1024,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
) -> Union[BaseLanguageModel, Callable]:
return ChatAnthropic(
anthropic_api_key=SecretStr(anthropic_api_key),
anthropic_api_url=anthropic_api_url,
model_kwargs=model_kwargs,
model_name=model_name,
temperature=temperature,
max_tokens=max_tokens, # type: ignore
top_k=top_k,
top_p=top_p,
)

View file

@ -1,131 +0,0 @@
from typing import Any, Dict, List, Optional
from langchain_community.llms.llamacpp import LlamaCpp
from langflow.interface.custom.custom_component import CustomComponent
class LlamaCppComponent(CustomComponent):
display_name = "LlamaCpp"
description = "llama.cpp model."
documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp"
def build_config(self):
return {
"grammar": {"display_name": "Grammar", "advanced": True},
"cache": {"display_name": "Cache", "advanced": True},
"client": {"display_name": "Client", "advanced": True},
"echo": {"display_name": "Echo", "advanced": True},
"f16_kv": {"display_name": "F16 KV", "advanced": True},
"grammar_path": {"display_name": "Grammar Path", "advanced": True},
"last_n_tokens_size": {"display_name": "Last N Tokens Size", "advanced": True},
"logits_all": {"display_name": "Logits All", "advanced": True},
"logprobs": {"display_name": "Logprobs", "advanced": True},
"lora_base": {"display_name": "Lora Base", "advanced": True},
"lora_path": {"display_name": "Lora Path", "advanced": True},
"max_tokens": {"display_name": "Max Tokens", "advanced": True},
"metadata": {"display_name": "Metadata", "advanced": True},
"model_kwargs": {"display_name": "Model Kwargs", "advanced": True},
"model_path": {
"display_name": "Model Path",
"field_type": "file",
"file_types": [".bin"],
"required": True,
},
"n_batch": {"display_name": "N Batch", "advanced": True},
"n_ctx": {"display_name": "N Ctx", "advanced": True},
"n_gpu_layers": {"display_name": "N GPU Layers", "advanced": True},
"n_parts": {"display_name": "N Parts", "advanced": True},
"n_threads": {"display_name": "N Threads", "advanced": True},
"repeat_penalty": {"display_name": "Repeat Penalty", "advanced": True},
"rope_freq_base": {"display_name": "Rope Freq Base", "advanced": True},
"rope_freq_scale": {"display_name": "Rope Freq Scale", "advanced": True},
"seed": {"display_name": "Seed", "advanced": True},
"stop": {"display_name": "Stop", "advanced": True},
"streaming": {"display_name": "Streaming", "advanced": True},
"suffix": {"display_name": "Suffix", "advanced": True},
"tags": {"display_name": "Tags", "advanced": True},
"temperature": {"display_name": "Temperature"},
"top_k": {"display_name": "Top K", "advanced": True},
"top_p": {"display_name": "Top P", "advanced": True},
"use_mlock": {"display_name": "Use Mlock", "advanced": True},
"use_mmap": {"display_name": "Use Mmap", "advanced": True},
"verbose": {"display_name": "Verbose", "advanced": True},
"vocab_only": {"display_name": "Vocab Only", "advanced": True},
}
def build(
self,
model_path: str,
grammar: Optional[str] = None,
cache: Optional[bool] = None,
client: Optional[Any] = None,
echo: Optional[bool] = False,
f16_kv: bool = True,
grammar_path: Optional[str] = None,
last_n_tokens_size: Optional[int] = 64,
logits_all: bool = False,
logprobs: Optional[int] = None,
lora_base: Optional[str] = None,
lora_path: Optional[str] = None,
max_tokens: Optional[int] = 256,
metadata: Optional[Dict] = None,
model_kwargs: Dict = {},
n_batch: Optional[int] = 8,
n_ctx: int = 512,
n_gpu_layers: Optional[int] = 1,
n_parts: int = -1,
n_threads: Optional[int] = 1,
repeat_penalty: Optional[float] = 1.1,
rope_freq_base: float = 10000.0,
rope_freq_scale: float = 1.0,
seed: int = -1,
stop: Optional[List[str]] = [],
streaming: bool = True,
suffix: Optional[str] = "",
tags: Optional[List[str]] = [],
temperature: Optional[float] = 0.8,
top_k: Optional[int] = 40,
top_p: Optional[float] = 0.95,
use_mlock: bool = False,
use_mmap: Optional[bool] = True,
verbose: bool = True,
vocab_only: bool = False,
) -> LlamaCpp:
return LlamaCpp(
model_path=model_path,
grammar=grammar,
cache=cache,
client=client,
echo=echo,
f16_kv=f16_kv,
grammar_path=grammar_path,
last_n_tokens_size=last_n_tokens_size,
logits_all=logits_all,
logprobs=logprobs,
lora_base=lora_base,
lora_path=lora_path,
max_tokens=max_tokens,
metadata=metadata,
model_kwargs=model_kwargs,
n_batch=n_batch,
n_ctx=n_ctx,
n_gpu_layers=n_gpu_layers,
n_parts=n_parts,
n_threads=n_threads,
repeat_penalty=repeat_penalty,
rope_freq_base=rope_freq_base,
rope_freq_scale=rope_freq_scale,
seed=seed,
stop=stop,
streaming=streaming,
suffix=suffix,
tags=tags,
temperature=temperature,
top_k=top_k,
top_p=top_p,
use_mlock=use_mlock,
use_mmap=use_mmap,
verbose=verbose,
vocab_only=vocab_only,
)

View file

@ -4,7 +4,6 @@ from .AnthropicSpecs import AnthropicComponent
from .AzureChatOpenAISpecs import AzureChatOpenAISpecsComponent
from .BaiduQianfanChatEndpointsSpecs import QianfanChatEndpointComponent
from .BaiduQianfanLLMEndpointsSpecs import QianfanLLMEndpointComponent
from .CTransformersSpecs import CTransformersComponent
from .ChatAnthropicSpecs import ChatAnthropicComponent
from .ChatLiteLLMSpecs import ChatLiteLLMComponent
from .ChatOllamaEndpointSpecs import ChatOllamaComponent
@ -13,7 +12,6 @@ from .ChatVertexAISpecs import ChatVertexAIComponent
from .CohereSpecs import CohereComponent
from .GoogleGenerativeAISpecs import GoogleGenerativeAIComponent
from .HuggingFaceEndpointsSpecs import HuggingFaceEndpointsComponent
from .LlamaCppSpecs import LlamaCppComponent
from .OllamaLLMSpecs import OllamaLLM
from .VertexAISpecs import VertexAIComponent
@ -24,7 +22,6 @@ __all__ = [
"AzureChatOpenAISpecsComponent",
"QianfanChatEndpointComponent",
"QianfanLLMEndpointComponent",
"CTransformersComponent",
"ChatAnthropicComponent",
"ChatLiteLLMComponent",
"ChatOllamaComponent",
@ -33,7 +30,6 @@ __all__ = [
"CohereComponent",
"GoogleGenerativeAIComponent",
"HuggingFaceEndpointsComponent",
"LlamaCppComponent",
"OllamaLLM",
"VertexAIComponent",
]

View file

@ -10,31 +10,50 @@ class AmazonBedrockComponent(LCModelComponent):
display_name: str = "Amazon Bedrock"
description: str = "Generate text using LLM model from Amazon Bedrock."
icon = "Amazon"
field_order = [
"model_id",
"credentials_profile_name",
"region_name",
"model_kwargs",
"endpoint_url",
"cache",
"stream",
"input_value",
"system_message",
]
def build_config(self):
return {
"model_id": {
"display_name": "Model Id",
"options": [
"ai21.j2-grande-instruct",
"ai21.j2-jumbo-instruct",
"ai21.j2-mid",
"ai21.j2-mid-v1",
"ai21.j2-ultra",
"ai21.j2-ultra-v1",
"anthropic.claude-instant-v1",
"anthropic.claude-v1",
"amazon.titan-text-express-v1",
"amazon.titan-text-lite-v1",
"amazon.titan-embed-text-v1",
"amazon.titan-embed-image-v1",
"amazon.titan-image-generator-v1",
"anthropic.claude-v2",
"anthropic.claude-v2:1",
"anthropic.claude-3-sonnet-20240229-v1:0",
"anthropic.claude-3-haiku-20240307-v1:0",
"anthropic.claude-instant-v1",
"ai21.j2-mid-v1",
"ai21.j2-ultra-v1",
"cohere.command-text-v14",
"cohere.command-light-text-v14",
"cohere.embed-english-v3",
"cohere.embed-multilingual-v3",
"meta.llama2-13b-chat-v1",
"meta.llama2-70b-chat-v1",
"mistral.mistral-7b-instruct-v0:2",
"mistral.mixtral-8x7b-instruct-v0:1",
],
},
"credentials_profile_name": {"display_name": "Credentials Profile Name"},
"streaming": {"display_name": "Streaming", "field_type": "bool"},
"endpoint_url": {"display_name": "Endpoint URL"},
"region_name": {"display_name": "Region Name"},
"model_kwargs": {"display_name": "Model Kwargs"},
"cache": {"display_name": "Cache"},
"code": {"advanced": True},
"input_value": {"display_name": "Input"},
"system_message": {"display_name": "System Message", "info": "System message to pass to the model."},
"stream": {
@ -52,7 +71,6 @@ class AmazonBedrockComponent(LCModelComponent):
region_name: Optional[str] = None,
model_kwargs: Optional[dict] = None,
endpoint_url: Optional[str] = None,
streaming: bool = False,
cache: Optional[bool] = None,
stream: bool = False,
) -> Text:
@ -63,7 +81,7 @@ class AmazonBedrockComponent(LCModelComponent):
region_name=region_name,
model_kwargs=model_kwargs,
endpoint_url=endpoint_url,
streaming=streaming,
streaming=stream,
cache=cache,
) # type: ignore
except Exception as e:

View file

@ -17,15 +17,17 @@ class AnthropicLLM(LCModelComponent):
"model": {
"display_name": "Model Name",
"options": [
"claude-3-opus-20240229",
"claude-3-sonnet-20240229",
"claude-3-haiku-20240307",
"claude-2.1",
"claude-2.0",
"claude-instant-1.2",
"claude-instant-1",
# Add more models as needed
],
"info": "https://python.langchain.com/docs/integrations/chat/anthropic",
"required": True,
"value": "claude-2.1",
"value": "claude-3-opus-20240229",
},
"anthropic_api_key": {
"display_name": "Anthropic API Key",
@ -43,8 +45,8 @@ class AnthropicLLM(LCModelComponent):
"field_type": "float",
"value": 0.7,
},
"api_endpoint": {
"display_name": "API Endpoint",
"anthropic_api_url": {
"display_name": "Anthropic API URL",
"info": "Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.",
},
"code": {"show": False},
@ -67,12 +69,12 @@ class AnthropicLLM(LCModelComponent):
anthropic_api_key: Optional[str] = None,
max_tokens: Optional[int] = None,
temperature: Optional[float] = None,
api_endpoint: Optional[str] = None,
anthropic_api_url: Optional[str] = None,
stream: bool = False,
) -> Text:
# Set default API endpoint if not provided
if not api_endpoint:
api_endpoint = "https://api.anthropic.com"
if not anthropic_api_url:
anthropic_api_url = "https://api.anthropic.com"
try:
output = ChatAnthropic(
@ -80,7 +82,7 @@ class AnthropicLLM(LCModelComponent):
anthropic_api_key=(SecretStr(anthropic_api_key) if anthropic_api_key else None),
max_tokens_to_sample=max_tokens, # type: ignore
temperature=temperature,
anthropic_api_url=api_endpoint,
anthropic_api_url=anthropic_api_url,
)
except Exception as e:
raise ValueError("Could not connect to Anthropic API.") from e

View file

@ -8,7 +8,7 @@ from langflow.field_typing import Text
class AzureChatOpenAIComponent(LCModelComponent):
display_name: str = "AzureOpenAI"
display_name: str = "Azure OpenAI"
description: str = "Generate text using LLM model from Azure OpenAI."
documentation: str = "https://python.langchain.com/docs/integrations/llms/azure_openai"
beta = False

View file

@ -8,7 +8,7 @@ from langflow.field_typing import Text
class QianfanChatEndpointComponent(LCModelComponent):
display_name: str = "QianfanChat"
display_name: str = "Qianfan"
description: str = (
"Generate text using Baidu Qianfan chat models. Get more detail from "
"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint."

View file

@ -1,59 +0,0 @@
from typing import Dict, Optional
from langchain_community.llms.ctransformers import CTransformers
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import Text
class CTransformersComponent(LCModelComponent):
display_name = "CTransformers"
description = "Generate text using CTransformers LLM models"
documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers"
def build_config(self):
return {
"model": {"display_name": "Model", "required": True},
"model_file": {
"display_name": "Model File",
"required": False,
"field_type": "file",
"file_types": [".bin"],
},
"model_type": {"display_name": "Model Type", "required": True},
"config": {
"display_name": "Config",
"advanced": True,
"required": False,
"field_type": "dict",
"value": '{"top_k":40,"top_p":0.95,"temperature":0.8,"repetition_penalty":1.1,"last_n_tokens":64,"seed":-1,"max_new_tokens":256,"stop":"","stream":"False","reset":"True","batch_size":8,"threads":-1,"context_length":-1,"gpu_layers":0}',
},
"input_value": {"display_name": "Input"},
"stream": {
"display_name": "Stream",
"info": "Stream the response from the model.",
},
"system_message": {
"display_name": "System Message",
"info": "System message to pass to the model.",
},
}
def build(
self,
model: str,
model_file: str,
input_value: Text,
model_type: str,
stream: bool = False,
config: Optional[Dict] = None,
) -> Text:
output = CTransformers(
client=None,
model=model,
model_file=model_file,
model_type=model_type,
config=config, # noqa
)
return self.get_result(runnable=output, stream=stream, input_value=input_value)

View file

@ -1,148 +0,0 @@
from typing import Any, Dict, List, Optional
from langchain_community.llms.llamacpp import LlamaCpp
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import Text
class LlamaCppComponent(LCModelComponent):
display_name = "LlamaCpp"
description = "Generate text using llama.cpp model."
documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp"
def build_config(self):
return {
"grammar": {"display_name": "Grammar", "advanced": True},
"cache": {"display_name": "Cache", "advanced": True},
"client": {"display_name": "Client", "advanced": True},
"echo": {"display_name": "Echo", "advanced": True},
"f16_kv": {"display_name": "F16 KV", "advanced": True},
"grammar_path": {"display_name": "Grammar Path", "advanced": True},
"last_n_tokens_size": {
"display_name": "Last N Tokens Size",
"advanced": True,
},
"logits_all": {"display_name": "Logits All", "advanced": True},
"logprobs": {"display_name": "Logprobs", "advanced": True},
"lora_base": {"display_name": "Lora Base", "advanced": True},
"lora_path": {"display_name": "Lora Path", "advanced": True},
"max_tokens": {"display_name": "Max Tokens", "advanced": True},
"metadata": {"display_name": "Metadata", "advanced": True},
"model_kwargs": {"display_name": "Model Kwargs", "advanced": True},
"model_path": {
"display_name": "Model Path",
"field_type": "file",
"file_types": [".bin"],
"required": True,
},
"n_batch": {"display_name": "N Batch", "advanced": True},
"n_ctx": {"display_name": "N Ctx", "advanced": True},
"n_gpu_layers": {"display_name": "N GPU Layers", "advanced": True},
"n_parts": {"display_name": "N Parts", "advanced": True},
"n_threads": {"display_name": "N Threads", "advanced": True},
"repeat_penalty": {"display_name": "Repeat Penalty", "advanced": True},
"rope_freq_base": {"display_name": "Rope Freq Base", "advanced": True},
"rope_freq_scale": {"display_name": "Rope Freq Scale", "advanced": True},
"seed": {"display_name": "Seed", "advanced": True},
"stop": {"display_name": "Stop", "advanced": True},
"streaming": {"display_name": "Streaming", "advanced": True},
"suffix": {"display_name": "Suffix", "advanced": True},
"tags": {"display_name": "Tags", "advanced": True},
"temperature": {"display_name": "Temperature"},
"top_k": {"display_name": "Top K", "advanced": True},
"top_p": {"display_name": "Top P", "advanced": True},
"use_mlock": {"display_name": "Use Mlock", "advanced": True},
"use_mmap": {"display_name": "Use Mmap", "advanced": True},
"verbose": {"display_name": "Verbose", "advanced": True},
"vocab_only": {"display_name": "Vocab Only", "advanced": True},
"input_value": {"display_name": "Input"},
"stream": {
"display_name": "Stream",
"info": "Stream the response from the model.",
},
"system_message": {
"display_name": "System Message",
"info": "System message to pass to the model.",
},
}
def build(
self,
model_path: str,
input_value: Text,
grammar: Optional[str] = None,
cache: Optional[bool] = None,
client: Optional[Any] = None,
echo: Optional[bool] = False,
f16_kv: bool = True,
grammar_path: Optional[str] = None,
last_n_tokens_size: Optional[int] = 64,
logits_all: bool = False,
logprobs: Optional[int] = None,
lora_base: Optional[str] = None,
lora_path: Optional[str] = None,
max_tokens: Optional[int] = 256,
metadata: Optional[Dict] = None,
model_kwargs: Dict = {},
n_batch: Optional[int] = 8,
n_ctx: int = 512,
n_gpu_layers: Optional[int] = 1,
n_parts: int = -1,
n_threads: Optional[int] = 1,
repeat_penalty: Optional[float] = 1.1,
rope_freq_base: float = 10000.0,
rope_freq_scale: float = 1.0,
seed: int = -1,
stop: Optional[List[str]] = [],
streaming: bool = True,
suffix: Optional[str] = "",
tags: Optional[List[str]] = [],
temperature: Optional[float] = 0.8,
top_k: Optional[int] = 40,
top_p: Optional[float] = 0.95,
use_mlock: bool = False,
use_mmap: Optional[bool] = True,
verbose: bool = True,
vocab_only: bool = False,
stream: bool = False,
) -> Text:
output = LlamaCpp(
model_path=model_path,
grammar=grammar,
cache=cache,
client=client,
echo=echo,
f16_kv=f16_kv,
grammar_path=grammar_path,
last_n_tokens_size=last_n_tokens_size,
logits_all=logits_all,
logprobs=logprobs,
lora_base=lora_base,
lora_path=lora_path,
max_tokens=max_tokens,
metadata=metadata,
model_kwargs=model_kwargs,
n_batch=n_batch,
n_ctx=n_ctx,
n_gpu_layers=n_gpu_layers,
n_parts=n_parts,
n_threads=n_threads,
repeat_penalty=repeat_penalty,
rope_freq_base=rope_freq_base,
rope_freq_scale=rope_freq_scale,
seed=seed,
stop=stop,
streaming=streaming,
suffix=suffix,
tags=tags,
temperature=temperature,
top_k=top_k,
top_p=top_p,
use_mlock=use_mlock,
use_mmap=use_mmap,
verbose=verbose,
vocab_only=vocab_only,
)
return self.get_result(runnable=output, stream=stream, input_value=input_value)

View file

@ -13,7 +13,7 @@ from langflow.field_typing import Text
class ChatOllamaComponent(LCModelComponent):
display_name = "ChatOllama"
display_name = "Ollama"
description = "Generate text using Local LLM for chat with Ollama."
icon = "Ollama"

View file

@ -7,7 +7,7 @@ from langflow.field_typing import Text
class ChatVertexAIComponent(LCModelComponent):
display_name = "ChatVertexAI"
display_name = "Vertex AI"
description = "Generate text using Vertex AI Chat large language models API."
icon = "VertexAI"

View file

@ -2,11 +2,9 @@ from .AmazonBedrockModel import AmazonBedrockComponent
from .AnthropicModel import AnthropicLLM
from .AzureOpenAIModel import AzureChatOpenAIComponent
from .BaiduQianfanChatModel import QianfanChatEndpointComponent
from .CTransformersModel import CTransformersComponent
from .CohereModel import CohereComponent
from .GoogleGenerativeAIModel import GoogleGenerativeAIComponent
from .HuggingFaceModel import HuggingFaceEndpointsComponent
from .LlamaCppModel import LlamaCppComponent
from .OllamaModel import ChatOllamaComponent
from .OpenAIModel import OpenAIModelComponent
from .VertexAiModel import ChatVertexAIComponent
@ -16,11 +14,9 @@ __all__ = [
"AnthropicLLM",
"AzureChatOpenAIComponent",
"QianfanChatEndpointComponent",
"CTransformersComponent",
"CohereComponent",
"GoogleGenerativeAIComponent",
"HuggingFaceEndpointsComponent",
"LlamaCppComponent",
"ChatOllamaComponent",
"OpenAIModelComponent",
"ChatVertexAIComponent",

View file

@ -7,7 +7,7 @@ from langflow.schema import Record
class ChatOutput(ChatComponent):
display_name = "Chat Output"
description = "Used to send a message to the chat."
description = "Used to send a chat message."
icon = "ChatOutput"
def build(
@ -17,6 +17,7 @@ class ChatOutput(ChatComponent):
input_value: Optional[str] = None,
session_id: Optional[str] = None,
return_record: Optional[bool] = False,
record_template: Optional[str] = "{text}",
) -> Union[Text, Record]:
return super().build(
sender=sender,
@ -24,4 +25,5 @@ class ChatOutput(ChatComponent):
input_value=input_value,
session_id=session_id,
return_record=return_record,
record_template=record_template,
)

View file

@ -6,11 +6,17 @@ from langflow.field_typing import Text
class TextOutput(TextComponent):
display_name = "Text Output"
description = "Used to pass text output to the next component."
description = "Used to send a text output."
field_config = {
"input_value": {"display_name": "Value"},
}
def build_config(self):
return {
"input_value": {
"display_name": "Value",
"input_types": ["Record"],
"info": "Text or Record to be passed as output.",
},
"record_template": {"display_name": "Record Template", "multiline": True},
}
def build(self, input_value: Optional[Text] = "") -> Text:
return super().build(input_value=input_value)
def build(self, input_value: Optional[Text] = "", record_template: str = "{text}") -> Text:
return super().build(input_value=input_value, record_template=record_template)

View file

@ -2,10 +2,12 @@ from .AmazonKendra import AmazonKendraRetrieverComponent
from .MetalRetriever import MetalRetrieverComponent
from .MultiQueryRetriever import MultiQueryRetrieverComponent
from .VectaraSelfQueryRetriver import VectaraSelfQueryRetriverComponent
from .VectorStoreRetriever import VectoStoreRetrieverComponent
__all__ = [
"AmazonKendraRetrieverComponent",
"MetalRetrieverComponent",
"MultiQueryRetrieverComponent",
"VectaraSelfQueryRetriverComponent",
"VectoStoreRetrieverComponent",
]

View file

@ -0,0 +1,5 @@
from .RetrieverTool import RetrieverToolComponent
from .SearchAPITool import SearchApiToolComponent
from .SearchApi import SearchApi
__all__ = ["RetrieverToolComponent", "SearchApiToolComponent", "SearchApi"]

View file

@ -23,51 +23,73 @@ class AstraDBSearchComponent(LCVectorStoreComponent):
"info": "Input value to search",
},
"embedding": {"display_name": "Embedding", "info": "Embedding to use"},
"collection_name": {"display_name": "Collection Name", "info": "Collection name"},
"token": {"display_name": "Token", "info": "Token to use", "password": True},
"api_endpoint": {"display_name": "API Endpoint", "info": "API Endpoint to use"},
"namespace": {"display_name": "Namespace", "info": "Namespace to use", "advanced": True},
"metric": {"display_name": "Metric", "info": "Metric to use", "advanced": True},
"batch_size": {"display_name": "Batch Size", "info": "Batch size to use", "advanced": True},
"collection_name": {
"display_name": "Collection Name",
"info": "The name of the collection within AstraDB where the vectors will be stored.",
},
"token": {
"display_name": "Token",
"info": "Authentication token for accessing AstraDB.",
"password": True,
},
"api_endpoint": {
"display_name": "API Endpoint",
"info": "API endpoint URL for the AstraDB service.",
},
"namespace": {
"display_name": "Namespace",
"info": "Optional namespace within AstraDB to use for the collection.",
"advanced": True,
},
"metric": {
"display_name": "Metric",
"info": "Optional distance metric for vector comparisons in the vector store.",
"advanced": True,
},
"batch_size": {
"display_name": "Batch Size",
"info": "Optional number of records to process in a single batch.",
"advanced": True,
},
"bulk_insert_batch_concurrency": {
"display_name": "Bulk Insert Batch Concurrency",
"info": "Bulk Insert Batch Concurrency to use",
"info": "Optional concurrency level for bulk insert operations.",
"advanced": True,
},
"bulk_insert_overwrite_concurrency": {
"display_name": "Bulk Insert Overwrite Concurrency",
"info": "Bulk Insert Overwrite Concurrency to use",
"info": "Optional concurrency level for bulk insert operations that overwrite existing records.",
"advanced": True,
},
"bulk_delete_concurrency": {
"display_name": "Bulk Delete Concurrency",
"info": "Bulk Delete Concurrency to use",
"info": "Optional concurrency level for bulk delete operations.",
"advanced": True,
},
"setup_mode": {
"display_name": "Setup Mode",
"info": "Setup mode for the vector store",
"info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.",
"options": ["Sync", "Async", "Off"],
"advanced": True,
},
"pre_delete_collection": {
"display_name": "Pre Delete Collection",
"info": "Pre delete collection",
"info": "Boolean flag to determine whether to delete the collection before creating a new one.",
"advanced": True,
},
"metadata_indexing_include": {
"display_name": "Metadata Indexing Include",
"info": "Metadata Indexing Include",
"info": "Optional list of metadata fields to include in the indexing.",
"advanced": True,
},
"metadata_indexing_exclude": {
"display_name": "Metadata Indexing Exclude",
"info": "Metadata Indexing Exclude",
"info": "Optional list of metadata fields to exclude from the indexing.",
"advanced": True,
},
"collection_indexing_policy": {
"display_name": "Collection Indexing Policy",
"info": "Collection Indexing Policy",
"info": "Optional dictionary defining the indexing policy for the collection.",
"advanced": True,
},
}
@ -77,9 +99,9 @@ class AstraDBSearchComponent(LCVectorStoreComponent):
embedding: Embeddings,
collection_name: str,
input_value: Text,
token: str,
api_endpoint: str,
search_type: str = "Similarity",
token: Optional[str] = None,
api_endpoint: Optional[str] = None,
namespace: Optional[str] = None,
metric: Optional[str] = None,
batch_size: Optional[int] = None,

View file

@ -0,0 +1,25 @@
from .AstraDBSearch import AstraDBSearchComponent
from .ChromaSearch import ChromaSearchComponent
from .FAISSSearch import FAISSSearchComponent
from .MongoDBAtlasVectorSearch import MongoDBAtlasSearchComponent
from .PineconeSearch import PineconeSearchComponent
from .QdrantSearch import QdrantSearchComponent
from .RedisSearch import RedisSearchComponent
from .SupabaseVectorStoreSearch import SupabaseSearchComponent
from .VectaraSearch import VectaraSearchComponent
from .WeaviateSearch import WeaviateSearchVectorStore
from .pgvectorSearch import PGVectorSearchComponent
__all__ = [
"AstraDBSearchComponent",
"ChromaSearchComponent",
"FAISSSearchComponent",
"MongoDBAtlasSearchComponent",
"PineconeSearchComponent",
"QdrantSearchComponent",
"RedisSearchComponent",
"SupabaseSearchComponent",
"VectaraSearchComponent",
"WeaviateSearchVectorStore",
"PGVectorSearchComponent",
]

View file

@ -16,53 +16,78 @@ class AstraDBVectorStoreComponent(CustomComponent):
def build_config(self):
return {
"inputs": {"display_name": "Inputs", "info": "Inputs to AstraDB"},
"inputs": {
"display_name": "Inputs",
"info": "Optional list of records to be processed and stored in the vector store.",
},
"embedding": {"display_name": "Embedding", "info": "Embedding to use"},
"collection_name": {"display_name": "Collection Name", "info": "Collection name"},
"token": {"display_name": "Token", "info": "Token to use", "password": True},
"api_endpoint": {"display_name": "API Endpoint", "info": "API Endpoint to use"},
"namespace": {"display_name": "Namespace", "info": "Namespace to use", "advanced": True},
"metric": {"display_name": "Metric", "info": "Metric to use", "advanced": True},
"batch_size": {"display_name": "Batch Size", "info": "Batch size to use", "advanced": True},
"collection_name": {
"display_name": "Collection Name",
"info": "The name of the collection within AstraDB where the vectors will be stored.",
},
"token": {
"display_name": "Token",
"info": "Authentication token for accessing AstraDB.",
"password": True,
},
"api_endpoint": {
"display_name": "API Endpoint",
"info": "API endpoint URL for the AstraDB service.",
},
"namespace": {
"display_name": "Namespace",
"info": "Optional namespace within AstraDB to use for the collection.",
"advanced": True,
},
"metric": {
"display_name": "Metric",
"info": "Optional distance metric for vector comparisons in the vector store.",
"advanced": True,
},
"batch_size": {
"display_name": "Batch Size",
"info": "Optional number of records to process in a single batch.",
"advanced": True,
},
"bulk_insert_batch_concurrency": {
"display_name": "Bulk Insert Batch Concurrency",
"info": "Bulk Insert Batch Concurrency to use",
"info": "Optional concurrency level for bulk insert operations.",
"advanced": True,
},
"bulk_insert_overwrite_concurrency": {
"display_name": "Bulk Insert Overwrite Concurrency",
"info": "Bulk Insert Overwrite Concurrency to use",
"info": "Optional concurrency level for bulk insert operations that overwrite existing records.",
"advanced": True,
},
"bulk_delete_concurrency": {
"display_name": "Bulk Delete Concurrency",
"info": "Bulk Delete Concurrency to use",
"info": "Optional concurrency level for bulk delete operations.",
"advanced": True,
},
"setup_mode": {
"display_name": "Setup Mode",
"info": "Setup mode for the vector store",
"info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.",
"options": ["Sync", "Async", "Off"],
"advanced": True,
},
"pre_delete_collection": {
"display_name": "Pre Delete Collection",
"info": "Pre delete collection",
"info": "Boolean flag to determine whether to delete the collection before creating a new one.",
"advanced": True,
},
"metadata_indexing_include": {
"display_name": "Metadata Indexing Include",
"info": "Metadata Indexing Include",
"info": "Optional list of metadata fields to include in the indexing.",
"advanced": True,
},
"metadata_indexing_exclude": {
"display_name": "Metadata Indexing Exclude",
"info": "Metadata Indexing Exclude",
"info": "Optional list of metadata fields to exclude from the indexing.",
"advanced": True,
},
"collection_indexing_policy": {
"display_name": "Collection Indexing Policy",
"info": "Collection Indexing Policy",
"info": "Optional dictionary defining the indexing policy for the collection.",
"advanced": True,
},
}
@ -70,17 +95,17 @@ class AstraDBVectorStoreComponent(CustomComponent):
def build(
self,
embedding: Embeddings,
token: str,
api_endpoint: str,
collection_name: str,
inputs: Optional[List[Record]] = None,
token: Optional[str] = None,
api_endpoint: Optional[str] = None,
namespace: Optional[str] = None,
metric: Optional[str] = None,
batch_size: Optional[int] = None,
bulk_insert_batch_concurrency: Optional[int] = None,
bulk_insert_overwrite_concurrency: Optional[int] = None,
bulk_delete_concurrency: Optional[int] = None,
setup_mode: str = "Sync",
setup_mode: str = "Async",
pre_delete_collection: bool = False,
metadata_indexing_include: Optional[List[str]] = None,
metadata_indexing_exclude: Optional[List[str]] = None,

View file

@ -1,44 +1,26 @@
from .AstraDB import AstraDBVectorStoreComponent
from .Chroma import ChromaComponent
from .ChromaSearch import ChromaSearchComponent
from .FAISS import FAISSComponent
from .FAISSSearch import FAISSSearchComponent
from .MongoDBAtlasVector import MongoDBAtlasComponent
from .MongoDBAtlasVectorSearch import MongoDBAtlasSearchComponent
from .Pinecone import PineconeComponent
from .PineconeSearch import PineconeSearchComponent
from .Qdrant import QdrantComponent
from .QdrantSearch import QdrantSearchComponent
from .Redis import RedisComponent
from .RedisSearch import RedisSearchComponent
from .SupabaseVectorStore import SupabaseComponent
from .SupabaseVectorStoreSearch import SupabaseSearchComponent
from .Vectara import VectaraComponent
from .VectaraSearch import VectaraSearchComponent
from .Weaviate import WeaviateVectorStoreComponent
from .WeaviateSearch import WeaviateSearchVectorStore
from .pgvector import PGVectorComponent
from .pgvectorSearch import PGVectorSearchComponent
__all__ = [
"AstraDBVectorStoreComponent",
"ChromaComponent",
"ChromaSearchComponent",
"FAISSComponent",
"FAISSSearchComponent",
"MongoDBAtlasComponent",
"MongoDBAtlasSearchComponent",
"PineconeComponent",
"PineconeSearchComponent",
"QdrantComponent",
"QdrantSearchComponent",
"RedisComponent",
"RedisSearchComponent",
"SupabaseComponent",
"SupabaseSearchComponent",
"VectaraComponent",
"VectaraSearchComponent",
"WeaviateVectorStoreComponent",
"WeaviateSearchVectorStore",
"base",
"PGVectorComponent",
"PGVectorSearchComponent",
]

View file

@ -237,10 +237,28 @@ class CodeParser:
def parse_return_statement(self, node: ast.FunctionDef) -> bool:
"""
Parses the return statement of a function or method node.
Parses the return statement of a function or method node, including nested returns.
"""
return any(isinstance(n, ast.Return) for n in node.body)
def has_return(node):
if isinstance(node, ast.Return):
return True
elif isinstance(node, ast.If):
return any(has_return(child) for child in node.body) or any(has_return(child) for child in node.orelse)
elif isinstance(node, ast.Try):
return (
any(has_return(child) for child in node.body)
or any(has_return(child) for child in node.handlers)
or any(has_return(child) for child in node.finalbody)
)
elif isinstance(node, (ast.For, ast.While)):
return any(has_return(child) for child in node.body) or any(has_return(child) for child in node.orelse)
elif isinstance(node, ast.With):
return any(has_return(child) for child in node.body)
else:
return False
return any(has_return(child) for child in node.body)
def parse_assign(self, stmt):
"""

View file

@ -32,6 +32,8 @@ def check_tools_in_params(params: Dict):
def instantiate_from_template(class_object, params: Dict):
from_template_params = {"template": params.pop("prompt", params.pop("template", ""))}
from_template_params.update(params)
if not from_template_params.get("template"):
raise ValueError("Prompt template is required")
return class_object.from_template(**from_template_params)

View file

@ -4,6 +4,7 @@ from loguru import logger
from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import llm_type_to_cls_dict
from langflow.services.deps import get_settings_service
from langflow.template.frontend_node.llms import LLMFrontendNode
from langflow.utils.util import build_template_from_class
@ -33,10 +34,11 @@ class LLMCreator(LangChainTypeCreator):
return None
def to_list(self) -> List[str]:
settings_service = get_settings_service()
return [
llm.__name__
for llm in self.type_to_loader_dict.values()
# if llm.__name__ in settings_service.settings.LLMS or settings_service.settings.DEV
if llm.__name__ in settings_service.settings.LLMS or settings_service.settings.DEV
]

View file

@ -1,7 +1,7 @@
from importlib import metadata
try:
__version__ = metadata.version(__package__)
__version__ = metadata.version("langflow")
except metadata.PackageNotFoundError:
__version__ = ""
del metadata

View file

@ -55,7 +55,7 @@
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.11",
"react-icons": "^4.10.1",
"react-icons": "^5.0.1",
"react-laag": "^2.0.5",
"react-markdown": "^8.0.7",
"react-router-dom": "^6.15.0",
@ -9363,9 +9363,9 @@
}
},
"node_modules/react-icons": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
"integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz",
"integrity": "sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==",
"peerDependencies": {
"react": "*"
}

View file

@ -50,7 +50,7 @@
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.11",
"react-icons": "^4.10.1",
"react-icons": "^5.0.1",
"react-laag": "^2.0.5",
"react-markdown": "^8.0.7",
"react-router-dom": "^6.15.0",

View file

@ -211,10 +211,12 @@ export default function GenericNode({
}
}, [validationStatus, validationStatus?.params]);
// const showNode = data.showNode ?? true;
const [showNode, setShowNode] = useState(data.showNode ?? true);
useEffect(() => {
setShowNode(data.showNode ?? true);
}, [data.showNode]);
const nameEditable = true;
const emojiRegex = /\p{Emoji}/u;
@ -438,7 +440,7 @@ export default function GenericNode({
event.preventDefault();
}}
data-testid={"title-" + data.node?.display_name}
className="generic-node-tooltip-div text-primary"
className="generic-node-tooltip-div cursor-text text-primary"
>
{data.node?.display_name}
</div>

View file

@ -13,6 +13,8 @@ export default function DropdownButton({
firstButtonName,
onFirstBtnClick,
options,
plusButton = false,
dropdownOptions = true,
}: dropdownButtonPropsType): JSX.Element {
const [showOptions, setShowOptions] = useState<boolean>(false);
@ -23,28 +25,33 @@ export default function DropdownButton({
<Button
id="new-project-btn"
variant="primary"
className="relative pr-10"
className={"relative" + dropdownOptions ? "" : " pr-10"}
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
onFirstBtnClick();
}}
>
{plusButton && (
<IconComponent name="Plus" className="main-page-nav-button" />
)}
{firstButtonName}
<div
className="absolute right-2 items-center text-muted-foreground"
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
setShowOptions(!showOptions);
}}
>
{!showOptions ? (
<IconComponent name="ChevronDown" />
) : (
<IconComponent name="ChevronUp" />
)}
</div>
{dropdownOptions && (
<div
className="absolute right-2 items-center text-muted-foreground"
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
setShowOptions(!showOptions);
}}
>
{!showOptions ? (
<IconComponent name="ChevronDown" />
) : (
<IconComponent name="ChevronUp" />
)}
</div>
)}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent

View file

@ -120,7 +120,7 @@ export default function IOView({
{/* TODO ADAPT TO ALL TYPES OF INPUTS AND OUTPUTS */}
<BaseModal.Header description={CHAT_FORM_DIALOG_SUBTITLE}>
<div className="flex items-center">
<span className="pr-2">Chat</span>
<span className="pr-2">Interaction Panel</span>
<IconComponent
name="prompts"
className="h-6 w-6 pl-1 text-foreground"

View file

@ -1,5 +1,6 @@
import { useContext, useEffect } from "react";
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
import { FaDiscord, FaGithub } from "react-icons/fa";
import { RiTwitterXFill } from "react-icons/ri";
import { Link, useLocation, useNavigate, useParams } from "react-router-dom";
import AlertDropdown from "../../alerts/alertDropDown";
import { USER_PROJECTS_HEADER } from "../../constants/constants";
@ -127,7 +128,7 @@ export default function Header(): JSX.Element {
rel="noreferrer"
className="text-muted-foreground"
>
<FaTwitter className="side-bar-button-size" />
<RiTwitterXFill className="side-bar-button-size" />
</a>
<a
href="https://discord.gg/EqksyE2EX9"

View file

@ -99,12 +99,16 @@ export default function InputComponent({
type="text"
onBlur={onInputLostFocus}
value={
selectedOption !== "" || !onChange ? selectedOption : value
(selectedOption !== "" || !onChange) && setSelectedOption
? selectedOption
: value
}
autoFocus={autoFocus}
disabled={disabled}
onClick={() => {
(selectedOption !== "" || !onChange) && setShowOptions(true);
(selectedOption !== "" || !onChange) &&
setSelectedOption &&
setShowOptions(true);
}}
required={required}
className={classNames(
@ -115,8 +119,12 @@ export default function InputComponent({
? " text-clip password "
: "",
editNode ? " input-edit-node " : "",
password && selectedOption === "" && editNode ? "pr-8" : "",
password && selectedOption === "" && !editNode ? "pr-10" : "",
password && setSelectedOption ? "pr-16" : "",
(!password && setSelectedOption) ||
(password && !setSelectedOption)
? "pr-8"
: "",
className!
)}
placeholder={password && editNode ? "Key" : placeholder}
@ -179,18 +187,32 @@ export default function InputComponent({
setShowOptions(false);
}}
>
<div className="flex w-full items-center justify-between">
<div className="group flex w-full items-center justify-between">
<div className="flex items-center">
<ForwardedIconComponent
name="Check"
<div
className={cn(
"mr-2 h-4 w-4 text-primary",
"relative mr-2 h-4 w-4",
selectedOption === option
? "opacity-100"
: "opacity-0"
)}
aria-hidden="true"
/>
>
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
<ForwardedIconComponent
name="Check"
className="mr-2 h-4 w-4 text-primary"
aria-hidden="true"
/>
</div>
<div className="absolute opacity-0 transition-all group-hover:opacity-100">
<ForwardedIconComponent
name="X"
className="mr-2 h-4 w-4 text-status-red"
aria-hidden="true"
/>
</div>
</div>
{option}
</div>
{optionButton && optionButton(option)}
@ -206,10 +228,12 @@ export default function InputComponent({
<div
className={cn(
"pointer-events-auto absolute inset-y-0 h-full w-full cursor-pointer",
selectedOption !== "" || !onChange ? "" : "hidden"
(selectedOption !== "" || !onChange) && setSelectedOption
? ""
: "hidden"
)}
onClick={
selectedOption !== "" || !onChange
(selectedOption !== "" || !onChange) && setSelectedOption
? (e) => {
setShowOptions((old) => !old);
e.preventDefault();
@ -221,30 +245,32 @@ export default function InputComponent({
</>
)}
<span
className={cn(
password && selectedOption === "" ? "right-8" : "right-0",
"absolute inset-y-0 flex items-center pr-2.5"
)}
>
<button
onClick={() => {
setShowOptions(!showOptions);
}}
{setSelectedOption && (
<span
className={cn(
selectedOption !== ""
? "text-medium-indigo"
: "text-muted-foreground",
"hover:text-accent-foreground"
password && selectedOption === "" ? "right-8" : "right-0",
"absolute inset-y-0 flex items-center pr-2.5"
)}
>
<ForwardedIconComponent
name={optionsIcon}
className={"h-4 w-4"}
aria-hidden="true"
/>
</button>
</span>
<button
onClick={() => {
setShowOptions(!showOptions);
}}
className={cn(
selectedOption !== ""
? "text-medium-indigo"
: "text-muted-foreground",
"hover:text-accent-foreground"
)}
>
<ForwardedIconComponent
name={optionsIcon}
className={"h-4 w-4"}
aria-hidden="true"
/>
</button>
</span>
)}
{password && selectedOption === "" && (
<button

View file

@ -107,7 +107,7 @@ export const CODE_DIALOG_SUBTITLE =
* @constant
*/
export const CHAT_FORM_DIALOG_SUBTITLE =
"Set up the input variables defined in prompt templates. Interact with agents and chains.";
"Adjust or overwrite input values, inspect outputs or interact through the chat console.";
/**
* The base text for subtitle of Edit Node Dialog
@ -732,12 +732,12 @@ export const PRIORITY_SIDEBAR_ORDER = [
"saved_components",
"inputs",
"outputs",
"prompts",
"data",
"prompt",
"models",
"vectorstores",
"vectorsearch",
"helpers",
"experimental",
];
export const NATIVE_CATEGORIES = [
"inputs",

View file

@ -33,7 +33,7 @@ export default function ChatInput({
<div className="relative">
<Textarea
onKeyDown={(event) => {
if (event.key === "Enter" && !lockChat && !event.shiftKey) {
if (event.key === "Enter" && !event.nativeEvent.isComposing && !lockChat && !event.shiftKey) {
sendMessage();
}
}}

View file

@ -5,7 +5,6 @@ import ShadTooltip from "../../../../components/ShadTooltipComponent";
import IconComponent from "../../../../components/genericIconComponent";
import { Input } from "../../../../components/ui/input";
import { Separator } from "../../../../components/ui/separator";
import { PRIORITY_SIDEBAR_ORDER } from "../../../../constants/constants";
import ExportModal from "../../../../modals/exportModal";
import ShareModal from "../../../../modals/shareModal";
import useAlertStore from "../../../../stores/alertStore";
@ -282,35 +281,7 @@ export default function ExtraSidebar(): JSX.Element {
</div>
</div>
)}
{index === PRIORITY_SIDEBAR_ORDER.length - 1 && (
<>
<a
target={"_blank"}
href="https://langflow.store"
className="components-disclosure-arrangement"
>
<div className="flex gap-4">
{/* BUG ON THIS ICON */}
<SparklesIcon
strokeWidth={1.5}
className="w-[22px] text-primary"
/>
<span className="components-disclosure-title">
Discover More
</span>
</div>
<div className="components-disclosure-div">
<div>
<LinkIcon className="h-4 w-4 text-foreground" />
</div>
</div>
</a>
<div className="p-2 px-4 text-sm font-semibold" key={index}>
Legacy Components
</div>
</>
)}
<DisclosureComponent
openDisc={
getFilterEdge.length !== 0 || search.length !== 0
@ -371,6 +342,32 @@ export default function ExtraSidebar(): JSX.Element {
))}
</div>
</DisclosureComponent>
{index === Object.keys(dataFilter).length - 1 && (
<>
<a
target={"_blank"}
href="https://langflow.store"
className="components-disclosure-arrangement"
>
<div className="flex gap-4">
{/* BUG ON THIS ICON */}
<SparklesIcon
strokeWidth={1.5}
className="w-[22px] text-primary"
/>
<span className="components-disclosure-title">
Discover More
</span>
</div>
<div className="components-disclosure-div">
<div>
<LinkIcon className="h-4 w-4 text-foreground" />
</div>
</div>
</a>
</>
)}
</>
) : (
<div key={index}></div>

View file

@ -85,7 +85,9 @@ export default function NodeToolbarComponent({
const [showModalAdvanced, setShowModalAdvanced] = useState(false);
const [showconfirmShare, setShowconfirmShare] = useState(false);
const [showOverrideModal, setShowOverrideModal] = useState(false);
const [flowComponent, setFlowComponent] = useState<FlowType>();
const [flowComponent, setFlowComponent] = useState<FlowType>(
createFlowComponent(cloneDeep(data), version)
);
const openInNewTab = (url) => {
window.open(url, "_blank", "noreferrer");
@ -285,7 +287,13 @@ export default function NodeToolbarComponent({
event.preventDefault();
setShowconfirmShare((state) => !state);
}
if (selected && (event.ctrlKey || event.metaKey) && event.key === "q") {
if (
selected &&
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.key === "Q"
) {
event.preventDefault();
if (isMinimal) {
setShowState((show) => !show);
@ -341,6 +349,10 @@ export default function NodeToolbarComponent({
title: `${data.id} docs is not available at the moment.`,
});
}
if (selected && (event.ctrlKey || event.metaKey) && event.key === "j") {
event.preventDefault();
downloadNode(flowComponent!);
}
}
document.addEventListener("keydown", onKeyDown);
@ -499,15 +511,17 @@ export default function NodeToolbarComponent({
/>
</SelectItem>
)}
{!hasStore && (
{(!hasStore || !hasApiKey || !validApiKey) && (
<SelectItem value={"Download"}>
<div className="flex">
<IconComponent
name="Download"
className="relative top-0.5 mr-2 h-4 w-4"
/>{" "}
Download{" "}
</div>{" "}
<ToolbarSelectItem
value="Download"
shift={false}
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
icon="Download"
styleObj={{ iconClasses: "relative top-0.5 mr-2 h-4 w-4" }}
keyboardKey={"J"}
dataTestId={"Dowload-button-nodeToolbar"}
/>
</SelectItem>
)}
<SelectItem
@ -525,24 +539,14 @@ export default function NodeToolbarComponent({
</SelectItem>
{isMinimal && (
<SelectItem value={"show"}>
<div className="flex">
<IconComponent
name={showNode ? "Minimize2" : "Maximize2"}
className="relative top-0.5 mr-2 h-4 w-4"
/>
{showNode ? "Minimize" : "Expand"}
{navigator.userAgent.toUpperCase().includes("MAC") ? (
<IconComponent
name="Command"
className="absolute right-[1.25rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
></IconComponent>
) : (
<span className="absolute right-[1.30rem] top-[0.40em] stroke-2">
Ctrl +{" "}
</span>
)}
<span className="absolute right-2 top-[0.46em]">Q</span>
</div>
<ToolbarSelectItem
icon={showNode ? "Minimize2" : "Maximize2"}
value={showNode ? "Minimize" : "Expand"}
isMac={navigator.userAgent.toUpperCase().includes("MAC")}
shift={true}
keyboardKey={"Q"}
dataTestId={"minimize-button-nodeToolbar"}
/>
</SelectItem>
)}
{isGroup && (

View file

@ -105,6 +105,8 @@ export default function HomePage(): JSX.Element {
firstButtonName="New Project"
onFirstBtnClick={() => setOpenModal(true)}
options={dropdownOptions}
plusButton={true}
dropdownOptions={false}
/>
</div>
}

View file

@ -4,7 +4,7 @@ import { DarkStoreType } from "../types/zustand/dark";
const startedStars = Number(window.localStorage.getItem("githubStars")) ?? 0;
export const useDarkStore = create<DarkStoreType>((set) => ({
export const useDarkStore = create<DarkStoreType>((set, get) => ({
dark: JSON.parse(window.localStorage.getItem("isDark")!) ?? false,
stars: startedStars,
version: "",
@ -15,14 +15,23 @@ export const useDarkStore = create<DarkStoreType>((set) => ({
});
},
refreshStars: () => {
if (window.localStorage.getItem("githubStars") !== null) {
set(() => ({ stars: startedStars }));
return;
let lastUpdated = window.localStorage.getItem("githubStarsLastUpdated");
let diff = 0;
// check if lastUpdated actually exists
if (lastUpdated !== null) {
diff = Math.abs(new Date().getTime() - new Date(lastUpdated).getTime());
}
getRepoStars("logspace-ai", "langflow").then((res) => {
window.localStorage.setItem("githubStars", res.toString());
set(() => ({ stars: res }));
});
// if lastUpdated is null or the difference is greater than 2 hours
if (lastUpdated === null || diff > 7200000) {
getRepoStars("logspace-ai", "langflow").then((res) => {
window.localStorage.setItem("githubStars", res.toString());
window.localStorage.setItem(
"githubStarsLastUpdated",
new Date().toString()
);
set(() => ({ stars: res, lastUpdated: new Date() }));
});
}
},
}));

View file

@ -689,6 +689,8 @@ export type dropdownButtonPropsType = {
firstButtonName: string;
onFirstBtnClick: () => void;
options: Array<{ name: string; onBtnClick: () => void }>;
plusButton?: boolean;
dropdownOptions?: boolean;
};
export type IOInputProps = {

View file

@ -119,6 +119,8 @@ export async function buildVertices({
try {
onValidateNodes(verticesOrderResponse.verticesToRun);
} catch (e) {
useFlowStore.getState().setIsBuilding(false);
return;
}
}

View file

@ -1170,7 +1170,7 @@ export function downloadNode(NodeFLow: FlowType) {
type: "application/json",
});
element.href = URL.createObjectURL(file);
element.download = `${NodeFLow.name}.json`;
element.download = `${NodeFLow?.name??"node"}.json`;
element.click();
}

View file

@ -236,6 +236,7 @@ export const nodeColors: { [char: string]: string } = {
embeddings: "#42BAA7",
documentloaders: "#7AAE42",
vectorstores: "#AA8742",
vectorsearch: "#AA8742",
textsplitters: "#B47CB5",
toolkits: "#DB2C2C",
wrappers: "#E6277A",
@ -248,6 +249,7 @@ export const nodeColors: { [char: string]: string } = {
retrievers: "#e6b25a",
unknown: "#9CA3AF",
custom_components: "#ab11ab",
Record:"#31a3cc"
};
export const nodeNames: { [char: string]: string } = {
@ -267,6 +269,7 @@ export const nodeNames: { [char: string]: string } = {
embeddings: "Embeddings",
documentloaders: "Loaders",
vectorstores: "Vector Stores",
vectorsearch: "Vector Search",
toolkits: "Toolkits",
wrappers: "Wrappers",
textsplitters: "Text Splitters",
@ -369,6 +372,7 @@ export const nodeIconsLucide: iconsType = {
saved_components: GradientSave,
documentloaders: Paperclip,
vectorstores: Layers,
vectorsearch: Search,
toolkits: Package2,
textsplitters: Scissors,
wrappers: Gift,
@ -387,7 +391,6 @@ export const nodeIconsLucide: iconsType = {
Trash2,
Boxes,
Network,
X,
XCircle,
Info,
CheckCircle2,

View file

@ -0,0 +1,358 @@
{
"id": "3f5e860d-1676-4fba-9d86-06db9f51e43a",
"data": {
"nodes": [
{
"id": "ChatInput-7hPDT",
"type": "genericNode",
"position": {
"x": 687,
"y": 41.9375
},
"data": {
"type": "ChatInput",
"node": {
"template": {
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Used to get user input from the chat.\"\n icon = \"ChatInput\"\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"type": "str",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "input_value",
"display_name": "Message",
"advanced": false,
"input_types": ["Text"],
"dynamic": false,
"info": "",
"load_from_db": false,
"title_case": false
},
"return_record": {
"type": "bool",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"value": false,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "return_record",
"display_name": "Return Record",
"advanced": false,
"dynamic": false,
"info": "Return the message as a record containing the sender, sender_name, and session_id.",
"load_from_db": false,
"title_case": false
},
"sender": {
"type": "str",
"required": false,
"placeholder": "",
"list": true,
"show": true,
"multiline": false,
"value": "User",
"fileTypes": [],
"file_path": "",
"password": false,
"options": ["Machine", "User"],
"name": "sender",
"display_name": "Sender Type",
"advanced": false,
"dynamic": false,
"info": "",
"load_from_db": false,
"title_case": false,
"input_types": ["Text"]
},
"sender_name": {
"type": "str",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"value": "User",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "sender_name",
"display_name": "Sender Name",
"advanced": false,
"dynamic": false,
"info": "",
"load_from_db": false,
"title_case": false,
"input_types": ["Text"]
},
"session_id": {
"type": "str",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "session_id",
"display_name": "Session ID",
"advanced": true,
"dynamic": false,
"info": "If provided, the message will be stored in the memory.",
"load_from_db": false,
"title_case": false,
"input_types": ["Text"]
},
"_type": "CustomComponent"
},
"description": "Used to get user input from the chat.",
"icon": "ChatInput",
"base_classes": ["Text", "object", "str", "Record"],
"display_name": "Chat Input",
"documentation": "",
"custom_fields": {
"sender": null,
"sender_name": null,
"input_value": null,
"session_id": null,
"return_record": null
},
"output_types": ["Text", "Record"],
"field_formatters": {},
"frozen": false,
"field_order": [],
"beta": false
},
"id": "ChatInput-7hPDT"
},
"selected": false,
"width": 384,
"height": 569,
"positionAbsolute": {
"x": 687,
"y": 41.9375
},
"dragging": false
},
{
"id": "ChatOutput-4sm9Z",
"type": "genericNode",
"position": {
"x": 4.939451516507972,
"y": 103.3695231904992
},
"data": {
"type": "ChatOutput",
"node": {
"template": {
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Used to send a message to the chat.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": true,
"dynamic": true,
"info": "",
"load_from_db": false,
"title_case": false
},
"input_value": {
"type": "str",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "input_value",
"display_name": "Message",
"advanced": false,
"input_types": ["Text"],
"dynamic": false,
"info": "",
"load_from_db": false,
"title_case": false
},
"return_record": {
"type": "bool",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"value": false,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "return_record",
"display_name": "Return Record",
"advanced": false,
"dynamic": false,
"info": "Return the message as a record containing the sender, sender_name, and session_id.",
"load_from_db": false,
"title_case": false
},
"sender": {
"type": "str",
"required": false,
"placeholder": "",
"list": true,
"show": true,
"multiline": false,
"value": "Machine",
"fileTypes": [],
"file_path": "",
"password": false,
"options": ["Machine", "User"],
"name": "sender",
"display_name": "Sender Type",
"advanced": false,
"dynamic": false,
"info": "",
"load_from_db": false,
"title_case": false,
"input_types": ["Text"]
},
"sender_name": {
"type": "str",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"value": "AI",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "sender_name",
"display_name": "Sender Name",
"advanced": false,
"dynamic": false,
"info": "",
"load_from_db": false,
"title_case": false,
"input_types": ["Text"]
},
"session_id": {
"type": "str",
"required": false,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "session_id",
"display_name": "Session ID",
"advanced": true,
"dynamic": false,
"info": "If provided, the message will be stored in the memory.",
"load_from_db": false,
"title_case": false,
"input_types": ["Text"]
},
"_type": "CustomComponent"
},
"description": "Used to send a message to the chat.",
"icon": "ChatOutput",
"base_classes": ["Text", "object", "str", "Record"],
"display_name": "Chat Output",
"documentation": "",
"custom_fields": {
"sender": null,
"sender_name": null,
"input_value": null,
"session_id": null,
"return_record": null
},
"output_types": ["Text", "Record"],
"field_formatters": {},
"frozen": false,
"field_order": [],
"beta": false
},
"id": "ChatOutput-4sm9Z"
},
"selected": true,
"width": 384,
"height": 569,
"positionAbsolute": {
"x": 4.939451516507972,
"y": 103.3695231904992
},
"dragging": false
}
],
"edges": [
{
"source": "ChatOutput-4sm9Z",
"sourceHandle": "{œbaseClassesœ:[œTextœ,œobjectœ,œstrœ,œRecordœ],œdataTypeœ:œChatOutputœ,œidœ:œChatOutput-4sm9Zœ}",
"target": "ChatInput-7hPDT",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatInput-7hPDTœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "ChatInput-7hPDT",
"inputTypes": ["Text"],
"type": "str"
},
"sourceHandle": {
"baseClasses": ["Text", "object", "str", "Record"],
"dataType": "ChatOutput",
"id": "ChatOutput-4sm9Z"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-ChatOutput-4sm9Z{œbaseClassesœ:[œTextœ,œobjectœ,œstrœ,œRecordœ],œdataTypeœ:œChatOutputœ,œidœ:œChatOutput-4sm9Zœ}-ChatInput-7hPDT{œfieldNameœ:œinput_valueœ,œidœ:œChatInput-7hPDTœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
}
],
"viewport": {
"x": 316.78239920440234,
"y": 182.84104875768622,
"zoom": 0.6070974421975234
}
},
"description": "flow to test ChatInput and output",
"name": "ChatITest",
"last_tested_version": "1.0.0a0",
"is_component": false
}

View file

@ -0,0 +1,46 @@
import { test } from "@playwright/test";
import { readFileSync } from "fs";
test.beforeEach(async ({ page }) => {
// await page.waitForTimeout(20000);
// test.setTimeout(120000);
});
test("chat_io_teste", async ({ page }) => {
await page.goto("/");
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/end-to-end/assets/ChatTest.json",
"utf-8"
);
// Create the DataTransfer and File
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data], "ChatTest.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(2000);
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(2000);
// Now dispatch
await page.dispatchEvent(
'//*[@id="react-flow-id"]/div[1]/div[1]/div',
"drop",
{
dataTransfer,
}
);
await page.getByLabel("fit view").click();
await page.getByText("Run", { exact: true }).click();
await page.getByPlaceholder("Send a message...").click();
await page.getByPlaceholder("Send a message...").fill("teste");
await page.getByRole("button").nth(1).click();
});

View file

@ -25,86 +25,31 @@ test("CodeAreaModalComponent", async ({ page }) => {
await page.getByTestId("code-button-modal").click();
let value = await page.locator('//*[@id="codeValue"]').inputValue();
if (
value !=
'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text'
) {
expect(false).toBeTruthy();
}
const code =
'def python_function(text: str) -> str:\n """This is a default python function that returns the input text"""\n return text';
const wCode =
'def python_function(text: str) -> st: """This is a default python function that returns the input text""" return text';
const assertCode =
'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text';
await page
.locator("#CodeEditor div")
.filter({ hasText: "def python_function(text: str" })
.nth(1)
.click();
await page.locator("textarea").press("Control+a");
await page.locator("textarea").fill(wCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await page.getByTestId("div-generic-node").click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
await page.locator('//*[@id="showdescription"]').click();
await page.waitForTimeout(1000);
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
await page.getByText("invalid syntax (<unknown>, line 1)").isVisible()
).toBeTruthy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showdescription"]').click();
expect(
await page.locator('//*[@id="showdescription"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showname"]').click();
expect(await page.locator('//*[@id="showname"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showreturn_direct"]').click();
expect(
await page.locator('//*[@id="showreturn_direct"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="code-input-0"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
await page.locator('//*[@id="saveChangesBtn"]').click();
await page.getByTestId("div-generic-node").click();
await page.getByTestId("code-button-modal").click();
}
await page.locator("textarea").press("Control+a");
await page.locator("textarea").fill(wCode);
await page.locator("textarea").fill(code);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
expect(await page.getByText("Code is ready to run").isVisible()).toBeTruthy();
await page.getByTestId("code-button-modal").click();
expect(await page.locator('//*[@id="codeValue"]').inputValue()).toBe(
assertCode
);
});

View file

@ -0,0 +1,17 @@
import { expect, test } from "@playwright/test";
test("curl_api_generation", async ({ page, context }) => {
await page.goto("/");
await page.locator('//*[@id="new-project-btn"]').click();
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
await page.getByRole("heading", { name: "Data Ingestion" }).click();
await page.waitForTimeout(2000);
await page.getByText("API", { exact: true }).click();
await page.getByRole("tab", { name: "cURL" }).click();
await page.getByRole("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText()
);
const clipboardContent = await handle.jsonValue();
expect(clipboardContent.length).toBeGreaterThan(0);
});

View file

@ -0,0 +1,17 @@
import { expect, test } from "@playwright/test";
test("python_api_generation", async ({ page, context }) => {
await page.goto("/");
await page.locator('//*[@id="new-project-btn"]').click();
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
await page.getByRole("heading", { name: "Data Ingestion" }).click();
await page.waitForTimeout(2000);
await page.getByText("API", { exact: true }).click();
await page.getByRole("tab", { name: "Python API" }).click();
await page.getByRole("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText()
);
const clipboardContent = await handle.jsonValue();
expect(clipboardContent.length).toBeGreaterThan(0);
});

View file

@ -0,0 +1,38 @@
import { expect, test } from "@playwright/test";
test("curl_api_generation", async ({ page, context }) => {
await page.goto("/");
await page.locator('//*[@id="new-project-btn"]').click();
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
await page.getByRole("heading", { name: "Data Ingestion" }).click();
await page.waitForTimeout(2000);
await page.getByText("API", { exact: true }).click();
await page.getByRole("tab", { name: "cURL" }).click();
await page.getByRole("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText()
);
const clipboardContent = await handle.jsonValue();
const oldValue = clipboardContent;
expect(clipboardContent.length).toBeGreaterThan(0);
await page.getByRole("tab", { name: "Tweaks" }).click();
await page
.getByRole("heading", { name: "URL" })
.locator("div")
.first()
.click();
await page.getByRole("textbox", { name: "Type something..." }).click();
await page
.getByRole("textbox", { name: "Type something..." })
.press("Control+a");
await page.getByRole("textbox", { name: "Type something..." }).fill("teste");
await page.getByRole("tab", { name: "cURL" }).click();
await page.getByRole("button", { name: "Copy Code" }).click();
const handle2 = await page.evaluateHandle(() =>
navigator.clipboard.readText()
);
const clipboardContent2 = await handle2.jsonValue();
const newValue = clipboardContent2;
expect(oldValue).not.toBe(newValue);
expect(clipboardContent2.length).toBeGreaterThan(clipboardContent.length);
});