Merge pull request #98 from logspace-ai/chain_loader

Chain loader
This commit is contained in:
Ibis Prevedello 2023-04-03 17:36:21 -03:00 • committed by GitHub
commit c1493dcc22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 132 additions and 285 deletions

View file

@ -7,7 +7,7 @@ from fastapi.staticfiles import StaticFiles
from langflow.main import create_app from langflow.main import create_app
from langflow.settings import settings from langflow.settings import settings
from langflow.utils.logger import configure, logger from langflow.utils.logger import configure
app = typer.Typer() app = typer.Typer()

View file

@ -1,8 +1,8 @@
chains: chains:
- LLMChain - LLMChain
- LLMMathChain - LLMMathChain
- LLMChecker - LLMCheckerChain
# - ConversationChain - ConversationChain
agents: agents:
- ZeroShotAgent - ZeroShotAgent
@ -31,19 +31,16 @@ wrappers:
- RequestsWrapper - RequestsWrapper
toolkits: toolkits:
- OpenAPIToolkit - OpenAPIToolkit
- JsonToolkit - JsonToolkit
memories: memories:
- ConversationBufferMemory - ConversationBufferMemory
embeddings: [] embeddings: []
vectorstores: [] vectorstores: []
documentloaders: [] documentloaders: []
dev: false dev: false

View file

@ -5,7 +5,7 @@
import types import types
from copy import deepcopy from copy import deepcopy
from typing import Any, Dict, List from typing import Any, Dict, List, Optional
from langflow.graph.constants import DIRECT_TYPES from langflow.graph.constants import DIRECT_TYPES
from langflow.graph.utils import load_file from langflow.graph.utils import load_file
@ -15,11 +15,11 @@ from langflow.utils.logger import logger
class Node: class Node:
def __init__(self, data: Dict, base_type: str | None = None) -> None: def __init__(self, data: Dict, base_type: Optional[str] = None) -> None:
self.id: str = data["id"] self.id: str = data["id"]
self._data = data self._data = data
self.edges: List[Edge] = [] self.edges: List[Edge] = []
self.base_type: str | None = base_type self.base_type: Optional[str] = base_type
self._parse_data() self._parse_data()
self._built_object = None self._built_object = None
self._built = False self._built = False
@ -80,51 +80,44 @@ class Node:
continue continue
# If the type is not transformable to a python base class # If the type is not transformable to a python base class
# then we need to get the edge that connects to this node # then we need to get the edge that connects to this node
if value["type"] == "file": if value.get("type") == "file":
# Load the type in value.get('suffixes') using # Load the type in value.get('suffixes') using
# what is inside value.get('content') # what is inside value.get('content')
# value.get('value') is the file name # value.get('value') is the file name
type_to_load = value.get("suffixes")
file_name = value.get("value") file_name = value.get("value")
content = value.get("content") content = value.get("content")
type_to_load = value.get("suffixes")
loaded_dict = load_file(file_name, content, type_to_load) loaded_dict = load_file(file_name, content, type_to_load)
params[key] = loaded_dict params[key] = loaded_dict
# We should check if the type is in something not # We should check if the type is in something not
# the opposite # the opposite
elif value["type"] not in DIRECT_TYPES: elif value.get("type") not in DIRECT_TYPES:
# Get the edge that connects to this node # Get the edge that connects to this node
try: edges = [
edge = next( edge
( for edge in self.edges
edge if edge.target == self and edge.matched_type in value["type"]
for edge in self.edges ]
if edge.target == self
and edge.matched_type in value["type"]
),
None,
)
except Exception as e:
raise e
# Get the output of the node that the edge connects to # Get the output of the node that the edge connects to
# if the value['list'] is True, then there will be more # if the value['list'] is True, then there will be more
# than one time setting to params[key] # than one time setting to params[key]
# so we need to append to a list if it exists # so we need to append to a list if it exists
# or create a new list if it doesn't # or create a new list if it doesn't
if edge is None and value["required"]: if value["required"] and not edges:
# break line # If a required parameter is not found, raise an error
raise ValueError( raise ValueError(
f"Required input {key} for module {self.node_type} not found" f"Required input {key} for module {self.node_type} not found"
) )
elif value["list"]: elif value["list"]:
if key not in params: # If this is a list parameter, append all sources to a list
params[key] = [] params[key] = [edge.source for edge in edges]
if edge is not None: elif edges:
params[key].append(edge.source) # If a single parameter is found, use its source
elif value["required"] or edge is not None: params[key] = edges[0].source
params[key] = edge.source
elif value["required"] or value.get("value"): elif value["required"] or value.get("value"):
params[key] = value["value"] params[key] = value["value"]

