mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-01 20:03:28 +02:00
Merge branch 'tool_manage_new' into 'code_intepreter'
accept goal during run; move more logic from role to planner See merge request agents/data_agents_opt!63
This commit is contained in:
commit
31a9410e6d
3 changed files with 50 additions and 45 deletions
|
|
@ -44,6 +44,48 @@ class Planner(BaseModel):
|
|||
def current_task_id(self):
|
||||
return self.plan.current_task_id
|
||||
|
||||
async def update_plan(self, goal: str = "", max_tasks: int = 3, max_retries: int = 3):
|
||||
if goal:
|
||||
self.plan = Plan(goal=goal)
|
||||
|
||||
plan_confirmed = False
|
||||
while not plan_confirmed:
|
||||
context = self.get_useful_memories()
|
||||
rsp = await WritePlan().run(context, max_tasks=max_tasks, use_tools=self.use_tools)
|
||||
self.working_memory.add(Message(content=rsp, role="assistant", cause_by=WritePlan))
|
||||
|
||||
# precheck plan before asking reviews
|
||||
is_plan_valid, error = precheck_update_plan_from_rsp(rsp, self.plan)
|
||||
if not is_plan_valid and max_retries > 0:
|
||||
error_msg = f"The generated plan is not valid with error: {error}, try regenerating, remember to generate either the whole plan or the single changed task only"
|
||||
logger.warning(error_msg)
|
||||
self.working_memory.add(Message(content=error_msg, role="assistant", cause_by=WritePlan))
|
||||
max_retries -= 1
|
||||
continue
|
||||
|
||||
_, plan_confirmed = await self.ask_review(trigger=ReviewConst.TASK_REVIEW_TRIGGER)
|
||||
|
||||
update_plan_from_rsp(rsp=rsp, current_plan=self.plan)
|
||||
|
||||
self.working_memory.clear()
|
||||
|
||||
async def process_task_result(self, task_result: TaskResult):
|
||||
# ask for acceptance, users can other refuse and change tasks in the plan
|
||||
review, task_result_confirmed = await self.ask_review(task_result)
|
||||
|
||||
if task_result_confirmed:
|
||||
# tick off this task and record progress
|
||||
await self.confirm_task(self.current_task, task_result, review)
|
||||
|
||||
elif "redo" in review:
|
||||
# Ask the Role to redo this task with help of review feedback,
|
||||
# useful when the code run is successful but the procedure or result is not what we want
|
||||
pass # simply pass, not confirming the result
|
||||
|
||||
else:
|
||||
# update plan according to user's feedback and to take on changed tasks
|
||||
await self.update_plan()
|
||||
|
||||
async def ask_review(
|
||||
self, task_result: TaskResult = None, auto_run: bool = None, trigger: str = ReviewConst.TASK_REVIEW_TRIGGER
|
||||
):
|
||||
|
|
@ -74,28 +116,6 @@ class Planner(BaseModel):
|
|||
self.working_memory.add(Message(content=review, role="user", cause_by=AskReview))
|
||||
await self.update_plan(review)
|
||||
|
||||
async def update_plan(self, max_tasks: int = 3, max_retries: int = 3):
|
||||
plan_confirmed = False
|
||||
while not plan_confirmed:
|
||||
context = self.get_useful_memories()
|
||||
rsp = await WritePlan().run(context, max_tasks=max_tasks, use_tools=self.use_tools)
|
||||
self.working_memory.add(Message(content=rsp, role="assistant", cause_by=WritePlan))
|
||||
|
||||
# precheck plan before asking reviews
|
||||
is_plan_valid, error = precheck_update_plan_from_rsp(rsp, self.plan)
|
||||
if not is_plan_valid and max_retries > 0:
|
||||
error_msg = f"The generated plan is not valid with error: {error}, try regenerating, remember to generate either the whole plan or the single changed task only"
|
||||
logger.warning(error_msg)
|
||||
self.working_memory.add(Message(content=error_msg, role="assistant", cause_by=WritePlan))
|
||||
max_retries -= 1
|
||||
continue
|
||||
|
||||
_, plan_confirmed = await self.ask_review(trigger=ReviewConst.TASK_REVIEW_TRIGGER)
|
||||
|
||||
update_plan_from_rsp(rsp=rsp, current_plan=self.plan)
|
||||
|
||||
self.working_memory.clear()
|
||||
|
||||
def get_useful_memories(self, task_exclude_field=None) -> list[Message]:
|
||||
"""find useful memories only to reduce context length and improve performance"""
|
||||
# TODO dataset description , code steps
|
||||
|
|
|
|||
|
|
@ -452,10 +452,11 @@ class Role(SerializationMixin, is_polymorphic_base=True):
|
|||
async def _plan_and_act(self) -> Message:
|
||||
"""first plan, then execute an action sequence, i.e. _think (of a plan) -> _act -> _act -> ... Use llm to come up with the plan dynamically."""
|
||||
|
||||
### Common Procedure in both single- and multi-agent setting ###
|
||||
# create initial plan and update until confirmation
|
||||
await self.planner.update_plan()
|
||||
# create initial plan and update it until confirmation
|
||||
goal = self.rc.memory.get()[-1].content # retreive latest user requirement
|
||||
await self.planner.update_plan(goal=goal)
|
||||
|
||||
# take on tasks until all finished
|
||||
while self.planner.current_task:
|
||||
task = self.planner.current_task
|
||||
logger.info(f"ready to take on task {task}")
|
||||
|
|
@ -463,25 +464,10 @@ class Role(SerializationMixin, is_polymorphic_base=True):
|
|||
# take on current task
|
||||
task_result = await self._act_on_task(task)
|
||||
|
||||
# ask for acceptance, users can other refuse and change tasks in the plan
|
||||
review, task_result_confirmed = await self.planner.ask_review(task_result)
|
||||
# process the result, such as reviewing, confirming, plan updating
|
||||
await self.planner.process_task_result(task_result)
|
||||
|
||||
if task_result_confirmed:
|
||||
# tick off this task and record progress
|
||||
await self.planner.confirm_task(task, task_result, review)
|
||||
|
||||
elif "redo" in review:
|
||||
# Ask the Role to redo this task with help of review feedback,
|
||||
# useful when the code run is successful but the procedure or result is not what we want
|
||||
continue
|
||||
|
||||
else:
|
||||
# update plan according to user's feedback and to take on changed tasks
|
||||
await self.planner.update_plan()
|
||||
|
||||
completed_plan_memory = self.planner.get_useful_memories() # completed plan as a outcome
|
||||
|
||||
rsp = completed_plan_memory[0]
|
||||
rsp = self.planner.get_useful_memories()[0] # return the completed plan as a response
|
||||
|
||||
self.rc.memory.add(rsp) # add to persistent memory
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,9 @@ async def run_code_interpreter(role_class, requirement, auto_run, use_tools, use
|
|||
"""
|
||||
|
||||
if role_class == "ci":
|
||||
role = CodeInterpreter(goal=requirement, auto_run=auto_run, use_tools=use_tools, tools=tools)
|
||||
role = CodeInterpreter(auto_run=auto_run, use_tools=use_tools, tools=tools)
|
||||
else:
|
||||
role = MLEngineer(
|
||||
goal=requirement,
|
||||
auto_run=auto_run,
|
||||
use_tools=use_tools,
|
||||
use_code_steps=use_code_steps,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue