Merge pull request #384 from fromlimbo/minecraft

complete critic_agent & review_task
This commit is contained in:
Sirui Hong 2023-10-01 23:55:03 +08:00 committed by GitHub
commit cbd071a10e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 145 additions and 21 deletions

View file

@ -4,8 +4,7 @@
# @Desc :
from metagpt.logs import logger
from metagpt.actions import Action
from metagpt.actions import Action
from metagpt.utils.minecraft import fix_and_parse_json
class VerifyTask(Action):
@ -17,22 +16,31 @@ class VerifyTask(Action):
def __init__(self, name="", context=None, llm=None):
super().__init__(name, context, llm)
self.vect_db = ""
async def run(self, *args, **kwargs):
task, status, review_info = None, False, ""
async def run(self,human_msg, system_msg, max_retries=5, *args, **kwargs):
# Implement the logic to verify the task here.
# Example: Verify the completion of a task.
# If verification is successful, return a success message.
# task, status, review_info = "", True, "Task verified successfully."
if max_retries == 0:
logger.info(f"Failed to parse Critic Agent response. Consider updating your prompt.")
return False, ""
if human_msg or system_msg is None:
return False, ""
critic = await self._aask(prompt=human_msg, system_msgs=system_msg)
try:
# Implement the logic to verify the task here.
# Example: Verify the completion of a task.
# If verification is successful, return a success message.
response = fix_and_parse_json(critic)
assert response["success"] in [True, False]
if "critique" not in response:
response["critique"] = ""
logger.info("Task verified successfully.")
task, status, review_info = "", True, "Task verified successfully."
# If verification fails, return an appropriate error message.
# return "Task verification failed due to [reason]."
return response["success"], response["critique"]
except Exception as e:
# Handle any exceptions that may occur during verification.
logger.error(f"Error verifying the task: {str(e)}")
task, status, review_info = None, False, "Task verified failed."
return task, status, review_info
return self.run(human_msg, system_msg, max_retries=max_retries-1)

View file

@ -3,9 +3,16 @@
# @Author : stellahong (stellahong@fuzhi.ai)
# @Desc :
from metagpt.roles.minecraft.minecraft_base import Minecraft as Base
from metagpt.actions.minecraft.review_task import VerifyTask
from metagpt.actions.minecraft.generate_actions import GenerateActionCode
from metagpt.actions.minecraft.manage_skills import AddNewSkills
from metagpt.roles.minecraft.minecraft_base import agent_registry
from metagpt.actions.minecraft.review_task import VerifyTask
from metagpt.utils.minecraft import load_prompt
from metagpt.schema import Message, HumanMessage, SystemMessage
from metagpt.logs import logger
@agent_registry.register("critic_agent")
class CriticReviewer(Base):
"""
self-verification
@ -20,8 +27,117 @@ class CriticReviewer(Base):
super().__init__(name, profile, goal, constraints)
# Initialize actions specific to the CriticReviewer role
self._init_actions([VerifyTask])
# Set events or actions the CriticReviewer should watch or be aware of
# 需要获取最新的events来进行评估
self._watch([GenerateActionCode])
self._watch([GenerateActionCode,AddNewSkills])
def render_system_message(self):
system_message = SystemMessage(content=load_prompt("critic"))
return system_message
def render_human_message(self, events, task, context, chest_observation):
assert events[-1][0] == "observe", "Last event must be observe"
biome = events[-1][1]["status"]["biome"]
time_of_day = events[-1][1]["status"]["timeOfDay"]
voxels = events[-1][1]["voxels"]
health = events[-1][1]["status"]["health"]
hunger = events[-1][1]["status"]["food"]
position = events[-1][1]["status"]["position"]
equipment = events[-1][1]["status"]["equipment"]
inventory_used = events[-1][1]["status"]["inventoryUsed"]
inventory = events[-1][1]["inventory"]
for i, (event_type, event) in enumerate(events):
if event_type == "onError":
print(f"\033[31mCritic Agent: Error occurs {event['onError']}\033[0m")
return None
observation = ""
observation += f"Biome: {biome}\n\n"
observation += f"Time: {time_of_day}\n\n"
if voxels:
observation += f"Nearby blocks: {', '.join(voxels)}\n\n"
else:
observation += f"Nearby blocks: None\n\n"
observation += f"Health: {health:.1f}/20\n\n"
observation += f"Hunger: {hunger:.1f}/20\n\n"
observation += f"Position: x={position['x']:.1f}, y={position['y']:.1f}, z={position['z']:.1f}\n\n"
observation += f"Equipment: {equipment}\n\n"
if inventory:
observation += f"Inventory ({inventory_used}/36): {inventory}\n\n"
else:
observation += f"Inventory ({inventory_used}/36): Empty\n\n"
observation += chest_observation
observation += f"Task: {task}\n\n"
if context:
observation += f"Context: {context}\n\n"
else:
observation += f"Context: None\n\n"
logger.info(f"****Critic Agent human message****\n: {observation}")
return HumanMessage(content=observation)
def encapsule_message(self,
events,
task,
context,
chest_observation,
*args,
**kwargs,
):
system_message = self.render_system_message()
human_message = self.render_human_message(
events=events,
task=task,
context=context,
chest_observation=chest_observation,
)
return {
"system_msg": [system_message.content],
"human_msg": human_message.content,
}
async def verify_task(self,human_msg, system_msg, *args, **kwargs):
success, critique = await VerifyTask().run(human_msg, system_msg, max_retries=5)
return Message(content=f"{critique}", instruct_content="verify_task", role=self.profile,
send_to=agent_registry.entries["skill_manager"]()._setting.name)#addnewskill
#TODO:if not success
async def _act(self) -> Message:
todo = self._rc.todo
logger.debug(f"Todo is {todo}")
# 获取最新的游戏周边信息
events = await self._obtain_events()
context = self.game_memory.context
task = self.game_memory.current_task
chest_observation = self.game_memory.chest_observation
message = self.encapsule_message(events=events,
task=task,
context=context,
chest_observation=chest_observation, )
logger.info(todo)
handler_map = {
VerifyTask: self.verify_task,
}
handler = handler_map.get(type(todo))
logger.info(handler)
if handler:
msg = await handler(**message)
msg.cause_by = type(todo)
logger.info(msg.send_to)
self._publish_message(msg)
return msg
raise ValueError(f"Unknown todo type: {type(todo)}")