View file

@ -17,7 +17,8 @@ from langflow.interface.llms.base import llm_creator
from langflow.interface.prompts.base import prompt_creator from langflow.interface.prompts.base import prompt_creator
from langflow.interface.toolkits.base import toolkits_creator from langflow.interface.toolkits.base import toolkits_creator
from langflow.interface.tools.base import tool_creator from langflow.interface.tools.base import tool_creator
from langflow.interface.tools.constants import ALL_TOOLS_NAMES, FILE_TOOLS from langflow.interface.tools.constants import FILE_TOOLS
from langflow.interface.tools.util import get_tools_dict
from langflow.interface.wrappers.base import wrapper_creator from langflow.interface.wrappers.base import wrapper_creator
from langflow.utils import payload from langflow.utils import payload
@ -113,7 +114,10 @@ class Graph:
nodes.append(AgentNode(node)) nodes.append(AgentNode(node))
elif node_type in chain_creator.to_list(): elif node_type in chain_creator.to_list():
nodes.append(ChainNode(node)) nodes.append(ChainNode(node))
elif node_type in tool_creator.to_list() or node_lc_type in ALL_TOOLS_NAMES: elif (
node_type in tool_creator.to_list()
or node_lc_type in get_tools_dict().keys()
):
if node_type in FILE_TOOLS: if node_type in FILE_TOOLS:
nodes.append(FileToolNode(node)) nodes.append(FileToolNode(node))
nodes.append(ToolNode(node)) nodes.append(ToolNode(node))

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langchain.agents import loading from langchain.agents import loading
@ -21,7 +21,7 @@ class AgentCreator(LangChainTypeCreator):
self.type_dict[name] = agent self.type_dict[name] = agent
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
try: try:
if name in get_custom_nodes(self.type_name).keys(): if name in get_custom_nodes(self.type_name).keys():
return get_custom_nodes(self.type_name)[name] return get_custom_nodes(self.type_name)[name]

View file

@ -1,17 +1,16 @@
from typing import Any, List, Optional from typing import Any, List, Optional
from langchain import LLMChain from langchain import LLMChain
from langchain.agents import AgentExecutor, ZeroShotAgent from langchain.agents import AgentExecutor, Tool, ZeroShotAgent, initialize_agent
from langchain.agents.agent_toolkits.json.prompt import JSON_PREFIX, JSON_SUFFIX from langchain.agents.agent_toolkits.json.prompt import JSON_PREFIX, JSON_SUFFIX
from langchain.agents.agent_toolkits.json.toolkit import JsonToolkit from langchain.agents.agent_toolkits.json.toolkit import JsonToolkit
from langchain.agents.agent_toolkits.pandas.prompt import PREFIX as PANDAS_PREFIX from langchain.agents.agent_toolkits.pandas.prompt import PREFIX as PANDAS_PREFIX
from langchain.agents.agent_toolkits.pandas.prompt import SUFFIX as PANDAS_SUFFIX from langchain.agents.agent_toolkits.pandas.prompt import SUFFIX as PANDAS_SUFFIX
from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS
from langchain.schema import BaseLanguageModel
from langchain.llms.base import BaseLLM from langchain.llms.base import BaseLLM
from langchain.tools.python.tool import PythonAstREPLTool
from langchain.agents import initialize_agent, Tool
from langchain.memory.chat_memory import BaseChatMemory from langchain.memory.chat_memory import BaseChatMemory
from langchain.schema import BaseLanguageModel
from langchain.tools.python.tool import PythonAstREPLTool
class JsonAgent(AgentExecutor): class JsonAgent(AgentExecutor):

View file

@ -1,10 +1,9 @@
from typing import Dict, List from typing import Dict, List, Optional
from langchain.chains import loading as chains_loading
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import chain_type_to_cls_dict
from langflow.settings import settings from langflow.settings import settings
from langflow.utils.util import build_template_from_function from langflow.utils.util import build_template_from_class
# Assuming necessary imports for Field, Template, and FrontendNode classes # Assuming necessary imports for Field, Template, and FrontendNode classes
@ -15,25 +14,20 @@ class ChainCreator(LangChainTypeCreator):
@property @property
def type_to_loader_dict(self) -> Dict: def type_to_loader_dict(self) -> Dict:
if self.type_dict is None: if self.type_dict is None:
self.type_dict = chains_loading.type_to_loader_dict self.type_dict = chain_type_to_cls_dict
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
try: try:
return build_template_from_function( return build_template_from_class(name, chain_type_to_cls_dict)
name, self.type_to_loader_dict, add_function=True
)
except ValueError as exc: except ValueError as exc:
raise ValueError("Chain not found") from exc raise ValueError("Memory not found") from exc
def to_list(self) -> List[str]: def to_list(self) -> List[str]:
return [ return [
chain.__annotations__["return"].__name__ chain.__name__
for chain in self.type_to_loader_dict.values() for chain in self.type_to_loader_dict.values()
if ( if chain.__name__ in settings.chains or settings.dev
chain.__annotations__["return"].__name__ in settings.chains
or settings.dev
)
] ]

View file

@ -1,108 +1,29 @@
from typing import Any from typing import Any
## LLM ## LLM
from langchain import llms, requests from langchain import (
chains,
document_loaders,
embeddings,
llms,
memory,
requests,
vectorstores,
)
from langchain.agents import agent_toolkits from langchain.agents import agent_toolkits
from langchain.chat_models import ChatOpenAI from langchain.chat_models import ChatOpenAI
## Memory
from langchain import memory
## Document Loaders
from langchain.document_loaders import (
AirbyteJSONLoader,
AZLyricsLoader,
CollegeConfidentialLoader,
CoNLLULoader,
CSVLoader,
DirectoryLoader,
EverNoteLoader,
FacebookChatLoader,
GCSDirectoryLoader,
GCSFileLoader,
GitbookLoader,
GoogleApiClient,
GoogleApiYoutubeLoader,
GoogleDriveLoader,
GutenbergLoader,
HNLoader,
IFixitLoader,
IMSDbLoader,
NotebookLoader,
NotionDirectoryLoader,
ObsidianLoader,
OnlinePDFLoader,
PagedPDFSplitter,
PDFMinerLoader,
PyMuPDFLoader,
PyPDFLoader,
ReadTheDocsLoader,
RoamLoader,
S3DirectoryLoader,
S3FileLoader,
SRTLoader,
TelegramChatLoader,
TextLoader,
UnstructuredEmailLoader,
UnstructuredFileIOLoader,
UnstructuredFileLoader,
UnstructuredHTMLLoader,
UnstructuredImageLoader,
UnstructuredMarkdownLoader,
UnstructuredPDFLoader,
# BSHTMLLoader,
UnstructuredPowerPointLoader,
UnstructuredURLLoader,
UnstructuredWordDocumentLoader,
WebBaseLoader,
YoutubeLoader,
)
## Embeddings
from langchain.embeddings import (
CohereEmbeddings,
FakeEmbeddings,
HuggingFaceEmbeddings,
HuggingFaceHubEmbeddings,
HuggingFaceInstructEmbeddings,
OpenAIEmbeddings,
SelfHostedEmbeddings,
SelfHostedHuggingFaceEmbeddings,
SelfHostedHuggingFaceInstructEmbeddings,
# SagemakerEndpointEmbeddings,
TensorflowHubEmbeddings,
)
## Vector Stores
from langchain.vectorstores import (
FAISS,
AtlasDB,
Chroma,
DeepLake,
ElasticVectorSearch,
Milvus,
OpenSearchVectorSearch,
Pinecone,
Qdrant,
VectorStore,
Weaviate,
)
## Toolkits
from langflow.interface.importing.utils import import_class from langflow.interface.importing.utils import import_class
## LLM ## LLM
llm_type_to_cls_dict = llms.type_to_cls_dict llm_type_to_cls_dict = llms.type_to_cls_dict
llm_type_to_cls_dict["openai-chat"] = ChatOpenAI # type: ignore llm_type_to_cls_dict["openai-chat"] = ChatOpenAI # type: ignore
## Chain ## Chain
# from langchain.chains.loading import type_to_loader_dict chain_type_to_cls_dict: dict[str, Any] = {
# from langchain.chains.conversation.base import ConversationChain chain_name: import_class(f"langchain.chains.{chain_name}")
for chain_name in chains.__all__
# chain_type_to_cls_dict = type_to_loader_dict }
# chain_type_to_cls_dict["conversation_chain"] = ConversationChain
toolkit_type_to_loader_dict: dict[str, Any] = { toolkit_type_to_loader_dict: dict[str, Any] = {
toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}") toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}")
@ -118,99 +39,33 @@ toolkit_type_to_cls_dict: dict[str, Any] = {
if not toolkit_name.islower() if not toolkit_name.islower()
} }
## Memory ## Memories
memory_type_to_cls_dict: dict[str, Any] = { memory_type_to_cls_dict: dict[str, Any] = {
memory_name: import_class(f"langchain.memory.{memory_name}") memory_name: import_class(f"langchain.memory.{memory_name}")
for memory_name in memory.__all__ for memory_name in memory.__all__
} }
## Wrappers
wrapper_type_to_cls_dict: dict[str, Any] = { wrapper_type_to_cls_dict: dict[str, Any] = {
wrapper.__name__: wrapper for wrapper in [requests.RequestsWrapper] wrapper.__name__: wrapper for wrapper in [requests.RequestsWrapper]
} }
## Embeddings ## Embeddings
embedding_type_to_cls_dict: dict[str, Any] = {
embedding_type_to_cls_dict = { embedding_name: import_class(f"langchain.embeddings.{embedding_name}")
"OpenAIEmbeddings": OpenAIEmbeddings, for embedding_name in embeddings.__all__
"HuggingFaceEmbeddings": HuggingFaceEmbeddings,
"CohereEmbeddings": CohereEmbeddings,
"HuggingFaceHubEmbeddings": HuggingFaceHubEmbeddings,
"TensorflowHubEmbeddings": TensorflowHubEmbeddings,
# "SagemakerEndpointEmbeddings": SagemakerEndpointEmbeddings,
"HuggingFaceInstructEmbeddings": HuggingFaceInstructEmbeddings,
"SelfHostedEmbeddings": SelfHostedEmbeddings,
"SelfHostedHuggingFaceEmbeddings": SelfHostedHuggingFaceEmbeddings,
"SelfHostedHuggingFaceInstructEmbeddings": SelfHostedHuggingFaceInstructEmbeddings,
"FakeEmbeddings": FakeEmbeddings,
} }
## Vector Stores ## Vector Stores
vectorstores_type_to_cls_dict: dict[str, Any] = {
vectorstores_type_to_cls_dict = { vectorstore_name: import_class(f"langchain.vectorstores.{vectorstore_name}")
"ElasticVectorSearch": ElasticVectorSearch, for vectorstore_name in vectorstores.__all__
"FAISS": FAISS,
"VectorStore": VectorStore,
"Pinecone": Pinecone,
"Weaviate": Weaviate,
"Qdrant": Qdrant,
"Milvus": Milvus,
"Chroma": Chroma,
"OpenSearchVectorSearch": OpenSearchVectorSearch,
"AtlasDB": AtlasDB,
"DeepLake": DeepLake,
} }
## Document Loaders ## Document Loaders
documentloaders_type_to_cls_dict: dict[str, Any] = {
documentloaders_type_to_cls_dict = { documentloader_name: import_class(
"UnstructuredFileLoader": UnstructuredFileLoader, f"langchain.document_loaders.{documentloader_name}"
"UnstructuredFileIOLoader": UnstructuredFileIOLoader, )
"UnstructuredURLLoader": UnstructuredURLLoader, for documentloader_name in document_loaders.__all__
"DirectoryLoader": DirectoryLoader,
"NotionDirectoryLoader": NotionDirectoryLoader,
"ReadTheDocsLoader": ReadTheDocsLoader,
"GoogleDriveLoader": GoogleDriveLoader,
"UnstructuredHTMLLoader": UnstructuredHTMLLoader,
# "BSHTMLLoader": BSHTMLLoader,
"UnstructuredPowerPointLoader": UnstructuredPowerPointLoader,
"UnstructuredWordDocumentLoader": UnstructuredWordDocumentLoader,
"UnstructuredPDFLoader": UnstructuredPDFLoader,
"UnstructuredImageLoader": UnstructuredImageLoader,
"ObsidianLoader": ObsidianLoader,
"UnstructuredEmailLoader": UnstructuredEmailLoader,
"UnstructuredMarkdownLoader": UnstructuredMarkdownLoader,
"RoamLoader": RoamLoader,
"YoutubeLoader": YoutubeLoader,
"S3FileLoader": S3FileLoader,
"TextLoader": TextLoader,
"HNLoader": HNLoader,
"GitbookLoader": GitbookLoader,
"S3DirectoryLoader": S3DirectoryLoader,
"GCSFileLoader": GCSFileLoader,
"GCSDirectoryLoader": GCSDirectoryLoader,
"WebBaseLoader": WebBaseLoader,
"IMSDbLoader": IMSDbLoader,
"AZLyricsLoader": AZLyricsLoader,
"CollegeConfidentialLoader": CollegeConfidentialLoader,
"IFixitLoader": IFixitLoader,
"GutenbergLoader": GutenbergLoader,
"PagedPDFSplitter": PagedPDFSplitter,
"PyPDFLoader": PyPDFLoader,
"EverNoteLoader": EverNoteLoader,
"AirbyteJSONLoader": AirbyteJSONLoader,
"OnlinePDFLoader": OnlinePDFLoader,
"PDFMinerLoader": PDFMinerLoader,
"PyMuPDFLoader": PyMuPDFLoader,
"TelegramChatLoader": TelegramChatLoader,
"SRTLoader": SRTLoader,
"FacebookChatLoader": FacebookChatLoader,
"NotebookLoader": NotebookLoader,
"CoNLLULoader": CoNLLULoader,
"GoogleApiYoutubeLoader": GoogleApiYoutubeLoader,
"GoogleApiClient": GoogleApiClient,
"CSVLoader": CSVLoader,
# "BlackboardLoader",
} }

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import documentloaders_type_to_cls_dict from langflow.interface.custom_lists import documentloaders_type_to_cls_dict
@ -13,7 +13,7 @@ class DocumentLoaderCreator(LangChainTypeCreator):
def type_to_loader_dict(self) -> Dict: def type_to_loader_dict(self) -> Dict:
return documentloaders_type_to_cls_dict return documentloaders_type_to_cls_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of a document loader.""" """Get the signature of a document loader."""
try: try:
return build_template_from_class(name, documentloaders_type_to_cls_dict) return build_template_from_class(name, documentloaders_type_to_cls_dict)

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import embedding_type_to_cls_dict from langflow.interface.custom_lists import embedding_type_to_cls_dict
@ -13,7 +13,7 @@ class EmbeddingCreator(LangChainTypeCreator):
def type_to_loader_dict(self) -> Dict: def type_to_loader_dict(self) -> Dict:
return embedding_type_to_cls_dict return embedding_type_to_cls_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of an embedding.""" """Get the signature of an embedding."""
try: try:
return build_template_from_class(name, embedding_type_to_cls_dict) return build_template_from_class(name, embedding_type_to_cls_dict)

