| | from __future__ import annotations |
| |
|
| | from typing import List, Optional, Sequence, Union |
| |
|
| | 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_core.tools.render import ToolsRenderer, render_text_description |
| |
|
| | from langchain.agents import AgentOutputParser |
| | from langchain.agents.format_scratchpad import format_log_to_str |
| | from langchain.agents.output_parsers import ReActSingleInputOutputParser |
| |
|
| |
|
| | def create_react_agent( |
| | llm: BaseLanguageModel, |
| | tools: Sequence[BaseTool], |
| | prompt: BasePromptTemplate, |
| | output_parser: Optional[AgentOutputParser] = None, |
| | tools_renderer: ToolsRenderer = render_text_description, |
| | *, |
| | stop_sequence: Union[bool, List[str]] = True, |
| | ) -> Runnable: |
| | """Create an agent that uses ReAct prompting. |
| | |
| | Based on paper "ReAct: Synergizing Reasoning and Acting in Language Models" |
| | (https://arxiv.org/abs/2210.03629) |
| | |
| | .. warning:: |
| | This implementation is based on the foundational ReAct paper but is older and not well-suited for production applications. |
| | For a more robust and feature-rich implementation, we recommend using the `create_react_agent` function from the LangGraph library. |
| | See the [reference doc](https://langchain-ai.github.io/langgraph/reference/prebuilt/#langgraph.prebuilt.chat_agent_executor.create_react_agent) |
| | for more information. |
| | |
| | Args: |
| | llm: LLM to use as the agent. |
| | tools: Tools this agent has access to. |
| | prompt: The prompt to use. See Prompt section below for more. |
| | output_parser: AgentOutputParser for parse the LLM output. |
| | tools_renderer: This controls how the tools are converted into a string and |
| | then passed into the LLM. Default is `render_text_description`. |
| | stop_sequence: bool or list of str. |
| | If True, adds a stop token of "Observation:" to avoid hallucinates. |
| | If False, does not add a stop token. |
| | If a list of str, uses the provided list as the stop tokens. |
| | |
| | Default is True. You may to set this to False if the LLM you are using |
| | does not support stop sequences. |
| | |
| | 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. |
| | |
| | Examples: |
| | |
| | .. code-block:: python |
| | |
| | from langchain import hub |
| | from langchain_community.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!", |
| | } |
| | ) |
| | |
| | Prompt: |
| | |
| | The prompt must have input keys: |
| | * `tools`: contains descriptions and arguments for each tool. |
| | * `tool_names`: contains all tool names. |
| | * `agent_scratchpad`: contains previous agent actions and tool outputs as a string. |
| | |
| | Here's an example: |
| | |
| | .. code-block:: python |
| | |
| | from langchain_core.prompts import PromptTemplate |
| | |
| | template = '''Answer the following questions as best you can. You have access to the following tools: |
| | |
| | {tools} |
| | |
| | Use the following format: |
| | |
| | Question: the input question you must answer |
| | Thought: you should always think about what to do |
| | Action: the action to take, should be one of [{tool_names}] |
| | Action Input: the input to the action |
| | Observation: the result of the action |
| | ... (this Thought/Action/Action Input/Observation can repeat N times) |
| | Thought: I now know the final answer |
| | Final Answer: the final answer to the original input question |
| | |
| | Begin! |
| | |
| | Question: {input} |
| | Thought:{agent_scratchpad}''' |
| | |
| | prompt = PromptTemplate.from_template(template) |
| | """ |
| | missing_vars = {"tools", "tool_names", "agent_scratchpad"}.difference( |
| | prompt.input_variables + list(prompt.partial_variables) |
| | ) |
| | if missing_vars: |
| | raise ValueError(f"Prompt missing required variables: {missing_vars}") |
| |
|
| | prompt = prompt.partial( |
| | tools=tools_renderer(list(tools)), |
| | tool_names=", ".join([t.name for t in tools]), |
| | ) |
| | if stop_sequence: |
| | stop = ["\nObservation"] if stop_sequence is True else stop_sequence |
| | llm_with_stop = llm.bind(stop=stop) |
| | else: |
| | llm_with_stop = llm |
| | output_parser = output_parser or ReActSingleInputOutputParser() |
| | agent = ( |
| | RunnablePassthrough.assign( |
| | agent_scratchpad=lambda x: format_log_to_str(x["intermediate_steps"]), |
| | ) |
| | | prompt |
| | | llm_with_stop |
| | | output_parser |
| | ) |
| | return agent |
| |
|