xml.py Value Error --> insufficient error information
Labels: name: area: agent, name: auto:bug

### System Info

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[27], line 5
      1 #### All together!
      2 # Put it all together now
      3 full_chain = {"topic": chain, "question": lambda x: x["question"]} | branch
----> 5 full_chain.invoke({"question":"what is the best city?"})

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/runnables/base.py:1427, in RunnableSequence.invoke(self, input, config)
   1425 try:
   1426     for i, step in enumerate(self.steps):
-> 1427         input = step.invoke(
   1428             input,
   1429             # mark each step as a child run
   1430             patch_config(
   1431                 config, callbacks=run_manager.get_child(f"seq:step:{i+1}")
   1432             ),
   1433         )
   1434 # finish the root run
   1435 except BaseException as e:

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/runnables/branch.py:186, in RunnableBranch.invoke(self, input, config, **kwargs)
    177     expression_value = condition.invoke(
    178         input,
    179         config=patch_config(
   (...)
    182         ),
    183     )
    185     if expression_value:
--> 186         output = runnable.invoke(
    187             input,
    188             config=patch_config(
    189                 config,
    190                 callbacks=run_manager.get_child(tag=f"branch:{idx + 1}"),
    191             ),
    192             **kwargs,
    193         )
    194         break
    195 else:

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/chains/base.py:89, in Chain.invoke(self, input, config, **kwargs)
     82 def invoke(
     83     self,
     84     input: Dict[str, Any],
     85     config: Optional[RunnableConfig] = None,
     86     **kwargs: Any,
     87 ) -> Dict[str, Any]:
     88     config = config or {}
---> 89     return self(
     90         input,
     91         callbacks=config.get("callbacks"),
     92         tags=config.get("tags"),
     93         metadata=config.get("metadata"),
     94         run_name=config.get("run_name"),
     95         **kwargs,
     96     )

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/chains/base.py:312, in Chain.__call__(self, inputs, return_only_outputs, callbacks, tags, metadata, run_name, include_run_info)
    310 except BaseException as e:
    311     run_manager.on_chain_error(e)
--> 312     raise e
    313 run_manager.on_chain_end(outputs)
    314 final_outputs: Dict[str, Any] = self.prep_outputs(
    315     inputs, outputs, return_only_outputs
    316 )

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/chains/base.py:306, in Chain.__call__(self, inputs, return_only_outputs, callbacks, tags, metadata, run_name, include_run_info)
    299 run_manager = callback_manager.on_chain_start(
    300     dumpd(self),
    301     inputs,
    302     name=run_name,
    303 )
    304 try:
    305     outputs = (
--> 306         self._call(inputs, run_manager=run_manager)
    307         if new_arg_supported
    308         else self._call(inputs)
    309     )
    310 except BaseException as e:
    311     run_manager.on_chain_error(e)

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/agents/agent.py:1251, in AgentExecutor._call(self, inputs, run_manager)
   1249 # We now enter the agent loop (until it returns something).
   1250 while self._should_continue(iterations, time_elapsed):
-> 1251     next_step_output = self._take_next_step(
   1252         name_to_tool_map,
   1253         color_mapping,
   1254         inputs,
   1255         intermediate_steps,
   1256         run_manager=run_manager,
   1257     )
   1258     if isinstance(next_step_output, AgentFinish):
   1259         return self._return(
   1260             next_step_output, intermediate_steps, run_manager=run_manager
   1261         )

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/agents/agent.py:1038, in AgentExecutor._take_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1035     intermediate_steps = self._prepare_intermediate_steps(intermediate_steps)
   1037     # Call the LLM to see what to do.
-> 1038     output = self.agent.plan(
   1039         intermediate_steps,
   1040         callbacks=run_manager.get_child() if run_manager else None,
   1041         **inputs,
   1042     )
   1043 except OutputParserException as e:
   1044     if isinstance(self.handle_parsing_errors, bool):

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/agents/agent.py:391, in RunnableAgent.plan(self, intermediate_steps, callbacks, **kwargs)
    379 """Given input, decided what to do.
    380 
    381 Args:
   (...)
    388     Action specifying what tool to use.
    389 """
    390 inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
--> 391 output = self.runnable.invoke(inputs, config={"callbacks": callbacks})
    392 return output

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/runnables/base.py:1427, in RunnableSequence.invoke(self, input, config)
   1425 try:
   1426     for i, step in enumerate(self.steps):
-> 1427         input = step.invoke(
   1428             input,
   1429             # mark each step as a child run
   1430             patch_config(
   1431                 config, callbacks=run_manager.get_child(f"seq:step:{i+1}")
   1432             ),
   1433         )
   1434 # finish the root run
   1435 except BaseException as e:

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/output_parsers/base.py:170, in BaseOutputParser.invoke(self, input, config)
    166 def invoke(
    167     self, input: Union[str, BaseMessage], config: Optional[RunnableConfig] = None
    168 ) -> T:
    169     if isinstance(input, BaseMessage):
--> 170         return self._call_with_config(
    171             lambda inner_input: self.parse_result(
    172                 [ChatGeneration(message=inner_input)]
    173             ),
    174             input,
    175             config,
    176             run_type="parser",
    177         )
    178     else:
    179         return self._call_with_config(
    180             lambda inner_input: self.parse_result([Generation(text=inner_input)]),
    181             input,
    182             config,
    183             run_type="parser",
    184         )

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/runnables/base.py:848, in Runnable._call_with_config(self, func, input, config, run_type, **kwargs)
    841 run_manager = callback_manager.on_chain_start(
    842     dumpd(self),
    843     input,
    844     run_type=run_type,
    845     name=config.get("run_name"),
    846 )
    847 try:
--> 848     output = call_func_with_variable_args(
    849         func, input, config, run_manager, **kwargs
    850     )
    851 except BaseException as e:
    852     run_manager.on_chain_error(e)

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/runnables/config.py:308, in call_func_with_variable_args(func, input, config, run_manager, **kwargs)
    306 if run_manager is not None and accepts_run_manager(func):
    307     kwargs["run_manager"] = run_manager
--> 308 return func(input, **kwargs)

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/output_parsers/base.py:171, in BaseOutputParser.invoke.<locals>.<lambda>(inner_input)
    166 def invoke(
    167     self, input: Union[str, BaseMessage], config: Optional[RunnableConfig] = None
    168 ) -> T:
    169     if isinstance(input, BaseMessage):
    170         return self._call_with_config(
--> 171             lambda inner_input: self.parse_result(
    172                 [ChatGeneration(message=inner_input)]
    173             ),
    174             input,
    175             config,
    176             run_type="parser",
    177         )
    178     else:
    179         return self._call_with_config(
    180             lambda inner_input: self.parse_result([Generation(text=inner_input)]),
    181             input,
    182             config,
    183             run_type="parser",
    184         )

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain_core/output_parsers/base.py:222, in BaseOutputParser.parse_result(self, result, partial)
    209 def parse_result(self, result: List[Generation], *, partial: bool = False) -> T:
    210     """Parse a list of candidate model Generations into a specific format.
    211 
    212     The return value is parsed from only the first Generation in the result, which
   (...)
    220         Structured output.
    221     """
--> 222     return self.parse(result[0].text)

File ~/miniconda3/envs/langchain_multiagent_env/lib/python3.8/site-packages/langchain/agents/output_parsers/xml.py:45, in XMLAgentOutputParser.parse(self, text)
     43     return AgentFinish(return_values={"output": answer}, log=text)
     44 else:
---> 45     raise ValueError(f"Could not parse output: {text}")

ValueError:

### Who can help?

_No response_

### Information

- [ ] The official example notebooks/scripts
- [ ] My own modified scripts

### Related Components

- [ ] LLMs/Chat Models
- [ ] Embedding Models
- [ ] Prompts / Prompt Templates / Prompt Selectors
- [X] Output Parsers
- [ ] Document Loaders
- [ ] Vector Stores / Retrievers
- [ ] Memory
- [ ] Agents / Agent Executors
- [ ] Tools / Toolkits
- [ ] Chains
- [ ] Callbacks/Tracing
- [ ] Async

