diff --git a/llama-index-core/llama_index/core/agent/react/output_parser.py b/llama-index-core/llama_index/core/agent/react/output_parser.py index 93a241daa4839f1304d3d961272f59ff6356eea4..d013fb66ccc02092309771f730fb84d8a4b38edc 100644 --- a/llama-index-core/llama_index/core/agent/react/output_parser.py +++ b/llama-index-core/llama_index/core/agent/react/output_parser.py @@ -15,7 +15,7 @@ from llama_index.core.types import BaseOutputParser def extract_tool_use(input_text: str) -> Tuple[str, str, str]: pattern = ( - r"\s*Thought: (.*?)\nAction: ([a-zA-Z0-9_]+).*?\nAction Input: .*?(\{.*\})" + r"\s*Thought: (.*?)\n+Action: ([a-zA-Z0-9_]+).*?\n+Action Input: .*?(\{.*\})" ) match = re.search(pattern, input_text, re.DOTALL) @@ -97,15 +97,16 @@ class ReActOutputParser(BaseOutputParser): is_streaming=is_streaming, ) + # An "Action" should take priority over an "Answer" + if "Action:" in output: + return parse_action_reasoning_step(output) + if "Answer:" in output: thought, answer = extract_final_response(output) return ResponseReasoningStep( thought=thought, response=answer, is_streaming=is_streaming ) - if "Action:" in output: - return parse_action_reasoning_step(output) - raise ValueError(f"Could not parse output: {output}") def format(self, output: str) -> str: diff --git a/llama-index-core/tests/agent/react/test_react_output_parser.py b/llama-index-core/tests/agent/react/test_react_output_parser.py index 4ee41d91ea0ed3190d39a06ee488cf42c2f2b936..1e7525fb022263eeaf293541d0807214ee4d96d0 100644 --- a/llama-index-core/tests/agent/react/test_react_output_parser.py +++ b/llama-index-core/tests/agent/react/test_react_output_parser.py @@ -22,6 +22,22 @@ def test_extract_tool_use() -> None: mock_input_text = """\ Thought: I need to use a tool to help me answer the question. Action: add +Action Input: {"a": 1, "b": 1} +""" + thought, action, action_input = extract_tool_use(mock_input_text) + assert thought == "I need to use a tool to help me answer the question." + assert action == "add" + assert action_input == '{"a": 1, "b": 1}' + + +def test_extract_tool_use_multiline() -> None: + mock_input_text = """\ +Thought: I need to use a tool to help me answer the question. + +Action: add + + + Action Input: {"a": 1, "b": 1} """ thought, action, action_input = extract_tool_use(mock_input_text)