langchain-ai / langchain

🦜🔗 Build context-aware reasoning applications
https://python.langchain.com
MIT License
92.31k stars 14.75k forks source link

agent created by create_react_agent() does not support early_stopping_method='generate' #24111

Open damonsuen opened 2 months ago

damonsuen commented 2 months ago

Checked other resources

Example Code

The following code:

agent = create_react_agent(llm, tools, prompt)

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    max_iterations=1,
    early_stopping_method="generate",
)

Error Message and Stack Trace (if applicable)

No response

Description

I am using create_react_agent() to create an agent. I want to let LLM to get the final answer when the max_iterations reached based on the existing information. But it seems the agent created by create_react_agent() does not support "early_stopping_method='generate'". It seems the agent type is BaseSingleActionAgent and return_stopped_response() does not handle "early_stopping_method='generate'"

    def return_stopped_response(
        self,
        early_stopping_method: str,
        intermediate_steps: List[Tuple[AgentAction, str]],
        **kwargs: Any,
    ) -> AgentFinish:
        """Return response when agent has been stopped due to max iterations."""
        if early_stopping_method == "force":
            # `force` just returns a constant string
            return AgentFinish(
                {"output": "Agent stopped due to iteration limit or time limit."}, ""
            )
        else:
            raise ValueError(
                f"Got unsupported early_stopping_method `{early_stopping_method}`"
            )

Can I assign it as Agent(BaseSingleActionAgent) when using create_react_agent() ?

System Info

System Information

OS: Windows OS Version: 10.0.19043 Python Version: 3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]

Package Information

langchain_core: 0.2.13 langchain: 0.2.7 langchain_community: 0.2.7 langsmith: 0.1.85 langchain_google_alloydb_pg: 0.2.2 langchain_google_community: 1.0.6 langchain_google_vertexai: 1.0.6 langchain_openai: 0.1.8 langchain_text_splitters: 0.2.2 langchainhub: 0.1.20 langgraph: 0.1.7 langserve: 0.2.2

eyurtsev commented 2 months ago

We recommend transitioning to langgraph agents:

https://python.langchain.com/v0.2/docs/how_to/migrate_agent/ https://langchain-ai.github.io/langgraph/how-tos/create-react-agent/

dkarthicks27 commented 2 months ago

You can modify your source code to tackle this issue for now

def return_stopped_response(
        self,
        early_stopping_method: str,
        intermediate_steps: List[Tuple[AgentAction, str]],
        **kwargs: Any,
    ) -> AgentFinish:
        """Return response when agent has been stopped due to max iterations."""
        if early_stopping_method == "force":
            # `force` just returns a constant string
            return AgentFinish(
                {"output": "Agent stopped due to iteration limit or time limit."}, ""
            )
        elif early_stopping_method == "generate":
            # Generate does one final forward pass
            thoughts = ""
            for action, observation in intermediate_steps:
                thoughts += action.log
                thoughts += (
                    f"\n{self.observation_prefix}{observation}\n{self.llm_prefix}"
                )
            # Adding to the previous steps, we now tell the LLM to make a final pred
            thoughts += (
                "\n\nI now need to return a final answer based on the previous steps:"
            )
            new_inputs = {"agent_scratchpad": thoughts, "stop": self._stop}
            full_inputs = {**kwargs, **new_inputs}
            full_output = self.llm_chain.predict(**full_inputs)
            # We try to extract a final answer
            parsed_output = self.output_parser.parse(full_output)
            if isinstance(parsed_output, AgentFinish):
                # If we can extract, we send the correct stuff
                return parsed_output
            else:
                # If we can extract, but the tool is not the final tool,
                # we just return the full output
                return AgentFinish({"output": full_output}, full_output)
        else:
            raise ValueError(
                "early_stopping_method should be one of `force` or `generate`, "
                f"got {early_stopping_method}"
            )