Merge branch 'zustand/io/migration' into cz/new-tests

This commit is contained in:
cristhianzl 2024-04-03 16:23:24 -03:00
commit ebea3d9649
101 changed files with 5377 additions and 1784 deletions

View file

@ -149,13 +149,13 @@ def run(
Run the Langflow.
"""
configure(log_level=log_level, log_file=log_file)
set_var_for_macos_issue()
# override env variables with .env file
if env_file:
load_dotenv(env_file, override=True)
configure(log_level=log_level, log_file=log_file)
update_settings(
config,
dev=dev,
@ -246,10 +246,10 @@ def get_free_port(port):
def print_banner(host, port):
# console = Console()
from langflow.version import __version__
word = "Langflow"
colors = ["#3300cc"]
colors = ["#6e42f5"]
styled_word = ""
@ -259,7 +259,7 @@ def print_banner(host, port):
# Title with emojis and gradient text
title = (
f"[bold]Welcome to :chains: {styled_word} [/bold]\n\n"
f"[bold]Welcome to :chains: {styled_word} v{__version__}[/bold]\n"
f"Access [link=http://{host}:{port}]http://{host}:{port}[/link]"
)
info_text = (
@ -307,7 +307,7 @@ def run_langflow(host, port, log_level, options, app):
def superuser(
username: str = typer.Option(..., prompt=True, help="Username for the superuser."),
password: str = typer.Option(..., prompt=True, hide_input=True, help="Password for the superuser."),
log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
log_level: str = typer.Option("error", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
):
"""
Create a superuser.

View file

@ -1,4 +1,5 @@
import os
import warnings
from logging.config import fileConfig
from alembic import context
@ -82,11 +83,12 @@ def run_migrations_online() -> None:
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata, render_as_batch=True)
with context.begin_transaction():
context.run_migrations()
with warnings.catch_warnings():
warnings.simplefilter("ignore")
with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata, render_as_batch=True)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():

View file

@ -58,9 +58,7 @@ class APIRequest(CustomComponent):
data = body if body else None
payload = json.dumps(data)
try:
response = await client.request(
method, url, headers=headers, content=payload, timeout=timeout
)
response = await client.request(method, url, headers=headers, content=payload, timeout=timeout)
try:
result = response.json()
except Exception:
@ -117,10 +115,7 @@ class APIRequest(CustomComponent):
bodies += [None] * (len(urls) - len(bodies)) # type: ignore
async with httpx.AsyncClient() as client:
results = await asyncio.gather(
*[
self.make_request(client, method, u, headers, rec, timeout)
for u, rec in zip(urls, bodies)
]
*[self.make_request(client, method, u, headers, rec, timeout) for u, rec in zip(urls, bodies)]
)
self.status = results
return results

View file

@ -9,7 +9,7 @@ from langchain_core.documents import Document
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
from langflow.field_typing import Text
from langflow.utils.util import build_loader_repr_from_records, unescape_string
from langflow.utils.util import unescape_string
class SplitTextComponent(CustomComponent):
@ -54,7 +54,6 @@ class SplitTextComponent(CustomComponent):
chunk_overlap: Optional[int] = 200,
recursive: bool = False,
) -> list[Record]:
separators = [unescape_string(x) for x in separators]
# Make sure chunk_size and chunk_overlap are ints

View file

@ -5,6 +5,7 @@ from pydantic.v1 import SecretStr
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import Text
class AnthropicLLM(LCModelComponent):

View file

@ -5,6 +5,7 @@ from langchain_openai import AzureChatOpenAI
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import Text
class AzureChatOpenAIComponent(LCModelComponent):

View file

@ -5,6 +5,7 @@ from pydantic.v1 import SecretStr
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import Text
class QianfanChatEndpointComponent(LCModelComponent):

View file

@ -2,7 +2,7 @@ from typing import Optional
from langchain_community.chat_models.cohere import ChatCohere
from pydantic.v1 import SecretStr
from langflow.field_typing import Text
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent

View file

@ -2,7 +2,7 @@ from typing import Optional
from langchain_google_genai import ChatGoogleGenerativeAI
from pydantic.v1 import SecretStr
from langflow.field_typing import Text, RangeSpec
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent

View file

@ -2,7 +2,7 @@ from typing import Optional
from langchain_community.chat_models.huggingface import ChatHuggingFace
from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint
from langflow.field_typing import Text
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent

View file

@ -4,6 +4,7 @@ from langchain_core.messages.base import BaseMessage
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
from langflow.field_typing import Text
class ChatVertexAIComponent(LCModelComponent):

View file

@ -92,6 +92,11 @@ class AstraDBSearchComponent(LCVectorStoreComponent):
"info": "Optional dictionary defining the indexing policy for the collection.",
"advanced": True,
},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build(
@ -102,6 +107,7 @@ class AstraDBSearchComponent(LCVectorStoreComponent):
token: str,
api_endpoint: str,
search_type: str = "Similarity",
number_of_results: int = 4,
namespace: Optional[str] = None,
metric: Optional[str] = None,
batch_size: Optional[int] = None,
@ -131,4 +137,12 @@ class AstraDBSearchComponent(LCVectorStoreComponent):
metadata_indexing_exclude=metadata_indexing_exclude,
collection_indexing_policy=collection_indexing_policy,
)
return self.search_with_vector_store(input_value, search_type, vector_store)
try:
return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)
except KeyError as e:
if "content" in str(e):
raise ValueError(
"You should ingest data through Langflow (or LangChain) to query it in Langflow. Your collection does not contain a field name 'content'."
)
else:
raise e

View file

@ -48,6 +48,11 @@ class ChromaSearchComponent(LCVectorStoreComponent):
"display_name": "Server SSL Enabled",
"advanced": True,
},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build(
@ -57,6 +62,7 @@ class ChromaSearchComponent(LCVectorStoreComponent):
collection_name: str,
embedding: Embeddings,
chroma_server_ssl_enabled: bool,
number_of_results: int = 4,
index_directory: Optional[str] = None,
chroma_server_cors_allow_origins: Optional[str] = None,
chroma_server_host: Optional[str] = None,
@ -102,4 +108,4 @@ class ChromaSearchComponent(LCVectorStoreComponent):
client_settings=chroma_settings,
)
return self.search_with_vector_store(input_value, search_type, vector_store)
return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)

View file

@ -21,6 +21,11 @@ class FAISSSearchComponent(LCVectorStoreComponent):
},
"input_value": {"display_name": "Input"},
"index_name": {"display_name": "Index Name"},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build(
@ -28,6 +33,7 @@ class FAISSSearchComponent(LCVectorStoreComponent):
input_value: Text,
embedding: Embeddings,
folder_path: str,
number_of_results: int = 4,
index_name: str = "langflow_index",
) -> List[Record]:
if not folder_path:
@ -38,5 +44,5 @@ class FAISSSearchComponent(LCVectorStoreComponent):
raise ValueError("Failed to load the FAISS index.")
return self.search_with_vector_store(
vector_store=vector_store, input_value=input_value, search_type="similarity"
vector_store=vector_store, input_value=input_value, search_type="similarity", k=number_of_results
)

View file

@ -23,6 +23,11 @@ class MongoDBAtlasSearchComponent(LCVectorStoreComponent):
"index_name": {"display_name": "Index Name"},
"mongodb_atlas_cluster_uri": {"display_name": "MongoDB Atlas Cluster URI"},
"search_kwargs": {"display_name": "Search Kwargs", "advanced": True},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -30,6 +35,7 @@ class MongoDBAtlasSearchComponent(LCVectorStoreComponent):
input_value: Text,
search_type: str,
embedding: Embeddings,
number_of_results: int = 4,
collection_name: str = "",
db_name: str = "",
index_name: str = "",
@ -47,5 +53,5 @@ class MongoDBAtlasSearchComponent(LCVectorStoreComponent):
if not vector_store:
raise ValueError("Failed to create MongoDB Atlas Vector Store")
return self.search_with_vector_store(
vector_store=vector_store, input_value=input_value, search_type=search_type
vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results
)

View file

@ -38,6 +38,11 @@ class PineconeSearchComponent(PineconeComponent, LCVectorStoreComponent):
"default": 1,
"advanced": True,
},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -46,6 +51,7 @@ class PineconeSearchComponent(PineconeComponent, LCVectorStoreComponent):
embedding: Embeddings,
pinecone_env: str,
text_key: str = "text",
number_of_results: int = 4,
pool_threads: int = 4,
index_name: Optional[str] = None,
pinecone_api_key: Optional[str] = None,
@ -66,5 +72,5 @@ class PineconeSearchComponent(PineconeComponent, LCVectorStoreComponent):
raise ValueError("Failed to load the Pinecone index.")
return self.search_with_vector_store(
vector_store=vector_store, input_value=input_value, search_type=search_type
vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results
)

View file

@ -41,6 +41,11 @@ class QdrantSearchComponent(QdrantComponent, LCVectorStoreComponent):
"search_kwargs": {"display_name": "Search Kwargs", "advanced": True},
"timeout": {"display_name": "Timeout", "advanced": True},
"url": {"display_name": "URL", "advanced": True},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -48,6 +53,7 @@ class QdrantSearchComponent(QdrantComponent, LCVectorStoreComponent):
input_value: Text,
embedding: Embeddings,
collection_name: str,
number_of_results: int = 4,
search_type: str = "similarity",
api_key: Optional[str] = None,
content_payload_key: str = "page_content",
@ -88,5 +94,5 @@ class QdrantSearchComponent(QdrantComponent, LCVectorStoreComponent):
raise ValueError("Failed to load the Qdrant index.")
return self.search_with_vector_store(
vector_store=vector_store, input_value=input_value, search_type=search_type
vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results
)

View file

@ -39,6 +39,11 @@ class RedisSearchComponent(RedisComponent, LCVectorStoreComponent):
"advanced": False,
},
"redis_index_name": {"display_name": "Redis Index", "advanced": False},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -48,6 +53,7 @@ class RedisSearchComponent(RedisComponent, LCVectorStoreComponent):
embedding: Embeddings,
redis_server_url: str,
redis_index_name: str,
number_of_results: int = 4,
schema: Optional[str] = None,
) -> List[Record]:
"""
@ -72,5 +78,5 @@ class RedisSearchComponent(RedisComponent, LCVectorStoreComponent):
raise ValueError("Failed to load the Redis index.")
return self.search_with_vector_store(
input_value=input_value, search_type=search_type, vector_store=vector_store
input_value=input_value, search_type=search_type, vector_store=vector_store, k=number_of_results
)

View file

@ -26,6 +26,11 @@ class SupabaseSearchComponent(LCVectorStoreComponent):
"supabase_service_key": {"display_name": "Supabase Service Key"},
"supabase_url": {"display_name": "Supabase URL"},
"table_name": {"display_name": "Table Name", "advanced": True},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build(
@ -33,6 +38,7 @@ class SupabaseSearchComponent(LCVectorStoreComponent):
input_value: Text,
search_type: str,
embedding: Embeddings,
number_of_results: int = 4,
query_name: str = "",
supabase_service_key: str = "",
supabase_url: str = "",
@ -45,4 +51,4 @@ class SupabaseSearchComponent(LCVectorStoreComponent):
table_name=table_name,
query_name=query_name,
)
return self.search_with_vector_store(input_value, search_type, vector_store)
return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)

View file

@ -34,6 +34,11 @@ class VectaraSearchComponent(VectaraComponent, LCVectorStoreComponent):
"display_name": "Files Url",
"info": "Make vectara object using url of files (optional)",
},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -43,6 +48,7 @@ class VectaraSearchComponent(VectaraComponent, LCVectorStoreComponent):
vectara_customer_id: str,
vectara_corpus_id: str,
vectara_api_key: str,
number_of_results: int = 4,
) -> List[Record]:
source = "Langflow"
vector_store = Vectara(
@ -56,5 +62,5 @@ class VectaraSearchComponent(VectaraComponent, LCVectorStoreComponent):
raise ValueError("Failed to create Vectara Vector Store")
return self.search_with_vector_store(
vector_store=vector_store, input_value=input_value, search_type=search_type
vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results
)

View file

@ -49,7 +49,11 @@ class WeaviateSearchVectorStore(WeaviateVectorStoreComponent, LCVectorStoreCompo
"field_type": "bool",
"advanced": True,
},
"code": {"show": False},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -57,6 +61,7 @@ class WeaviateSearchVectorStore(WeaviateVectorStoreComponent, LCVectorStoreCompo
input_value: Text,
search_type: str,
url: str,
number_of_results: int = 4,
search_by_text: bool = False,
api_key: Optional[str] = None,
index_name: Optional[str] = None,
@ -77,5 +82,5 @@ class WeaviateSearchVectorStore(WeaviateVectorStoreComponent, LCVectorStoreCompo
raise ValueError("Failed to load the Weaviate index.")
return self.search_with_vector_store(
vector_store=vector_store, input_value=input_value, search_type=search_type
vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results
)

View file

@ -33,6 +33,11 @@ class PGVectorSearchComponent(PGVectorComponent, LCVectorStoreComponent):
},
"collection_name": {"display_name": "Table", "advanced": False},
"input_value": {"display_name": "Input"},
"number_of_results": {
"display_name": "Number of Results",
"info": "Number of results to return.",
"advanced": True,
},
}
def build( # type: ignore[override]
@ -42,6 +47,7 @@ class PGVectorSearchComponent(PGVectorComponent, LCVectorStoreComponent):
search_type: str,
pg_server_url: str,
collection_name: str,
number_of_results: int = 4,
) -> List[Record]:
"""
Builds the Vector Store or BaseRetriever object.
@ -64,5 +70,5 @@ class PGVectorSearchComponent(PGVectorComponent, LCVectorStoreComponent):
except Exception as e:
raise RuntimeError(f"Failed to build PGVector: {e}")
return self.search_with_vector_store(
input_value=input_value, search_type=search_type, vector_store=vector_store
input_value=input_value, search_type=search_type, vector_store=vector_store, k=number_of_results
)

View file