### Reproduction

```
from langchain.prompts import PromptTemplate
from langchain.schema.output_parser import StrOutputParser


from langchain.chat_models import AzureChatOpenAI

import openai
openai.api_key = "........................................."

llm = AzureChatOpenAI(
    azure_endpoint=".......................................",
    openai_api_version="....................................",
    deployment_name=..............................................'',
    openai_api_key=openai.api_key,
    openai_api_type="azure",
    temperature=0
)

from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain.callbacks.stdout import StdOutCallbackHandler

memory = ConversationBufferMemory(return_messages=True)

chain = LLMChain(prompt = PromptTemplate.from_template(template="""
Given the user question below, classify it as either being about 'city', `weather` or `other`.
                                     
Do not respond with more than one word.
<question>```

{question}
</question>
Classification:""",
                           output_parser = StrOutputParser(),
    ), 
                 llm = llm,
                 memory = memory,
                 callbacks=[StdOutCallbackHandler()]
)

from langchain.agents import XMLAgent, tool, AgentExecutor
from langchain.chat_models import ChatAnthropic

model = llm

@tool
def search(query: str) -> str:
    """Search things about current wheather."""
    return "32 degrees"  #  32 degrees    Dzień Dobry przyjacielu!

tool_list = [search

@tool
def find_city(query: str) -> str:
    """Search the answer"""
    return "Gdynia"  #  32 degrees    

city_tool_list = [find_city]

prompt = XMLAgent.get_default_prompt()

def convert_intermediate_steps(intermediate_steps):
    log = ""
    for action, observation in intermediate_steps:
        print('\n')
        print(action)
        print(observation)
        log += (
            f"<tool>{action.tool}</tool><tool_input>{action.tool_input}"
            f"</tool_input><observation>{observation}</observation>"
        )
    return log

def convert_tools(tools):
    return "\n".join([f"{tool.name}: {tool.description}" for tool in tools])

agent = (
    {
        "question": lambda x: x["question"],
        "intermediate_steps": lambda x: convert_intermediate_steps(x["intermediate_steps"])
    }
    | prompt.partial(tools=convert_tools(tool_list))
    | model.bind(stop=["</tool_input>", "</final_answer>"]) 
    | XMLAgent.get_default_output_parser()
)

agent_executor = AgentExecutor(agent=agent, tools=tool_list, verbose=True)

city_prompt = XMLAgent.get_default_prompt()

new_template = """Use the tools to find the answer.

You have access to the following tools:

{tools}

In order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>
For example, if you have a tool called 'find_city' that could run and search best city:

<tool>find_city</tool><tool_input>what city?</tool_input>
<observation>Gdynia</observation>

When you are done, respond with a final answer between <final_answer></final_answer>. For example:

<final_answer>The city is Gdynia</final_answer>

Begin!

Question: {question}"""

city_prompt.messages[0].prompt.template = new_template

city_agent = (
    {
        "question": lambda x: x["question"],
        "intermediate_steps": lambda x: convert_intermediate_steps(x["intermediate_steps"])
    }
    | city_prompt.partial(tools=convert_tools(city_tool_list))
    | model.bind(stop=["</tool_input>", "</final_answer>"])  # .bind(memory=memory)
    | XMLAgent.get_default_output_parser()
)
city_agent_executor = AgentExecutor(agent=city_agent, tools=city_tool_list, verbose=True)
general_chain = PromptTemplate.from_template("""Respond to the following question:

Question: {question}
Answer:""") | llm

from langchain.schema.runnable import RunnableBranch

branch = RunnableBranch(
  (lambda x: "weather" in x["topic"]['text'].lower(), agent_executor),
  (lambda x: "city" in x["topic"]['text'].lower(), city_agent_executor),
  general_chain
)

full_chain = {"topic": chain, "question": lambda x: x["question"]} | branch
full_chain.invoke({"question":"what is the best city?"})
```
```

### Expected behavior

In xml.py 
langchain==0.0.341
line 45.
Is now:
`raise ValueError`
It would be better to have:
`raise ValueError(f"Could not pa](url)rse output: {text}")`