mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-17 15:35:21 +02:00
在mc branch添加相关的actions
This commit is contained in:
parent
3f892482a2
commit
5f521d4270
17 changed files with 878 additions and 0 deletions
35
metagpt/actions/minecraft/__init__.py
Normal file
35
metagpt/actions/minecraft/__init__.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:26
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from enum import Enum
|
||||
|
||||
from metagpt.actions.action import Action
|
||||
from metagpt.actions.action_output import ActionOutput
|
||||
from metagpt.actions.minecraft.design_curriculumn import DesignTask, DesignCurriculum
|
||||
from metagpt.actions.minecraft.generate_actions import GenerateActionCode, SummarizeLog
|
||||
from metagpt.actions.minecraft.manage_skills import RetrieveSkills, GenerateSkillDescription, AddNewSkills
|
||||
from metagpt.actions.minecraft.review_task import VerifyTask
|
||||
from metagpt.actions.minecraft.player_action import PlayerActions
|
||||
|
||||
|
||||
class ActionType(Enum):
|
||||
"""All types of Actions, used for indexing."""
|
||||
|
||||
Design_Task = DesignTask
|
||||
Design_Curriculum = DesignCurriculum
|
||||
Generate_Action_Code = GenerateActionCode
|
||||
Summarize_Log = SummarizeLog
|
||||
Retrieve_Skills = RetrieveSkills
|
||||
Generate_Skill_Description = GenerateSkillDescription
|
||||
Add_New_Skills = AddNewSkills
|
||||
Verify_Task = VerifyTask
|
||||
Player_Actions = PlayerActions
|
||||
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ActionType",
|
||||
"Action",
|
||||
"ActionOutput",
|
||||
]
|
||||
84
metagpt/actions/minecraft/design_curriculumn.py
Normal file
84
metagpt/actions/minecraft/design_curriculumn.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:56
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.logs import logger
|
||||
from metagpt.actions import Action
|
||||
|
||||
|
||||
class DesignTask(Action):
|
||||
"""
|
||||
Action class for decomposing a task.
|
||||
Refer to the code in the voyager/agents/curriculum.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
def decompose_task(self, query):
|
||||
# Implement the logic to decompose a task here.
|
||||
return ""
|
||||
|
||||
async def propose_next_ai_task(self, prompts, system_msg):
|
||||
"""
|
||||
Refer to the code in the voyager/agents/curriculum.py propose_next_ai_task() for implementation details.
|
||||
Returns:
|
||||
|
||||
"""
|
||||
curriculum = await self._aask(prompt=prompts, system_msgs=system_msg)
|
||||
|
||||
logger.info(f"\033[31m****Curriculum Agent ai message****\n{curriculum}\033[0m")
|
||||
|
||||
def parse_llm_response(self, llm_resp):
|
||||
# Implement the logic to parse the LLM response here.
|
||||
return "", ""
|
||||
|
||||
async def run(self, human_msg, system_msg, *args, **kwargs):
|
||||
logger.info(f"run {self.__repr__()}")
|
||||
|
||||
# Call the language model to generate a response.
|
||||
|
||||
llm_response = await self.propose_next_ai_task(prompts=human_msg, system_msg=system_msg)
|
||||
|
||||
# Parse the response from the language model.
|
||||
task, context = self.parse_llm_response(llm_response)
|
||||
|
||||
return task, context
|
||||
|
||||
|
||||
class DesignCurriculum(Action):
|
||||
"""
|
||||
Action class for designing curriculum-related questions.
|
||||
Refer to the code in the voyager/agents/curriculum.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
self.vect_db = ""
|
||||
|
||||
def get_task_context(self):
|
||||
# Implement the logic for a specific task in generating context.
|
||||
return ""
|
||||
|
||||
def generate_qa(self):
|
||||
# Implement the logic to generate curriculum-related questions and answers.
|
||||
question = ""
|
||||
answer = ""
|
||||
context = f"Question: {question}\n{answer}"
|
||||
return context
|
||||
|
||||
def generate_qa_step1(self):
|
||||
# Implement the logic for a specific step in generating questions and answers.
|
||||
return ""
|
||||
|
||||
def generate_qa_step2(self):
|
||||
# Implement the logic for another specific step in generating questions and answers.
|
||||
return ""
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
logger.info(f"run {self.__repr__()}")
|
||||
# Generate curriculum-related questions and answers.
|
||||
curriculum_qa = self.generate_qa()
|
||||
|
||||
# Return the generated questions and answers.
|
||||
return curriculum_qa
|
||||
57
metagpt/actions/minecraft/generate_actions.py
Normal file
57
metagpt/actions/minecraft/generate_actions.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 15:44
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.logs import logger
|
||||
from metagpt.actions import Action
|
||||
|
||||
|
||||
class GenerateActionCode(Action):
|
||||
"""
|
||||
Action class for generating action code.
|
||||
Refer to the code in the voyager/agents/action.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
async def generate_code(self):
|
||||
"""
|
||||
Generate action code logic.
|
||||
|
||||
Implement the logic for generating action code here.
|
||||
"""
|
||||
return ""
|
||||
|
||||
async def run(self, human_msg, system_msg=[], *args, **kwargs):
|
||||
logger.info(f"run {self.__repr__()}")
|
||||
# Generate action code.
|
||||
generated_code = await self.generate_code()
|
||||
|
||||
# Return the generated code.
|
||||
return generated_code
|
||||
|
||||
|
||||
class SummarizeLog(Action):
|
||||
"""
|
||||
Action class for parsing and summarizing logs.
|
||||
Refer to the code in the voyager/agents/action.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
async def summarize_logs(self):
|
||||
"""
|
||||
Summarize chatlogs.
|
||||
|
||||
Implement the logic for summarizing chatlogs here.
|
||||
"""
|
||||
return ""
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
# Summarize chatlogs.
|
||||
summary = await self.summarize_logs()
|
||||
|
||||
# Return the summary.
|
||||
return summary
|
||||
53
metagpt/actions/minecraft/manage_skills.py
Normal file
53
metagpt/actions/minecraft/manage_skills.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:56
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.actions import Action
|
||||
|
||||
|
||||
class RetrieveSkills(Action):
|
||||
"""
|
||||
Action class for retrieving skills.
|
||||
Refer to the code in the voyager/agents/skill.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
self.vect_db = ""
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
# Implement the logic for retrieving skills here.
|
||||
return []
|
||||
|
||||
|
||||
class AddNewSkills(Action):
|
||||
"""
|
||||
Action class for adding new skills.
|
||||
Refer to the code in the voyager/agents/skill.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
# Implement the logic for adding new skills here.
|
||||
pass
|
||||
|
||||
|
||||
class GenerateSkillDescription(Action):
|
||||
"""
|
||||
Action class for generating skill descriptions.
|
||||
Refer to the code in the voyager/agents/skill.py for implementation details.
|
||||
"""
|
||||
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
# Implement the logic for generating skill descriptions here.
|
||||
pass
|
||||
|
||||
|
||||
|
||||
10
metagpt/actions/minecraft/player_action.py
Normal file
10
metagpt/actions/minecraft/player_action.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 17:06
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.actions import Action
|
||||
|
||||
class PlayerActions(Action):
|
||||
"""Minecraft player info without any implementation details"""
|
||||
async def run(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
38
metagpt/actions/minecraft/review_task.py
Normal file
38
metagpt/actions/minecraft/review_task.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:56
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.logs import logger
|
||||
from metagpt.actions import Action
|
||||
|
||||
from metagpt.actions import Action
|
||||
|
||||
|
||||
class VerifyTask(Action):
|
||||
"""
|
||||
Action class for verifying a task.
|
||||
Refer to the code in the voyager/agents/critic.py for implementation details.
|
||||
"""
|
||||
|
||||
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, ""
|
||||
try:
|
||||
# Implement the logic to verify the task here.
|
||||
|
||||
# Example: Verify the completion of a task.
|
||||
|
||||
# If verification is successful, return a success message.
|
||||
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]."
|
||||
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
|
||||
110
metagpt/minecraft_team.py
Normal file
110
metagpt/minecraft_team.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:14
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from typing import Iterable, Dict, Any
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles import Role
|
||||
from metagpt.schema import Message
|
||||
from metagpt.software_company import SoftwareCompany
|
||||
|
||||
from metagpt.actions.minecraft.player_action import PlayerActions
|
||||
from metagpt.roles.minecraft.minecraft_base import Minecraft
|
||||
from metagpt.environment import Environment
|
||||
|
||||
|
||||
class GameMemory(BaseModel):
|
||||
"""
|
||||
游戏环境的记忆,用于多个agent进行信息的共享和缓存,而不需要重复在自己的角色内维护缓存
|
||||
"""
|
||||
event: dict[str, Any] = Field(default_factory=dict)
|
||||
current_task: str = Field(default="Craft 4 wooden planks")
|
||||
task_execution_time: float = Field(default=float)
|
||||
context: str = Field(default="")
|
||||
|
||||
def register_roles(self, roles: Iterable[Minecraft]):
|
||||
for role in roles:
|
||||
role.set_memory(self)
|
||||
|
||||
def update_event(self, event: Dict):
|
||||
self.event = event
|
||||
|
||||
def update_task(self, task: str):
|
||||
self.current_task = task
|
||||
|
||||
def update_context(self, context: str):
|
||||
self.context = context
|
||||
|
||||
async def on_event(self, *args):
|
||||
"""
|
||||
Retrieve Minecraft events.
|
||||
|
||||
This function is used to obtain events from the Minecraft environment. Check the implementation in
|
||||
the 'voyager/env/bridge.py step()' function to capture events generated within the game.
|
||||
|
||||
Returns:
|
||||
list: A list of Minecraft events.
|
||||
|
||||
Raises:
|
||||
Exception: If there is an issue retrieving events.
|
||||
"""
|
||||
try:
|
||||
# Implement the logic to retrieve Minecraft events here.
|
||||
events = {
|
||||
"Biome": "river",
|
||||
"Time": "night",
|
||||
"Nearby blocks": "water, dirt, stone, coal_ore, sandstone, grass_block, sand, grass, oak_leaves, fern, seagrass, tall_seagrass",
|
||||
"Nearby entities(nearest to farthest)": "turtle, salmon",
|
||||
"Health": "20.0 / 20",
|
||||
"Hunger": "20.0 / 20",
|
||||
"Position": "x = -47.5, y = 63.0, z = -283.5",
|
||||
"Equipment": [],
|
||||
"Inventory(0 / 36)": "Empty",
|
||||
"Chests": ""
|
||||
}
|
||||
# Example: events = minecraft_api.get_events()
|
||||
|
||||
return events
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to retrieve Minecraft events: {str(e)}")
|
||||
raise {}
|
||||
|
||||
|
||||
class MinecraftPlayer(SoftwareCompany):
|
||||
"""
|
||||
Software Company: Possesses a team, SOP (Standard Operating Procedures), and a platform for instant messaging,
|
||||
dedicated to writing executable code.
|
||||
"""
|
||||
environment: Environment = Field(default_factory=Environment)
|
||||
game_memory: GameMemory = Field(default_factory=GameMemory)
|
||||
investment: float = Field(default=50.0)
|
||||
task: str = Field(default="")
|
||||
game_info: dict = Field(default={})
|
||||
|
||||
def hire(self, roles: list[Role]):
|
||||
self.environment.add_roles(roles)
|
||||
self.game_memory.register_roles(roles)
|
||||
|
||||
def start(self, task):
|
||||
"""Start a project from publishing boss requirement."""
|
||||
self.task = task
|
||||
self.environment.publish_message(Message(role="Player", content=task, cause_by=PlayerActions))
|
||||
logger.info(self.game_info)
|
||||
|
||||
def _save(self):
|
||||
logger.info(self.json())
|
||||
|
||||
async def run(self, n_round=3):
|
||||
"""Run company until target round or no money"""
|
||||
while n_round > 0:
|
||||
# self._save()
|
||||
n_round -= 1
|
||||
logger.debug(f"{n_round=}")
|
||||
self._check_balance()
|
||||
await self.environment.run()
|
||||
|
||||
return self.environment.history
|
||||
|
||||
|
||||
4
metagpt/roles/minecraft/__init__.py
Normal file
4
metagpt/roles/minecraft/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:27
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
78
metagpt/roles/minecraft/action_developer.py
Normal file
78
metagpt/roles/minecraft/action_developer.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 12:45
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles.minecraft.minecraft_base import Minecraft as Base
|
||||
from metagpt.schema import Message, HumanMessage, SystemMessage
|
||||
from metagpt.roles.minecraft.minecraft_base import agent_registry
|
||||
from metagpt.actions.minecraft.generate_actions import GenerateActionCode
|
||||
from metagpt.actions.minecraft.design_curriculumn import DesignCurriculum
|
||||
from metagpt.actions.minecraft.manage_skills import GenerateSkillDescription, RetrieveSkills, AddNewSkills
|
||||
|
||||
|
||||
@agent_registry.register("action_developer")
|
||||
class ActionDeveloper(Base):
|
||||
"""
|
||||
iterative prompting mechanism in paper.
|
||||
generate action code based on environment observation and plan, as well as skills retrieval results
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "Bob",
|
||||
profile: str = "Generate code for specified tasks",
|
||||
goal: str = "Produce accurate and efficient code solutions in Python and JavaScript",
|
||||
constraints: str = "Adhere to coding best practices and style guidelines",
|
||||
) -> None:
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
# Initialize actions specific to the Action role
|
||||
self._init_actions([GenerateActionCode])
|
||||
|
||||
# Set events or actions the ActionAgent should watch or be aware of
|
||||
# 需要根据events进行自己chest_observation的更新
|
||||
self._watch([RetrieveSkills])
|
||||
|
||||
async def _observe(self) -> int:
|
||||
await super()._observe()
|
||||
for msg in self._rc.news:
|
||||
logger.info(msg.send_to == self._setting.name)
|
||||
self._rc.news = [
|
||||
msg for msg in self._rc.news if msg.send_to == self._setting.name
|
||||
] # only relevant msgs count as observed news
|
||||
logger.info(len(self._rc.news))
|
||||
return len(self._rc.news)
|
||||
|
||||
async def generate_action_code(self, human_msg, system_msg, *args, **kwargs):
|
||||
code = await GenerateActionCode().run(human_msg)
|
||||
logger.info(code)
|
||||
msg = Message(content=f"test_action", instruct_content="generate_action_code", role=self.profile)
|
||||
logger.info(msg)
|
||||
return msg
|
||||
|
||||
async def _act(self) -> Message:
|
||||
todo = self._rc.todo
|
||||
logger.debug(f"Todo is {todo}")
|
||||
|
||||
# 获取最新的游戏周边信息
|
||||
context = self.game_memory.context
|
||||
task = self.game_memory.current_task
|
||||
|
||||
message = self.encapsule_message(task, context)
|
||||
logger.info(todo)
|
||||
handler_map = {
|
||||
|
||||
GenerateActionCode: self.generate_action_code,
|
||||
}
|
||||
handler = handler_map.get(type(todo))
|
||||
logger.info(handler)
|
||||
|
||||
if handler:
|
||||
msg = await handler(**message)
|
||||
logger.info(msg)
|
||||
msg.cause_by = type(todo)
|
||||
logger.info(msg.send_to)
|
||||
self._publish_message(msg)
|
||||
return msg
|
||||
|
||||
raise ValueError(f"Unknown todo type: {type(todo)}")
|
||||
27
metagpt/roles/minecraft/critic_agent.py
Normal file
27
metagpt/roles/minecraft/critic_agent.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 12:46
|
||||
# @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
|
||||
|
||||
class CriticReviewer(Base):
|
||||
"""
|
||||
self-verification
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "Simon",
|
||||
profile: str = "Task Reviewer",
|
||||
goal: str = "To provide insightful and constructive feedback on a wide range of content types, helping creators improve their work and maintaining high-quality standards.",
|
||||
constraints: str = "Adherence to ethical reviewing practices, respectful communication, and confidentiality of sensitive information.",
|
||||
) -> None:
|
||||
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])
|
||||
|
||||
93
metagpt/roles/minecraft/curriculum_agent.py
Normal file
93
metagpt/roles/minecraft/curriculum_agent.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 12:45
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.logs import logger
|
||||
from metagpt.schema import Message, HumanMessage, SystemMessage
|
||||
from metagpt.roles.minecraft.minecraft_base import Minecraft as Base
|
||||
from metagpt.actions.minecraft.design_curriculumn import DesignCurriculum, DesignTask
|
||||
from metagpt.actions.minecraft.player_action import PlayerActions
|
||||
|
||||
|
||||
class CurriculumDesigner(Base):
|
||||
"""
|
||||
CurriculumDesigner is the automatic curriculum in paper, refer to the code voyager/agents/curriculum.py
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "David",
|
||||
profile: str = "Expertise in minecraft task design and curriculum development.",
|
||||
goal: str = " Collect and integrate learner feedback to improve and refine educational content and pathways",
|
||||
constraints: str = "Limited budget and resources for the development of educational content and technology tools."
|
||||
) -> None:
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
# Initialize actions specific to the Action role
|
||||
self._init_actions([DesignTask, DesignCurriculum])
|
||||
|
||||
# Set events or actions the ActionAgent should watch or be aware of
|
||||
self._watch([PlayerActions, DesignTask])
|
||||
|
||||
def render_human_message(self, msg, *args, **kwargs):
|
||||
return HumanMessage(content=msg)
|
||||
|
||||
def render_system_message(self, msg, *args, **kwargs):
|
||||
return SystemMessage(content=msg)
|
||||
|
||||
async def handle_task_design(self, human_msg, system_msg, *args, **kwargs):
|
||||
"""
|
||||
Args:
|
||||
human_msg:
|
||||
system_msg:
|
||||
*args:
|
||||
**kwargs:
|
||||
|
||||
Returns:
|
||||
"""
|
||||
task = await DesignTask().run(human_msg, system_msg, *args, **kwargs)
|
||||
self.perform_game_info_callback(task, self.game_memory.update_task)
|
||||
return Message(content=f"{task}", instruct_content="task_design", role=self.profile)
|
||||
|
||||
async def handle_curriculum_design(self, human_msg, system_msg, *args, **kwargs):
|
||||
"""
|
||||
refer to the context generation in voyager
|
||||
Args:
|
||||
human_msg:
|
||||
system_msg:
|
||||
*args:
|
||||
**kwargs:
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
context = await DesignCurriculum().run(human_msg, system_msg, *args, **kwargs)
|
||||
self.perform_game_info_callback(context, self.game_memory.update_context)
|
||||
return Message(content=f"{context}", instruct_content="curriculum_design", role=self.profile)
|
||||
|
||||
async def _act(self) -> Message:
|
||||
todo = self._rc.todo
|
||||
logger.debug(f"Todo is {todo}")
|
||||
|
||||
# 获取最新的游戏周边环境信息
|
||||
event = await self._obtain_events()
|
||||
task = self.game_memory.current_task
|
||||
context = self.game_memory.context
|
||||
|
||||
msg = self._rc.memory.get(k=1)[0]
|
||||
query = msg.content
|
||||
|
||||
message = self.encapsule_message(query, task, event)
|
||||
|
||||
handler_map = {
|
||||
|
||||
DesignTask: self.handle_task_design,
|
||||
DesignCurriculum: self.handle_curriculum_design,
|
||||
}
|
||||
handler = handler_map.get(type(todo))
|
||||
if handler:
|
||||
msg = await handler(**message)
|
||||
msg.cause_by = type(todo)
|
||||
self._publish_message(msg)
|
||||
return msg
|
||||
|
||||
raise ValueError(f"Unknown todo type: {type(todo)}")
|
||||
68
metagpt/roles/minecraft/event_handler.py
Normal file
68
metagpt/roles/minecraft/event_handler.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 14:29
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
import json
|
||||
|
||||
from metagpt.logs import logger
|
||||
|
||||
from metagpt.roles.minecraft.minecraft_base import Minecraft as Base
|
||||
from metagpt.schema import Message
|
||||
from metagpt.actions.minecraft.player_action import PlayerActions
|
||||
from metagpt.actions.minecraft.generate_actions import GenerateActionCode
|
||||
from metagpt.actions.minecraft.process_event import HandleEvents
|
||||
|
||||
|
||||
class EventHandler(Base):
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "Thompson",
|
||||
profile: str = "Minecraft Event Handler",
|
||||
goal: str = "To efficiently manage and respond to in-game events, providing information about the player.",
|
||||
constraints: str = "Resource availability, server performance, adherence to server rules and regulations.",
|
||||
) -> None:
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
# Initialize actions specific to the EventHandler role
|
||||
self._init_actions([HandleEvents])
|
||||
|
||||
# Set events or actions the EventHandler should watch or be aware of
|
||||
self._watch([PlayerActions, GenerateActionCode])
|
||||
self.last_events = {"env_events": {},
|
||||
"execute_results": {}}
|
||||
|
||||
|
||||
async def _act(self) -> Message:
|
||||
# 获取最新的消息
|
||||
|
||||
msg = self._rc.memory.get(k=1)[0]
|
||||
query = msg.content if self._rc.state == 0 else msg.instruct_content
|
||||
"""
|
||||
todo: parse query info from message, e.g. test_round and action code
|
||||
"""
|
||||
test_round = 1
|
||||
logger.info(msg.cause_by)
|
||||
|
||||
if msg.cause_by == GenerateActionCode: # 进行生成的代码执行, 获取的结果用于进行AI评估
|
||||
events = await HandleEvents().run(query)
|
||||
result_msg = Message(
|
||||
content=f"Round {test_round} of rollout done",
|
||||
role=self.profile,
|
||||
cause_by=HandleEvents,
|
||||
sent_from=self.profile,
|
||||
send_to="Task Reviewer",
|
||||
)
|
||||
|
||||
self.perform_game_info_callback(events, self.game_memory.update_event)
|
||||
|
||||
else:
|
||||
events = await HandleEvents().run(query)
|
||||
result_msg = Message(
|
||||
content=events,
|
||||
role=self.profile,
|
||||
cause_by=HandleEvents,
|
||||
sent_from=self.profile,
|
||||
send_to="",
|
||||
)
|
||||
|
||||
self.perform_game_info_callback(events, self.game_memory.update_event)
|
||||
return result_msg
|
||||
105
metagpt/roles/minecraft/minecraft_base.py
Normal file
105
metagpt/roles/minecraft/minecraft_base.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 21:38
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
import contextlib
|
||||
import json
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles.role import Role
|
||||
from metagpt.schema import HumanMessage, SystemMessage
|
||||
|
||||
from typing import Dict
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Registry(BaseModel):
|
||||
"""Registry for storing and building classes."""
|
||||
|
||||
name: str
|
||||
entries: Dict = {}
|
||||
|
||||
def register(self, key: str):
|
||||
def decorator(class_builder):
|
||||
self.entries[key] = class_builder
|
||||
return class_builder
|
||||
|
||||
return decorator
|
||||
|
||||
def build(self, type: str, **kwargs):
|
||||
if type not in self.entries:
|
||||
raise ValueError(
|
||||
f'{type} is not registered. Please register with the .register("{type}") method provided in {self.name} registry'
|
||||
)
|
||||
return self.entries[type](**kwargs)
|
||||
|
||||
def get_all_entries(self):
|
||||
return self.entries
|
||||
|
||||
class Minecraft(Role):
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "MC",
|
||||
profile: str = "Minecraft Role",
|
||||
goal: str = "",
|
||||
constraints: str = "",
|
||||
) -> None:
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
self.game_memory = None
|
||||
self.event = {}
|
||||
|
||||
|
||||
#
|
||||
async def _think(self) -> None:
|
||||
if len(self._actions) == 1:
|
||||
# If there is only one action, then only this one can be performed
|
||||
self._set_state(0)
|
||||
return True
|
||||
|
||||
if self._rc.todo is None:
|
||||
logger.info("0")
|
||||
self._set_state(0)
|
||||
return True
|
||||
|
||||
if self._rc.state + 1 < len(self._states):
|
||||
self._set_state(self._rc.state + 1)
|
||||
logger.info("1")
|
||||
return True
|
||||
else:
|
||||
self._rc.todo = None
|
||||
logger.info("2")
|
||||
|
||||
return False
|
||||
|
||||
async def _obtain_events(self):
|
||||
return await self.game_memory.on_event()
|
||||
|
||||
def set_memory(self, shared_memory: 'GameMemory'):
|
||||
self.game_memory = shared_memory
|
||||
|
||||
def render_human_message(self, msg, *args, **kwargs):
|
||||
return HumanMessage(content=msg)
|
||||
|
||||
def render_system_message(self, msg, *args, **kwargs):
|
||||
return SystemMessage(content=msg)
|
||||
|
||||
@staticmethod
|
||||
def perform_game_info_callback(info: object, callback: object) -> object:
|
||||
logger.debug(info)
|
||||
callback(info)
|
||||
|
||||
def encapsule_message(self, msg, *args, **kwargs):
|
||||
human_msg = self.render_human_message(msg, *args, **kwargs)
|
||||
system_msg = self.render_system_message(msg, *args, **kwargs)
|
||||
return {"system_msg": [system_msg.content],
|
||||
"human_msg": human_msg.content}
|
||||
|
||||
agent_registry = Registry(name="Minecraft")
|
||||
|
||||
if __name__ == "__main__":
|
||||
mc = Minecraft()
|
||||
result = "Async operation result"
|
||||
# 调用回调函数,并传递结果
|
||||
# mc.perform_memory_callback(mc.my_callback)
|
||||
print(mc.game_memory.current_task)
|
||||
71
metagpt/roles/minecraft/skill_manager.py
Normal file
71
metagpt/roles/minecraft/skill_manager.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/23 12:46
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles.minecraft.minecraft_base import Minecraft as Base
|
||||
from metagpt.roles.minecraft.minecraft_base import agent_registry
|
||||
from metagpt.schema import Message, HumanMessage, SystemMessage
|
||||
from metagpt.actions.minecraft.manage_skills import GenerateSkillDescription, RetrieveSkills, AddNewSkills
|
||||
from metagpt.actions.minecraft.review_task import VerifyTask
|
||||
from metagpt.actions.minecraft.design_curriculumn import DesignCurriculum
|
||||
|
||||
|
||||
|
||||
@agent_registry.register("skill_manager")
|
||||
class SkillManager(Base):
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "John",
|
||||
profile: str = "Skills Management Specialist",
|
||||
goal: str = "To oversee and optimize the acquisition, development, and utilization of skills within the organization, ensuring workforce competence and efficiency.",
|
||||
constraints: str = "Resource allocation, training budgets, and alignment with organizational goals.",
|
||||
) -> None:
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
# Initialize actions specific to the SkillManager role
|
||||
self._init_actions([RetrieveSkills, GenerateSkillDescription, AddNewSkills])
|
||||
|
||||
# Set events or actions the SkillManager should watch or be aware of
|
||||
self._watch([DesignCurriculum, VerifyTask, RetrieveSkills, GenerateSkillDescription])
|
||||
|
||||
async def retrieve_skills(self, human_msg, system_msg, *args, **kwargs):
|
||||
skills = await RetrieveSkills().run(human_msg)
|
||||
logger.info(
|
||||
f"\033[33mRender Action Agent system message with {len(skills)} skills\033[0m"
|
||||
)
|
||||
return Message(content=f"{skills}", instruct_content="retrieve_skills", role=self.profile,
|
||||
send_to=agent_registry.entries["action_developer"]()._setting.name)
|
||||
|
||||
async def generate_skill_descp(self, human_msg, system_msg, *args, **kwargs):
|
||||
desp = await GenerateSkillDescription().run(human_msg)
|
||||
return Message(content=f"{desp}", instruct_content="generate_skill_descp", role=self.profile)
|
||||
|
||||
async def handle_add_new_skills(self, human_msg, system_msg, *args, **kwargs):
|
||||
new_skills = await AddNewSkills().run(human_msg)
|
||||
return Message(content=f"", instruct_content="generate_skill_descp", role=self.profile)
|
||||
|
||||
async def _act(self) -> Message:
|
||||
todo = self._rc.todo
|
||||
logger.debug(f"Todo is {todo}")
|
||||
|
||||
# 获取最新的游戏周边信息
|
||||
context = self.game_memory.context
|
||||
|
||||
msg = self._rc.memory.get(k=1)[0]
|
||||
|
||||
message = self.encapsule_message(context)
|
||||
|
||||
handler_map = {
|
||||
DesignCurriculum: self.retrieve_skills,
|
||||
RetrieveSkills: self.retrieve_skills,
|
||||
GenerateSkillDescription: self.generate_skill_descp,
|
||||
AddNewSkills: self.handle_add_new_skills,
|
||||
}
|
||||
handler = handler_map.get(type(todo))
|
||||
if handler:
|
||||
msg = await handler(**message)
|
||||
msg.cause_by = type(todo)
|
||||
self._publish_message(msg)
|
||||
return msg
|
||||
|
||||
raise ValueError(f"Unknown todo type: {type(todo)}")
|
||||
4
metagpt/utils/minecraft/__init__.py
Normal file
4
metagpt/utils/minecraft/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/24 0:32
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
9
metagpt/utils/minecraft/load_prompts.py
Normal file
9
metagpt/utils/minecraft/load_prompts.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/24 11:03
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
import pkg_resources
|
||||
|
||||
|
||||
def load_prompt(prompt):
|
||||
pass
|
||||
32
minecraft_run.py
Normal file
32
minecraft_run.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Date : 2023/9/24 11:09
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
import asyncio
|
||||
|
||||
from metagpt.roles.minecraft.curriculum_agent import CurriculumDesigner
|
||||
from metagpt.roles.minecraft.skill_manager import SkillManager
|
||||
from metagpt.roles.minecraft.action_developer import ActionDeveloper
|
||||
from metagpt.roles.minecraft.critic_agent import CriticReviewer
|
||||
from metagpt.minecraft_team import MinecraftPlayer
|
||||
|
||||
|
||||
async def learn(task="Start", investment: float = 50.0, n_round: int = 3):
|
||||
mc_player = MinecraftPlayer()
|
||||
mc_player.hire(
|
||||
[
|
||||
CurriculumDesigner(),
|
||||
ActionDeveloper(),
|
||||
CriticReviewer(),
|
||||
SkillManager(),
|
||||
|
||||
]
|
||||
)
|
||||
|
||||
mc_player.invest(investment)
|
||||
mc_player.start(task)
|
||||
await mc_player.run(n_round=n_round)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(learn())
|
||||
Loading…
Add table
Add a link
Reference in a new issue