MetaGPT
MetaGPT copied to clipboard
ReAct loop can not stop gracefully, usually not stop.
Bug description
- I created a role that simply counts up to 3, after which the goal is considered accomplished. All the LLM I tried usually would not set next_state to -1 in role._think() when operating in ReAct mode.
- After I essentially solved 1. the role encountered difficulties in exiting gracefully.
2024-05-24 08:33:16.872 | INFO | metagpt.roles.role:_think:397 - End actions with next_state=-1
2024-05-24 08:33:16.874 | WARNING | metagpt.utils.common:wrapper:649 - There is a exception in role's execution, in order to resume, we delete the newest role communication message in the role's memory.
Traceback (most recent call last):
File "/home/wei/kf/MetaGPT/metagpt/utils/common.py", line 640, in wrapper
return await func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/wei/kf/MetaGPT/metagpt/roles/role.py", line 551, in run
rsp = await self.react()
^^^^^^^^^^^^^^^^^^
File "/home/wei/kf/MetaGPT/metagpt/roles/role.py", line 520, in react
rsp = await self._react()
^^^^^^^^^^^^^^^^^^^
File "/home/wei/kf/MetaGPT/metagpt/roles/role.py", line 475, in _react
rsp = await self._act()
^^^^^^^^^^^^^^^^^
File "/home/wei/kf/MetaGPT/workspace/counter.py", line 53, in _act
logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
During handling of the above exception, another exception occurred:
Bug solved method
I suppose this issue arises because the LLM might get confused after being instructed 'Just answer a number between 0-{n_states}', and then being told 'If you think you have completed your goal and don't need to go to any of the stages, return -1.' LLM may not be able to return -1.
class Role(SerializationMixin, ContextMixin, BaseModel):
async def _think(self) -> bool:
"""Consider what to do and decide on the next course of action. Return false if nothing can be done."""
....
next_state = await self.llm.aask(prompt)
next_state = extract_state_value_from_output(next_state)
....
self._set_state(next_state)
===== after change =====
return next_state >= 0
==== before changed =====
return True