Merge branch 'python_custom_node_component' of personal:logspace-ai/langflow into python_custom_node_component
This commit is contained in:
commit
8fe7cd3472
9 changed files with 144 additions and 26 deletions
|
|
@ -71,10 +71,14 @@ class ClassCodeExtractor:
|
||||||
self.function_entrypoint_name), None
|
self.function_entrypoint_name), None
|
||||||
)
|
)
|
||||||
|
|
||||||
funtion_args = build_function.get("arguments", None)
|
if build_function:
|
||||||
|
function_args = build_function.get("arguments", None)
|
||||||
return_type = build_function.get("return_type", None)
|
return_type = build_function.get("return_type", None)
|
||||||
|
else:
|
||||||
|
function_args = None
|
||||||
|
return_type = None
|
||||||
|
|
||||||
return funtion_args, return_type
|
return function_args, return_type
|
||||||
|
|
||||||
|
|
||||||
def is_valid_class_template(code: dict):
|
def is_valid_class_template(code: dict):
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ tools:
|
||||||
- Calculator
|
- Calculator
|
||||||
- Serper Search
|
- Serper Search
|
||||||
- Tool
|
- Tool
|
||||||
|
- CustomComponent
|
||||||
- PythonFunctionTool
|
- PythonFunctionTool
|
||||||
- PythonFunction
|
- PythonFunction
|
||||||
- JsonSpec
|
- JsonSpec
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ CUSTOM_NODES = {
|
||||||
"tools": {
|
"tools": {
|
||||||
"PythonFunctionTool": frontend_node.tools.PythonFunctionToolNode(),
|
"PythonFunctionTool": frontend_node.tools.PythonFunctionToolNode(),
|
||||||
"PythonFunction": frontend_node.tools.PythonFunctionNode(),
|
"PythonFunction": frontend_node.tools.PythonFunctionNode(),
|
||||||
|
"CustomComponent": frontend_node.tools.CustomComponentNode(),
|
||||||
"Tool": frontend_node.tools.ToolNode(),
|
"Tool": frontend_node.tools.ToolNode(),
|
||||||
},
|
},
|
||||||
"agents": {
|
"agents": {
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ def instantiate_tool(node_type, class_object, params):
|
||||||
if node_type == "JsonSpec":
|
if node_type == "JsonSpec":
|
||||||
params["dict_"] = load_file_into_dict(params.pop("path"))
|
params["dict_"] = load_file_into_dict(params.pop("path"))
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
elif node_type == "PythonFunctionTool":
|
elif node_type in ["PythonFunctionTool", "CustomComponent"]:
|
||||||
params["func"] = get_function(params.get("code"))
|
params["func"] = get_function(params.get("code"))
|
||||||
return class_object(**params)
|
return class_object(**params)
|
||||||
# For backward compatibility
|
# For backward compatibility
|
||||||
|
|
@ -243,7 +243,8 @@ def replace_zero_shot_prompt_with_prompt_template(nodes):
|
||||||
if tool["type"] != "chatOutputNode"
|
if tool["type"] != "chatOutputNode"
|
||||||
and "Tool" in tool["data"]["node"]["base_classes"]
|
and "Tool" in tool["data"]["node"]["base_classes"]
|
||||||
]
|
]
|
||||||
node["data"] = build_prompt_template(prompt=node["data"], tools=tools)
|
node["data"] = build_prompt_template(
|
||||||
|
prompt=node["data"], tools=tools)
|
||||||
break
|
break
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
|
@ -260,7 +261,8 @@ def load_agent_executor(agent_class: type[agent_module.Agent], params, **kwargs)
|
||||||
tool_names = [tool.name for tool in allowed_tools]
|
tool_names = [tool.name for tool in allowed_tools]
|
||||||
# Agent class requires an output_parser but Agent classes
|
# Agent class requires an output_parser but Agent classes
|
||||||
# have a default output_parser.
|
# have a default output_parser.
|
||||||
agent = agent_class(allowed_tools=tool_names, llm_chain=llm_chain) # type: ignore
|
agent = agent_class(allowed_tools=tool_names,
|
||||||
|
llm_chain=llm_chain) # type: ignore
|
||||||
return AgentExecutor.from_agent_and_tools(
|
return AgentExecutor.from_agent_and_tools(
|
||||||
agent=agent,
|
agent=agent,
|
||||||
tools=allowed_tools,
|
tools=allowed_tools,
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,22 @@ from langchain.agents.load_tools import (
|
||||||
from langchain.tools.json.tool import JsonSpec
|
from langchain.tools.json.tool import JsonSpec
|
||||||
|
|
||||||
from langflow.interface.importing.utils import import_class
|
from langflow.interface.importing.utils import import_class
|
||||||
from langflow.interface.tools.custom import PythonFunctionTool, PythonFunction
|
from langflow.interface.tools.custom import (
|
||||||
|
PythonFunctionTool,
|
||||||
|
PythonFunction,
|
||||||
|
CustomComponent
|
||||||
|
)
|
||||||
|
|
||||||
FILE_TOOLS = {"JsonSpec": JsonSpec}
|
FILE_TOOLS = {"JsonSpec": JsonSpec}
|
||||||
CUSTOM_TOOLS = {
|
CUSTOM_TOOLS = {
|
||||||
"Tool": Tool,
|
"Tool": Tool,
|
||||||
|
"CustomComponent": CustomComponent,
|
||||||
"PythonFunctionTool": PythonFunctionTool,
|
"PythonFunctionTool": PythonFunctionTool,
|
||||||
"PythonFunction": PythonFunction,
|
"PythonFunction": PythonFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
OTHER_TOOLS = {tool: import_class(f"langchain.tools.{tool}") for tool in tools.__all__}
|
OTHER_TOOLS = {tool: import_class(f"langchain.tools.{tool}")
|
||||||
|
for tool in tools.__all__}
|
||||||
|
|
||||||
ALL_TOOLS_NAMES = {
|
ALL_TOOLS_NAMES = {
|
||||||
**_BASE_TOOLS,
|
**_BASE_TOOLS,
|
||||||
|
|
|
||||||
|
|
@ -52,3 +52,9 @@ class PythonFunction(Function):
|
||||||
"""Python function"""
|
"""Python function"""
|
||||||
|
|
||||||
code: str
|
code: str
|
||||||
|
|
||||||
|
|
||||||
|
class CustomComponent(Function):
|
||||||
|
"""Python function"""
|
||||||
|
|
||||||
|
code: str
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ from langflow.interface.utilities.base import utility_creator
|
||||||
from langflow.interface.vector_store.base import vectorstore_creator
|
from langflow.interface.vector_store.base import vectorstore_creator
|
||||||
from langflow.interface.wrappers.base import wrapper_creator
|
from langflow.interface.wrappers.base import wrapper_creator
|
||||||
|
|
||||||
|
from langflow.template.field.base import TemplateField
|
||||||
|
from langflow.template.frontend_node.tools import CustomComponentNode
|
||||||
|
|
||||||
|
|
||||||
def get_type_list():
|
def get_type_list():
|
||||||
"""Get a list of all langchain types"""
|
"""Get a list of all langchain types"""
|
||||||
|
|
@ -54,6 +57,7 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union
|
||||||
return all_types
|
return all_types
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Move to correct place
|
||||||
def find_class_type(class_name, classes_dict):
|
def find_class_type(class_name, classes_dict):
|
||||||
return next(
|
return next(
|
||||||
(
|
(
|
||||||
|
|
@ -65,10 +69,23 @@ def find_class_type(class_name, classes_dict):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_langchain_template_custom_component(raw_code, function_args, function_return_type):
|
# TODO: Move to correct place
|
||||||
type_list = get_type_list()
|
def add_new_custom_field(template, field_name: str, field_type: str):
|
||||||
type_and_class = find_class_type("Tool", type_list)
|
new_field = TemplateField(
|
||||||
|
name=field_name,
|
||||||
|
field_type=field_type,
|
||||||
|
show=True,
|
||||||
|
advanced=False
|
||||||
|
)
|
||||||
|
template.get('template')[field_name] = new_field.to_dict()
|
||||||
|
template.get('custom_fields').append(field_name)
|
||||||
|
|
||||||
|
return template
|
||||||
|
|
||||||
|
# TODO: Move to correct place
|
||||||
|
|
||||||
|
|
||||||
|
def add_code_field(template, raw_code):
|
||||||
# Field with the Python code to allow update
|
# Field with the Python code to allow update
|
||||||
code_field = {
|
code_field = {
|
||||||
"code": {
|
"code": {
|
||||||
|
|
@ -84,13 +101,47 @@ def build_langchain_template_custom_component(raw_code, function_args, function_
|
||||||
"list": False
|
"list": False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template.get('template')['code'] = code_field.get('code')
|
||||||
|
|
||||||
|
return template
|
||||||
|
|
||||||
|
|
||||||
|
def build_langchain_template_custom_component(raw_code, function_args, function_return_type):
|
||||||
|
# type_list = get_type_list()
|
||||||
|
# type_and_class = find_class_type("Tool", type_list)
|
||||||
|
# node = get_custom_nodes(node_type: str)
|
||||||
|
|
||||||
|
# TODO: Build base template
|
||||||
|
template = llm_creator.to_dict()['llms']['ChatOpenAI']
|
||||||
|
|
||||||
|
template = CustomComponentNode().to_dict().get('CustomComponent')
|
||||||
|
|
||||||
# TODO: Add extra fields
|
# TODO: Add extra fields
|
||||||
|
template = add_new_custom_field(
|
||||||
|
template,
|
||||||
|
"my_id",
|
||||||
|
"str"
|
||||||
|
)
|
||||||
|
|
||||||
# TODO: Build template result
|
template = add_new_custom_field(
|
||||||
template = chain_creator.to_dict()['chains']['ConversationChain']
|
template,
|
||||||
|
"year",
|
||||||
|
"int"
|
||||||
|
)
|
||||||
|
|
||||||
template.get('template')['code'] = code_field.get('code')
|
template = add_new_custom_field(
|
||||||
|
template,
|
||||||
|
"other_field",
|
||||||
|
"bool"
|
||||||
|
)
|
||||||
|
|
||||||
|
template = add_code_field(
|
||||||
|
template,
|
||||||
|
raw_code
|
||||||
|
)
|
||||||
|
|
||||||
|
# criar um vertex
|
||||||
|
# olhar loading.py
|
||||||
|
|
||||||
return template
|
return template
|
||||||
# return globals()['tool_creator'].to_dict()[type_and_class['type']][type_and_class['class']]
|
# return globals()['tool_creator'].to_dict()[type_and_class['type']][type_and_class['class']]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.base import FrontendNode
|
from langflow.template.frontend_node.base import FrontendNode
|
||||||
from langflow.template.template.base import Template
|
from langflow.template.template.base import Template
|
||||||
from langflow.utils.constants import DEFAULT_PYTHON_FUNCTION
|
from langflow.utils.constants import (
|
||||||
|
DEFAULT_PYTHON_FUNCTION,
|
||||||
|
DEFAULT_CUSTOM_COMPONENT_CODE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ToolNode(FrontendNode):
|
class ToolNode(FrontendNode):
|
||||||
|
|
@ -137,3 +140,27 @@ class PythonFunctionNode(FrontendNode):
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return super().to_dict()
|
return super().to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
class CustomComponentNode(FrontendNode):
|
||||||
|
name: str = "CustomComponent"
|
||||||
|
template: Template = Template(
|
||||||
|
type_name="CustomComponent",
|
||||||
|
fields=[
|
||||||
|
TemplateField(
|
||||||
|
field_type="code",
|
||||||
|
required=True,
|
||||||
|
placeholder="",
|
||||||
|
is_list=False,
|
||||||
|
show=True,
|
||||||
|
value=DEFAULT_CUSTOM_COMPONENT_CODE,
|
||||||
|
name="code",
|
||||||
|
advanced=False,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
description: str = "Python Class to be executed."
|
||||||
|
base_classes: list[str] = []
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return super().to_dict()
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,30 @@ CHAT_OPENAI_MODELS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
ANTHROPIC_MODELS = [
|
ANTHROPIC_MODELS = [
|
||||||
"claude-v1", # largest model, ideal for a wide range of more complex tasks.
|
# 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-v1",
|
||||||
"claude-instant-v1", # A smaller model with far lower latency, sampling at roughly 40 words/sec!
|
# An enhanced version of claude-v1 with a 100,000 token (roughly 75,000 word) context window.
|
||||||
"claude-instant-v1-100k", # Like claude-instant-v1 with a 100,000 token context window but retains its performance.
|
"claude-v1-100k",
|
||||||
|
# A smaller model with far lower latency, sampling at roughly 40 words/sec!
|
||||||
|
"claude-instant-v1",
|
||||||
|
# Like claude-instant-v1 with a 100,000 token context window but retains its performance.
|
||||||
|
"claude-instant-v1-100k",
|
||||||
|
|
||||||
# Specific sub-versions of the above models:
|
# Specific sub-versions of the above models:
|
||||||
"claude-v1.3", # Vs claude-v1.2: better instruction-following, code, and non-English dialogue and writing.
|
# 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.3",
|
||||||
"claude-v1.2", # Vs claude-v1.1: small adv in general helpfulness, instruction following, coding, and other tasks.
|
# An enhanced version of claude-v1.3 with a 100,000 token (roughly 75,000 word) context window.
|
||||||
"claude-v1.0", # An earlier version of claude-v1.
|
"claude-v1.3-100k",
|
||||||
"claude-instant-v1.1", # Latest version of claude-instant-v1. Better than claude-instant-v1.0 at most tasks.
|
# Vs claude-v1.1: small adv in general helpfulness, instruction following, coding, and other tasks.
|
||||||
"claude-instant-v1.1-100k", # Version of claude-instant-v1.1 with a 100K token context window.
|
"claude-v1.2",
|
||||||
"claude-instant-v1.0", # An earlier version of claude-instant-v1.
|
# An earlier version of claude-v1.
|
||||||
|
"claude-v1.0",
|
||||||
|
# Latest version of claude-instant-v1. Better than claude-instant-v1.0 at most tasks.
|
||||||
|
"claude-instant-v1.1",
|
||||||
|
# Version of claude-instant-v1.1 with a 100K token context window.
|
||||||
|
"claude-instant-v1.1-100k",
|
||||||
|
# An earlier version of claude-instant-v1.
|
||||||
|
"claude-instant-v1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
DEFAULT_PYTHON_FUNCTION = """
|
DEFAULT_PYTHON_FUNCTION = """
|
||||||
|
|
@ -36,4 +48,12 @@ def python_function(text: str) -> str:
|
||||||
\"\"\"This is a default python function that returns the input text\"\"\"
|
\"\"\"This is a default python function that returns the input text\"\"\"
|
||||||
return text
|
return text
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
DEFAULT_CUSTOM_COMPONENT_CODE = """
|
||||||
|
def custom_component(text: str) -> str:
|
||||||
|
\"\"\"This is a default custom component function that returns the input text\"\"\"
|
||||||
|
\"\"\"TODO: Add a Class template\"\"\"
|
||||||
|
return text
|
||||||
|
"""
|
||||||
|
|
||||||
DIRECT_TYPES = ["str", "bool", "code", "int", "float", "Any", "prompt"]
|
DIRECT_TYPES = ["str", "bool", "code", "int", "float", "Any", "prompt"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue