feat: jsonagent

This commit is contained in:
Gabriel Almeida 2023-03-30 08:48:41 -03:00
commit 22c3c83d6a
7 changed files with 80 additions and 4 deletions

View file

@ -4,6 +4,7 @@ from langflow.template import nodes
CUSTOM_NODES = { CUSTOM_NODES = {
"prompts": {**nodes.ZeroShotPromptNode().to_dict()}, "prompts": {**nodes.ZeroShotPromptNode().to_dict()},
"tools": {**nodes.PythonFunctionNode().to_dict(), **nodes.ToolNode().to_dict()}, "tools": {**nodes.PythonFunctionNode().to_dict(), **nodes.ToolNode().to_dict()},
"agents": {**nodes.JsonAgentNode().to_dict()},
} }

View file

@ -59,6 +59,7 @@ toolkit_type_to_cls_dict: dict[str, Any] = {
if not toolkit_name.islower() if not toolkit_name.islower()
} }
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]
} }

View file

@ -1,6 +1,12 @@
from typing import Callable, Optional from typing import Callable, Optional
from langchain import LLMChain, PromptTemplate
from langchain.agents import AgentExecutor, ZeroShotAgent
from langflow.utils import validate from langflow.utils import validate
from pydantic import BaseModel, validator from pydantic import BaseModel, validator
from langchain.agents.agent_toolkits.json.prompt import JSON_PREFIX, JSON_SUFFIX
from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS
from langchain.agents.agent_toolkits.json.toolkit import JsonToolkit
from langchain.schema import BaseLanguageModel
class Function(BaseModel): class Function(BaseModel):
@ -33,3 +39,31 @@ class PythonFunction(Function):
"""Python function""" """Python function"""
code: str code: str
class JsonAgent(BaseModel):
"""Json agent"""
toolkit: JsonToolkit
llm: BaseLanguageModel
def __init__(self, toolkit: JsonToolkit, llm: BaseLanguageModel):
super().__init__(toolkit=toolkit, llm=llm)
self.toolkit = toolkit
tools = self.toolkit.get_tools()
tool_names = [tool.name for tool in tools]
prompt = ZeroShotAgent.create_prompt(
tools,
prefix=JSON_PREFIX,
suffix=JSON_SUFFIX,
format_instructions=FORMAT_INSTRUCTIONS,
input_variables=None,
)
llm_chain = LLMChain(
llm=llm,
prompt=prompt,
)
agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)
return AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True
)

View file

@ -10,7 +10,7 @@ from langflow.settings import settings
from langflow.utils import util from langflow.utils import util
from langchain.agents.load_tools import get_all_tool_names from langchain.agents.load_tools import get_all_tool_names
from langchain.agents import Tool from langchain.agents import Tool
from langflow.interface.custom_types import PythonFunction from langflow.interface.custom_types import JsonAgent, PythonFunction
from langchain.tools.json.tool import JsonSpec from langchain.tools.json.tool import JsonSpec
OTHER_TOOLS = {"JsonSpec": JsonSpec} OTHER_TOOLS = {"JsonSpec": JsonSpec}
@ -50,7 +50,7 @@ def list_agents():
agent.__name__ agent.__name__
for agent in agents.loading.AGENT_TO_CLASS.values() for agent in agents.loading.AGENT_TO_CLASS.values()
if agent.__name__ in settings.agents or settings.dev if agent.__name__ in settings.agents or settings.dev
] ] + [JsonAgent.__name__]
def list_toolkis(): def list_toolkis():

View file

@ -40,7 +40,7 @@ def get_toolkit_signature(name: str):
"""Get the signature of a toolkit.""" """Get the signature of a toolkit."""
try: try:
if name.islower(): if name.islower():
pass ...
# return util.build_template_from_function( # return util.build_template_from_function(
# name, toolkit_type_to_loader_dict, add_function=True # name, toolkit_type_to_loader_dict, add_function=True
# ) # )
@ -77,6 +77,8 @@ def get_chain_signature(name: str):
def get_agent_signature(name: str): def get_agent_signature(name: str):
"""Get the signature of an agent.""" """Get the signature of an agent."""
try: try:
if name in customs.get_custom_nodes("agents").keys():
return customs.get_custom_nodes("agents")[name]
return util.build_template_from_class( return util.build_template_from_class(
name, agents.loading.AGENT_TO_CLASS, add_function=True name, agents.loading.AGENT_TO_CLASS, add_function=True
) )

View file

@ -112,3 +112,35 @@ class ToolNode(FrontendNode):
def to_dict(self): def to_dict(self):
return super().to_dict() return super().to_dict()
class JsonAgentNode(FrontendNode):
name: str = "JsonAgent"
template: Template = Template(
type_name="json_agent",
fields=[
Field(
field_type="BaseToolkit",
required=True,
placeholder="",
is_list=False,
show=True,
value="",
name="toolkit",
),
Field(
field_type="BaseLanguageModel",
required=True,
placeholder="",
is_list=False,
show=True,
value="",
name="LLM",
),
],
)
description: str = """Construct a json agent from an LLM and tools."""
base_classes: list[str] = ["BaseAgent"]
def to_dict(self):
return super().to_dict()

View file

@ -406,6 +406,7 @@ def format_dict(d, name: Optional[str] = None):
"examples", "examples",
"temperature", "temperature",
"model_name", "model_name",
"headers",
] ]
or "api_key" in key or "api_key" in key
) )
@ -427,7 +428,7 @@ def format_dict(d, name: Optional[str] = None):
# Replace dict type with str # Replace dict type with str
if "dict" in value["type"].lower(): if "dict" in value["type"].lower():
value["type"] = "str" value["type"] = "code"
value["file"] = key in ["dict_"] value["file"] = key in ["dict_"]
@ -436,6 +437,11 @@ def format_dict(d, name: Optional[str] = None):
value["value"] = value["default"] value["value"] = value["default"]
value.pop("default") value.pop("default")
if key == "headers":
value[
"value"
] = """{'Authorization':
'Bearer <token>'}"""
# Add options to openai # Add options to openai
if name == "OpenAI" and key == "model_name": if name == "OpenAI" and key == "model_name":
value["options"] = constants.OPENAI_MODELS value["options"] = constants.OPENAI_MODELS