Merge branch 'zustand/io/migration' into cz/new-tests
This commit is contained in:
commit
ebea3d9649
101 changed files with 5377 additions and 1784 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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__()
|
||||
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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."""
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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>"
|
||||
|
|
|
|||
225
src/backend/base/poetry.lock
generated
225
src/backend/base/poetry.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
from .model import LCModelComponent
|
||||
|
||||
__all__ = ["LCModelComponent"]
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
18
src/frontend/package-lock.json
generated
18
src/frontend/package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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) => (
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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={
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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, {
|
||||
|
|
|
|||
|
|
@ -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"}>
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ export default function ShareModal({
|
|||
});
|
||||
});
|
||||
};
|
||||
console.log("ShareModal");
|
||||
|
||||
const handleUpdateComponent = () => {
|
||||
handleShareComponent(true);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 } = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue