Repository: geekan/MetaGPT
File: metagpt/roles/role.py (Python)

Code before:
        """Get the role description (position)"""
        return self._setting.profile

    def _get_prefix(self):
        """Get the role prefix"""
        if self._setting.desc:
            return self._setting.desc
        return PREFIX_TEMPLATE.format(**self._setting.dict())

    async def _think(self) -> None:
        """Think about what to do and decide on the next action"""
        if len(self._actions) == 1:
            # If there is only one action, then only this one can be performed
            self._set_state(0)
            return
        prompt = self._get_prefix()
        prompt += STATE_TEMPLATE.format(history=self._rc.history, states="\n".join(self._states),
                                        n_states=len(self._states) - 1, previous_state=self._rc.state)
        # print(prompt)
        next_state = await self._llm.aask(prompt)
        logger.debug(f"{prompt=}")
        if not next_state.isdigit() or int(next_state) not in range(-1, len(self._states)):
            logger.warning(f'Invalid answer of state, {next_state=}')
            next_state = None
        else:
            next_state = int(next_state)
            if next_state == -1:
                logger.info(f"End actions with {next_state=}")
                next_state = None
        self._set_state(next_state)

    async def _act(self) -> Message:
        # prompt = self.get_prefix()
        # prompt += ROLE_TEMPLATE.format(name=self.profile, state=self.states[self.state], result=response,
        #                                history=self.history)

        logger.info(f"{self._setting}: ready to {self._rc.todo}")
        response = await self._rc.todo.run(self._rc.important_memory)
        # logger.info(response)
        if isinstance(response, ActionOutput):
            msg = Message(content=response.content, instruct_content=response.instruct_content,
                        role=self.profile, cause_by=type(self._rc.todo))
        else:
            msg = Message(content=response, role=self.profile, cause_by=type(self._rc.todo))
        self._rc.memory.add(msg)
        # logger.debug(f"{response}")

        return msg

    async def _observe(self) -> int:
        """Observe from the environment, obtain important information, and add it to memory"""

Review comment (suggestion):
in react mode, if it's the first think, there is no previous state but the self._rc.state=None. Does it cause an influence? What about self._rc_state default value = -1 to make it meet int type.

Code after:
        self._rc.todo = self._actions[self._rc.state] if state >= 0 else None

    def set_env(self, env: 'Environment'):
        """Set the environment in which the role works. The role can talk to the environment and can also receive messages by observing."""
        self._rc.env = env

    @property
    def profile(self):
        """Get the role description (position)"""
        return self._setting.profile

    def _get_prefix(self):
        """Get the role prefix"""
        if self._setting.desc:
            return self._setting.desc
        return PREFIX_TEMPLATE.format(**self._setting.dict())

    async def _think(self) -> None:
        """Think about what to do and decide on the next action"""
        if len(self._actions) == 1:
            # If there is only one action, then only this one can be performed
            self._set_state(0)
            return
        prompt = self._get_prefix()
        prompt += STATE_TEMPLATE.format(history=self._rc.history, states="\n".join(self._states),
                                        n_states=len(self._states) - 1, previous_state=self._rc.state)
        # print(prompt)
        next_state = await self._llm.aask(prompt)
        logger.debug(f"{prompt=}")
        if (not next_state.isdigit() and next_state != "-1") \
            or int(next_state) not in range(-1, len(self._states)):
            logger.warning(f'Invalid answer of state, {next_state=}, will be set to -1')
            next_state = -1
        else:
            next_state = int(next_state)
            if next_state == -1:
                logger.info(f"End actions with {next_state=}")
        self._set_state(next_state)

    async def _act(self) -> Message:
        # prompt = self.get_prefix()
        # prompt += ROLE_TEMPLATE.format(name=self.profile, state=self.states[self.state], result=response,
        #                                history=self.history)

        logger.info(f"{self._setting}: ready to {self._rc.todo}")
        response = await self._rc.todo.run(self._rc.important_memory)
        # logger.info(response)
        if isinstance(response, ActionOutput):
            msg = Message(content=response.content, instruct_content=response.instruct_content,
                        role=self.profile, cause_by=type(self._rc.todo))
        else: