From 52592ad1667714115469efafefb9fc81d0d4a24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=98=E6=9D=83=20=E9=A9=AC?= Date: Mon, 8 Apr 2024 12:40:20 +0800 Subject: [PATCH 1/2] fixbug: intent type error --- metagpt/actions/di/detect_intent.py | 31 +++++++++++++++++++---------- metagpt/roles/di/mgx.py | 4 ++-- tests/metagpt/roles/di/test_mgx.py | 6 +++--- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/metagpt/actions/di/detect_intent.py b/metagpt/actions/di/detect_intent.py index 92d4aeb54..1fb1c9089 100644 --- a/metagpt/actions/di/detect_intent.py +++ b/metagpt/actions/di/detect_intent.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import re from enum import Enum from typing import Tuple @@ -78,13 +79,16 @@ DETECT_PROMPT = """ # Intentions {intentions} # Task -Classify user requirement into one type of the above intentions, output the name of the intention directly. -Intention name: +Classify user requirement into one type of the above intentions, output the index of the intention directly. +Intention index: """ REQ_WITH_SOP = """ {user_requirement} -You should follow the following Standard Operating Procedure: +## Knowledge +To meet user requirements, the following standard operating procedure(SOP) must be used. +SOP descriptions cannot be modified; user requirements can only be appended to the end of corresponding steps. + {sop} """ @@ -92,17 +96,24 @@ You should follow the following Standard Operating Procedure: class DetectIntent(Action): async def run(self, with_message: Message, **kwargs) -> Tuple[str, str]: user_requirement = with_message.content - intentions = "\n".join([f"{si.type_name}: {si.value.description}" for si in SOPItem]) + mappings = {i + 1: si for i, si in enumerate(SOPItem)} + intentions = "\n".join([f"{i+1}. {si.type_name}: {si.value.description}" for i, si in enumerate(SOPItem)]) prompt = DETECT_PROMPT.format(user_requirement=user_requirement, intentions=intentions) - sop_type = await self._aask(prompt) - sop_type = sop_type.strip() - - item = SOPItem.get_type(sop_type) - sop = item.sop if item else None + rsp = await self._aask(prompt) + match = re.search(r"\d+", rsp) + index = len(SOPItem) + 1 # 1-based + if match: + index = int(match.group()) # 1-based + sop = mappings[index].value.sop if index in mappings else None + sop_type = mappings[index].type_name if index in mappings else SOPItem.OTHER.type_name req_with_sop = ( - REQ_WITH_SOP.format(user_requirement=user_requirement, sop="\n".join(sop)) if sop else user_requirement + REQ_WITH_SOP.format( + user_requirement=user_requirement, sop="\n".join([f"{i+1}. {v}" for i, v in enumerate(sop)]) + ) + if sop + else user_requirement ) return req_with_sop, sop_type diff --git a/metagpt/roles/di/mgx.py b/metagpt/roles/di/mgx.py index 1002a559c..0fa7c77b6 100644 --- a/metagpt/roles/di/mgx.py +++ b/metagpt/roles/di/mgx.py @@ -14,7 +14,7 @@ class MGX(DataInterpreter): use_intent: bool = True intents: Dict = {} - async def _detect_intent(self, user_msg: Message): + async def _detect_intent(self, user_msg: Message) -> str: todo = DetectIntent(context=self.context) request_with_sop, sop_type = await todo.run(user_msg) logger.info(f"{sop_type} {request_with_sop}") @@ -24,7 +24,7 @@ class MGX(DataInterpreter): """first plan, then execute an action sequence, i.e. _think (of a plan) -> _act -> _act -> ... Use llm to come up with the plan dynamically.""" # create initial plan and update it until confirmation - goal = self.rc.memory.get()[-1].content # retreive latest user requirement + goal = self.rc.memory.get()[-1].content # retrieve latest user requirement if self.use_intent: # add mode user_message = Message(content=goal, role="user") goal = await self._detect_intent(user_message) diff --git a/tests/metagpt/roles/di/test_mgx.py b/tests/metagpt/roles/di/test_mgx.py index 534e32499..3c08fb356 100644 --- a/tests/metagpt/roles/di/test_mgx.py +++ b/tests/metagpt/roles/di/test_mgx.py @@ -139,11 +139,11 @@ DEMO3_CONTENT = [ "user_messages", [ [Message.model_validate(i) for i in DEMO2_CONTENT if i["role"] == "user"], - [Message.model_validate(i) for i in DEMO_CONTENT if i["role"] == "user"], - [Message.model_validate(i) for i in DEMO1_CONTENT if i["role"] == "user"], + # [Message.model_validate(i) for i in DEMO_CONTENT if i["role"] == "user"], + # [Message.model_validate(i) for i in DEMO1_CONTENT if i["role"] == "user"], ], ) -@pytest.mark.skip +# @pytest.mark.skip async def test_mgx(user_messages: List[Message], context): mgx = MGX(context=context, tools=[""]) From c9a42e85bbf775300c38a685e66f3fe9e97d9b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=98=E6=9D=83=20=E9=A9=AC?= Date: Mon, 8 Apr 2024 12:43:19 +0800 Subject: [PATCH 2/2] fixbug: intent type error --- tests/metagpt/roles/di/test_mgx.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/metagpt/roles/di/test_mgx.py b/tests/metagpt/roles/di/test_mgx.py index 3c08fb356..534e32499 100644 --- a/tests/metagpt/roles/di/test_mgx.py +++ b/tests/metagpt/roles/di/test_mgx.py @@ -139,11 +139,11 @@ DEMO3_CONTENT = [ "user_messages", [ [Message.model_validate(i) for i in DEMO2_CONTENT if i["role"] == "user"], - # [Message.model_validate(i) for i in DEMO_CONTENT if i["role"] == "user"], - # [Message.model_validate(i) for i in DEMO1_CONTENT if i["role"] == "user"], + [Message.model_validate(i) for i in DEMO_CONTENT if i["role"] == "user"], + [Message.model_validate(i) for i in DEMO1_CONTENT if i["role"] == "user"], ], ) -# @pytest.mark.skip +@pytest.mark.skip async def test_mgx(user_messages: List[Message], context): mgx = MGX(context=context, tools=[""])