View file

@ -6,9 +6,10 @@ from typing import Any
from langchain import PromptTemplate from langchain import PromptTemplate
from langchain.agents import Agent from langchain.agents import Agent
from langchain.chains.base import Chain from langchain.chains.base import Chain
from langchain.chat_models.base import BaseChatModel
from langchain.llms.base import BaseLLM from langchain.llms.base import BaseLLM
from langchain.tools import BaseTool from langchain.tools import BaseTool
from langchain.chat_models.base import BaseChatModel
from langflow.interface.tools.util import get_tool_by_name from langflow.interface.tools.util import get_tool_by_name

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import llm_type_to_cls_dict from langflow.interface.custom_lists import llm_type_to_cls_dict
@ -15,7 +15,7 @@ class LLMCreator(LangChainTypeCreator):
self.type_dict = llm_type_to_cls_dict self.type_dict = llm_type_to_cls_dict
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of an llm.""" """Get the signature of an llm."""
try: try:
return build_template_from_class(name, llm_type_to_cls_dict) return build_template_from_class(name, llm_type_to_cls_dict)

View file

@ -22,7 +22,7 @@ from langflow.interface.agents.custom import CUSTOM_AGENTS
from langflow.interface.importing.utils import import_by_type from langflow.interface.importing.utils import import_by_type
from langflow.interface.toolkits.base import toolkits_creator from langflow.interface.toolkits.base import toolkits_creator
from langflow.interface.types import get_type_list from langflow.interface.types import get_type_list
from langflow.utils import payload, util, validate from langflow.utils import util, validate
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any: def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import memory_type_to_cls_dict from langflow.interface.custom_lists import memory_type_to_cls_dict
@ -15,7 +15,7 @@ class MemoryCreator(LangChainTypeCreator):
self.type_dict = memory_type_to_cls_dict self.type_dict = memory_type_to_cls_dict
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of a memory.""" """Get the signature of a memory."""
try: try:
return build_template_from_class(name, memory_type_to_cls_dict) return build_template_from_class(name, memory_type_to_cls_dict)

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langchain.prompts import loading from langchain.prompts import loading
@ -17,7 +17,7 @@ class PromptCreator(LangChainTypeCreator):
self.type_dict = loading.type_to_loader_dict self.type_dict = loading.type_to_loader_dict
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
try: try:
if name in get_custom_nodes(self.type_name).keys(): if name in get_custom_nodes(self.type_name).keys():
return get_custom_nodes(self.type_name)[name] return get_custom_nodes(self.type_name)[name]

View file

@ -1,11 +1,11 @@
from typing import List, Optional from typing import List, Optional
from langchain.prompts import PromptTemplate from langchain.prompts import PromptTemplate
from pydantic import root_validator
from langflow.graph.utils import extract_input_variables_from_prompt from langflow.graph.utils import extract_input_variables_from_prompt
from langflow.template.base import Template, TemplateField from langflow.template.base import Template, TemplateField
from langflow.template.nodes import PromptTemplateNode from langflow.template.nodes import PromptTemplateNode
from pydantic import root_validator
CHARACTER_PROMPT = """I want you to act like {character} from {series}. CHARACTER_PROMPT = """I want you to act like {character} from {series}.
I want you to respond and answer like {character}. do not write any explanations. only answer like {character}. I want you to respond and answer like {character}. do not write any explanations. only answer like {character}.

View file

@ -1,12 +1,11 @@
import contextlib import contextlib
import io import io
import re import re
from typing import Any, Dict, List, Tuple from typing import Any, Dict
from langflow.cache.utils import compute_hash, load_cache, save_cache from langflow.cache.utils import compute_hash, load_cache, save_cache
from langflow.graph.graph import Graph from langflow.graph.graph import Graph
from langflow.interface import loading from langflow.interface import loading
from langflow.utils import payload
from langflow.utils.logger import logger from langflow.utils.logger import logger

View file

