feat: prevent agent parser from causing action loops

This commit is contained in:
Lucas Gomide
2025-07-18 16:35:07 -03:00
parent c978c4f495
commit 7c5558bc13
3 changed files with 52 additions and 11 deletions

View File

@@ -145,6 +145,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
while not isinstance(formatted_answer, AgentFinish):
try:
if has_reached_max_iterations(self.iterations, self.max_iter):
self._parser.reached_max_iterations()
formatted_answer = handle_max_iterations_exceeded(
formatted_answer,
printer=self._printer,

View File

@@ -65,25 +65,27 @@ class CrewAgentParser:
"""
_i18n: I18N = I18N()
_max_iterations_reached: bool = False
agent: Any = None
def __init__(self, agent: Optional[Any] = None):
self.agent = agent
def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
cleaned_text = self._clean_agent_observations(text)
def reached_max_iterations(self) -> None:
self._max_iterations_reached = True
def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
thought = self._extract_thought(text)
includes_answer = FINAL_ANSWER_ACTION in text
action_match = self._find_last_action_input_pair(cleaned_text)
action_match = self._find_last_action_input_pair(text)
# Prevent tool bypassing when both Action and Final Answer are present
# If the model returns both, we PRIORITIZE the action to force tool execution
if includes_answer and action_match:
return self._create_agent_action(thought, action_match, cleaned_text)
if not self._max_iterations_reached and includes_answer and action_match:
return self._create_agent_action(thought, action_match, text)
elif includes_answer:
final_answer = cleaned_text.split(FINAL_ANSWER_ACTION)[-1].strip()
final_answer = text.split(FINAL_ANSWER_ACTION)[-1].strip()
# Check whether the final answer ends with triple backticks.
if final_answer.endswith("```"):
# Count occurrences of triple backticks in the final answer.
@@ -91,17 +93,17 @@ class CrewAgentParser:
# If count is odd then it's an unmatched trailing set; remove it.
if count % 2 != 0:
final_answer = final_answer[:-3].rstrip()
return AgentFinish(thought, final_answer, cleaned_text)
return AgentFinish(thought, final_answer, text)
elif action_match:
return self._create_agent_action(thought, action_match, cleaned_text)
return self._create_agent_action(thought, action_match, text)
if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", cleaned_text, re.DOTALL):
if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL):
raise OutputParserException(
f"{MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE}\n{self._i18n.slice('final_answer_format')}",
)
elif not re.search(
r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)", cleaned_text, re.DOTALL
r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)", text, re.DOTALL
):
raise OutputParserException(
MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE,
@@ -151,7 +153,8 @@ class CrewAgentParser:
return str(result)
def _create_agent_action(self, thought: str, action_match: dict, cleaned_text: str) -> AgentAction:
def _create_agent_action(self, thought: str, action_match: dict, text: str) -> AgentAction:
cleaned_text = self._clean_agent_observations(text)
action = action_match["action"]
clean_action = self._clean_action(action)
action_input = action_match["input"]

View File

@@ -482,3 +482,40 @@ def test_ensure_agent_finish_is_selected_when_no_action_was_provided(parser):
assert isinstance(result, AgentFinish)
assert result.text.strip() == text.strip()
def test_ensure_max_iteration_reached_and_agent_hallucinates_observation_and_final_answer(parser):
text = """Let's continue our effort to gather comprehensive, well-rounded information about AI in healthcare in 2023 to compile a detailed research report effectively.
Action: Web Search
Action Input: {"search_query": "innovations in AI for healthcare 2023 latest updates and challenges"}
Observation: The search is yielding repeated and abundant information on the fragmented, redundant regulatory frameworks, clinical validation importance, and varied insights about AIs ongoing integration challenges in healthcare. To ensure a rich mix of insights, let's compile, structure, and organize these insights into a coherent report.
Thought: I now have ample information to construct a research report detailing innovations, challenges, and opportunities of AI in healthcare in 2023.
Final Answer: The finalized detailed research report on AI in Healthcare, 2023:
Title: Current Innovations, Challenges, and Potential of AI in Healthcare - 2023 Overview
Introduction:
The integration of Artificial Intelligence (AI) in healthcare is heralding a new era of modern medicine. In 2023, substantial technological advancements have brought about transformative changes in healthcare delivery. This report explores the latest AI innovations, identifies prevalent challenges, and discusses the potential opportunities in healthcare.
Conclusion:
AI continues to reshape the healthcare landscape in 2023. Facing challenges head-on with robust solutions will unlock unparalleled benefits, positioning AI as a cornerstone for future medical and healthcare advancements. With ongoing improvements in regulations, data quality, and validation processes, the full potential of AI in healthcare stands to be realized.
"""
parser.reached_max_iterations()
result = parser.parse(text)
expected_text = """
The finalized detailed research report on AI in Healthcare, 2023:
Title: Current Innovations, Challenges, and Potential of AI in Healthcare - 2023 Overview
Introduction:
The integration of Artificial Intelligence (AI) in healthcare is heralding a new era of modern medicine. In 2023, substantial technological advancements have brought about transformative changes in healthcare delivery. This report explores the latest AI innovations, identifies prevalent challenges, and discusses the potential opportunities in healthcare.
Conclusion:
AI continues to reshape the healthcare landscape in 2023. Facing challenges head-on with robust solutions will unlock unparalleled benefits, positioning AI as a cornerstone for future medical and healthcare advancements. With ongoing improvements in regulations, data quality, and validation processes, the full potential of AI in healthcare stands to be realized.
"""
assert isinstance(result, AgentFinish)
assert result.output.strip() == expected_text.strip()