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.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: 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", "\nFinal", "Answer:"] 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 = ( { "agent_scratchpad": RunnablePassthrough(), } | prompt | llm_with_stop # | output_parser ) return agent