Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Universal tool calling ReAct agent #40

Merged
merged 4 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/_test_single_openai_tools_react.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from langchain_community.tools import DuckDuckGoSearchRun

from motleycrew import MotleyCrew
from motleycrew.agents.langchain.openai_tools_react import ReactOpenAIToolsAgent
from motleycrew.agents.langchain.tool_calling_react import ReActToolCallingAgent
from motleycrew.agents.langchain.react import ReactMotleyAgent
from motleycrew.common import configure_logging
from motleycrew.tasks import SimpleTask
Expand All @@ -14,7 +14,7 @@ def main():

tools = [search_tool]

researcher = ReactOpenAIToolsAgent(tools=tools, verbose=True)
researcher = ReActToolCallingAgent(tools=tools, verbose=True)
researcher2 = ReactMotleyAgent(tools=tools, verbose=True)

outputs = []
Expand Down
59 changes: 59 additions & 0 deletions examples/tool_calling_with_memory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from dotenv import load_dotenv
from langchain_community.tools import DuckDuckGoSearchRun

from motleycrew import MotleyCrew
from motleycrew.agents.langchain.tool_calling_react import ReActToolCallingAgent
from motleycrew.common import configure_logging
from motleycrew.tasks import SimpleTask

from motleycrew.common.llms import init_llm
from motleycrew.common import LLMFramework, LLMFamily


def main():
search_tool = DuckDuckGoSearchRun()

tools = [search_tool]

researcher = ReActToolCallingAgent(
tools=tools,
verbose=True,
with_history=True,
# llm=init_llm(
# llm_framework=LLMFramework.LANGCHAIN,
# llm_family=LLMFamily.ANTHROPIC,
# llm_name="claude-3-sonnet-20240229",
# ),
)

outputs = []

crew = MotleyCrew()
task = SimpleTask(
crew=crew,
name="produce comprehensive analysis report on AI advancements",
description="""Conduct a comprehensive analysis of the latest advancements in AI.
Identify key trends, breakthrough technologies, and potential industry impacts.
Your final answer MUST be a full analysis report""",
agent=researcher,
)
crew.run()
print(task.output)

# See whether the researcher's memory persists across tasks
tldr_task = SimpleTask(
crew=crew,
name="provide a TLDR summary of the report",
description="Write a short summary of the comprehensive analysis report on AI advancements that you just wrote.",
agent=researcher,
)

crew.run()
print(tldr_task.output)


if __name__ == "__main__":
configure_logging(verbose=True)

load_dotenv()
main()
1 change: 0 additions & 1 deletion motleycrew/agents/langchain/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from .langchain import LangchainMotleyAgent

from .react import ReactMotleyAgent
from .openai_tools_react import OpenAIToolsAgentOutputParser
41 changes: 37 additions & 4 deletions motleycrew/agents/langchain/langchain.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
""" Module description """

from typing import Any, Optional, Sequence, Callable

from langchain.agents import AgentExecutor
from langchain_core.runnables import RunnableConfig
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory, InMemoryChatMessageHistory
from langchain_core.language_models import BaseLanguageModel
from langchain_core.prompts.chat import ChatPromptTemplate


from motleycrew.agents.parent import MotleyAgentParent
from motleycrew.agents.abstract_parent import MotleyAgentAbstractParent

Expand All @@ -25,8 +29,10 @@ def __init__(
agent_factory: MotleyAgentFactory | None = None,
tools: Sequence[MotleySupportedTool] | None = None,
verbose: bool = False,
with_history: bool = False,
chat_history: BaseChatMessageHistory | None = None,
):
""" Description
"""Description

Args:
description (str):
Expand All @@ -43,13 +49,32 @@ def __init__(
verbose=verbose,
)

self.with_history = with_history
self.chat_history = chat_history or InMemoryChatMessageHistory()

def materialize(self):
"""Materialize the agent and wrap it in RunnableWithMessageHistory if needed."""
if self.is_materialized:
return

super().materialize()
if self.with_history:
if isinstance(self._agent, RunnableWithMessageHistory):
return
self._agent = RunnableWithMessageHistory(
runnable=self._agent,
get_session_history=lambda _: self.chat_history,
input_messages_key="input",
history_messages_key="chat_history",
)

def invoke(
self,
task_dict: dict,
config: Optional[RunnableConfig] = None,
**kwargs: Any,
) -> Any:
""" Description
"""Description

Args:
task_dict (dict):
Expand All @@ -66,11 +91,17 @@ def invoke(
raise ValueError("Task must have a prompt")

config = add_default_callbacks_to_langchain_config(config)
if self.with_history:
config["configurable"] = config.get("configurable") or {}
config["configurable"]["session_id"] = (
config["configurable"].get("session_id") or "default"
)

result = self.agent.invoke({"input": prompt}, config, **kwargs)
output = result.get("output")
if output is None:
raise Exception("Agent {} result does not contain output: {}".format(self, result))

return output

@staticmethod
Expand All @@ -83,9 +114,10 @@ def from_function(
tools: Sequence[MotleySupportedTool] | None = None,
prompt: ChatPromptTemplate | Sequence[ChatPromptTemplate] | None = None,
require_tools: bool = False,
with_history: bool = False,
verbose: bool = False,
) -> "LangchainMotleyAgent":
""" Description
"""Description

Args:
function (Callable):
Expand Down Expand Up @@ -123,6 +155,7 @@ def agent_factory(tools: dict[str, MotleyTool]):
name=name,
agent_factory=agent_factory,
tools=tools,
with_history=with_history,
verbose=verbose,
)

Expand All @@ -133,7 +166,7 @@ def from_agent(
tools: Sequence[MotleySupportedTool] | None = None,
verbose: bool = False,
) -> "LangchainMotleyAgent":
""" Description
"""Description

Args:
agent (AgentExecutor):
Expand Down
Loading
Loading