diff --git a/metagpt/actions/ask_review.py b/metagpt/actions/ask_review.py index 7eb553b7e..0d671648b 100644 --- a/metagpt/actions/ask_review.py +++ b/metagpt/actions/ask_review.py @@ -23,14 +23,15 @@ class ReviewConst: class AskReview(Action): - async def run(self, context: List[Message], plan: Plan = None, trigger: str = "task"): - logger.info("Current overall plan:") - logger.info( - "\n".join([f"{task.task_id}: {task.instruction}, is_finished: {task.is_finished}" for task in plan.tasks]) - ) + async def run(self, context: List[Message] = [], plan: Plan = None, trigger: str = "task"): + if plan: + logger.info("Current overall plan:") + logger.info( + "\n".join([f"{task.task_id}: {task.instruction}, is_finished: {task.is_finished}" for task in plan.tasks]) + ) logger.info("most recent context:") - latest_action = context[-1].cause_by if context[-1].cause_by else "" + latest_action = context[-1].cause_by if context and context[-1].cause_by else "" review_instruction = ( ReviewConst.TASK_REVIEW_INSTRUCTION if trigger == ReviewConst.TASK_REVIEW_TRIGGER diff --git a/metagpt/actions/write_analysis_code.py b/metagpt/actions/write_analysis_code.py index aef86122b..c5f9c9166 100644 --- a/metagpt/actions/write_analysis_code.py +++ b/metagpt/actions/write_analysis_code.py @@ -12,7 +12,7 @@ import yaml from tenacity import retry, stop_after_attempt, wait_fixed from metagpt.actions import Action -from metagpt.const import METAGPT_ROOT +from metagpt.const import METAGPT_ROOT, TOOL_SCHEMA_PATH from metagpt.llm import LLM from metagpt.logs import logger from metagpt.prompts.ml_engineer import ( @@ -93,7 +93,7 @@ class WriteCodeByGenerate(BaseWriteAnalysisCode): class WriteCodeWithTools(BaseWriteAnalysisCode): """Write code with help of local available tools. Choose tools first, then generate code to use the tools""" - schema_path: Union[Path, str] = METAGPT_ROOT / "metagpt/tools/functions/schemas" + schema_path: Union[Path, str] = TOOL_SCHEMA_PATH available_tools: dict = {} def __init__(self, **kwargs): diff --git a/metagpt/const.py b/metagpt/const.py index 811ff9516..b1666e092 100644 --- a/metagpt/const.py +++ b/metagpt/const.py @@ -70,6 +70,7 @@ TMP = METAGPT_ROOT / "tmp" SOURCE_ROOT = METAGPT_ROOT / "metagpt" PROMPT_PATH = SOURCE_ROOT / "prompts" SKILL_DIRECTORY = SOURCE_ROOT / "skills" +TOOL_SCHEMA_PATH = METAGPT_ROOT / "metagpt/tools/functions/schemas" # REAL CONSTS diff --git a/metagpt/roles/code_interpreter.py b/metagpt/roles/code_interpreter.py index 6bbd923e6..9b13d8dcb 100644 --- a/metagpt/roles/code_interpreter.py +++ b/metagpt/roles/code_interpreter.py @@ -13,6 +13,7 @@ from metagpt.utils.save_code import save_code_file class CodeInterpreter(Role): + auto_run: bool = True use_tools: bool = False make_udfs: bool = False # whether to save user-defined functions execute_code: ExecutePyCode = Field(default_factory=ExecutePyCode, exclude=True) @@ -22,12 +23,12 @@ class CodeInterpreter(Role): name="Charlie", profile="CodeInterpreter", goal="", - auto_run=False, + auto_run=True, use_tools=False, make_udfs=False, **kwargs, ): - super().__init__(name=name, profile=profile, goal=goal, use_tools=use_tools, make_udfs=make_udfs, **kwargs) + super().__init__(name=name, profile=profile, goal=goal, auto_run=auto_run, use_tools=use_tools, make_udfs=make_udfs, **kwargs) self._set_react_mode(react_mode="plan_and_act", auto_run=auto_run, use_tools=use_tools) @property @@ -96,4 +97,4 @@ class CodeInterpreter(Role): logger.info("Plan completed. Now start to make tools ...") tool_maker = ToolMaker() for task in self.planner.plan.get_finished_tasks(): - await tool_maker.make_tool(task.code, task.instruction, task.task_id) + await tool_maker.make_tool(code=task.code, instruction=task.instruction, task_id=task.task_id, auto_run=self.auto_run) diff --git a/metagpt/roles/ml_engineer.py b/metagpt/roles/ml_engineer.py index 639a517d6..cf903347d 100644 --- a/metagpt/roles/ml_engineer.py +++ b/metagpt/roles/ml_engineer.py @@ -12,7 +12,6 @@ from metagpt.utils.common import any_to_str class MLEngineer(CodeInterpreter): - auto_run: bool = False use_code_steps: bool = False use_udfs: bool = False data_desc: dict = {} diff --git a/metagpt/roles/tool_maker.py b/metagpt/roles/tool_maker.py index 7fec7b739..5453fd807 100644 --- a/metagpt/roles/tool_maker.py +++ b/metagpt/roles/tool_maker.py @@ -1,5 +1,6 @@ from pydantic import Field +from metagpt.actions.ask_review import AskReview from metagpt.actions.execute_code import ExecutePyCode from metagpt.actions.write_analysis_code import MakeTools from metagpt.logs import logger @@ -10,7 +11,7 @@ from metagpt.utils.common import remove_comments class ToolMaker(Role): execute_code: ExecutePyCode = Field(default_factory=ExecutePyCode, exclude=True) - async def make_tool(self, code: str, instruction: str, task_id: str = ""): + async def make_tool(self, code: str, instruction: str, task_id: str = "", auto_run=True): if len(remove_comments(code).split("\n")) < 5: # no need to consider trivial codes with fewer than 5 lines return @@ -41,4 +42,12 @@ class ToolMaker(Role): break # save successful tool code in udf if execute_success: - make_tools.save(tool_code) + _, confirmed = await self.ask_review(auto_run=auto_run) + if confirmed: + make_tools.save(tool_code) + + async def ask_review(self, auto_run: bool = True): + if not auto_run: + review, confirmed = await AskReview().run() + return review, confirmed + return "", True