mirror of
https://github.com/hwchase17/langchain.git
synced 2025-05-31 12:09:58 +00:00
[langchain] agents code changes (#15278)
<!-- Thank you for contributing to LangChain! Please title your PR "<package>: <description>", where <package> is whichever of langchain, community, core, experimental, etc. is being modified. Replace this entire comment with: - **Description:** a description of the change, - **Issue:** the issue # it fixes if applicable, - **Dependencies:** any dependencies required for this change, - **Twitter handle:** we announce bigger features on Twitter. If your PR gets announced, and you'd like a mention, we'll gladly shout you out!
This commit is contained in:
parent
b86803153e
commit
90aa26a90e
@ -56,6 +56,7 @@ from langchain.agents.agent_types import AgentType
|
||||
from langchain.agents.conversational.base import ConversationalAgent
|
||||
from langchain.agents.conversational_chat.base import ConversationalChatAgent
|
||||
from langchain.agents.initialize import initialize_agent
|
||||
from langchain.agents.json_chat.base import create_json_chat_agent
|
||||
from langchain.agents.load_tools import (
|
||||
get_all_tool_names,
|
||||
load_huggingface_tool,
|
||||
@ -63,13 +64,24 @@ from langchain.agents.load_tools import (
|
||||
)
|
||||
from langchain.agents.loading import load_agent
|
||||
from langchain.agents.mrkl.base import MRKLChain, ZeroShotAgent
|
||||
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
|
||||
from langchain.agents.openai_functions_agent.base import (
|
||||
OpenAIFunctionsAgent,
|
||||
create_openai_functions_agent,
|
||||
)
|
||||
from langchain.agents.openai_functions_multi_agent.base import OpenAIMultiFunctionsAgent
|
||||
from langchain.agents.openai_tools.base import create_openai_tools_agent
|
||||
from langchain.agents.react.agent import create_react_agent
|
||||
from langchain.agents.react.base import ReActChain, ReActTextWorldAgent
|
||||
from langchain.agents.self_ask_with_search.base import SelfAskWithSearchChain
|
||||
from langchain.agents.structured_chat.base import StructuredChatAgent
|
||||
from langchain.agents.self_ask_with_search.base import (
|
||||
SelfAskWithSearchChain,
|
||||
create_self_ask_with_search_agent,
|
||||
)
|
||||
from langchain.agents.structured_chat.base import (
|
||||
StructuredChatAgent,
|
||||
create_structured_chat_agent,
|
||||
)
|
||||
from langchain.agents.tools import Tool, tool
|
||||
from langchain.agents.xml.base import XMLAgent
|
||||
from langchain.agents.xml.base import XMLAgent, create_xml_agent
|
||||
|
||||
DEPRECATED_CODE = [
|
||||
"create_csv_agent",
|
||||
@ -133,4 +145,11 @@ __all__ = [
|
||||
"load_tools",
|
||||
"tool",
|
||||
"XMLAgent",
|
||||
"create_openai_functions_agent",
|
||||
"create_xml_agent",
|
||||
"create_react_agent",
|
||||
"create_openai_tools_agent",
|
||||
"create_self_ask_with_search_agent",
|
||||
"create_json_chat_agent",
|
||||
"create_structured_chat_agent",
|
||||
]
|
||||
|
83
libs/langchain/langchain/agents/json_chat/base.py
Normal file
83
libs/langchain/langchain/agents/json_chat/base.py
Normal file
@ -0,0 +1,83 @@
|
||||
from typing import Sequence
|
||||
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.prompts.chat import ChatPromptTemplate
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from langchain.agents.format_scratchpad import format_log_to_messages
|
||||
from langchain.agents.json_chat.prompt import TEMPLATE_TOOL_RESPONSE
|
||||
from langchain.agents.output_parsers import JSONAgentOutputParser
|
||||
from langchain.tools.render import render_text_description
|
||||
|
||||
|
||||
def create_json_chat_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: ChatPromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent that uses JSON to format its logic, build for Chat Models.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain import hub
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
from langchain.agents import AgentExecutor, create_json_chat_agent
|
||||
|
||||
prompt = hub.pull("hwchase17/react-chat-json")
|
||||
model = ChatOpenAI()
|
||||
tools = ...
|
||||
|
||||
agent = create_json_chat_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
# Using with chat history
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
agent_executor.invoke(
|
||||
{
|
||||
"input": "what's my name?",
|
||||
"chat_history": [
|
||||
HumanMessage(content="hi! my name is bob"),
|
||||
AIMessage(content="Hello Bob! How can I assist you today?"),
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent.
|
||||
tools: Tools this agent has access to.
|
||||
prompt: The prompt to use, must have input keys of
|
||||
`tools`, `tool_names`, and `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
missing_vars = {"tools", "tool_names", "agent_scratchpad"}.difference(
|
||||
prompt.input_variables
|
||||
)
|
||||
if missing_vars:
|
||||
raise ValueError(f"Prompt missing required variables: {missing_vars}")
|
||||
|
||||
prompt = prompt.partial(
|
||||
tools=render_text_description(list(tools)),
|
||||
tool_names=", ".join([t.name for t in tools]),
|
||||
)
|
||||
llm_with_stop = llm.bind(stop=["\nObservation"])
|
||||
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_log_to_messages(
|
||||
x["intermediate_steps"], template_tool_response=TEMPLATE_TOOL_RESPONSE
|
||||
)
|
||||
)
|
||||
| prompt
|
||||
| llm_with_stop
|
||||
| JSONAgentOutputParser()
|
||||
)
|
||||
return agent
|
9
libs/langchain/langchain/agents/json_chat/prompt.py
Normal file
9
libs/langchain/langchain/agents/json_chat/prompt.py
Normal file
@ -0,0 +1,9 @@
|
||||
# flake8: noqa
|
||||
TEMPLATE_TOOL_RESPONSE = """TOOL RESPONSE:
|
||||
---------------------
|
||||
{observation}
|
||||
|
||||
USER'S INPUT
|
||||
--------------------
|
||||
|
||||
Okay, so what is the response to my last comment? If using information obtained from the tools you must mention it explicitly without mentioning the tool names - I have forgotten all TOOL RESPONSES! Remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else - even if you just want to respond to the user. Do NOT respond with anything except a JSON snippet no matter what!"""
|
@ -15,6 +15,7 @@ from langchain_core.prompts.chat import (
|
||||
MessagesPlaceholder,
|
||||
)
|
||||
from langchain_core.pydantic_v1 import root_validator
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from langchain.agents import BaseSingleActionAgent
|
||||
@ -226,3 +227,73 @@ class OpenAIFunctionsAgent(BaseSingleActionAgent):
|
||||
callback_manager=callback_manager,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
def create_openai_functions_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: ChatPromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent that uses OpenAI function calling.
|
||||
|
||||
Examples:
|
||||
|
||||
Creating an agent with no memory
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
from langchain.agents import AgentExecutor, create_openai_functions_agent
|
||||
from langchain import hub
|
||||
|
||||
prompt = hub.pull("hwchase17/openai-functions-agent")
|
||||
model = ChatOpenAI()
|
||||
tools = ...
|
||||
|
||||
agent = create_openai_functions_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
# Using with chat history
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
agent_executor.invoke(
|
||||
{
|
||||
"input": "what's my name?",
|
||||
"chat_history": [
|
||||
HumanMessage(content="hi! my name is bob"),
|
||||
AIMessage(content="Hello Bob! How can I assist you today?"),
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent. Should work with OpenAI function calling,
|
||||
so either be an OpenAI model that supports that or a wrapper of
|
||||
a different model that adds in equivalent support.
|
||||
tools: Tools this agent has access to.
|
||||
prompt: The prompt to use, must have an input key of `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
if "agent_scratchpad" not in prompt.input_variables:
|
||||
raise ValueError(
|
||||
"Prompt must have input variable `agent_scratchpad`, but wasn't found. "
|
||||
f"Found {prompt.input_variables} instead."
|
||||
)
|
||||
llm_with_tools = llm.bind(
|
||||
functions=[format_tool_to_openai_function(t) for t in tools]
|
||||
)
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_to_openai_function_messages(
|
||||
x["intermediate_steps"]
|
||||
)
|
||||
)
|
||||
| prompt
|
||||
| llm_with_tools
|
||||
| OpenAIFunctionsAgentOutputParser()
|
||||
)
|
||||
return agent
|
||||
|
79
libs/langchain/langchain/agents/openai_tools/base.py
Normal file
79
libs/langchain/langchain/agents/openai_tools/base.py
Normal file
@ -0,0 +1,79 @@
|
||||
from typing import Sequence
|
||||
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.prompts.chat import ChatPromptTemplate
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from langchain.agents.format_scratchpad.openai_tools import (
|
||||
format_to_openai_tool_messages,
|
||||
)
|
||||
from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser
|
||||
from langchain.tools.render import format_tool_to_openai_tool
|
||||
|
||||
|
||||
def create_openai_tools_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: ChatPromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent that uses OpenAI tools.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain import hub
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
from langchain.agents import AgentExecutor, create_openai_tools_agent
|
||||
|
||||
prompt = hub.pull("hwchase17/openai-tools-agent")
|
||||
model = ChatOpenAI()
|
||||
tools = ...
|
||||
|
||||
agent = create_openai_tools_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
# Using with chat history
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
agent_executor.invoke(
|
||||
{
|
||||
"input": "what's my name?",
|
||||
"chat_history": [
|
||||
HumanMessage(content="hi! my name is bob"),
|
||||
AIMessage(content="Hello Bob! How can I assist you today?"),
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent.
|
||||
tools: Tools this agent has access to.
|
||||
prompt: The prompt to use, must have input keys of `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
missing_vars = {"agent_scratchpad"}.difference(prompt.input_variables)
|
||||
if missing_vars:
|
||||
raise ValueError(f"Prompt missing required variables: {missing_vars}")
|
||||
|
||||
llm_with_tools = llm.bind(
|
||||
tools=[format_tool_to_openai_tool(tool) for tool in tools]
|
||||
)
|
||||
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_to_openai_tool_messages(
|
||||
x["intermediate_steps"]
|
||||
)
|
||||
)
|
||||
| prompt
|
||||
| llm_with_tools
|
||||
| OpenAIToolsAgentOutputParser()
|
||||
)
|
||||
return agent
|
79
libs/langchain/langchain/agents/react/agent.py
Normal file
79
libs/langchain/langchain/agents/react/agent.py
Normal file
@ -0,0 +1,79 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Sequence
|
||||
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.prompts import BasePromptTemplate
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from langchain.agents.format_scratchpad import format_log_to_str
|
||||
from langchain.agents.output_parsers import ReActSingleInputOutputParser
|
||||
from langchain.tools.render import render_text_description
|
||||
|
||||
|
||||
def create_react_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: BasePromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent that uses ReAct prompting.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain import hub
|
||||
from langchain.llms import OpenAI
|
||||
from langchain.agents import AgentExecutor, create_react_agent
|
||||
|
||||
prompt = hub.pull("hwchase17/react")
|
||||
model = OpenAI()
|
||||
tools = ...
|
||||
|
||||
agent = create_react_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
# Use with chat history
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
agent_executor.invoke(
|
||||
{
|
||||
"input": "what's my name?",
|
||||
# Notice that chat_history is a string
|
||||
# since this prompt is aimed at LLMs, not chat models
|
||||
"chat_history": "Human: My name is Bob\nAI: Hello Bob!",
|
||||
}
|
||||
)
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent.
|
||||
tools: Tools this agent has access to.
|
||||
prompt: The prompt to use, must have input keys of
|
||||
`tools`, `tool_names`, and `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
missing_vars = {"tools", "tool_names", "agent_scratchpad"}.difference(
|
||||
prompt.input_variables
|
||||
)
|
||||
if missing_vars:
|
||||
raise ValueError(f"Prompt missing required variables: {missing_vars}")
|
||||
|
||||
prompt = prompt.partial(
|
||||
tools=render_text_description(list(tools)),
|
||||
tool_names=", ".join([t.name for t in tools]),
|
||||
)
|
||||
llm_with_stop = llm.bind(stop=["\nObservation"])
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_log_to_str(x["intermediate_steps"]),
|
||||
)
|
||||
| prompt
|
||||
| llm_with_stop
|
||||
| ReActSingleInputOutputParser()
|
||||
)
|
||||
return agent
|
@ -4,10 +4,12 @@ from typing import Any, Sequence, Union
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.prompts import BasePromptTemplate
|
||||
from langchain_core.pydantic_v1 import Field
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from langchain.agents.agent import Agent, AgentExecutor, AgentOutputParser
|
||||
from langchain.agents.agent_types import AgentType
|
||||
from langchain.agents.format_scratchpad import format_log_to_str
|
||||
from langchain.agents.self_ask_with_search.output_parser import SelfAskOutputParser
|
||||
from langchain.agents.self_ask_with_search.prompt import PROMPT
|
||||
from langchain.agents.tools import Tool
|
||||
@ -79,3 +81,70 @@ class SelfAskWithSearchChain(AgentExecutor):
|
||||
)
|
||||
agent = SelfAskWithSearchAgent.from_llm_and_tools(llm, [search_tool])
|
||||
super().__init__(agent=agent, tools=[search_tool], **kwargs)
|
||||
|
||||
|
||||
def create_self_ask_with_search_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: BasePromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent that uses self-ask with search prompting.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain import hub
|
||||
from langchain.chat_models import ChatAnthropic
|
||||
from langchain.agents import (
|
||||
AgentExecutor, create_self_ask_with_search_agent
|
||||
)
|
||||
|
||||
prompt = hub.pull("hwchase17/self-ask-with-search")
|
||||
model = ChatAnthropic()
|
||||
tools = [...] # Should just be one tool with name `Intermediate Answer`
|
||||
|
||||
agent = create_self_ask_with_search_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent.
|
||||
tools: List of tools. Should just be of length 1, with that tool having
|
||||
name `Intermediate Answer`
|
||||
prompt: The prompt to use, must have input keys of `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
missing_vars = {"agent_scratchpad"}.difference(prompt.input_variables)
|
||||
if missing_vars:
|
||||
raise ValueError(f"Prompt missing required variables: {missing_vars}")
|
||||
|
||||
if len(tools) != 1:
|
||||
raise ValueError("This agent expects exactly one tool")
|
||||
tool = list(tools)[0]
|
||||
if tool.name != "Intermediate Answer":
|
||||
raise ValueError(
|
||||
"This agent expects the tool to be named `Intermediate Answer`"
|
||||
)
|
||||
|
||||
llm_with_stop = llm.bind(stop=["\nIntermediate answer:"])
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_log_to_str(
|
||||
x["intermediate_steps"],
|
||||
observation_prefix="\nIntermediate answer: ",
|
||||
llm_prefix="",
|
||||
),
|
||||
# Give it a default
|
||||
chat_history=lambda x: x.get("chat_history", ""),
|
||||
)
|
||||
| prompt
|
||||
| llm_with_stop
|
||||
| SelfAskOutputParser()
|
||||
)
|
||||
return agent
|
||||
|
@ -10,8 +10,11 @@ from langchain_core.prompts.chat import (
|
||||
SystemMessagePromptTemplate,
|
||||
)
|
||||
from langchain_core.pydantic_v1 import Field
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
|
||||
from langchain.agents.agent import Agent, AgentOutputParser
|
||||
from langchain.agents.format_scratchpad import format_log_to_str
|
||||
from langchain.agents.output_parsers import JSONAgentOutputParser
|
||||
from langchain.agents.structured_chat.output_parser import (
|
||||
StructuredChatOutputParserWithRetries,
|
||||
)
|
||||
@ -19,6 +22,7 @@ from langchain.agents.structured_chat.prompt import FORMAT_INSTRUCTIONS, PREFIX,
|
||||
from langchain.callbacks.base import BaseCallbackManager
|
||||
from langchain.chains.llm import LLMChain
|
||||
from langchain.tools import BaseTool
|
||||
from langchain.tools.render import render_text_description_and_args
|
||||
|
||||
HUMAN_MESSAGE_TEMPLATE = "{input}\n\n{agent_scratchpad}"
|
||||
|
||||
@ -142,3 +146,73 @@ class StructuredChatAgent(Agent):
|
||||
@property
|
||||
def _agent_type(self) -> str:
|
||||
raise ValueError
|
||||
|
||||
|
||||
def create_structured_chat_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: ChatPromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent aimed at supporting tools with multiple inputs.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain import hub
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
from langchain.agents import AgentExecutor, create_structured_chat_agent
|
||||
|
||||
prompt = hub.pull("hwchase17/structured-chat-agent")
|
||||
model = ChatOpenAI()
|
||||
tools = ...
|
||||
|
||||
agent = create_structured_chat_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
# Using with chat history
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
agent_executor.invoke(
|
||||
{
|
||||
"input": "what's my name?",
|
||||
"chat_history": [
|
||||
HumanMessage(content="hi! my name is bob"),
|
||||
AIMessage(content="Hello Bob! How can I assist you today?"),
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent.
|
||||
tools: Tools this agent has access to.
|
||||
prompt: The prompt to use, must have input keys of
|
||||
`tools`, `tool_names`, and `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
missing_vars = {"tools", "tool_names", "agent_scratchpad"}.difference(
|
||||
prompt.input_variables
|
||||
)
|
||||
if missing_vars:
|
||||
raise ValueError(f"Prompt missing required variables: {missing_vars}")
|
||||
|
||||
prompt = prompt.partial(
|
||||
tools=render_text_description_and_args(list(tools)),
|
||||
tool_names=", ".join([t.name for t in tools]),
|
||||
)
|
||||
llm_with_stop = llm.bind(stop=["Observation"])
|
||||
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_log_to_str(x["intermediate_steps"]),
|
||||
)
|
||||
| prompt
|
||||
| llm_with_stop
|
||||
| JSONAgentOutputParser()
|
||||
)
|
||||
return agent
|
||||
|
@ -1,14 +1,19 @@
|
||||
from typing import Any, List, Tuple, Union
|
||||
from typing import Any, List, Sequence, Tuple, Union
|
||||
|
||||
from langchain_core.agents import AgentAction, AgentFinish
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.prompts.base import BasePromptTemplate
|
||||
from langchain_core.prompts.chat import AIMessagePromptTemplate, ChatPromptTemplate
|
||||
from langchain_core.runnables import Runnable, RunnablePassthrough
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from langchain.agents.agent import BaseSingleActionAgent
|
||||
from langchain.agents.output_parsers.xml import XMLAgentOutputParser
|
||||
from langchain.agents.format_scratchpad import format_xml
|
||||
from langchain.agents.output_parsers import XMLAgentOutputParser
|
||||
from langchain.agents.xml.prompt import agent_instructions
|
||||
from langchain.callbacks.base import Callbacks
|
||||
from langchain.chains.llm import LLMChain
|
||||
from langchain.tools.render import render_text_description
|
||||
|
||||
|
||||
class XMLAgent(BaseSingleActionAgent):
|
||||
@ -42,9 +47,10 @@ class XMLAgent(BaseSingleActionAgent):
|
||||
|
||||
@staticmethod
|
||||
def get_default_prompt() -> ChatPromptTemplate:
|
||||
return ChatPromptTemplate.from_template(
|
||||
agent_instructions
|
||||
) + AIMessagePromptTemplate.from_template("{intermediate_steps}")
|
||||
base_prompt = ChatPromptTemplate.from_template(agent_instructions)
|
||||
return base_prompt + AIMessagePromptTemplate.from_template(
|
||||
"{intermediate_steps}"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_default_output_parser() -> XMLAgentOutputParser:
|
||||
@ -97,3 +103,69 @@ class XMLAgent(BaseSingleActionAgent):
|
||||
}
|
||||
response = await self.llm_chain.acall(inputs, callbacks=callbacks)
|
||||
return response[self.llm_chain.output_key]
|
||||
|
||||
|
||||
def create_xml_agent(
|
||||
llm: BaseLanguageModel, tools: Sequence[BaseTool], prompt: BasePromptTemplate
|
||||
) -> Runnable:
|
||||
"""Create an agent that uses XML to format its logic.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain import hub
|
||||
from langchain.chat_models import ChatAnthropic
|
||||
from langchain.agents import AgentExecutor, create_xml_agent
|
||||
|
||||
prompt = hub.pull("hwchase17/xml-agent-convo")
|
||||
model = ChatAnthropic()
|
||||
tools = ...
|
||||
|
||||
agent = create_xml_agent(model, tools, prompt)
|
||||
agent_executor = AgentExecutor(agent=agent, tools=tools)
|
||||
|
||||
agent_executor.invoke({"input": "hi"})
|
||||
|
||||
# Use with chat history
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
agent_executor.invoke(
|
||||
{
|
||||
"input": "what's my name?",
|
||||
# Notice that chat_history is a string
|
||||
# since this prompt is aimed at LLMs, not chat models
|
||||
"chat_history": "Human: My name is Bob\nAI: Hello Bob!",
|
||||
}
|
||||
)
|
||||
|
||||
Args:
|
||||
llm: LLM to use as the agent.
|
||||
tools: Tools this agent has access to.
|
||||
prompt: The prompt to use, must have input keys of
|
||||
`tools` and `agent_scratchpad`.
|
||||
|
||||
Returns:
|
||||
A runnable sequence representing an agent. It takes as input all the same input
|
||||
variables as the prompt passed in does. It returns as output either an
|
||||
AgentAction or AgentFinish.
|
||||
|
||||
"""
|
||||
missing_vars = {"tools", "agent_scratchpad"}.difference(prompt.input_variables)
|
||||
if missing_vars:
|
||||
raise ValueError(f"Prompt missing required variables: {missing_vars}")
|
||||
|
||||
prompt = prompt.partial(
|
||||
tools=render_text_description(list(tools)),
|
||||
)
|
||||
llm_with_stop = llm.bind(stop=["</tool_input>"])
|
||||
|
||||
agent = (
|
||||
RunnablePassthrough.assign(
|
||||
agent_scratchpad=lambda x: format_xml(x["intermediate_steps"]),
|
||||
)
|
||||
| prompt
|
||||
| llm_with_stop
|
||||
| XMLAgentOutputParser()
|
||||
)
|
||||
return agent
|
||||
|
@ -1,4 +1,5 @@
|
||||
# flake8: noqa
|
||||
# TODO: deprecate
|
||||
agent_instructions = """You are a helpful assistant. Help the user answer any questions.
|
||||
|
||||
You have access to the following tools:
|
||||
|
@ -35,6 +35,13 @@ EXPECTED_ALL = [
|
||||
"load_tools",
|
||||
"tool",
|
||||
"XMLAgent",
|
||||
"create_openai_functions_agent",
|
||||
"create_xml_agent",
|
||||
"create_react_agent",
|
||||
"create_openai_tools_agent",
|
||||
"create_self_ask_with_search_agent",
|
||||
"create_json_chat_agent",
|
||||
"create_structured_chat_agent",
|
||||
]
|
||||
|
||||
|
||||
|
@ -35,6 +35,13 @@ _EXPECTED = [
|
||||
"load_huggingface_tool",
|
||||
"load_tools",
|
||||
"tool",
|
||||
"create_openai_functions_agent",
|
||||
"create_xml_agent",
|
||||
"create_react_agent",
|
||||
"create_openai_tools_agent",
|
||||
"create_self_ask_with_search_agent",
|
||||
"create_json_chat_agent",
|
||||
"create_structured_chat_agent",
|
||||
]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user