diff --git a/metagpt/roles/di/data_analyst.py b/metagpt/roles/di/data_analyst.py index 359094c8e..6385bd349 100644 --- a/metagpt/roles/di/data_analyst.py +++ b/metagpt/roles/di/data_analyst.py @@ -25,6 +25,7 @@ from metagpt.utils.common import CodeParser class DataAnalyst(DataInterpreter): name: str = "David" profile: str = "DataAnalyst" + goal: str = "Take on any data-related tasks, such as data analysis, machine learning, deep learning, web browsing, web scraping, web searching, web deployment, terminal operation, git and github operation, etc." react_mode: Literal["react"] = "react" max_react_loop: int = 20 # used for react mode task_result: TaskResult = None @@ -55,7 +56,7 @@ class DataAnalyst(DataInterpreter): self._set_state(0) # HACK: Init Planner, control it through dynamic thinking; Consider formalizing as a react mode - self.planner = Planner(goal=self.goal, working_memory=self.rc.working_memory, auto_run=True) + self.planner = Planner(goal="", working_memory=self.rc.working_memory, auto_run=True) return self @@ -69,6 +70,8 @@ class DataAnalyst(DataInterpreter): example = KeywordExpRetriever().retrieve(self.user_requirement) else: self.working_memory.add_batch(self.rc.news) + context = "\n\n".join([str(mem) for mem in self.working_memory.get()]) + example = KeywordExpRetriever().retrieve(context) plan_status = self.planner.plan.model_dump(include=["goal", "tasks"]) for task in plan_status["tasks"]: @@ -96,6 +99,8 @@ class DataAnalyst(DataInterpreter): self.planner.plan.current_task.is_success = ( is_success # mark is_success, determine is_finished later in thinking ) + + # FIXME: task result is always overwritten by the last act, whereas it can be made of of multiple acts self.task_result = TaskResult(code=code, result=result, is_success=is_success) return Message(content="Task completed", role="assistant", sent_from=self._setting, cause_by=WriteAnalysisCode) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index edc49a1a0..7beb1b404 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -159,44 +159,101 @@ class SimpleExpRetriever(ExpRetriever): class KeywordExpRetriever(ExpRetriever): """An experience retriever that returns examples based on keywords in the context.""" - EXAMPLE: dict = { - "deploy": """ - ## example 1 - User Requirement: launch a service from workspace/web_snake_game/web_snake_game, and deploy it to public - Explanation: Launching a service requires Terminal tool with daemon mode, write this into task instruction. - ```json - [ - { - "command_name": "append_task", - "args": { - "task_id": "1", - "dependent_task_ids": [], - "instruction": "Use the Terminal tool to launch the service in daemon mode", - "assignee": "David" - } - }, - { - "command_name": "append_task", - "args": { - "task_id": "2", - "dependent_task_ids": ["1"], - "instruction": "Test the service with a simple request", - "assignee": "David" - } - }, - { - "command_name": "append_task", - "args": { - "task_id": "3", - "dependent_task_ids": ["2"], - "instruction": "Deploy the service to public", - "assignee": "David" - } - }, - """ - } - def retrieve(self, context: str) -> str: if "deploy" in context.lower(): - return self.EXAMPLE["deploy"] + return DEPLOY_EXAMPLE + elif "issue" in context.lower(): + return FIX_ISSUE_EXAMPLE return "" + + +DEPLOY_EXAMPLE = """ +## example 1 +User Requirement: launch a service from workspace/web_snake_game/web_snake_game, and deploy it to public +Explanation: Launching a service requires Terminal tool with daemon mode, write this into task instruction. +```json +[ + { + "command_name": "append_task", + "args": { + "task_id": "1", + "dependent_task_ids": [], + "instruction": "Use the Terminal tool to launch the service in daemon mode", + "assignee": "David" + } + }, + { + "command_name": "append_task", + "args": { + "task_id": "2", + "dependent_task_ids": ["1"], + "instruction": "Test the service with a simple request", + "assignee": "David" + } + }, + { + "command_name": "append_task", + "args": { + "task_id": "3", + "dependent_task_ids": ["2"], + "instruction": "Deploy the service to public", + "assignee": "David" + } + }, +""" + + +FIX_ISSUE_EXAMPLE = """ +## example 1 +User Requirement: Write a fix for this issue: https://github.com/xxx/xxx/issues/xxx, and commit and push your changes. +Explanation: The requirement is for software development, focusing on fixing an issue in an existing repository. The process is broken down into several steps, each demanding specific actions and tools. +```json +[ + { + "command_name": "append_task", + "args": { + "task_id": "1", + "dependent_task_ids": [], + "instruction": "Read the issue description to understand the problem using the Browser tool.", + "assignee": "David" + } + }, + { + "command_name": "append_task", + "args": { + "task_id": "2", + "dependent_task_ids": ["1"], + "instruction": "Clone the repository using the Terminal tool.", + "assignee": "David" + } + }, + { + "command_name": "append_task", + "args": { + "task_id": "3", + "dependent_task_ids": ["2"], + "instruction": "Use Editor to search the relevant function(s), then diagnose and identify the source of the problem.", + "assignee": "David" + } + }, + { + "command_name": "append_task", + "args": { + "task_id": "4", + "dependent_task_ids": ["3"], + "instruction": "Use Editor tool to fix the problem in the corresponding file(s).", + "assignee": "David" + } + }, + { + "command_name": "append_task", + "args": { + "task_id": "5", + "dependent_task_ids": ["4"], + "instruction": "Commit, push the changes to the repository.", + "assignee": "David" + } + }, +] +``` +"""