Merge branch 'dev' into mainPage
This commit is contained in:
commit
56d0898861
33 changed files with 436 additions and 250 deletions
|
|
@ -9,7 +9,7 @@ from langflow.api.base import (
|
|||
PromptValidationResponse,
|
||||
validate_prompt,
|
||||
)
|
||||
from langflow.graph.node.types import VectorStoreNode
|
||||
from langflow.graph.vertex.types import VectorStoreVertex
|
||||
from langflow.interface.run import build_graph
|
||||
from langflow.utils.logger import logger
|
||||
from langflow.utils.validate import validate_code
|
||||
|
|
@ -49,7 +49,7 @@ def post_validate_node(node_id: str, data: dict):
|
|||
node = graph.get_node(node_id)
|
||||
if node is None:
|
||||
raise ValueError(f"Node {node_id} not found")
|
||||
if not isinstance(node, VectorStoreNode):
|
||||
if not isinstance(node, VectorStoreVertex):
|
||||
node.build()
|
||||
return json.dumps({"valid": True, "params": str(node._built_object_repr())})
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ llms:
|
|||
- LlamaCpp
|
||||
- CTransformers
|
||||
- Cohere
|
||||
- Anthropic
|
||||
- ChatAnthropic
|
||||
memories:
|
||||
- ConversationBufferMemory
|
||||
- ConversationSummaryMemory
|
||||
|
|
@ -79,7 +81,7 @@ tools:
|
|||
- Calculator
|
||||
- Serper Search
|
||||
- Tool
|
||||
- PythonFunction
|
||||
- PythonFunctionTool
|
||||
- JsonSpec
|
||||
- News API
|
||||
- TMDB API
|
||||
|
|
@ -118,6 +120,7 @@ vectorstores:
|
|||
- Chroma
|
||||
- Qdrant
|
||||
- Weaviate
|
||||
- FAISS
|
||||
wrappers:
|
||||
- RequestsWrapper
|
||||
# - ChatPromptTemplate
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from langflow.template import frontend_node
|
|||
CUSTOM_NODES = {
|
||||
"prompts": {"ZeroShotPrompt": frontend_node.prompts.ZeroShotPromptNode()},
|
||||
"tools": {
|
||||
"PythonFunction": frontend_node.tools.PythonFunctionNode(),
|
||||
"PythonFunctionTool": frontend_node.tools.PythonFunctionToolNode(),
|
||||
"Tool": frontend_node.tools.ToolNode(),
|
||||
},
|
||||
"agents": {
|
||||
|
|
|
|||
|
|
@ -1,35 +1,35 @@
|
|||
from langflow.graph.edge.base import Edge
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.node.base import Node
|
||||
from langflow.graph.node.types import (
|
||||
AgentNode,
|
||||
ChainNode,
|
||||
DocumentLoaderNode,
|
||||
EmbeddingNode,
|
||||
LLMNode,
|
||||
MemoryNode,
|
||||
PromptNode,
|
||||
TextSplitterNode,
|
||||
ToolNode,
|
||||
ToolkitNode,
|
||||
VectorStoreNode,
|
||||
WrapperNode,
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.graph.vertex.types import (
|
||||
AgentVertex,
|
||||
ChainVertex,
|
||||
DocumentLoaderVertex,
|
||||
EmbeddingVertex,
|
||||
LLMVertex,
|
||||
MemoryVertex,
|
||||
PromptVertex,
|
||||
TextSplitterVertex,
|
||||
ToolVertex,
|
||||
ToolkitVertex,
|
||||
VectorStoreVertex,
|
||||
WrapperVertex,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Graph",
|
||||
"Node",
|
||||
"Vertex",
|
||||
"Edge",
|
||||
"AgentNode",
|
||||
"ChainNode",
|
||||
"DocumentLoaderNode",
|
||||
"EmbeddingNode",
|
||||
"LLMNode",
|
||||
"MemoryNode",
|
||||
"PromptNode",
|
||||
"TextSplitterNode",
|
||||
"ToolNode",
|
||||
"ToolkitNode",
|
||||
"VectorStoreNode",
|
||||
"WrapperNode",
|
||||
"AgentVertex",
|
||||
"ChainVertex",
|
||||
"DocumentLoaderVertex",
|
||||
"EmbeddingVertex",
|
||||
"LLMVertex",
|
||||
"MemoryVertex",
|
||||
"PromptVertex",
|
||||
"TextSplitterVertex",
|
||||
"ToolVertex",
|
||||
"ToolkitVertex",
|
||||
"VectorStoreVertex",
|
||||
"WrapperVertex",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ from langflow.utils.logger import logger
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.graph.node.base import Node
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
|
||||
|
||||
class Edge:
|
||||
def __init__(self, source: "Node", target: "Node"):
|
||||
self.source: "Node" = source
|
||||
self.target: "Node" = target
|
||||
def __init__(self, source: "Vertex", target: "Vertex"):
|
||||
self.source: "Vertex" = source
|
||||
self.target: "Vertex" = target
|
||||
self.validate_edge()
|
||||
|
||||
def validate_edge(self) -> None:
|
||||
|
|
@ -41,7 +41,7 @@ class Edge:
|
|||
logger.debug(self.target_reqs)
|
||||
if no_matched_type:
|
||||
raise ValueError(
|
||||
f"Edge between {self.source.node_type} and {self.target.node_type} "
|
||||
f"Edge between {self.source.vertex_type} and {self.target.vertex_type} "
|
||||
f"has no matched type"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
from typing import Dict, List, Type, Union
|
||||
|
||||
from langflow.graph.edge.base import Edge
|
||||
from langflow.graph.graph.constants import NODE_TYPE_MAP
|
||||
from langflow.graph.node.base import Node
|
||||
from langflow.graph.node.types import (
|
||||
FileToolNode,
|
||||
LLMNode,
|
||||
ToolkitNode,
|
||||
from langflow.graph.graph.constants import VERTEX_TYPE_MAP
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.graph.vertex.types import (
|
||||
FileToolVertex,
|
||||
LLMVertex,
|
||||
ToolkitVertex,
|
||||
)
|
||||
from langflow.interface.tools.constants import FILE_TOOLS
|
||||
from langflow.utils import payload
|
||||
|
|
@ -26,7 +26,7 @@ class Graph:
|
|||
|
||||
def _build_graph(self) -> None:
|
||||
"""Builds the graph from the nodes and edges."""
|
||||
self.nodes = self._build_nodes()
|
||||
self.nodes = self._build_vertices()
|
||||
self.edges = self._build_edges()
|
||||
for edge in self.edges:
|
||||
edge.source.add_edge(edge)
|
||||
|
|
@ -43,12 +43,12 @@ class Graph:
|
|||
llm_node = None
|
||||
for node in self.nodes:
|
||||
node._build_params()
|
||||
if isinstance(node, LLMNode):
|
||||
if isinstance(node, LLMVertex):
|
||||
llm_node = node
|
||||
|
||||
if llm_node:
|
||||
for node in self.nodes:
|
||||
if isinstance(node, ToolkitNode):
|
||||
if isinstance(node, ToolkitVertex):
|
||||
node.params["llm"] = llm_node
|
||||
|
||||
def _remove_invalid_nodes(self) -> None:
|
||||
|
|
@ -60,23 +60,23 @@ class Graph:
|
|||
or (len(self.nodes) == 1 and len(self.edges) == 0)
|
||||
]
|
||||
|
||||
def _validate_node(self, node: Node) -> bool:
|
||||
def _validate_node(self, node: Vertex) -> bool:
|
||||
"""Validates a node."""
|
||||
# All nodes that do not have edges are invalid
|
||||
return len(node.edges) > 0
|
||||
|
||||
def get_node(self, node_id: str) -> Union[None, Node]:
|
||||
def get_node(self, node_id: str) -> Union[None, Vertex]:
|
||||
"""Returns a node by id."""
|
||||
return next((node for node in self.nodes if node.id == node_id), None)
|
||||
|
||||
def get_nodes_with_target(self, node: Node) -> List[Node]:
|
||||
def get_nodes_with_target(self, node: Vertex) -> List[Vertex]:
|
||||
"""Returns the nodes connected to a node."""
|
||||
connected_nodes: List[Node] = [
|
||||
connected_nodes: List[Vertex] = [
|
||||
edge.source for edge in self.edges if edge.target == node
|
||||
]
|
||||
return connected_nodes
|
||||
|
||||
def build(self) -> List[Node]:
|
||||
def build(self) -> List[Vertex]:
|
||||
"""Builds the graph."""
|
||||
# Get root node
|
||||
root_node = payload.get_root_node(self)
|
||||
|
|
@ -84,9 +84,9 @@ class Graph:
|
|||
raise ValueError("No root node found")
|
||||
return root_node.build()
|
||||
|
||||
def get_node_neighbors(self, node: Node) -> Dict[Node, int]:
|
||||
def get_node_neighbors(self, node: Vertex) -> Dict[Vertex, int]:
|
||||
"""Returns the neighbors of a node."""
|
||||
neighbors: Dict[Node, int] = {}
|
||||
neighbors: Dict[Vertex, int] = {}
|
||||
for edge in self.edges:
|
||||
if edge.source == node:
|
||||
neighbor = edge.target
|
||||
|
|
@ -117,28 +117,30 @@ class Graph:
|
|||
edges.append(Edge(source, target))
|
||||
return edges
|
||||
|
||||
def _get_node_class(self, node_type: str, node_lc_type: str) -> Type[Node]:
|
||||
def _get_vertex_class(self, node_type: str, node_lc_type: str) -> Type[Vertex]:
|
||||
"""Returns the node class based on the node type."""
|
||||
if node_type in FILE_TOOLS:
|
||||
return FileToolNode
|
||||
if node_type in NODE_TYPE_MAP:
|
||||
return NODE_TYPE_MAP[node_type]
|
||||
return NODE_TYPE_MAP[node_lc_type] if node_lc_type in NODE_TYPE_MAP else Node
|
||||
return FileToolVertex
|
||||
if node_type in VERTEX_TYPE_MAP:
|
||||
return VERTEX_TYPE_MAP[node_type]
|
||||
return (
|
||||
VERTEX_TYPE_MAP[node_lc_type] if node_lc_type in VERTEX_TYPE_MAP else Vertex
|
||||
)
|
||||
|
||||
def _build_nodes(self) -> List[Node]:
|
||||
"""Builds the nodes of the graph."""
|
||||
nodes: List[Node] = []
|
||||
def _build_vertices(self) -> List[Vertex]:
|
||||
"""Builds the vertices of the graph."""
|
||||
nodes: List[Vertex] = []
|
||||
for node in self._nodes:
|
||||
node_data = node["data"]
|
||||
node_type: str = node_data["type"] # type: ignore
|
||||
node_lc_type: str = node_data["node"]["template"]["_type"] # type: ignore
|
||||
|
||||
NodeClass = self._get_node_class(node_type, node_lc_type)
|
||||
nodes.append(NodeClass(node))
|
||||
VertexClass = self._get_vertex_class(node_type, node_lc_type)
|
||||
nodes.append(VertexClass(node))
|
||||
|
||||
return nodes
|
||||
|
||||
def get_children_by_node_type(self, node: Node, node_type: str) -> List[Node]:
|
||||
def get_children_by_node_type(self, node: Vertex, node_type: str) -> List[Vertex]:
|
||||
"""Returns the children of a node based on the node type."""
|
||||
children = []
|
||||
node_types = [node.data["type"]]
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
from langflow.graph.node.base import Node
|
||||
from langflow.graph.node.types import (
|
||||
AgentNode,
|
||||
ChainNode,
|
||||
DocumentLoaderNode,
|
||||
EmbeddingNode,
|
||||
LLMNode,
|
||||
MemoryNode,
|
||||
PromptNode,
|
||||
TextSplitterNode,
|
||||
ToolNode,
|
||||
ToolkitNode,
|
||||
VectorStoreNode,
|
||||
WrapperNode,
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.graph.vertex.types import (
|
||||
AgentVertex,
|
||||
ChainVertex,
|
||||
DocumentLoaderVertex,
|
||||
EmbeddingVertex,
|
||||
LLMVertex,
|
||||
MemoryVertex,
|
||||
PromptVertex,
|
||||
TextSplitterVertex,
|
||||
ToolVertex,
|
||||
ToolkitVertex,
|
||||
VectorStoreVertex,
|
||||
WrapperVertex,
|
||||
)
|
||||
from langflow.interface.agents.base import agent_creator
|
||||
from langflow.interface.chains.base import chain_creator
|
||||
|
|
@ -33,17 +33,17 @@ from typing import Dict, Type
|
|||
DIRECT_TYPES = ["str", "bool", "code", "int", "float", "Any", "prompt"]
|
||||
|
||||
|
||||
NODE_TYPE_MAP: Dict[str, Type[Node]] = {
|
||||
**{t: PromptNode for t in prompt_creator.to_list()},
|
||||
**{t: AgentNode for t in agent_creator.to_list()},
|
||||
**{t: ChainNode for t in chain_creator.to_list()},
|
||||
**{t: ToolNode for t in tool_creator.to_list()},
|
||||
**{t: ToolkitNode for t in toolkits_creator.to_list()},
|
||||
**{t: WrapperNode for t in wrapper_creator.to_list()},
|
||||
**{t: LLMNode for t in llm_creator.to_list()},
|
||||
**{t: MemoryNode for t in memory_creator.to_list()},
|
||||
**{t: EmbeddingNode for t in embedding_creator.to_list()},
|
||||
**{t: VectorStoreNode for t in vectorstore_creator.to_list()},
|
||||
**{t: DocumentLoaderNode for t in documentloader_creator.to_list()},
|
||||
**{t: TextSplitterNode for t in textsplitter_creator.to_list()},
|
||||
VERTEX_TYPE_MAP: Dict[str, Type[Vertex]] = {
|
||||
**{t: PromptVertex for t in prompt_creator.to_list()},
|
||||
**{t: AgentVertex for t in agent_creator.to_list()},
|
||||
**{t: ChainVertex for t in chain_creator.to_list()},
|
||||
**{t: ToolVertex for t in tool_creator.to_list()},
|
||||
**{t: ToolkitVertex for t in toolkits_creator.to_list()},
|
||||
**{t: WrapperVertex for t in wrapper_creator.to_list()},
|
||||
**{t: LLMVertex for t in llm_creator.to_list()},
|
||||
**{t: MemoryVertex for t in memory_creator.to_list()},
|
||||
**{t: EmbeddingVertex for t in embedding_creator.to_list()},
|
||||
**{t: VectorStoreVertex for t in vectorstore_creator.to_list()},
|
||||
**{t: DocumentLoaderVertex for t in documentloader_creator.to_list()},
|
||||
**{t: TextSplitterVertex for t in textsplitter_creator.to_list()},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from langflow.cache import base as cache_utils
|
||||
from langflow.graph.node.constants import DIRECT_TYPES
|
||||
from langflow.graph.vertex.constants import DIRECT_TYPES
|
||||
from langflow.interface import loading
|
||||
from langflow.interface.listing import ALL_TYPES_DICT
|
||||
from langflow.utils.logger import logger
|
||||
|
|
@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|||
from langflow.graph.edge.base import Edge
|
||||
|
||||
|
||||
class Node:
|
||||
class Vertex:
|
||||
def __init__(self, data: Dict, base_type: Optional[str] = None) -> None:
|
||||
self.id: str = data["id"]
|
||||
self._data = data
|
||||
|
|
@ -48,12 +48,12 @@ class Node:
|
|||
]
|
||||
|
||||
template_dict = self.data["node"]["template"]
|
||||
self.node_type = (
|
||||
self.vertex_type = (
|
||||
self.data["type"] if "Tool" not in self.output else template_dict["_type"]
|
||||
)
|
||||
if self.base_type is None:
|
||||
for base_type, value in ALL_TYPES_DICT.items():
|
||||
if self.node_type in value:
|
||||
if self.vertex_type in value:
|
||||
self.base_type = base_type
|
||||
break
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ class Node:
|
|||
if value["required"] and not edges:
|
||||
# If a required parameter is not found, raise an error
|
||||
raise ValueError(
|
||||
f"Required input {key} for module {self.node_type} not found"
|
||||
f"Required input {key} for module {self.vertex_type} not found"
|
||||
)
|
||||
elif value["list"]:
|
||||
# If this is a list parameter, append all sources to a list
|
||||
|
|
@ -128,7 +128,7 @@ class Node:
|
|||
# so we need to check if value has value
|
||||
new_value = value.get("value")
|
||||
if new_value is None:
|
||||
warnings.warn(f"Value for {key} in {self.node_type} is None. ")
|
||||
warnings.warn(f"Value for {key} in {self.vertex_type} is None. ")
|
||||
if value.get("type") == "int":
|
||||
with contextlib.suppress(TypeError, ValueError):
|
||||
new_value = int(new_value) # type: ignore
|
||||
|
|
@ -148,12 +148,12 @@ class Node:
|
|||
# and continue
|
||||
# Another aspect is that the node_type is the class that we need to import
|
||||
# and instantiate with these built params
|
||||
logger.debug(f"Building {self.node_type}")
|
||||
logger.debug(f"Building {self.vertex_type}")
|
||||
# Build each node in the params dict
|
||||
for key, value in self.params.copy().items():
|
||||
# Check if Node or list of Nodes and not self
|
||||
# to avoid recursion
|
||||
if isinstance(value, Node):
|
||||
if isinstance(value, Vertex):
|
||||
if value == self:
|
||||
del self.params[key]
|
||||
continue
|
||||
|
|
@ -177,7 +177,7 @@ class Node:
|
|||
|
||||
self.params[key] = result
|
||||
elif isinstance(value, list) and all(
|
||||
isinstance(node, Node) for node in value
|
||||
isinstance(node, Vertex) for node in value
|
||||
):
|
||||
self.params[key] = []
|
||||
for node in value:
|
||||
|
|
@ -193,17 +193,17 @@ class Node:
|
|||
|
||||
try:
|
||||
self._built_object = loading.instantiate_class(
|
||||
node_type=self.node_type,
|
||||
node_type=self.vertex_type,
|
||||
base_type=self.base_type,
|
||||
params=self.params,
|
||||
)
|
||||
except Exception as exc:
|
||||
raise ValueError(
|
||||
f"Error building node {self.node_type}: {str(exc)}"
|
||||
f"Error building node {self.vertex_type}: {str(exc)}"
|
||||
) from exc
|
||||
|
||||
if self._built_object is None:
|
||||
raise ValueError(f"Node type {self.node_type} not found")
|
||||
raise ValueError(f"Node type {self.vertex_type} not found")
|
||||
|
||||
self._built = True
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ class Node:
|
|||
return f"Node(id={self.id}, data={self.data})"
|
||||
|
||||
def __eq__(self, __o: object) -> bool:
|
||||
return self.id == __o.id if isinstance(__o, Node) else False
|
||||
return self.id == __o.id if isinstance(__o, Vertex) else False
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return id(self)
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from langflow.graph.node.base import Node
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.graph.utils import extract_input_variables_from_prompt
|
||||
|
||||
|
||||
class AgentNode(Node):
|
||||
class AgentVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="agents")
|
||||
|
||||
self.tools: List[ToolNode] = []
|
||||
self.chains: List[ChainNode] = []
|
||||
self.tools: List[ToolVertex] = []
|
||||
self.chains: List[ChainVertex] = []
|
||||
|
||||
def _set_tools_and_chains(self) -> None:
|
||||
for edge in self.edges:
|
||||
source_node = edge.source
|
||||
if isinstance(source_node, ToolNode):
|
||||
if isinstance(source_node, ToolVertex):
|
||||
self.tools.append(source_node)
|
||||
elif isinstance(source_node, ChainNode):
|
||||
elif isinstance(source_node, ChainVertex):
|
||||
self.chains.append(source_node)
|
||||
|
||||
def build(self, force: bool = False) -> Any:
|
||||
|
|
@ -33,24 +33,28 @@ class AgentNode(Node):
|
|||
self._build()
|
||||
|
||||
#! Cannot deepcopy VectorStore, VectorStoreRouter, or SQL agents
|
||||
if self.node_type in ["VectorStoreAgent", "VectorStoreRouterAgent", "SQLAgent"]:
|
||||
if self.vertex_type in [
|
||||
"VectorStoreAgent",
|
||||
"VectorStoreRouterAgent",
|
||||
"SQLAgent",
|
||||
]:
|
||||
return self._built_object
|
||||
return self._built_object
|
||||
|
||||
|
||||
class ToolNode(Node):
|
||||
class ToolVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="tools")
|
||||
|
||||
|
||||
class PromptNode(Node):
|
||||
class PromptVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="prompts")
|
||||
|
||||
def build(
|
||||
self,
|
||||
force: bool = False,
|
||||
tools: Optional[Union[List[Node], List[ToolNode]]] = None,
|
||||
tools: Optional[Union[List[Vertex], List[ToolVertex]]] = None,
|
||||
) -> Any:
|
||||
if not self._built or force:
|
||||
if (
|
||||
|
|
@ -59,7 +63,7 @@ class PromptNode(Node):
|
|||
):
|
||||
self.params["input_variables"] = []
|
||||
# Check if it is a ZeroShotPrompt and needs a tool
|
||||
if "ShotPrompt" in self.node_type:
|
||||
if "ShotPrompt" in self.vertex_type:
|
||||
tools = (
|
||||
[tool_node.build() for tool_node in tools]
|
||||
if tools is not None
|
||||
|
|
@ -83,31 +87,31 @@ class PromptNode(Node):
|
|||
return self._built_object
|
||||
|
||||
|
||||
class ChainNode(Node):
|
||||
class ChainVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="chains")
|
||||
|
||||
def build(
|
||||
self,
|
||||
force: bool = False,
|
||||
tools: Optional[Union[List[Node], List[ToolNode]]] = None,
|
||||
tools: Optional[Union[List[Vertex], List[ToolVertex]]] = None,
|
||||
) -> Any:
|
||||
if not self._built or force:
|
||||
# Check if the chain requires a PromptNode
|
||||
for key, value in self.params.items():
|
||||
if isinstance(value, PromptNode):
|
||||
if isinstance(value, PromptVertex):
|
||||
# Build the PromptNode, passing the tools if available
|
||||
self.params[key] = value.build(tools=tools, force=force)
|
||||
|
||||
self._build()
|
||||
|
||||
#! Cannot deepcopy SQLDatabaseChain
|
||||
if self.node_type in ["SQLDatabaseChain"]:
|
||||
if self.vertex_type in ["SQLDatabaseChain"]:
|
||||
return self._built_object
|
||||
return self._built_object
|
||||
|
||||
|
||||
class LLMNode(Node):
|
||||
class LLMVertex(Vertex):
|
||||
built_node_type = None
|
||||
class_built_object = None
|
||||
|
||||
|
|
@ -117,28 +121,28 @@ class LLMNode(Node):
|
|||
def build(self, force: bool = False) -> Any:
|
||||
# LLM is different because some models might take up too much memory
|
||||
# or time to load. So we only load them when we need them.ß
|
||||
if self.node_type == self.built_node_type:
|
||||
if self.vertex_type == self.built_node_type:
|
||||
return self.class_built_object
|
||||
if not self._built or force:
|
||||
self._build()
|
||||
self.built_node_type = self.node_type
|
||||
self.built_node_type = self.vertex_type
|
||||
self.class_built_object = self._built_object
|
||||
# Avoid deepcopying the LLM
|
||||
# that are loaded from a file
|
||||
return self._built_object
|
||||
|
||||
|
||||
class ToolkitNode(Node):
|
||||
class ToolkitVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="toolkits")
|
||||
|
||||
|
||||
class FileToolNode(ToolNode):
|
||||
class FileToolVertex(ToolVertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data)
|
||||
|
||||
|
||||
class WrapperNode(Node):
|
||||
class WrapperVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="wrappers")
|
||||
|
||||
|
|
@ -150,7 +154,7 @@ class WrapperNode(Node):
|
|||
return self._built_object
|
||||
|
||||
|
||||
class DocumentLoaderNode(Node):
|
||||
class DocumentLoaderVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="documentloaders")
|
||||
|
||||
|
|
@ -158,17 +162,17 @@ class DocumentLoaderNode(Node):
|
|||
# This built_object is a list of documents. Maybe we should
|
||||
# show how many documents are in the list?
|
||||
if self._built_object:
|
||||
return f"""{self.node_type}({len(self._built_object)} documents)
|
||||
return f"""{self.vertex_type}({len(self._built_object)} documents)
|
||||
Documents: {self._built_object[:3]}..."""
|
||||
return f"{self.node_type}()"
|
||||
return f"{self.vertex_type}()"
|
||||
|
||||
|
||||
class EmbeddingNode(Node):
|
||||
class EmbeddingVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="embeddings")
|
||||
|
||||
|
||||
class VectorStoreNode(Node):
|
||||
class VectorStoreVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="vectorstores")
|
||||
|
||||
|
|
@ -176,12 +180,12 @@ class VectorStoreNode(Node):
|
|||
return "Vector stores can take time to build. It will build on the first query."
|
||||
|
||||
|
||||
class MemoryNode(Node):
|
||||
class MemoryVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="memory")
|
||||
|
||||
|
||||
class TextSplitterNode(Node):
|
||||
class TextSplitterVertex(Vertex):
|
||||
def __init__(self, data: Dict):
|
||||
super().__init__(data, base_type="textsplitters")
|
||||
|
||||
|
|
@ -189,5 +193,6 @@ class TextSplitterNode(Node):
|
|||
# This built_object is a list of documents. Maybe we should
|
||||
# show how many documents are in the list?
|
||||
if self._built_object:
|
||||
return f"""{self.node_type}({len(self._built_object)} documents)\nDocuments: {self._built_object[:3]}..."""
|
||||
return f"{self.node_type}()"
|
||||
return f"""{self.vertex_type}({len(self._built_object)} documents)
|
||||
\nDocuments: {self._built_object[:3]}..."""
|
||||
return f"{self.vertex_type}()"
|
||||
|
|
@ -11,12 +11,14 @@ from langchain import (
|
|||
text_splitter,
|
||||
)
|
||||
from langchain.agents import agent_toolkits
|
||||
from langchain.chat_models import ChatAnthropic
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
|
||||
from langflow.interface.importing.utils import import_class
|
||||
|
||||
## LLMs
|
||||
llm_type_to_cls_dict = llms.type_to_cls_dict
|
||||
llm_type_to_cls_dict["anthropic-chat"] = ChatAnthropic # type: ignore
|
||||
llm_type_to_cls_dict["openai-chat"] = ChatOpenAI # type: ignore
|
||||
|
||||
## Chains
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from langchain.base_language import BaseLanguageModel
|
|||
from langchain.chains.base import Chain
|
||||
from langchain.chat_models.base import BaseChatModel
|
||||
from langchain.tools import BaseTool
|
||||
from langflow.utils import validate
|
||||
|
||||
|
||||
def import_module(module_path: str) -> Any:
|
||||
|
|
@ -147,3 +148,10 @@ def import_utility(utility: str) -> Any:
|
|||
if utility == "SQLDatabase":
|
||||
return import_class(f"langchain.sql_database.{utility}")
|
||||
return import_class(f"langchain.utilities.{utility}")
|
||||
|
||||
|
||||
def get_function(code):
|
||||
"""Get the function"""
|
||||
function_name = validate.extract_function_name(code)
|
||||
|
||||
return validate.create_function(code, function_name)
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ from langchain.llms.loading import load_llm_from_config
|
|||
from pydantic import ValidationError
|
||||
|
||||
from langflow.interface.agents.custom import CUSTOM_AGENTS
|
||||
from langflow.interface.importing.utils import import_by_type
|
||||
from langflow.interface.importing.utils import get_function, import_by_type
|
||||
from langflow.interface.run import fix_memory_inputs
|
||||
from langflow.interface.toolkits.base import toolkits_creator
|
||||
from langflow.interface.types import get_type_list
|
||||
from langflow.interface.utils import load_file_into_dict
|
||||
from langflow.utils import util, validate
|
||||
from langflow.utils import util
|
||||
|
||||
|
||||
def instantiate_class(node_type: str, base_type: str, params: Dict) -> Any:
|
||||
|
|
@ -100,11 +100,9 @@ def instantiate_tool(node_type, class_object, params):
|
|||
if node_type == "JsonSpec":
|
||||
params["dict_"] = load_file_into_dict(params.pop("path"))
|
||||
return class_object(**params)
|
||||
elif node_type == "PythonFunction":
|
||||
function_string = params["code"]
|
||||
if isinstance(function_string, str):
|
||||
return validate.eval_function(function_string)
|
||||
raise ValueError("Function should be a string")
|
||||
elif node_type == "PythonFunctionTool":
|
||||
params["func"] = get_function(params.get("code"))
|
||||
return class_object(**params)
|
||||
elif node_type.lower() == "tool":
|
||||
return class_object(**params)
|
||||
return class_object(**params)
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ class ToolCreator(LangChainTypeCreator):
|
|||
|
||||
for tool, tool_fcn in ALL_TOOLS_NAMES.items():
|
||||
tool_params = get_tool_params(tool_fcn)
|
||||
tool_name = tool_params.get("name", tool)
|
||||
|
||||
tool_name = tool_params.get("name") or tool
|
||||
|
||||
if tool_name in settings.tools or settings.dev:
|
||||
if tool_name == "JsonSpec":
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ from langchain.agents.load_tools import (
|
|||
from langchain.tools.json.tool import JsonSpec
|
||||
|
||||
from langflow.interface.importing.utils import import_class
|
||||
from langflow.interface.tools.custom import PythonFunction
|
||||
from langflow.interface.tools.custom import PythonFunctionTool
|
||||
|
||||
FILE_TOOLS = {"JsonSpec": JsonSpec}
|
||||
CUSTOM_TOOLS = {"Tool": Tool, "PythonFunction": PythonFunction}
|
||||
CUSTOM_TOOLS = {"Tool": Tool, "PythonFunctionTool": PythonFunctionTool}
|
||||
|
||||
OTHER_TOOLS = {tool: import_class(f"langchain.tools.{tool}") for tool in tools.__all__}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
from typing import Callable, Optional
|
||||
from typing import Optional
|
||||
from langflow.interface.importing.utils import get_function
|
||||
|
||||
from pydantic import BaseModel, validator
|
||||
|
||||
from langflow.utils import validate
|
||||
from langchain.agents.tools import Tool
|
||||
|
||||
|
||||
class Function(BaseModel):
|
||||
code: str
|
||||
function: Optional[Callable] = None
|
||||
imports: Optional[str] = None
|
||||
|
||||
# Eval code and store the function
|
||||
|
|
@ -24,14 +25,17 @@ class Function(BaseModel):
|
|||
|
||||
return v
|
||||
|
||||
def get_function(self):
|
||||
"""Get the function"""
|
||||
function_name = validate.extract_function_name(self.code)
|
||||
|
||||
return validate.create_function(self.code, function_name)
|
||||
|
||||
|
||||
class PythonFunction(Function):
|
||||
class PythonFunctionTool(Function, Tool):
|
||||
"""Python function"""
|
||||
|
||||
name: str = "Custom Tool"
|
||||
description: str
|
||||
code: str
|
||||
|
||||
def ___init__(self, name: str, description: str, code: str):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.code = code
|
||||
self.func = get_function(self.code)
|
||||
super().__init__(name=name, description=description, func=self.func)
|
||||
|
|
|
|||
|
|
@ -125,6 +125,9 @@ class FrontendNode(BaseModel):
|
|||
elif name == "ChatOpenAI" and key == "model_name":
|
||||
field.options = constants.CHAT_OPENAI_MODELS
|
||||
field.is_list = True
|
||||
elif (name == "Anthropic" or name == "ChatAnthropic") and key == "model_name":
|
||||
field.options = constants.ANTHROPIC_MODELS
|
||||
field.is_list = True
|
||||
if "api_key" in key and "OpenAI" in str(name):
|
||||
field.display_name = "OpenAI API Key"
|
||||
field.required = False
|
||||
|
|
|
|||
|
|
@ -59,11 +59,33 @@ class ToolNode(FrontendNode):
|
|||
return super().to_dict()
|
||||
|
||||
|
||||
class PythonFunctionNode(FrontendNode):
|
||||
name: str = "PythonFunction"
|
||||
class PythonFunctionToolNode(FrontendNode):
|
||||
name: str = "PythonFunctionTool"
|
||||
template: Template = Template(
|
||||
type_name="python_function",
|
||||
type_name="PythonFunctionTool",
|
||||
fields=[
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
multiline=False,
|
||||
value="",
|
||||
name="name",
|
||||
advanced=False,
|
||||
),
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
multiline=False,
|
||||
value="",
|
||||
name="description",
|
||||
advanced=False,
|
||||
),
|
||||
TemplateField(
|
||||
field_type="code",
|
||||
required=True,
|
||||
|
|
@ -73,11 +95,11 @@ class PythonFunctionNode(FrontendNode):
|
|||
value=DEFAULT_PYTHON_FUNCTION,
|
||||
name="code",
|
||||
advanced=False,
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
description: str = "Python function to be executed."
|
||||
base_classes: list[str] = ["function"]
|
||||
base_classes: list[str] = ["Tool"]
|
||||
|
||||
def to_dict(self):
|
||||
return super().to_dict()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,20 @@ OPENAI_MODELS = [
|
|||
]
|
||||
CHAT_OPENAI_MODELS = ["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]
|
||||
|
||||
ANTHROPIC_MODELS = [
|
||||
"claude-v1", # largest model, ideal for a wide range of more complex tasks.
|
||||
"claude-v1-100k", # An enhanced version of claude-v1 with a 100,000 token (roughly 75,000 word) context window.
|
||||
"claude-instant-v1", # A smaller model with far lower latency, sampling at roughly 40 words/sec!
|
||||
"claude-instant-v1-100k", # Like claude-instant-v1 with a 100,000 token context window but retains its performance.
|
||||
# Specific sub-versions of the above models:
|
||||
"claude-v1.3", # Vs claude-v1.2: better instruction-following, code, and non-English dialogue and writing.
|
||||
"claude-v1.3-100k", # An enhanced version of claude-v1.3 with a 100,000 token (roughly 75,000 word) context window.
|
||||
"claude-v1.2", # Vs claude-v1.1: small adv in general helpfulness, instruction following, coding, and other tasks.
|
||||
"claude-v1.0", # An earlier version of claude-v1.
|
||||
"claude-instant-v1.1", # Latest version of claude-instant-v1. Better than claude-instant-v1.0 at most tasks.
|
||||
"claude-instant-v1.1-100k", # Version of claude-instant-v1.1 with a 100K token context window.
|
||||
"claude-instant-v1.0", # An earlier version of claude-instant-v1.
|
||||
]
|
||||
|
||||
DEFAULT_PYTHON_FUNCTION = """
|
||||
def python_function(text: str) -> str:
|
||||
|
|
|
|||
|
|
@ -302,7 +302,9 @@ def format_dict(d, name: Optional[str] = None):
|
|||
elif name == "ChatOpenAI" and key == "model_name":
|
||||
value["options"] = constants.CHAT_OPENAI_MODELS
|
||||
value["list"] = True
|
||||
|
||||
elif (name == "Anthropic" or name == "ChatAnthropic") and key == "model_name":
|
||||
value["options"] = constants.ANTHROPIC_MODELS
|
||||
value["list"] = True
|
||||
return d
|
||||
|
||||
|
||||
|
|
|
|||
9
src/frontend/src/icons/Anthropic/anthropic.svg
Normal file
9
src/frontend/src/icons/Anthropic/anthropic.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="-170.333 113.047 600 67.4" width="600" height="67.4">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
.st0{fill:#1F1F1E;}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="st0" d="M -23.533 126.747 L -1.633 126.747 L -1.633 179.347 L 12.367 179.347 L 12.367 126.747 L 34.267 126.747 L 34.267 114.147 L -23.533 114.147 L -23.533 126.747 Z M -48.133 159.747 L -77.433 114.147 L -93.233 114.147 L -93.233 179.247 L -79.733 179.247 L -79.733 133.647 L -50.433 179.347 L -34.633 179.347 L -34.633 114.247 L -48.133 114.247 L -48.133 159.747 Z M 90.067 140.147 L 59.367 140.147 L 59.367 114.147 L 45.367 114.147 L 45.367 179.247 L 59.367 179.247 L 59.367 152.647 L 90.067 152.647 L 90.067 179.247 L 104.067 179.247 L 104.067 114.147 L 90.067 114.147 L 90.067 140.147 Z M -144.333 114.147 L -170.333 179.247 L -155.833 179.247 L -150.533 165.547 L -123.333 165.547 L -118.033 179.247 L -103.533 179.247 L -129.533 114.147 L -144.333 114.147 Z M -145.833 153.547 L -136.933 130.647 L -128.033 153.547 L -145.833 153.547 Z M 219.667 113.047 C 200.867 113.047 187.567 127.047 187.567 146.847 C 187.567 166.447 200.867 180.447 219.667 180.447 C 238.367 180.447 251.567 166.447 251.567 146.847 C 251.567 127.047 238.367 113.047 219.667 113.047 Z M 219.667 167.447 C 208.667 167.447 201.967 159.647 201.967 146.847 C 201.967 133.947 208.667 126.047 219.667 126.047 C 230.567 126.047 237.167 133.847 237.167 146.847 C 237.167 159.547 230.567 167.447 219.667 167.447 Z M 414.767 157.447 C 412.367 163.747 407.467 167.447 400.867 167.447 C 389.867 167.447 383.167 159.647 383.167 146.847 C 383.167 133.947 389.867 126.047 400.867 126.047 C 407.467 126.047 412.267 129.647 414.767 136.047 L 429.567 136.047 C 425.967 122.047 415.067 113.047 400.867 113.047 C 382.067 113.047 368.767 127.047 368.767 146.847 C 368.767 166.447 382.067 180.447 400.867 180.447 C 415.067 180.447 425.967 171.347 429.667 157.447 L 414.767 157.447 Z M 325.867 114.147 L 351.867 179.247 L 366.067 179.247 L 340.067 114.147 L 325.867 114.147 Z M 296.367 114.147 L 264.567 114.147 L 264.567 179.247 L 278.567 179.247 L 278.567 155.647 L 296.467 155.647 C 311.267 155.647 320.267 147.847 320.267 134.847 C 320.267 121.947 311.167 114.147 296.367 114.147 Z M 295.767 143.147 L 278.567 143.147 L 278.567 126.747 L 295.767 126.747 C 302.667 126.747 306.267 129.547 306.267 134.947 C 306.267 140.347 302.667 143.147 295.767 143.147 Z M 176.867 134.047 C 176.867 121.747 167.867 114.247 153.067 114.247 L 121.267 114.247 L 121.267 179.347 L 135.267 179.347 L 135.267 153.847 L 150.767 153.847 L 164.767 179.347 L 180.167 179.347 L 164.667 151.947 C 172.367 148.847 176.867 142.647 176.867 134.047 Z M 135.167 126.747 L 152.367 126.747 C 159.267 126.747 162.867 129.247 162.867 134.047 C 162.867 138.747 159.267 141.347 152.367 141.347 L 135.167 141.347 L 135.167 126.747 Z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
11
src/frontend/src/icons/Anthropic/anthropic_box.svg
Normal file
11
src/frontend/src/icons/Anthropic/anthropic_box.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="-126.9 247.9 207.161 212.728" width="207.161" height="212.728">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
.st0{fill:#1F1F1E;}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="st0" d="M 19.9 260.5 L 41.8 260.5 L 41.8 313.1 L 55.8 313.1 L 55.8 260.5 L 77.7 260.5 L 77.7 247.9 L 19.9 247.9 L 19.9 260.5 Z M -4.7 293.5 L -34 247.9 L -49.8 247.9 L -49.8 313 L -36.3 313 L -36.3 267.4 L -7 313.1 L 8.8 313.1 L 8.8 248 L -4.7 248 L -4.7 293.5 Z M -100.9 247.9 L -126.9 313 L -112.4 313 L -107.1 299.3 L -79.9 299.3 L -74.6 313 L -60.1 313 L -86.1 247.9 L -100.9 247.9 Z M -102.4 287.3 L -93.5 264.4 L -84.6 287.3 L -102.4 287.3 Z"></path>
|
||||
<path class="st0" d="M 38.246 437.628 C 35.846 443.928 30.946 447.628 24.346 447.628 C 13.346 447.628 6.646 439.828 6.646 427.028 C 6.646 414.128 13.346 406.228 24.346 406.228 C 30.946 406.228 35.746 409.828 38.246 416.228 L 53.046 416.228 C 49.446 402.228 38.546 393.228 24.346 393.228 C 5.546 393.228 -7.754 407.228 -7.754 427.028 C -7.754 446.628 5.546 460.628 24.346 460.628 C 38.546 460.628 49.446 451.528 53.146 437.628 L 38.246 437.628 Z M -50.654 394.328 L -24.654 459.428 L -10.454 459.428 L -36.454 394.328 L -50.654 394.328 Z M -80.154 394.328 L -111.954 394.328 L -111.954 459.428 L -97.954 459.428 L -97.954 435.828 L -80.054 435.828 C -65.254 435.828 -56.254 428.028 -56.254 415.028 C -56.254 402.128 -65.354 394.328 -80.154 394.328 Z M -80.754 423.328 L -97.954 423.328 L -97.954 406.928 L -80.754 406.928 C -73.854 406.928 -70.254 409.728 -70.254 415.128 C -70.254 420.528 -73.854 423.328 -80.754 423.328 Z"></path>
|
||||
<path class="st0" d="M -81.239 347.704 L -111.939 347.704 L -111.939 321.704 L -125.939 321.704 L -125.939 386.804 L -111.939 386.804 L -111.939 360.204 L -81.239 360.204 L -81.239 386.804 L -67.239 386.804 L -67.239 321.704 L -81.239 321.704 L -81.239 347.704 Z M 48.361 320.604 C 29.561 320.604 16.261 334.604 16.261 354.404 C 16.261 374.004 29.561 388.004 48.361 388.004 C 67.061 388.004 80.261 374.004 80.261 354.404 C 80.261 334.604 67.061 320.604 48.361 320.604 Z M 48.361 375.004 C 37.361 375.004 30.661 367.204 30.661 354.404 C 30.661 341.504 37.361 333.604 48.361 333.604 C 59.261 333.604 65.861 341.404 65.861 354.404 C 65.861 367.104 59.261 375.004 48.361 375.004 Z M 5.561 341.604 C 5.561 329.304 -3.439 321.804 -18.239 321.804 L -50.039 321.804 L -50.039 386.904 L -36.039 386.904 L -36.039 361.404 L -20.539 361.404 L -6.539 386.904 L 8.861 386.904 L -6.639 359.504 C 1.061 356.404 5.561 350.204 5.561 341.604 Z M -36.139 334.304 L -18.939 334.304 C -12.039 334.304 -8.439 336.804 -8.439 341.604 C -8.439 346.304 -12.039 348.904 -18.939 348.904 L -36.139 348.904 L -36.139 334.304 Z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
9
src/frontend/src/icons/Anthropic/index.tsx
Normal file
9
src/frontend/src/icons/Anthropic/index.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import { ReactComponent as AnthropicSVG } from "./anthropic_box.svg";
|
||||
|
||||
export const AnthropicIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <AnthropicSVG ref={ref} {...props} />;
|
||||
});
|
||||
|
|
@ -5,6 +5,7 @@ import { DisclosureComponentType } from "../../../../types/components";
|
|||
export default function DisclosureComponent({
|
||||
button: { title, Icon, buttons = [] },
|
||||
children,
|
||||
openDisc,
|
||||
}: DisclosureComponentType) {
|
||||
return (
|
||||
<Disclosure as="div" key={title}>
|
||||
|
|
@ -27,14 +28,14 @@ export default function DisclosureComponent({
|
|||
<div>
|
||||
<ChevronRightIcon
|
||||
className={`${
|
||||
open ? "rotate-90 transform" : ""
|
||||
open || openDisc ? "rotate-90 transform" : ""
|
||||
} h-4 w-4 text-gray-800 dark:text-white`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
</div>
|
||||
<Disclosure.Panel as="div" className="-mt-px">
|
||||
<Disclosure.Panel as="div" className="-mt-px" static={openDisc}>
|
||||
{children}
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
|||
export default function ExtraSidebar() {
|
||||
const { data } = useContext(typesContext);
|
||||
const [dataFilter, setFilterData] = useState(data);
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
function onDragStart(
|
||||
event: React.DragEvent<any>,
|
||||
|
|
@ -58,6 +59,7 @@ export default function ExtraSidebar() {
|
|||
className="dark:text-white focus:outline-none block w-full rounded-md py-1.5 ps-3 pr-9 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 sm:text-sm sm:leading-6 dark:ring-0 dark:bg-[#2d3747] dark:focus:outline-none"
|
||||
onChange={(e) => {
|
||||
handleSearchInput(e.target.value);
|
||||
setSearch(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<div className="absolute inset-y-0 right-0 flex py-1.5 pr-3 items-center">
|
||||
|
|
@ -71,6 +73,7 @@ export default function ExtraSidebar() {
|
|||
.map((d: keyof APIObjectType, i) =>
|
||||
Object.keys(dataFilter[d]).length > 0 ? (
|
||||
<DisclosureComponent
|
||||
openDisc={search.length == 0 ? false : true}
|
||||
key={i}
|
||||
button={{
|
||||
title: nodeNames[d] ?? nodeNames.unknown,
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ export type FileComponentType = {
|
|||
|
||||
export type DisclosureComponentType = {
|
||||
children: ReactNode;
|
||||
openDisc: boolean;
|
||||
button: {
|
||||
title: string;
|
||||
Icon: ForwardRefExoticComponent<React.SVGProps<SVGSVGElement>>;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { FlowType, NodeType } from "./types/flow";
|
|||
import { APITemplateType, TemplateVariableType } from "./types/api";
|
||||
import _ from "lodash";
|
||||
import { ChromaIcon } from "./icons/ChromaIcon";
|
||||
import { AnthropicIcon } from "./icons/Anthropic";
|
||||
import { AirbyteIcon } from "./icons/Airbyte";
|
||||
import { AzIcon } from "./icons/AzLogo";
|
||||
import { BingIcon } from "./icons/Bing";
|
||||
|
|
@ -155,6 +156,8 @@ export const nodeIcons: {
|
|||
AirbyteJSONLoader: AirbyteIcon,
|
||||
// SerpAPIWrapper: SerperIcon,
|
||||
// AZLyricsLoader: AzIcon,
|
||||
Anthropic: AnthropicIcon,
|
||||
ChatAnthropic: AnthropicIcon,
|
||||
BingSearchAPIWrapper: BingIcon,
|
||||
BingSearchRun: BingIcon,
|
||||
Cohere: CohereIcon,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue