MetaGPT icon indicating copy to clipboard operation
MetaGPT copied to clipboard

BUG, the index states and _think is not match?

Open tonystz opened this issue 1 year ago • 2 comments
trafficstars

role.py文件中,set_actions里面的索引是从1开始,但是在_think方法里面却是从0开始,会导致最后一个action选不到

set_actions

    def set_actions(self, actions: list[Union[Action, Type[Action]]]):
            ....
            self.states.append(f"{len(self.actions) - 1}. {action}") #索引是从1开始

_think

if (not next_state.isdigit() and next_state != "-1") or int(next_state) not in range(-1, len(self.states))

tonystz avatar Mar 28 '24 09:03 tonystz

@garylin2099 It seems that we have discussed this issue, but I am also very confused about the modification here.

geekan avatar Mar 28 '24 14:03 geekan

  1. state是从0开始的,-1表示无效state. 截屏2024-03-29 15 29 15

  2. self.states.append(f"{len(self.actions) - 1}. {action}")的最小值是0:

    def _reset(self):
        self.states = []
        self.actions = []
    def set_actions(self, actions: list[Union[Action, Type[Action]]]):
        self._reset()
        for action in actions:
            if not isinstance(action, Action):
                i = action(context=self.context)
            else:
                if self.is_human and not isinstance(action.llm, HumanProvider):
                    logger.warning(
                        f"is_human attribute does not take effect, "
                        f"as Role's {str(action)} was initialized using LLM, "
                        f"try passing in Action classes instead of initialized instances"
                    )
                i = action
            self._init_action(i)
            self.actions.append(i)
            self.states.append(f"{len(self.actions) - 1}. {action}") #  len(self.actions)的最小值是1,所以states的第一条的值是"0. xxx"
  1. 相应的, _think中的promptstates的值也是以"0. xx"开始的。
    async def _think(self) -> bool:
        """Consider what to do and decide on the next course of action. Return false if nothing can be done."""
        ......
        prompt += STATE_TEMPLATE.format(
            history=self.rc.history,
            states="\n".join(self.states), #  states的第一条的值是"0. xxx"
            n_states=len(self.states) - 1,
            previous_state=self.rc.state,
        )

        next_state = await self.llm.aask(prompt)

所以, next_state中的结果也应该是"0. xxx"。 4. 假设self.states=["0. xxx"],即next_state的值可能是{'-1, '0'}. 不同next_state对应的(not next_state.isdigit() and next_state != "-1") or int(next_state) not in range(-1, len(self.states))

  • next_state='-1'时,False
  • next_state='0'时,False
  • next_state='1'时,True
  • next_state>'1'时,True 这块逻辑并没有问题:
        if (not next_state.isdigit() and next_state != "-1") or int(next_state) not in range(-1, len(self.states)): # next_state值异常
            logger.warning(f"Invalid answer of state, {next_state=}, will be set to -1")
            next_state = -1
        else: # next_state值正常
            next_state = int(next_state)
            if next_state == -1:
                logger.info(f"End actions with {next_state=}")

iorisa avatar Mar 29 '24 07:03 iorisa

I find the new code correct.

tonystz avatar Apr 01 '24 03:04 tonystz