@ -19,6 +19,8 @@ class LCVectorStoreComponent(CustomComponent):
input_value: Text,
search_type: str,
vector_store: Union[VectorStore, BaseRetriever],
k=10,
**kwargs,
) -> List[Record]:
"""
Search for records in the vector store based on the input value and search type.
@ -37,7 +39,7 @@ class LCVectorStoreComponent(CustomComponent):
docs: List[Document] = []
if input_value and isinstance(input_value, str) and hasattr(vector_store, "search"):
docs = vector_store.search(query=input_value, search_type=search_type.lower())
docs = vector_store.search(query=input_value, search_type=search_type.lower(), k=k, **kwargs)
else:
raise ValueError("Invalid inputs provided.")
records = docs_to_records(docs)

View file

@ -1,7 +1,7 @@
import asyncio
from collections import defaultdict, deque
from itertools import chain
from typing import TYPE_CHECKING, Callable, Coroutine, Dict, Generator, List, Literal, Optional, Type, Union
from typing import TYPE_CHECKING, Callable, Coroutine, Dict, Generator, List, Optional, Type, Union
from loguru import logger

View file

@ -192,6 +192,7 @@ def delete_start_projects(session):
).all()
for flow in flows:
session.delete(flow)
session.commit()
def create_or_update_starter_projects():

View file

@ -982,7 +982,7 @@
"zoom": 0.47344308394045925
}
},
"description": "",
"description": "This flow can be used to create a blog post following instructions from the user, using two other blogs as reference.",
"name": "Blog Writer",
"last_tested_version": "1.0.0a0",
"is_component": false

View file

@ -3,7 +3,7 @@
"data": {
"nodes": [
{
"id": "Prompt-6qkyO",
"id": "Prompt-amqBu",
"type": "genericNode",
"position": {
"x": 2191.5837146441663,
@ -109,7 +109,7 @@
"beta": false,
"error": null
},
"id": "Prompt-6qkyO",
"id": "Prompt-amqBu",
"description": "Create a prompt template with dynamic variables.",
"display_name": "Prompt"
},
@ -123,7 +123,7 @@
"dragging": false
},
{
"id": "Prompt-8M7lZ",
"id": "Prompt-gTNiz",
"type": "genericNode",
"position": {
"x": 3731.0813766902447,
@ -229,16 +229,17 @@
"beta": false,
"error": null
},
"id": "Prompt-8M7lZ",
"id": "Prompt-gTNiz",
"description": "Create a prompt template with dynamic variables.",
"display_name": "Prompt"
},
"selected": false,
"width": 384,
"height": 385
"height": 385,
"dragging": false
},
{
"id": "ChatOutput-TKkOi",
"id": "ChatOutput-EJkG3",
"type": "genericNode",
"position": {
"x": 3722.1747844849388,
@ -426,7 +427,7 @@
"field_order": [],
"beta": false
},
"id": "ChatOutput-TKkOi"
"id": "ChatOutput-EJkG3"
},
"selected": false,
"width": 384,
@ -434,7 +435,7 @@
"dragging": false
},
{
"id": "ChatOutput-WOZJj",
"id": "ChatOutput-DNmvg",
"type": "genericNode",
"position": {
"x": 5077.71285886074,
@ -622,14 +623,14 @@
"field_order": [],
"beta": false
},
"id": "ChatOutput-WOZJj"
"id": "ChatOutput-DNmvg"
},
"selected": false,
"width": 384,
"height": 385
},
{
"id": "TextInput-fd38z",
"id": "TextInput-sptaH",
"type": "genericNode",
"position": {
"x": 1700.5624822024752,
@ -725,9 +726,9 @@
"field_order": [],
"beta": false
},
"id": "TextInput-fd38z"
"id": "TextInput-sptaH"
},
"selected": true,
"selected": false,
"width": 384,
"height": 290,
"positionAbsolute": {
@ -737,11 +738,11 @@
"dragging": false
},
{
"id": "TextOutput-LH9pW",
"id": "TextOutput-2MS4a",
"type": "genericNode",
"position": {
"x": 2429.4897030584134,
"y": 552.2482060219679
"x": 2917.216113690115,
"y": 513.0058511435552
},
"data": {
"type": "TextOutput",
@ -833,19 +834,19 @@
"field_order": [],
"beta": false
},
"id": "TextOutput-LH9pW"
"id": "TextOutput-2MS4a"
},
"selected": false,
"width": 384,
"height": 290,
"positionAbsolute": {
"x": 2429.4897030584134,
"y": 552.2482060219679
"x": 2917.216113690115,
"y": 513.0058511435552
},
"dragging": false
},
{
"id": "OpenAIModel-WAiN2",
"id": "OpenAIModel-uYXZJ",
"type": "genericNode",
"position": {
"x": 2925.784767523062,
@ -1111,7 +1112,7 @@
],
"beta": false
},
"id": "OpenAIModel-WAiN2"
"id": "OpenAIModel-uYXZJ"
},
"selected": false,
"width": 384,
@ -1123,7 +1124,7 @@
"dragging": false
},
{
"id": "TextOutput-ZUN0s",
"id": "TextOutput-MUDOR",
"type": "genericNode",
"position": {
"x": 4446.064323520379,
@ -1219,7 +1220,7 @@
"field_order": [],
"beta": false
},
"id": "TextOutput-ZUN0s"
"id": "TextOutput-MUDOR"
},
"selected": false,
"width": 384,
@ -1231,7 +1232,7 @@
}
},
{
"id": "OpenAIModel-4b8eN",
"id": "OpenAIModel-XawYB",
"type": "genericNode",
"position": {
"x": 4500.152018344182,
@ -1497,7 +1498,7 @@
],
"beta": false
},
"id": "OpenAIModel-4b8eN"
"id": "OpenAIModel-XawYB"
},
"selected": false,
"width": 384,
@ -1511,14 +1512,14 @@
],
"edges": [
{
"source": "TextInput-fd38z",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-fd38zœ}",
"target": "Prompt-6qkyO",
"targetHandle": "{œfieldNameœ:œdocumentœ,œidœ:œPrompt-6qkyOœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}",
"source": "TextInput-sptaH",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-sptaHœ}",
"target": "Prompt-amqBu",
"targetHandle": "{œfieldNameœ:œdocumentœ,œidœ:œPrompt-amqBuœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "document",
"id": "Prompt-6qkyO",
"id": "Prompt-amqBu",
"inputTypes": [
"Document",
"BaseOutputParser",
@ -1534,24 +1535,24 @@
"object"
],
"dataType": "TextInput",
"id": "TextInput-fd38z"
"id": "TextInput-sptaH"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-TextInput-fd38z{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-fd38zœ}-Prompt-6qkyO{œfieldNameœ:œdocumentœ,œidœ:œPrompt-6qkyOœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-TextInput-sptaH{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-sptaHœ}-Prompt-amqBu{œfieldNameœ:œdocumentœ,œidœ:œPrompt-amqBuœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}"
},
{
"source": "Prompt-6qkyO",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-6qkyOœ}",
"target": "TextOutput-LH9pW",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-LH9pWœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}",
"source": "Prompt-amqBu",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}",
"target": "TextOutput-2MS4a",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-2MS4aœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "TextOutput-LH9pW",
"id": "TextOutput-2MS4a",
"inputTypes": [
"Record",
"Text"
@ -1565,24 +1566,24 @@
"Text"
],
"dataType": "Prompt",
"id": "Prompt-6qkyO"
"id": "Prompt-amqBu"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-Prompt-6qkyO{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-6qkyOœ}-TextOutput-LH9pW{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-LH9pWœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-Prompt-amqBu{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}-TextOutput-2MS4a{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-2MS4aœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}"
},
{
"source": "Prompt-6qkyO",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-6qkyOœ}",
"target": "OpenAIModel-WAiN2",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-WAiN2œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"source": "Prompt-amqBu",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}",
"target": "OpenAIModel-uYXZJ",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-uYXZJœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "OpenAIModel-WAiN2",
"id": "OpenAIModel-uYXZJ",
"inputTypes": [
"Text"
],
@ -1595,24 +1596,24 @@
"Text"
],
"dataType": "Prompt",
"id": "Prompt-6qkyO"
"id": "Prompt-amqBu"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-Prompt-6qkyO{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-6qkyOœ}-OpenAIModel-WAiN2{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-WAiN2œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-Prompt-amqBu{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}-OpenAIModel-uYXZJ{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-uYXZJœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
},
{
"source": "OpenAIModel-WAiN2",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-WAiN2œ}",
"target": "Prompt-8M7lZ",
"targetHandle": "{œfieldNameœ:œsummaryœ,œidœ:œPrompt-8M7lZœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}",
"source": "OpenAIModel-uYXZJ",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}",
"target": "Prompt-gTNiz",
"targetHandle": "{œfieldNameœ:œsummaryœ,œidœ:œPrompt-gTNizœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "summary",
"id": "Prompt-8M7lZ",
"id": "Prompt-gTNiz",
"inputTypes": [
"Document",
"BaseOutputParser",
@ -1628,24 +1629,24 @@
"object"
],
"dataType": "OpenAIModel",
"id": "OpenAIModel-WAiN2"
"id": "OpenAIModel-uYXZJ"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-OpenAIModel-WAiN2{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-WAiN2œ}-Prompt-8M7lZ{œfieldNameœ:œsummaryœ,œidœ:œPrompt-8M7lZœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-OpenAIModel-uYXZJ{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}-Prompt-gTNiz{œfieldNameœ:œsummaryœ,œidœ:œPrompt-gTNizœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}"
},
{
"source": "OpenAIModel-WAiN2",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-WAiN2œ}",
"target": "ChatOutput-TKkOi",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-TKkOiœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"source": "OpenAIModel-uYXZJ",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}",
"target": "ChatOutput-EJkG3",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-EJkG3œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "ChatOutput-TKkOi",
"id": "ChatOutput-EJkG3",
"inputTypes": [
"Text"
],
@ -1658,24 +1659,24 @@
"object"
],
"dataType": "OpenAIModel",
"id": "OpenAIModel-WAiN2"
"id": "OpenAIModel-uYXZJ"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-OpenAIModel-WAiN2{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-WAiN2œ}-ChatOutput-TKkOi{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-TKkOiœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-OpenAIModel-uYXZJ{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}-ChatOutput-EJkG3{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-EJkG3œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
},
{
"source": "Prompt-8M7lZ",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-8M7lZœ}",
"target": "TextOutput-ZUN0s",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-ZUN0sœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}",
"source": "Prompt-gTNiz",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}",
"target": "TextOutput-MUDOR",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-MUDORœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "TextOutput-ZUN0s",
"id": "TextOutput-MUDOR",
"inputTypes": [
"Record",
"Text"
@ -1689,24 +1690,24 @@
"Text"
],
"dataType": "Prompt",
"id": "Prompt-8M7lZ"
"id": "Prompt-gTNiz"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-Prompt-8M7lZ{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-8M7lZœ}-TextOutput-ZUN0s{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-ZUN0sœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-Prompt-gTNiz{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}-TextOutput-MUDOR{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-MUDORœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}"
},
{
"source": "Prompt-8M7lZ",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-8M7lZœ}",
"target": "OpenAIModel-4b8eN",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-4b8eNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"source": "Prompt-gTNiz",
"sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}",
"target": "OpenAIModel-XawYB",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XawYBœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "OpenAIModel-4b8eN",
"id": "OpenAIModel-XawYB",
"inputTypes": [
"Text"
],
@ -1719,24 +1720,24 @@
"Text"
],
"dataType": "Prompt",
"id": "Prompt-8M7lZ"
"id": "Prompt-gTNiz"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-Prompt-8M7lZ{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-8M7lZœ}-OpenAIModel-4b8eN{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-4b8eNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-Prompt-gTNiz{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}-OpenAIModel-XawYB{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XawYBœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
},
{
"source": "OpenAIModel-4b8eN",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-4b8eNœ}",
"target": "ChatOutput-WOZJj",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-WOZJjœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"source": "OpenAIModel-XawYB",
"sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XawYBœ}",
"target": "ChatOutput-DNmvg",
"targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DNmvgœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "input_value",
"id": "ChatOutput-WOZJj",
"id": "ChatOutput-DNmvg",
"inputTypes": [
"Text"
],
@ -1749,20 +1750,20 @@
"object"
],
"dataType": "OpenAIModel",
"id": "OpenAIModel-4b8eN"
"id": "OpenAIModel-XawYB"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-foreground stroke-connection",
"id": "reactflow__edge-OpenAIModel-4b8eN{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-4b8eNœ}-ChatOutput-WOZJj{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-WOZJjœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
"className": "stroke-gray-900 stroke-connection",
"id": "reactflow__edge-OpenAIModel-XawYB{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XawYBœ}-ChatOutput-DNmvg{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DNmvgœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}"
}
],
"viewport": {
"x": -269.16751160112597,
"y": 42.28236292358156,
"zoom": 0.30778611191960875
"x": -383.7251879618552,
"y": 69.19813933800037,
"zoom": 0.3105753483695743
}
},
"description": "The Prompt Chaining flow chains prompts with LLMs, refining outputs through iterative stages.",

View file

@ -1,3 +1,4 @@
import warnings
from typing import Callable, Dict, List, Optional
from langchain.agents import agent_toolkits
@ -29,13 +30,15 @@ class ToolkitCreator(LangChainTypeCreator):
@property
def type_to_loader_dict(self) -> Dict:
if self.type_dict is None:
settings_service = get_settings_service()
self.type_dict = {
toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}")
# if toolkit_name is not lower case it is a class
for toolkit_name in agent_toolkits.__all__
if not toolkit_name.islower() and toolkit_name in settings_service.settings.TOOLKITS
}
with warnings.catch_warnings():
warnings.simplefilter("ignore")
settings_service = get_settings_service()
self.type_dict = {
toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}")
# if toolkit_name is not lower case it is a class
for toolkit_name in agent_toolkits.__all__
if not toolkit_name.islower() and toolkit_name in settings_service.settings.TOOLKITS
}
return self.type_dict

View file

@ -1,6 +1,7 @@
from typing import Dict, List, Optional
from langchain.agents.load_tools import _EXTRA_LLM_TOOLS, _EXTRA_OPTIONAL_TOOLS, _LLM_TOOLS
from langflow.interface.base import LangChainTypeCreator
from langflow.interface.tools.constants import ALL_TOOLS_NAMES, CUSTOM_TOOLS, FILE_TOOLS, OTHER_TOOLS
from langflow.interface.tools.util import get_tool_params

View file

@ -9,6 +9,7 @@ from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from loguru import logger
from langflow.api import router
from langflow.initial_setup.setup import create_or_update_starter_projects
@ -106,6 +107,7 @@ def get_static_files_dir():
def setup_app(static_files_dir: Optional[Path] = None, backend_only: bool = False) -> FastAPI:
"""Setup the FastAPI app."""
# get the directory of the current file
logger.info(f"Setting up app with static files directory {static_files_dir}")
if not static_files_dir:
static_files_dir = get_static_files_dir()
@ -128,7 +130,7 @@ if __name__ == "__main__":
host="127.0.0.1",
port=7860,
workers=get_number_of_workers(),
log_level="debug",
log_level="error",
reload=True,
loop="asyncio",
)

View file

@ -1,3 +1,5 @@
import os
from gunicorn.app.base import BaseApplication # type: ignore
from uvicorn.workers import UvicornWorker
@ -11,6 +13,7 @@ class LangflowApplication(BaseApplication):
self.options = options or {}
self.options["worker_class"] = "langflow.server.LangflowUvicornWorker"
self.options["loglevel"] = os.getenv("LANGFLOW_LOG_LEVEL", "error").lower()
self.application = app
super().__init__()

View file

@ -1,3 +1,4 @@
from datetime import datetime
import time
from pathlib import Path
from typing import TYPE_CHECKING
@ -124,10 +125,16 @@ class DatabaseService(Service):
# if not self.script_location.exists(): # this is not the correct way to check if alembic has been initialized
# We need to check if the alembic_version table exists
# if not, we need to initialize alembic
alembic_cfg = Config()
# stdout should be something like sys.stdout
# which is a buffer
# I don't want to output anything
# subprocess.DEVNULL is an int
buffer = open(self.script_location / "alembic.log", "w")
alembic_cfg = Config(stdout=buffer)
# alembic_cfg.attributes["connection"] = session
alembic_cfg.set_main_option("script_location", str(self.script_location))
alembic_cfg.set_main_option("sqlalchemy.url", self.database_url)
should_initialize_alembic = False
with Session(self.engine) as session:
# If the table does not exist it throws an error
@ -150,6 +157,7 @@ class DatabaseService(Service):
logger.info(f"Running DB migrations in {self.script_location}")
try:
buffer.write(f"{datetime.now().isoformat()}: Checking migrations\n")
command.check(alembic_cfg)
except Exception as exc:
if isinstance(exc, (util.exc.CommandError, util.exc.AutogenerateDiffsDetected)):
@ -157,6 +165,7 @@ class DatabaseService(Service):
time.sleep(3)
try:
buffer.write(f"{datetime.now().isoformat()}: Checking migrations\n")
command.check(alembic_cfg)
except util.exc.AutogenerateDiffsDetected as exc:
logger.error(f"AutogenerateDiffsDetected: {exc}")

View file

@ -40,9 +40,9 @@ class AuthSettings(BaseSettings):
"""The Secure attribute of the refresh token cookie."""
REFRESH_HTTPONLY: bool = True
"""The HttpOnly attribute of the refresh token cookie."""
ACCESS_SAME_SITE: Literal["lax", "strict", "none"] = "none"
ACCESS_SAME_SITE: Literal["lax", "strict", "none"] = "lax"
"""The SameSite attribute of the access token cookie."""
ACCESS_SECURE: bool = True
ACCESS_SECURE: bool = False
"""The Secure attribute of the access token cookie."""
ACCESS_HTTPONLY: bool = False
"""The HttpOnly attribute of the access token cookie."""

View file

@ -94,7 +94,8 @@ class FrontendNode(BaseModel):
def process_base_classes(self, base_classes: List[str]) -> List[str]:
"""Removes unwanted base classes from the list of base classes."""
return list(set(base_classes))
sorted_base_classes = sorted(list(set(base_classes)), key=lambda x: x.lower())
return sorted_base_classes
@field_serializer("display_name")
def process_display_name(self, display_name: str) -> str:

View file

@ -28,7 +28,7 @@ def configure(log_level: Optional[str] = None, log_file: Optional[Path] = None):
if os.getenv("LANGFLOW_LOG_LEVEL", "").upper() in VALID_LOG_LEVELS and log_level is None:
log_level = os.getenv("LANGFLOW_LOG_LEVEL")
if log_level is None:
log_level = "INFO"
log_level = "ERROR"
# Human-readable
log_format = (
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> - <level>"

View file

@ -2050,13 +2050,13 @@ files = [
[[package]]
name = "importlib-metadata"
version = "6.11.0"
version = "7.0.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"},
{file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"},
{file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"},
{file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"},
]
[package.dependencies]
@ -2487,13 +2487,13 @@ extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.
[[package]]
name = "langchain-core"
version = "0.1.37"
version = "0.1.38"
description = "Building applications with LLMs through composability"
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
{file = "langchain_core-0.1.37-py3-none-any.whl", hash = "sha256:63c6aecb0f2eb1a21f8e944da622748cfeafa2cc3d94c0182ffa8038bd00fe0b"},
{file = "langchain_core-0.1.37.tar.gz", hash = "sha256:3db7008796e25aea90f98c2159dbf29bf1fd296bdcb78dc2d8183a92fdde4433"},
{file = "langchain_core-0.1.38-py3-none-any.whl", hash = "sha256:d881b2754254cb4bdb0d5bb56e5c138d032b6e75e5cb21f151b01224b322e02b"},
{file = "langchain_core-0.1.38.tar.gz", hash = "sha256:ee8da6d061c06cce7dc22fec224b6ecbc3a8de106d6dd9f409c7fe448ea41861"},
]
[package.dependencies]
@ -3071,7 +3071,6 @@ files = [
{file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"},
{file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"},
{file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"},
{file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"},
{file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"},
]
@ -3372,57 +3371,42 @@ sympy = "*"
[[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"
[[package]]
name = "opentelemetry-exporter-otlp"
version = "1.23.0"
description = "OpenTelemetry Collector Exporters"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_exporter_otlp-1.23.0-py3-none-any.whl", hash = "sha256:92371fdc8d7803465a45801fe30cd8c522ef355a385b0a1d5346d32f77511ea2"},
{file = "opentelemetry_exporter_otlp-1.23.0.tar.gz", hash = "sha256:4af8798f9bc3bddb92fcbb5b4aa9d0e955d962aa1d9bceaab08891c355a9f907"},
]
[package.dependencies]
opentelemetry-exporter-otlp-proto-grpc = "1.23.0"
opentelemetry-exporter-otlp-proto-http = "1.23.0"
importlib-metadata = ">=6.0,<=7.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]
@ -3430,45 +3414,22 @@ 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"]
[[package]]
name = "opentelemetry-exporter-otlp-proto-http"
version = "1.23.0"
description = "OpenTelemetry Collector Protobuf over HTTP Exporter"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_exporter_otlp_proto_http-1.23.0-py3-none-any.whl", hash = "sha256:ad853b58681df8efcb2cfc93be2b5fd86351c99ff4ab47dc917da384b8650d91"},
{file = "opentelemetry_exporter_otlp_proto_http-1.23.0.tar.gz", hash = "sha256:088eac2320f4a604e2d9ff71aced71fdae601ac6457005fb0303d6bbbf44e6ca"},
]
[package.dependencies]
deprecated = ">=1.2.6"
googleapis-common-protos = ">=1.52,<2.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"
requests = ">=2.7,<3.0"
[package.extras]
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]
@ -3478,78 +3439,55 @@ 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"
version = "0.44b0"
description = "OpenTelemetry HTTPX Instrumentation"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_instrumentation_httpx-0.44b0-py3-none-any.whl", hash = "sha256:a4f1121b6212b018e719ef6a9a2f8317c329edd01a61452b7250f574f7d95a91"},
{file = "opentelemetry_instrumentation_httpx-0.44b0.tar.gz", hash = "sha256:6cc81c4182f54dfb0d15774e3e48bb90d3ed44e9ad8bf5eef2a64a7197f945d8"},
]
[package.dependencies]
opentelemetry-api = ">=1.12,<2.0"
opentelemetry-instrumentation = "0.44b0"
opentelemetry-semantic-conventions = "0.44b0"
opentelemetry-util-http = "0.44b0"
[package.extras]
instruments = ["httpx (>=0.18.0)"]
test = ["opentelemetry-instrumentation-httpx[instruments]", "opentelemetry-sdk (>=1.12,<2.0)", "opentelemetry-test-utils (==0.44b0)"]
[[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]
@ -3557,40 +3495,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]]
@ -3892,6 +3830,41 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
typing = ["typing-extensions"]
xmp = ["defusedxml"]
[[package]]
name = "pip"
version = "24.0"
description = "The PyPA recommended tool for installing Python packages."
optional = false
python-versions = ">=3.7"
files = [
{file = "pip-24.0-py3-none-any.whl", hash = "sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc"},
{file = "pip-24.0.tar.gz", hash = "sha256:ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2"},
]
[[package]]
name = "pip-tools"
version = "7.4.1"
description = "pip-tools keeps your pinned dependencies fresh."
optional = false
python-versions = ">=3.8"
files = [
{file = "pip-tools-7.4.1.tar.gz", hash = "sha256:864826f5073864450e24dbeeb85ce3920cdfb09848a3d69ebf537b521f14bcc9"},
{file = "pip_tools-7.4.1-py3-none-any.whl", hash = "sha256:4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9"},
]
[package.dependencies]
build = ">=1.0.0"
click = ">=8"
pip = ">=22.2"
pyproject_hooks = "*"
setuptools = "*"
tomli = {version = "*", markers = "python_version < \"3.11\""}
wheel = "*"
[package.extras]
coverage = ["covdefaults", "pytest-cov"]
testing = ["flit_core (>=2,<4)", "poetry_core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist", "tomli-w"]
[[package]]
name = "platformdirs"
version = "4.2.0"
@ -5344,13 +5317,13 @@ files = [
[[package]]
name = "types-pyasn1"
version = "0.5.0.20240301"
version = "0.6.0.20240402"
description = "Typing stubs for pyasn1"
optional = false
python-versions = ">=3.8"
files = [
{file = "types-pyasn1-0.5.0.20240301.tar.gz", hash = "sha256:da328f5771d54a2016863270b281047f9cc38e39f65a297ba9f987d5de3403f1"},
{file = "types_pyasn1-0.5.0.20240301-py3-none-any.whl", hash = "sha256:d9989899184bbd6e2adf6f812c8f49c48197fceea251a6fb13666dae3203f80d"},
{file = "types-pyasn1-0.6.0.20240402.tar.gz", hash = "sha256:5d54dcb33f69dd269071ca098e923ac20c5f03c814631fa7f3ed9ee035a5da3a"},
{file = "types_pyasn1-0.6.0.20240402-py3-none-any.whl", hash = "sha256:848d01e7313c200acc035a8b3d377fe7b2aecbe77f2be49eb160a7f82835aaaf"},
]
[[package]]
@ -5431,13 +5404,13 @@ types-pyOpenSSL = "*"
[[package]]
name = "types-requests"
version = "2.31.0.20240311"
version = "2.31.0.20240402"
description = "Typing stubs for requests"
optional = false
python-versions = ">=3.8"
files = [
{file = "types-requests-2.31.0.20240311.tar.gz", hash = "sha256:b1c1b66abfb7fa79aae09097a811c4aa97130eb8831c60e47aee4ca344731ca5"},
{file = "types_requests-2.31.0.20240311-py3-none-any.whl", hash = "sha256:47872893d65a38e282ee9f277a4ee50d1b28bd592040df7d1fdaffdf3779937d"},
{file = "types-requests-2.31.0.20240402.tar.gz", hash = "sha256:e5c09a202f8ae79cd6ffbbba2203b6c3775a83126283bb2a6abbc129abc02a12"},
{file = "types_requests-2.31.0.20240402-py3-none-any.whl", hash = "sha256:bd7eb7102168d4b5b489f15cdd9842b63ab7fe56aa82a0589fa595b94195acf4"},
]
[package.dependencies]
@ -5779,6 +5752,20 @@ MarkupSafe = ">=2.1.1"
[package.extras]
watchdog = ["watchdog (>=2.3)"]
[[package]]
name = "wheel"
version = "0.43.0"
description = "A built-package format for Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "wheel-0.43.0-py3-none-any.whl", hash = "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"},
{file = "wheel-0.43.0.tar.gz", hash = "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85"},
]
[package.extras]
test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
[[package]]
name = "win32-setctime"
version = "1.1.0"
@ -6083,4 +6070,4 @@ local = []
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<3.12"
content-hash = "5a06c86bfbf2cc209bcb3f202bd749af1c8146aa08c10fd69152c170f890866d"
content-hash = "455e5f44f2e5dcbc3e0359658d7c4ef9f93e40c99841c9de99311a0ecad483c2"

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "langflow-base"
version = "0.0.13"
version = "0.0.16"
description = "A Python package with a built-in web application"
authors = ["Logspace <contact@logspace.ai>"]
maintainers = [
@ -52,12 +52,6 @@ docstring-parser = "^0.15"
python-jose = "^3.3.0"
pandas = "2.2.0"
multiprocess = "^0.70.14"
opentelemetry-api = "^1.23.0"
opentelemetry-sdk = "^1.23.0"
opentelemetry-exporter-otlp = "^1.23.0"
opentelemetry-instrumentation-fastapi = "^0.44b0"
opentelemetry-instrumentation-httpx = "^0.44b0"
opentelemetry-instrumentation-asgi = "^0.44b0"
duckdb = "^0.9.2"
python-socketio = "^5.11.0"
python-docx = "^1.1.0"
@ -93,7 +87,7 @@ pytest-sugar = "^0.9.7"
[tool.poetry.extras]
deploy = ["langchain-serve", "celery", "redis", "flower"]
deploy = ["celery", "redis", "flower"]
local = ["llama-cpp-python", "sentence-transformers", "ctransformers"]
all = ["deploy", "local"]

View file

@ -1,70 +0,0 @@
from typing import List, Union
from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent
from langflow import CustomComponent
from langflow.field_typing import BaseMemory, Text, Tool
class LCAgentComponent(CustomComponent):
def build_config(self):
return {
"lc": {
"display_name": "LangChain",
"info": "The LangChain to interact with.",
},
"handle_parsing_errors": {
"display_name": "Handle Parsing Errors",
"info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.",
"advanced": True,
},
"output_key": {
"display_name": "Output Key",
"info": "The key to use to get the output from the agent.",
"advanced": True,
},
"memory": {
"display_name": "Memory",
"info": "Memory to use for the agent.",
},
"tools": {
"display_name": "Tools",
"info": "Tools the agent can use.",
},
"input_value": {
"display_name": "Input",
"info": "Input text to pass to the agent.",
},
}
async def run_agent(
self,
agent: Union[BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor],
inputs: str,
input_variables: list[str],
tools: List[Tool],
memory: BaseMemory = None,
handle_parsing_errors: bool = True,
output_key: str = "output",
) -> Text:
if isinstance(agent, AgentExecutor):
runnable = agent
else:
runnable = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True, memory=memory, handle_parsing_errors=handle_parsing_errors
)
input_dict = {"input": inputs}
for var in input_variables:
if var not in ["agent_scratchpad", "input"]:
input_dict[var] = ""
result = await runnable.ainvoke(input_dict)
self.status = result
if output_key in result:
return result.get(output_key)
elif "output" not in result:
if output_key != "output":
raise ValueError(f"Output key not found in result. Tried '{output_key}' and 'output'.")
else:
raise ValueError("Output key not found in result. Tried 'output'.")
return result.get("output")

View file

@ -1,3 +0,0 @@
from .model import LCModelComponent
__all__ = ["LCModelComponent"]

View file

@ -1,48 +0,0 @@
from typing import Optional
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_core.language_models.llms import LLM
from langchain_core.messages import HumanMessage, SystemMessage
from langflow import CustomComponent
class LCModelComponent(CustomComponent):
display_name: str = "Model Name"
description: str = "Model Description"
def get_result(self, runnable: LLM, stream: bool, input_value: str):
"""
Retrieves the result from the output of a Runnable object.
Args:
output (Runnable): The output object to retrieve the result from.
stream (bool): Indicates whether to use streaming or invocation mode.
input_value (str): The input value to pass to the output object.
Returns:
The result obtained from the output object.
"""
if stream:
result = runnable.stream(input_value)
else:
message = runnable.invoke(input_value)
result = message.content if hasattr(message, "content") else message
self.status = result
return result
def get_chat_result(
self, runnable: BaseChatModel, stream: bool, input_value: str, system_message: Optional[str] = None
):
messages = []
if input_value:
messages.append(HumanMessage(input_value))
if system_message:
messages.append(SystemMessage(system_message))
if stream:
result = runnable.stream(messages)
else:
message = runnable.invoke(messages)
result = message.content
self.status = result
return result

View file

@ -1,37 +0,0 @@
from langchain_community.tools.searchapi import SearchAPIRun
from langchain_community.utilities.searchapi import SearchApiAPIWrapper
from langflow import CustomComponent
from langflow.field_typing import Tool
class SearchApiToolComponent(CustomComponent):
display_name: str = "SearchApi Tool"
description: str = "Real-time search engine results API."
documentation: str = "https://www.searchapi.io/docs/google"
field_config = {
"engine": {
"display_name": "Engine",
"field_type": "str",
"info": "The search engine to use.",
},
"api_key": {
"display_name": "API Key",
"field_type": "str",
"required": True,
"password": True,
"info": "The API key to use SearchApi.",
},
}
def build(
self,
engine: str,
api_key: str,
) -> Tool:
search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key)
tool = SearchAPIRun(api_wrapper=search_api_wrapper)
self.status = tool
return tool

View file

@ -1,103 +0,0 @@
from contextlib import contextmanager
from typing import TYPE_CHECKING, Generator
from langflow.services import ServiceType, service_manager
if TYPE_CHECKING:
from sqlmodel import Session
from langflow.services.cache.service import CacheService
from langflow.services.chat.service import ChatService
from langflow.services.credentials.service import CredentialService
from langflow.services.database.service import DatabaseService
from langflow.services.monitor.service import MonitorService
from langflow.services.plugins.service import PluginService
from langflow.services.session.service import SessionService
from langflow.services.settings.service import SettingsService
from langflow.services.socket.service import SocketIOService
from langflow.services.storage.service import StorageService
from langflow.services.store.service import StoreService
from langflow.services.task.service import TaskService
def get_socket_service() -> "SocketIOService":
return service_manager.get(ServiceType.SOCKETIO_SERVICE) # type: ignore
def get_storage_service() -> "StorageService":
return service_manager.get(ServiceType.STORAGE_SERVICE) # type: ignore
def get_credential_service() -> "CredentialService":
return service_manager.get(ServiceType.CREDENTIAL_SERVICE) # type: ignore
def get_plugins_service() -> "PluginService":
return service_manager.get(ServiceType.PLUGIN_SERVICE) # type: ignore
def get_settings_service() -> "SettingsService":
try:
return service_manager.get(ServiceType.SETTINGS_SERVICE) # type: ignore
except ValueError:
# initialize settings service
from langflow.services.manager import initialize_settings_service
initialize_settings_service()
return service_manager.get(ServiceType.SETTINGS_SERVICE) # type: ignore
def get_db_service() -> "DatabaseService":
return service_manager.get(ServiceType.DATABASE_SERVICE) # type: ignore
def get_session() -> Generator["Session", None, None]:
db_service = get_db_service()
yield from db_service.get_session()
@contextmanager
def session_scope():
"""
Context manager for managing a session scope.
Yields:
session: The session object.
Raises:
Exception: If an error occurs during the session scope.
"""
session = next(get_session())
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
def get_cache_service() -> "CacheService":
return service_manager.get(ServiceType.CACHE_SERVICE) # type: ignore
def get_session_service() -> "SessionService":
return service_manager.get(ServiceType.SESSION_SERVICE) # type: ignore
def get_monitor_service() -> "MonitorService":
return service_manager.get(ServiceType.MONITOR_SERVICE) # type: ignore
def get_task_service() -> "TaskService":
return service_manager.get(ServiceType.TASK_SERVICE) # type: ignore
def get_chat_service() -> "ChatService":
return service_manager.get(ServiceType.CHAT_SERVICE) # type: ignore
def get_store_service() -> "StoreService":
return service_manager.get(ServiceType.STORE_SERVICE) # type: ignore

View file

@ -1,83 +0,0 @@
import importlib
import inspect
from typing import TYPE_CHECKING, Type, get_type_hints
from cachetools import LRUCache, cached
from loguru import logger
from langflow.services.schema import ServiceType
if TYPE_CHECKING:
from langflow.services.base import Service
class ServiceFactory:
def __init__(
self,
service_class,
):
self.service_class = service_class
self.dependencies = infer_service_types(self, import_all_services_into_a_dict())
def create(self, *args, **kwargs) -> "Service":
raise self.service_class(*args, **kwargs)
def hash_factory(factory: ServiceFactory) -> str:
return factory.service_class.__name__
def hash_dict(d: dict) -> str:
return str(d)
def hash_infer_service_types_args(factory_class: Type[ServiceFactory], available_services=None) -> str:
factory_hash = hash_factory(factory_class)
services_hash = hash_dict(available_services)
return f"{factory_hash}_{services_hash}"
@cached(cache=LRUCache(maxsize=10), key=hash_infer_service_types_args)
def infer_service_types(factory_class: Type[ServiceFactory], available_services=None) -> "ServiceType":
create_method = factory_class.create
type_hints = get_type_hints(create_method, globalns=available_services)
service_types = []
for param_name, param_type in type_hints.items():
# Skip the return type if it's included in type hints
if param_name == "return":
continue
# Convert the type to the expected enum format directly without appending "_SERVICE"
type_name = param_type.__name__.upper().replace("SERVICE", "_SERVICE")
try:
# Attempt to find a matching enum value
service_type = ServiceType[type_name]
service_types.append(service_type)
except KeyError:
raise ValueError(f"No matching ServiceType for parameter type: {param_type.__name__}")
return service_types
@cached(cache=LRUCache(maxsize=1))
def import_all_services_into_a_dict():
# Services are all in langflow.services.{service_name}.service
# and are subclass of Service
# We want to import all of them and put them in a dict
# to use as globals
from langflow.services.base import Service
services = {}
for service_type in ServiceType:
try:
service_name = ServiceType(service_type).value.replace("_service", "")
module_name = f"langflow.services.{service_name}.service"
module = importlib.import_module(module_name)
for name, obj in inspect.getmembers(module, inspect.isclass):
if issubclass(obj, Service) and obj is not Service:
services[name] = obj
break
except Exception as exc:
logger.exception(exc)
raise RuntimeError("Could not initialize services. Please check your settings.") from exc
return services

View file

@ -1,16 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<script src="/node_modules/ace-builds/src-min-noconflict/ace.js" type="text/javascript"></script>
<script
src="/node_modules/ace-builds/src-min-noconflict/ace.js"
type="module"
></script>
<title>Langflow</title>
</head>
<body id='body' style="width: 100%; height:100%">
</head>
<body id="body" style="width: 100%; height: 100%">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div style="width: 100vw; height:100vh" id='root'></div>
<div style="width: 100vw; height: 100vh" id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</body>
</html>

View file

@ -969,9 +969,9 @@
}
},
"node_modules/@humanwhocodes/object-schema": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
"integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"dev": true
},
"node_modules/@isaacs/cliui": {
@ -4888,9 +4888,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001600",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz",
"integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==",
"version": "1.0.30001603",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001603.tgz",
"integrity": "sha512-iL2iSS0eDILMb9n5yKQoTBim9jMZ0Yrk8g0N9K7UzYyWnfIKzXBZD5ngpM37ZcL/cv0Mli8XtVMRYMQAfFpi5Q==",
"funding": [
{
"type": "opencollective",
@ -5677,9 +5677,9 @@
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.722",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.722.tgz",
"integrity": "sha512-5nLE0TWFFpZ80Crhtp4pIp8LXCztjYX41yUcV6b+bKR2PqzjskTMOOlBi1VjBHlvHwS+4gar7kNKOrsbsewEZQ=="
"version": "1.4.723",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.723.tgz",
"integrity": "sha512-rxFVtrMGMFROr4qqU6n95rUi9IlfIm+lIAt+hOToy/9r6CDv0XiEcQdC3VP71y1pE5CFTzKV0RvxOGYCPWWHPw=="
},
"node_modules/emoji-regex": {
"version": "9.2.2",

View file

@ -205,7 +205,7 @@ export default function CodeTabsComponent({
<div className="api-modal-according-display">
<div
className={classNames(
"h-[70vh] w-full rounded-lg bg-muted overflow-y-auto overflow-x-hidden custom-scroll"
"h-[70vh] w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll"
)}
>
{data?.map((node: any, i) => (

View file

@ -1,10 +1,28 @@
const SvgGoogleGenerativeAI = (props) => (<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" {...props}>
<path d="M16 8.016A8.522 8.522 0 008.016 16h-.032A8.521 8.521 0 000 8.016v-.032A8.521 8.521 0 007.984 0h.032A8.522 8.522 0 0016 7.984v.032z" fill="url(#prefix__paint0_radial_980_20147)"/>
<defs>
<radialGradient id="prefix__paint0_radial_980_20147" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(16.1326 5.4553 -43.70045 129.2322 1.588 6.503)">
<stop offset=".067" stop-color="#9168C0"/><stop offset=".343" stop-color="#5684D1"/><stop offset=".672" stop-color="#1BA1E3"/>
const SvgGoogleGenerativeAI = (props) => (
<svg
fill="none"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
{...props}
>
<path
d="M16 8.016A8.522 8.522 0 008.016 16h-.032A8.521 8.521 0 000 8.016v-.032A8.521 8.521 0 007.984 0h.032A8.522 8.522 0 0016 7.984v.032z"
fill="url(#prefix__paint0_radial_980_20147)"
/>
<defs>
<radialGradient
id="prefix__paint0_radial_980_20147"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(16.1326 5.4553 -43.70045 129.2322 1.588 6.503)"
>
<stop offset=".067" stop-color="#9168C0" />
<stop offset=".343" stop-color="#5684D1" />
<stop offset=".672" stop-color="#1BA1E3" />
</radialGradient>
</defs>
</defs>
</svg>
);
export default SvgGoogleGenerativeAI;

View file

@ -28,9 +28,7 @@ import {
LANGFLOW_SUPPORTED_TYPES,
limitScrollFieldsModal,
} from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import useFlowStore from "../../stores/flowStore";
import { useGlobalVariablesStore } from "../../stores/globalVariables";
import { NodeDataType } from "../../types/flow";
import {
convertObjToArray,

View file

@ -23,7 +23,9 @@ export default function IOFieldView({
case "TextInput":
return (
<Textarea
className={`w-full custom-scroll ${left ? " min-h-32" : " h-full"}`}
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
}`}
placeholder={"Enter text..."}
value={node.data.node!.template["input_value"].value}
onChange={(e) => {
@ -54,7 +56,9 @@ export default function IOFieldView({
default:
return (
<Textarea
className={`w-full custom-scroll ${left ? " min-h-32" : " h-full"}`}
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
}`}
placeholder={"Enter text..."}
value={node.data.node!.template["input_value"]}
onChange={(e) => {
@ -74,7 +78,9 @@ export default function IOFieldView({
case "TextOutput":
return (
<Textarea
className={`w-full custom-scroll ${left ? " min-h-32" : " h-full"}`}
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
}`}
placeholder={"Empty"}
// update to real value on flowPool
value={
@ -89,7 +95,9 @@ export default function IOFieldView({
default:
return (
<Textarea
className={`w-full custom-scroll ${left ? " min-h-32" : " h-full"}`}
className={`w-full custom-scroll ${
left ? " min-h-32" : " h-full"
}`}
placeholder={"Empty"}
// update to real value on flowPool
value={

View file

@ -9,6 +9,7 @@ import Robot from "../../../../../assets/robot.png";
import SanitizedHTMLWrapper from "../../../../../components/SanitizedHTMLWrapper";
import CodeTabsComponent from "../../../../../components/codeTabsComponent";
import IconComponent from "../../../../../components/genericIconComponent";
import useAlertStore from "../../../../../stores/alertStore";
import useFlowStore from "../../../../../stores/flowStore";
import { chatMessagePropsType } from "../../../../../types/components";
import { classNames, cn } from "../../../../../utils/utils";
@ -33,6 +34,7 @@ export default function ChatMessage({
const [isStreaming, setIsStreaming] = useState(false);
const eventSource = useRef<EventSource | undefined>(undefined);
const updateFlowPool = useFlowStore((state) => state.updateFlowPool);
const setErrorData = useAlertStore((state) => state.setErrorData);
const chatMessageRef = useRef(chatMessage);
// Sync ref with state
@ -53,10 +55,17 @@ export default function ChatMessage({
setChatMessage((prev) => prev + parsedData.chunk);
}
};
eventSource.current.onerror = (event) => {
eventSource.current.onerror = (event: any) => {
setIsStreaming(false);
eventSource.current?.close();
setStreamUrl(undefined);
if (JSON.parse(event.data)?.error) {
setErrorData({
title: "Error on Streaming",
list: [JSON.parse(event.data)?.error],
});
}
updateChat(chat, chatMessageRef.current);
reject(new Error("Streaming failed"));
};
eventSource.current.addEventListener("close", (event) => {

View file

@ -1,6 +1,5 @@
import { useEffect, useRef, useState } from "react";
import IconComponent from "../../../../components/genericIconComponent";
import { NOCHATOUTPUT_NOTICE_ALERT } from "../../../../constants/alerts_constants";
import {
CHAT_FIRST_INITIAL_TEXT,
CHAT_SECOND_INITIAL_TEXT,
@ -124,7 +123,7 @@ export default function ChatView({
message: string,
stream_url?: string
) {
if (message === "") return;
// if (message === "") return;
chat.message = message;
// chat is one of the chatHistory
updateFlowPool(chat.componentId, {

View file

@ -10,6 +10,12 @@ export default function NewFlowModal({
}: newFlowModalPropsType): JSX.Element {
const examples = useFlowsManagerStore((state) => state.examples);
examples.forEach((example) => {
if (example.name === "Blog Writter") {
example.name = "Blog Writer";
}
});
return (
<BaseModal size="three-cards" open={open} setOpen={setOpen}>
<BaseModal.Header description={"Select a template below"}>

View file

@ -143,7 +143,6 @@ export default function ShareModal({
});
});
};
console.log("ShareModal");
const handleUpdateComponent = () => {
handleShareComponent(true);

View file

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

View file

@ -378,7 +378,7 @@ export default function ExtraSidebar(): JSX.Element {
Object.keys(dataFilter[SBSectionName]).length > 0 ? (
<>
<DisclosureComponent
isChild={false}
isChild={false}
openDisc={
getFilterEdge.length !== 0 || search.length !== 0
? true

View file

@ -664,6 +664,9 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
let newEdges = cloneDeep(excludedEdges);
const { nodes, edges } = groupNode.data.node!.flow!.data!;
const lastNode = findLastNode(groupNode.data.node!.flow!.data!);
newEdges = newEdges.filter(
(e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id)
);
newEdges.forEach((edge) => {
if (lastNode && edge.source === lastNode.id) {
edge.source = groupNode.id;

View file

@ -21,8 +21,8 @@ import {
ChevronsLeft,
ChevronsRight,
ChevronsUpDown,
Circle,
ChevronsUpDownIcon,
Circle,
CircleDot,
Clipboard,
Code,
@ -252,9 +252,8 @@ export const nodeColors: { [char: string]: string } = {
retrievers: "#e6b25a",
unknown: "#9CA3AF",
custom_components: "#ab11ab",
Records:"#31a3cc",
Record:"#31a3cc",
Records: "#31a3cc",
Record: "#31a3cc",
};
export const nodeNames: { [char: string]: string } = {