From d864ec88f345b05b3f37495404a2310356002112 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Fri, 28 Jun 2024 15:18:10 +0800 Subject: [PATCH 1/5] =?UTF-8?q?update:=201.=20DA=E5=A2=9E=E5=8A=A0json?= =?UTF-8?q?=E5=AE=B9=E9=94=99=202.=20=E6=8F=90=E7=A4=BA=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=BC=BA=E5=88=B6=E8=A6=81=E6=B1=82=E4=BB=A5[=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=EF=BC=88=E7=8E=B0=E5=9C=A8=E5=B9=B3=E5=8F=B0=E6=B5=81?= =?UTF-8?q?=E5=BC=8F=E8=A7=A3=E6=9E=90json=E7=9A=84=EF=BC=8C=E8=80=8Cjson?= =?UTF-8?q?=E5=AE=B9=E9=94=99=E6=98=AFjson=E5=85=A8=E9=83=A8=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E5=AE=8C=E6=89=8D=E6=9C=89=E7=9A=84=EF=BC=8C=E6=89=80?= =?UTF-8?q?=E4=BB=A5=E5=A6=82=E6=9E=9Cjson=E4=B8=8D=E6=98=AF=E4=BB=A5[?= =?UTF-8?q?=E5=BC=80=E5=A4=B4=E7=9A=84=E8=AF=9D=EF=BC=8C=E6=B5=81=E5=BC=8F?= =?UTF-8?q?=E5=B0=B1=E5=A4=B1=E6=95=88=E4=BA=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/prompts/di/data_analyst.py | 1 + metagpt/prompts/di/role_zero.py | 1 + metagpt/roles/di/data_analyst.py | 22 ++++++++++++++++++---- metagpt/strategy/thinking_command.py | 3 ++- metagpt/tools/tool_recommend.py | 18 ++++++++++++++++-- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/metagpt/prompts/di/data_analyst.py b/metagpt/prompts/di/data_analyst.py index 8450b2fe1..9ee17b4fd 100644 --- a/metagpt/prompts/di/data_analyst.py +++ b/metagpt/prompts/di/data_analyst.py @@ -40,4 +40,5 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` +Notice: your output must been started with **```json [** """ diff --git a/metagpt/prompts/di/role_zero.py b/metagpt/prompts/di/role_zero.py index a33487d81..de02df0b9 100644 --- a/metagpt/prompts/di/role_zero.py +++ b/metagpt/prompts/di/role_zero.py @@ -49,6 +49,7 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` +Notice: your output must been started with **```json [** """ JSON_REPAIR_PROMPT = """ diff --git a/metagpt/roles/di/data_analyst.py b/metagpt/roles/di/data_analyst.py index d4d67742b..1f8bd0862 100644 --- a/metagpt/roles/di/data_analyst.py +++ b/metagpt/roles/di/data_analyst.py @@ -9,6 +9,7 @@ from metagpt.actions import Action from metagpt.actions.di.write_analysis_code import WriteAnalysisCode from metagpt.logs import logger from metagpt.prompts.di.data_analyst import CMD_PROMPT +from metagpt.prompts.di.role_zero import JSON_REPAIR_PROMPT from metagpt.roles.di.data_interpreter import DataInterpreter from metagpt.schema import Message, TaskResult from metagpt.strategy.experience_retriever import KeywordExpRetriever @@ -21,6 +22,7 @@ from metagpt.strategy.thinking_command import ( from metagpt.tools.tool_recommend import BM25ToolRecommender from metagpt.utils.common import CodeParser from metagpt.utils.report import ThoughtReporter +from metagpt.utils.repair_llm_raw_output import repair_llm_raw_output, RepairType class DataAnalyst(DataInterpreter): @@ -83,11 +85,23 @@ class DataAnalyst(DataInterpreter): # print(*context, sep="\n" + "*" * 5 + "\n") async with ThoughtReporter(enable_llm_stream=True): rsp = await self.llm.aask(context) - self.commands = json.loads(CodeParser.parse_code(block=None, lang='json', text=rsp)) + + try: + commands = CodeParser.parse_code(block=None, lang="json", text=rsp) + commands = json.loads(repair_llm_raw_output(output=commands, req_keys=[None], repair_type=RepairType.JSON)) + except json.JSONDecodeError as e: + commands = await self.llm.aask(msg=JSON_REPAIR_PROMPT.format(json_data=rsp)) + commands = json.loads(CodeParser.parse_code(block=None, lang="json", text=commands)) + except Exception as e: + tb = traceback.format_exc() + print(tb) + + # 为了对LLM不按格式生成进行容错 + if isinstance(commands, dict): + commands = commands["commands"] if "commands" in commands else [commands] + self.rc.working_memory.add(Message(content=rsp, role="assistant")) - - await run_commands(self, self.commands, self.rc.working_memory) - + await run_commands(self, commands, self.rc.working_memory) return bool(self.rc.todo) async def _act(self) -> Message: diff --git a/metagpt/strategy/thinking_command.py b/metagpt/strategy/thinking_command.py index 14fdf5950..f08afa448 100644 --- a/metagpt/strategy/thinking_command.py +++ b/metagpt/strategy/thinking_command.py @@ -100,7 +100,8 @@ def run_plan_command(role: Role, cmd: list[dict]): elif cmd["command_name"] == Command.FINISH_CURRENT_TASK.cmd_name: if role.planner.plan.is_plan_finished(): return - role.planner.plan.current_task.update_task_result(task_result=role.task_result) + if role.task_result: + role.planner.plan.current_task.update_task_result(task_result=role.task_result) role.planner.plan.finish_current_task() role.rc.working_memory.clear() diff --git a/metagpt/tools/tool_recommend.py b/metagpt/tools/tool_recommend.py index 05e8e1400..1e86b5d89 100644 --- a/metagpt/tools/tool_recommend.py +++ b/metagpt/tools/tool_recommend.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import traceback from typing import Any import numpy as np @@ -14,6 +15,8 @@ from metagpt.tools import TOOL_REGISTRY from metagpt.tools.tool_data_type import Tool from metagpt.tools.tool_registry import validate_tool_names from metagpt.utils.common import CodeParser +from metagpt.utils.repair_llm_raw_output import repair_llm_raw_output, RepairType +from metagpt.prompts.di.role_zero import JSON_REPAIR_PROMPT TOOL_INFO_PROMPT = """ ## Capabilities @@ -132,9 +135,20 @@ class ToolRecommender(BaseModel): topk=topk, ) rsp = await LLM().aask(prompt, stream=False) - rsp = CodeParser.parse_code(text=rsp) - ranked_tools = json.loads(rsp) + try: + ranked_tools = CodeParser.parse_code(block=None, lang="json", text=rsp) + ranked_tools = json.loads(repair_llm_raw_output(output=ranked_tools, req_keys=[None], repair_type=RepairType.JSON)) + except json.JSONDecodeError as e: + ranked_tools = await self.llm.aask(msg=JSON_REPAIR_PROMPT.format(json_data=rsp)) + ranked_tools = json.loads(CodeParser.parse_code(block=None, lang="json", text=ranked_tools)) + except Exception as e: + tb = traceback.format_exc() + print(tb) + + # 为了对LLM不按格式生成进行容错 + if isinstance(ranked_tools, dict): + ranked_tools = list(ranked_tools.values())[0] valid_tools = validate_tool_names(ranked_tools) return list(valid_tools.values())[:topk] From 853f5fc40072f4c180d77022716fe25adce3423a Mon Sep 17 00:00:00 2001 From: zhanglei Date: Fri, 28 Jun 2024 15:36:57 +0800 Subject: [PATCH 2/5] =?UTF-8?q?update:=20=E5=A2=9E=E5=8A=A0=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/roles/di/data_analyst.py | 3 +++ metagpt/tools/tool_recommend.py | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/metagpt/roles/di/data_analyst.py b/metagpt/roles/di/data_analyst.py index 1f8bd0862..22afca1a6 100644 --- a/metagpt/roles/di/data_analyst.py +++ b/metagpt/roles/di/data_analyst.py @@ -86,6 +86,8 @@ class DataAnalyst(DataInterpreter): async with ThoughtReporter(enable_llm_stream=True): rsp = await self.llm.aask(context) + # 临时方案,待role zero的版本完成可将本注释内的代码直接替换掉 + # -------------开始--------------- try: commands = CodeParser.parse_code(block=None, lang="json", text=rsp) commands = json.loads(repair_llm_raw_output(output=commands, req_keys=[None], repair_type=RepairType.JSON)) @@ -99,6 +101,7 @@ class DataAnalyst(DataInterpreter): # 为了对LLM不按格式生成进行容错 if isinstance(commands, dict): commands = commands["commands"] if "commands" in commands else [commands] + # -------------结束--------------- self.rc.working_memory.add(Message(content=rsp, role="assistant")) await run_commands(self, commands, self.rc.working_memory) diff --git a/metagpt/tools/tool_recommend.py b/metagpt/tools/tool_recommend.py index 1e86b5d89..e92ae4bb5 100644 --- a/metagpt/tools/tool_recommend.py +++ b/metagpt/tools/tool_recommend.py @@ -136,6 +136,8 @@ class ToolRecommender(BaseModel): ) rsp = await LLM().aask(prompt, stream=False) + # 临时方案,待role zero的版本完成可将本注释内的代码直接替换掉 + # -------------开始--------------- try: ranked_tools = CodeParser.parse_code(block=None, lang="json", text=rsp) ranked_tools = json.loads(repair_llm_raw_output(output=ranked_tools, req_keys=[None], repair_type=RepairType.JSON)) @@ -149,6 +151,8 @@ class ToolRecommender(BaseModel): # 为了对LLM不按格式生成进行容错 if isinstance(ranked_tools, dict): ranked_tools = list(ranked_tools.values())[0] + # -------------结束--------------- + valid_tools = validate_tool_names(ranked_tools) return list(valid_tools.values())[:topk] From ad32edf1979d315f34c2485b6745a620bcce89b4 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Fri, 28 Jun 2024 16:03:37 +0800 Subject: [PATCH 3/5] update: cr commit --- metagpt/prompts/di/data_analyst.py | 2 +- metagpt/prompts/di/role_zero.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/metagpt/prompts/di/data_analyst.py b/metagpt/prompts/di/data_analyst.py index 9ee17b4fd..6a20b57ff 100644 --- a/metagpt/prompts/di/data_analyst.py +++ b/metagpt/prompts/di/data_analyst.py @@ -40,5 +40,5 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` -Notice: your output must been started with **```json [** +Notice: your output JSON data section must been started with **```json [** """ diff --git a/metagpt/prompts/di/role_zero.py b/metagpt/prompts/di/role_zero.py index de02df0b9..5a14d0b79 100644 --- a/metagpt/prompts/di/role_zero.py +++ b/metagpt/prompts/di/role_zero.py @@ -49,8 +49,7 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` -Notice: your output must been started with **```json [** - +Notice: your output JSON data section must been started with **```json [** """ JSON_REPAIR_PROMPT = """ ## json data From c7b9bbeb0abde33232d3374f8a47518800800527 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Fri, 28 Jun 2024 16:15:00 +0800 Subject: [PATCH 4/5] update: cr commit --- metagpt/prompts/di/data_analyst.py | 2 +- metagpt/prompts/di/role_zero.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/metagpt/prompts/di/data_analyst.py b/metagpt/prompts/di/data_analyst.py index 6a20b57ff..d26f2bf09 100644 --- a/metagpt/prompts/di/data_analyst.py +++ b/metagpt/prompts/di/data_analyst.py @@ -40,5 +40,5 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` -Notice: your output JSON data section must been started with **```json [** +Notice: your output JSON data section must start with **```json [** """ diff --git a/metagpt/prompts/di/role_zero.py b/metagpt/prompts/di/role_zero.py index 5a14d0b79..8f4a8804e 100644 --- a/metagpt/prompts/di/role_zero.py +++ b/metagpt/prompts/di/role_zero.py @@ -49,7 +49,7 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` -Notice: your output JSON data section must been started with **```json [** +Notice: your output JSON data section must start with **```json [** """ JSON_REPAIR_PROMPT = """ ## json data From f24dfec780ca323fc345a05405461cdd038732de Mon Sep 17 00:00:00 2001 From: zhanglei Date: Fri, 28 Jun 2024 16:22:34 +0800 Subject: [PATCH 5/5] update: cr commit --- metagpt/tools/tool_recommend.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/metagpt/tools/tool_recommend.py b/metagpt/tools/tool_recommend.py index e92ae4bb5..9f425fffe 100644 --- a/metagpt/tools/tool_recommend.py +++ b/metagpt/tools/tool_recommend.py @@ -10,13 +10,13 @@ from rank_bm25 import BM25Okapi from metagpt.llm import LLM from metagpt.logs import logger +from metagpt.prompts.di.role_zero import JSON_REPAIR_PROMPT from metagpt.schema import Plan from metagpt.tools import TOOL_REGISTRY from metagpt.tools.tool_data_type import Tool from metagpt.tools.tool_registry import validate_tool_names from metagpt.utils.common import CodeParser -from metagpt.utils.repair_llm_raw_output import repair_llm_raw_output, RepairType -from metagpt.prompts.di.role_zero import JSON_REPAIR_PROMPT +from metagpt.utils.repair_llm_raw_output import RepairType, repair_llm_raw_output TOOL_INFO_PROMPT = """ ## Capabilities @@ -140,11 +140,13 @@ class ToolRecommender(BaseModel): # -------------开始--------------- try: ranked_tools = CodeParser.parse_code(block=None, lang="json", text=rsp) - ranked_tools = json.loads(repair_llm_raw_output(output=ranked_tools, req_keys=[None], repair_type=RepairType.JSON)) - except json.JSONDecodeError as e: + ranked_tools = json.loads( + repair_llm_raw_output(output=ranked_tools, req_keys=[None], repair_type=RepairType.JSON) + ) + except json.JSONDecodeError: ranked_tools = await self.llm.aask(msg=JSON_REPAIR_PROMPT.format(json_data=rsp)) ranked_tools = json.loads(CodeParser.parse_code(block=None, lang="json", text=ranked_tools)) - except Exception as e: + except Exception: tb = traceback.format_exc() print(tb)