@ -1,4 +1,4 @@
from typing import Callable, Dict, List from typing import Callable, Dict, List, Optional
from langchain.agents import agent_toolkits from langchain.agents import agent_toolkits
@ -39,7 +39,7 @@ class ToolkitCreator(LangChainTypeCreator):
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
try: try:
return build_template_from_class(name, self.type_to_loader_dict) return build_template_from_class(name, self.type_to_loader_dict)
except ValueError as exc: except ValueError as exc:

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langchain.agents.load_tools import ( from langchain.agents.load_tools import (
_BASE_TOOLS, _BASE_TOOLS,
@ -10,7 +10,6 @@ from langchain.agents.load_tools import (
from langflow.custom import customs from langflow.custom import customs
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.tools.constants import ( from langflow.interface.tools.constants import (
ALL_TOOLS_NAMES,
CUSTOM_TOOLS, CUSTOM_TOOLS,
FILE_TOOLS, FILE_TOOLS,
) )
@ -60,7 +59,7 @@ TOOL_INPUTS = {
class ToolCreator(LangChainTypeCreator): class ToolCreator(LangChainTypeCreator):
type_name: str = "tools" type_name: str = "tools"
tools_dict: Dict | None = None tools_dict: Optional[Dict] = None
@property @property
def type_to_loader_dict(self) -> Dict: def type_to_loader_dict(self) -> Dict:
@ -68,7 +67,7 @@ class ToolCreator(LangChainTypeCreator):
self.tools_dict = get_tools_dict() self.tools_dict = get_tools_dict()
return self.tools_dict return self.tools_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of a tool.""" """Get the signature of a tool."""
base_classes = ["Tool"] base_classes = ["Tool"]
@ -133,8 +132,8 @@ class ToolCreator(LangChainTypeCreator):
tools = [] tools = []
for tool in ALL_TOOLS_NAMES: for tool, fcn in get_tools_dict().items():
tool_params = get_tool_params(get_tool_by_name(tool)) tool_params = get_tool_params(fcn)
if tool_params and not tool_params.get("name"): if tool_params and not tool_params.get("name"):
tool_params["name"] = tool tool_params["name"] = tool
@ -145,9 +144,7 @@ class ToolCreator(LangChainTypeCreator):
): ):
tools.append(tool_params["name"]) tools.append(tool_params["name"])
# Add Tool return tools
custom_tools = customs.get_custom_nodes("tools")
return tools + list(custom_tools.keys())
tool_creator = ToolCreator() tool_creator = ToolCreator()

View file

@ -1,11 +1,21 @@
from langchain.agents import Tool from langchain.agents import Tool
from langchain.agents.load_tools import get_all_tool_names from langchain.agents.load_tools import (
_BASE_TOOLS,
_EXTRA_LLM_TOOLS,
_EXTRA_OPTIONAL_TOOLS,
_LLM_TOOLS,
)
from langchain.tools.json.tool import JsonSpec from langchain.tools.json.tool import JsonSpec
from langflow.interface.custom.types import PythonFunction from langflow.interface.custom.types import PythonFunction
FILE_TOOLS = {"JsonSpec": JsonSpec} FILE_TOOLS = {"JsonSpec": JsonSpec}
CUSTOM_TOOLS = {"Tool": Tool, "PythonFunction": PythonFunction} CUSTOM_TOOLS = {"Tool": Tool, "PythonFunction": PythonFunction}
ALL_TOOLS_NAMES = set( ALL_TOOLS_NAMES = {
get_all_tool_names() + list(CUSTOM_TOOLS.keys()) + list(FILE_TOOLS.keys()) **_BASE_TOOLS,
) **_LLM_TOOLS, # type: ignore
**{k: v[0] for k, v in _EXTRA_LLM_TOOLS.items()}, # type: ignore
**{k: v[0] for k, v in _EXTRA_OPTIONAL_TOOLS.items()},
**CUSTOM_TOOLS,
**FILE_TOOLS, # type: ignore
}

View file

@ -2,28 +2,22 @@ import ast
import inspect import inspect
from typing import Dict, Union from typing import Dict, Union
from langchain.agents.load_tools import (
_BASE_TOOLS,
_EXTRA_LLM_TOOLS,
_EXTRA_OPTIONAL_TOOLS,
_LLM_TOOLS,
)
from langchain.agents.tools import Tool from langchain.agents.tools import Tool
from langflow.interface.tools.constants import CUSTOM_TOOLS, FILE_TOOLS from langflow.interface.tools.constants import ALL_TOOLS_NAMES
def get_tools_dict(): def get_tools_dict():
"""Get the tools dictionary.""" """Get the tools dictionary."""
return { all_tools = {}
**_BASE_TOOLS,
**_LLM_TOOLS, for tool, fcn in ALL_TOOLS_NAMES.items():
**{k: v[0] for k, v in _EXTRA_LLM_TOOLS.items()}, if tool_params := get_tool_params(fcn):
**{k: v[0] for k, v in _EXTRA_OPTIONAL_TOOLS.items()}, tool_name = tool_params.get("name") or str(tool)
**CUSTOM_TOOLS, all_tools[tool_name] = fcn
**FILE_TOOLS,
} return all_tools
def get_tool_by_name(name: str): def get_tool_by_name(name: str):

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langflow.interface.base import LangChainTypeCreator from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import vectorstores_type_to_cls_dict from langflow.interface.custom_lists import vectorstores_type_to_cls_dict
@ -13,7 +13,7 @@ class VectorstoreCreator(LangChainTypeCreator):
def type_to_loader_dict(self) -> Dict: def type_to_loader_dict(self) -> Dict:
return vectorstores_type_to_cls_dict return vectorstores_type_to_cls_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of an embedding.""" """Get the signature of an embedding."""
try: try:
return build_template_from_class(name, vectorstores_type_to_cls_dict) return build_template_from_class(name, vectorstores_type_to_cls_dict)

View file

@ -1,4 +1,4 @@
from typing import Dict, List from typing import Dict, List, Optional
from langchain import requests from langchain import requests
@ -17,7 +17,7 @@ class WrapperCreator(LangChainTypeCreator):
} }
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Optional[Dict]:
try: try:
return build_template_from_class(name, self.type_to_loader_dict) return build_template_from_class(name, self.type_to_loader_dict)
except ValueError as exc: except ValueError as exc:

View file

@ -1,9 +1,10 @@
from typing import Optional from typing import Optional
from langchain.agents import loading
from langchain.agents.mrkl import prompt from langchain.agents.mrkl import prompt
from langflow.template.base import FrontendNode, Template, TemplateField from langflow.template.base import FrontendNode, Template, TemplateField
from langflow.utils.constants import DEFAULT_PYTHON_FUNCTION from langflow.utils.constants import DEFAULT_PYTHON_FUNCTION
from langchain.agents import loading
class ZeroShotPromptNode(FrontendNode): class ZeroShotPromptNode(FrontendNode):

View file

@ -1,5 +1,6 @@
import logging import logging
from pathlib import Path from pathlib import Path
from rich.logging import RichHandler from rich.logging import RichHandler
logger = logging.getLogger("langflow") logger = logging.getLogger("langflow")

View file

@ -432,7 +432,7 @@
"placeholder": "", "placeholder": "",
"value": "---" "value": "---"
}, },
"_type": "google-serper" "_type": "Serper Search"
}, },
"name": "Serper Search", "name": "Serper Search",
"description": "A low-cost Google Search API. Useful for when you need to answer questions about current events. Input should be a search query.", "description": "A low-cost Google Search API. Useful for when you need to answer questions about current events. Input should be a search query.",

View file

@ -3,7 +3,7 @@ import tempfile
from pathlib import Path from pathlib import Path
import pytest import pytest
from langflow.cache.utils import PREFIX, compute_hash from langflow.cache.utils import PREFIX, save_cache
from langflow.interface.run import load_langchain_object from langflow.interface.run import load_langchain_object
@ -42,13 +42,15 @@ def langchain_objects_are_equal(obj1, obj2):
def test_cache_creation(basic_data_graph): def test_cache_creation(basic_data_graph):
# Compute hash for the input data_graph # Compute hash for the input data_graph
computed_hash = compute_hash(basic_data_graph)
# Call process_graph function to build and cache the langchain_object # Call process_graph function to build and cache the langchain_object
_ = load_langchain_object(basic_data_graph) is_first_message = True
computed_hash, langchain_object = load_langchain_object(
basic_data_graph, is_first_message=is_first_message
)
save_cache(computed_hash, langchain_object, is_first_message)
# Check if the cache file exists # Check if the cache file exists
cache_file = Path(tempfile.gettempdir()) / f"{PREFIX}_{computed_hash}.dill" cache_file = Path(tempfile.gettempdir()) / f"{PREFIX}_{computed_hash}.dill"
assert cache_file.exists() assert cache_file.exists()