mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-17 15:35:21 +02:00
update code
This commit is contained in:
parent
f70ba27d35
commit
37a7a96bbe
13 changed files with 255 additions and 215 deletions
5
Temp.md
5
Temp.md
|
|
@ -31,6 +31,8 @@ ### 0926: 环境信息获取和更新 on_event()实际内容
|
|||
mc_player.set_port(2465) # Modify this to your LAN port
|
||||
```
|
||||
|
||||
*注意世界游戏模式为生存,这样人物才会有血量,饥饿和库存概念;*
|
||||
|
||||
python minecraft_run.py
|
||||
|
||||
<img src="docs/resources/workspace/minecraft_tests/on_event.jpeg" style="zoom:67%;" />
|
||||
|
|
@ -67,3 +69,6 @@ ### 0930:Curriculum agent 更新
|
|||
1. 若本地已克隆项目不好更改可尝试:删除 metagpt/mineflayer_env/mineflayer + 重新copy voyager/env/mineflayer到目录下 + (npm install...0926.B命令)
|
||||
2. 重新拉取最新提交+重新配置
|
||||
|
||||
### 第一人称视角
|
||||
|
||||
目前使用3007端口,可自行修改,代码运行以后,在浏览器输入127.0.0.1:3007访问
|
||||
|
|
@ -84,4 +84,7 @@ MODEL_FOR_RESEARCHER_REPORT: gpt-3.5-turbo-16k
|
|||
### browser path for pyppeteer engine, support Chrome, Chromium,MS Edge
|
||||
#PYPPETEER_EXECUTABLE_PATH: "/usr/bin/google-chrome-stable"
|
||||
|
||||
PROMPT_FORMAT: json #json or markdown
|
||||
PROMPT_FORMAT: json #json or markdown
|
||||
|
||||
### Minecraft
|
||||
RESUME: false # If load json from ckpt dir(include chest_memory, skills, ...)
|
||||
|
|
@ -21,11 +21,11 @@ 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)
|
||||
self.llm.model = "gpt-3.5-turbo"
|
||||
|
||||
|
||||
async def decompose_task(self, query, events):
|
||||
system_msgs = SystemMessage(
|
||||
content=load_prompt("curriculum_task_decomposition")
|
||||
|
|
@ -34,11 +34,11 @@ class DesignTask(Action):
|
|||
events=events, chest_observation=""
|
||||
) + HumanMessage(content=f"Final task: {query}")
|
||||
logger.info(f"Curriculum Agent task decomposition\nFinal task: {query}")
|
||||
|
||||
|
||||
rsp = await self._aask(prompt=prompt, system_msgs=system_msgs)
|
||||
logger.info(f"Curriculum Agent task decomposition\n{rsp}")
|
||||
return fix_and_parse_json(rsp)
|
||||
|
||||
|
||||
def parse_llm_response(self, llm_resp):
|
||||
task = ""
|
||||
for line in llm_resp.split("\n"):
|
||||
|
|
@ -46,14 +46,14 @@ class DesignTask(Action):
|
|||
task = line[5:].replace(".", "").strip()
|
||||
assert task, "Task not found in Curriculum Agent response"
|
||||
return {"next_task": task}
|
||||
|
||||
|
||||
async def generate_task(self, human_msg, system_msg, max_retries=5):
|
||||
"""
|
||||
Refer to the code in the voyager/agents/curriculum.py propose_next_ai_task() for implementation details.
|
||||
Returns: task & context
|
||||
|
||||
"""
|
||||
|
||||
|
||||
if max_retries == 0:
|
||||
raise RuntimeError("Max retries reached, failed to propose task.")
|
||||
curriculum = await self._aask(prompt=human_msg, system_msgs=system_msg)
|
||||
|
|
@ -72,14 +72,14 @@ class DesignTask(Action):
|
|||
system_msg=system_msg,
|
||||
max_retries=max_retries - 1,
|
||||
)
|
||||
|
||||
|
||||
async def run(self, human_msg, system_msg, *args, **kwargs):
|
||||
logger.info(f"run {self.__repr__()}")
|
||||
|
||||
|
||||
# Call the language model to generate a response.
|
||||
|
||||
|
||||
task = await self.generate_task(human_msg=human_msg, system_msg=system_msg)
|
||||
|
||||
|
||||
return task
|
||||
|
||||
|
||||
|
|
@ -88,49 +88,51 @@ 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)
|
||||
# voyager vectordb using
|
||||
|
||||
@classmethod
|
||||
def generate_qa(cls, events, chest_observation):
|
||||
|
||||
async def generate_qa(self, events, human_msg, system_msg):
|
||||
"""
|
||||
Generate qa for DesignTask's HumanMessage
|
||||
"""
|
||||
questions_new, _ = cls.generate_qa_step1(
|
||||
events=events, chest_observation=chest_observation
|
||||
questions_new = await self.generate_qa_step1(
|
||||
events=events, human_msg=human_msg, system_msg=system_msg
|
||||
)
|
||||
logger.debug(f"Generate_qa_step1 result list is HERE: {questions_new}")
|
||||
|
||||
questions = []
|
||||
answers = []
|
||||
for question in questions_new:
|
||||
if cls.qa_cache_questions_vectordb._collection.count() > 0:
|
||||
if self.qa_cache_questions_vectordb._collection.count() > 0:
|
||||
docs_and_scores = (
|
||||
cls.qa_cache_questions_vectordb.similarity_search_with_score(
|
||||
self.qa_cache_questions_vectordb.similarity_search_with_score(
|
||||
question, k=1
|
||||
)
|
||||
)
|
||||
if docs_and_scores and docs_and_scores[0][1] < 0.05:
|
||||
question_cached = docs_and_scores[0][0].page_content
|
||||
assert question_cached in cls.qa_cache
|
||||
answer_cached = cls.qa_cache[question_cached]
|
||||
assert question_cached in self.qa_cache
|
||||
answer_cached = self.qa_cache[question_cached]
|
||||
questions.append(question_cached)
|
||||
answers.append(answer_cached)
|
||||
continue
|
||||
answer = cls.generate_qa_step2(question=question)
|
||||
assert question not in cls.qa_cache
|
||||
cls.qa_cache[question] = answer
|
||||
cls.qa_cache_questions_vectordb.add_texts(
|
||||
answer = await self.generate_qa_step2(question=question)
|
||||
assert question not in self.qa_cache
|
||||
self.qa_cache[question] = answer
|
||||
self.qa_cache_questions_vectordb.add_texts(
|
||||
texts=[question],
|
||||
)
|
||||
with open(f"{CKPT_DIR}/curriculum/qa_cache.json", "w") as f:
|
||||
json.dump(cls.qa_cache, f)
|
||||
cls.qa_cache_questions_vectordb.persist()
|
||||
json.dump(self.qa_cache, f)
|
||||
self.qa_cache_questions_vectordb.persist()
|
||||
questions.append(question)
|
||||
answers.append(answer)
|
||||
assert len(questions_new) == len(questions) == len(answers)
|
||||
logger.info(f"Curriculum Agent generate_qa Questions: {questions}")
|
||||
logger.info(f"Curriculum Agent generate_qa Answers: {answers}")
|
||||
return questions, answers
|
||||
|
||||
|
||||
async def generate_qa_step1(self, events, human_msg, system_msg):
|
||||
biome = events[-1][1]["status"]["biome"].replace("_", " ")
|
||||
questions = [
|
||||
|
|
@ -139,7 +141,7 @@ class DesignCurriculum(Action):
|
|||
f"What are the mobs that I can find in the {biome} in Minecraft?",
|
||||
]
|
||||
qa_response = await self._aask(prompt=human_msg, system_msgs=system_msg)
|
||||
|
||||
|
||||
try:
|
||||
# Regex pattern to extract question and concept pairs
|
||||
pattern = r"Question \d+: (.+)\nConcept \d+: (.+)"
|
||||
|
|
@ -154,10 +156,10 @@ class DesignCurriculum(Action):
|
|||
f"QA step 1 ask questions: {e}."
|
||||
)
|
||||
return questions
|
||||
|
||||
|
||||
async def generate_qa_step2(self, question):
|
||||
# Implement the logic for another specific step in generating questions and answers.
|
||||
logger.info(f"Curriculum Agent Question: {question}")
|
||||
# logger.info(f"Curriculum Agent generate_qa_step2 Question: {question}")
|
||||
human_msg = HumanMessage(content=f"Question: {question}").content
|
||||
system_msg = [
|
||||
SystemMessage(
|
||||
|
|
@ -165,16 +167,16 @@ class DesignCurriculum(Action):
|
|||
).content
|
||||
]
|
||||
answer = await self._aask(prompt=human_msg, system_msgs=system_msg)
|
||||
logger.info(f"Curriculum Agent {answer}")
|
||||
# logger.info(f"Curriculum Agent generate_qa_step2 answer: {answer}")
|
||||
return answer
|
||||
|
||||
|
||||
async def get_context_from_task(self, task):
|
||||
"""
|
||||
Args: task
|
||||
Returns: context: "Question: {question}\n{answer}"
|
||||
if include ore in question, gpt will try to use tool with skill touch enhancement to mine
|
||||
"""
|
||||
|
||||
|
||||
question = (
|
||||
f"How to {task.replace('_', ' ').replace(' ore', '').replace(' ores', '').replace('.', '').strip().lower()}"
|
||||
f" in Minecraft?"
|
||||
|
|
@ -192,14 +194,14 @@ class DesignCurriculum(Action):
|
|||
self.qa_cache_questions_vectordb.persist()
|
||||
context = f"Question: {question}\n{answer}"
|
||||
return context
|
||||
|
||||
|
||||
async def generate_context(self, task, max_retries=5):
|
||||
"""
|
||||
Refer to the code in the voyager/agents/curriculum.py propose_next_ai_task() for implementation details.
|
||||
Returns: context
|
||||
|
||||
"""
|
||||
|
||||
|
||||
if max_retries == 0:
|
||||
raise RuntimeError("Max retries reached, failed to propose context.")
|
||||
try:
|
||||
|
|
@ -213,12 +215,12 @@ class DesignCurriculum(Action):
|
|||
task=task,
|
||||
max_retries=max_retries - 1,
|
||||
)
|
||||
|
||||
|
||||
async def run(self, task, human_msg, system_msg, *args, **kwargs):
|
||||
logger.info(f"run {self.__repr__()}")
|
||||
# Generate curriculum-related questions and answers.
|
||||
# curriculum_qustion = await self.generate_qa_step1(events, human_msg, system_msg)
|
||||
curriculum_context = await self.generate_context(task)
|
||||
|
||||
|
||||
# Return the generated questions and answers.
|
||||
return curriculum_context
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ 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)
|
||||
self.llm.model = "gpt-4"
|
||||
|
||||
|
||||
async def generate_code(self, human_msg, system_msg=[]):
|
||||
"""
|
||||
Generate action code logic.
|
||||
|
|
@ -27,22 +27,23 @@ class GenerateActionCode(Action):
|
|||
rsp = await self._aask(prompt=human_msg, system_msgs=system_msg)
|
||||
parsed_result = parse_action_response(rsp)
|
||||
# logger.info(f"parsed_result is HERE: {parsed_result}")
|
||||
|
||||
|
||||
try:
|
||||
return (
|
||||
parsed_result["program_code"],
|
||||
parsed_result["program_code"] + "\n" + parsed_result["exec_code"],
|
||||
parsed_result["program_name"],
|
||||
)
|
||||
except:
|
||||
logger.error(f"Failed to parse response: {parsed_result}")
|
||||
return None, None
|
||||
|
||||
return None, None, None # TODO: midify to "", "", ""
|
||||
|
||||
async def run(self, human_msg, system_msg, *args, **kwargs):
|
||||
logger.info(f"run {self.__repr__()}")
|
||||
# Generate action code.
|
||||
generated_code, program_name = await self.generate_code(
|
||||
program_code, generated_code, program_name = await self.generate_code(
|
||||
human_msg=human_msg, system_msg=system_msg
|
||||
)
|
||||
|
||||
|
||||
# Return the generated code.
|
||||
return generated_code, program_name
|
||||
return program_code, generated_code, program_name
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
import os
|
||||
import json
|
||||
|
||||
from traits.trait_types import self
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.actions.minecraft.player_action import PlayerActions as Action
|
||||
from metagpt.const import CKPT_DIR
|
||||
|
|
@ -15,11 +17,11 @@ 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.llm.model = "gpt-3.5-turbo"
|
||||
|
||||
|
||||
async def run(self, query, skills, *args, **kwargs):
|
||||
# Implement the logic for retrieving skills here.
|
||||
k = min(self.vectordb._collection.count(), self.retrieval_top_k)
|
||||
|
|
@ -42,13 +44,13 @@ 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)
|
||||
self.llm.model = "gpt-3.5-turbo"
|
||||
|
||||
|
||||
async def run(
|
||||
self, task, program_name, program_code, skills, skill_desp, *args, **kwargs
|
||||
self, task, program_name, program_code, skills, skill_desp, *args, **kwargs
|
||||
):
|
||||
# Implement the logic for adding new skills here.
|
||||
# TODO: Fix this
|
||||
|
|
@ -75,12 +77,7 @@ class AddNewSkills(Action):
|
|||
ids=[program_name],
|
||||
metadatas=[{"name": program_name}],
|
||||
)
|
||||
|
||||
# FIXME
|
||||
# assert self.vectordb._collection.count() == len(
|
||||
# skills
|
||||
# ), "vectordb is not synced with skills.json"
|
||||
|
||||
|
||||
with open(f"{CKPT_DIR}/skill/code/{dumped_program_name}.js", "w") as f:
|
||||
f.write(program_code)
|
||||
with open(f"{CKPT_DIR}/skill/description/{dumped_program_name}.txt", "w") as f:
|
||||
|
|
@ -99,13 +96,13 @@ 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)
|
||||
self.llm.model = "gpt-3.5-turbo"
|
||||
|
||||
|
||||
async def run(self, program_name, human_message, system_message, *args, **kwargs):
|
||||
# Implement the logic for generating skill descriptions here.
|
||||
rsp = await self._aask(prompt=human_message, system_msgs=system_message)
|
||||
skill_description = f" // { rsp}"
|
||||
skill_description = f" // {rsp}"
|
||||
return f"async function {program_name}(bot) {{\n{skill_description}\n}}"
|
||||
|
|
|
|||
|
|
@ -2,58 +2,70 @@
|
|||
# @Date : 2023/9/23 17:06
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
import json
|
||||
|
||||
from metagpt.actions import Action
|
||||
from langchain.vectorstores import Chroma
|
||||
from langchain.embeddings.openai import OpenAIEmbeddings
|
||||
from metagpt.document_store import FaissStore
|
||||
|
||||
from metagpt.const import CKPT_DIR
|
||||
from metagpt.config import CONFIG
|
||||
|
||||
|
||||
class PlayerActions(Action):
|
||||
def __init__(self, name="", context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
self.skills = {}
|
||||
self.skills = {} # for skills.json
|
||||
self.qa_cache = {}
|
||||
self.check_init = True
|
||||
|
||||
if (
|
||||
CONFIG.resume
|
||||
): # TODO: now for assert only, no update, cuz program using in step()
|
||||
with open(f"{CKPT_DIR}/skill/skills.json", "r") as f:
|
||||
self.skills = json.load(f)
|
||||
|
||||
with open(f"{CKPT_DIR}/curriculum/qa_cache.json", "r") as f:
|
||||
self.qa_cache = json.load(f)
|
||||
|
||||
self.retrieval_top_k = 5
|
||||
|
||||
self.vectordb = Chroma(
|
||||
collection_name="skill_vectordb",
|
||||
embedding_function=OpenAIEmbeddings(),
|
||||
persist_directory=f"{CKPT_DIR}/skill/vectordb",
|
||||
)
|
||||
|
||||
|
||||
self.qa_cache_questions_vectordb = Chroma(
|
||||
collection_name="qa_cache_questions_vectordb",
|
||||
embedding_function=OpenAIEmbeddings(),
|
||||
persist_directory=f"{CKPT_DIR}/curriculum/vectordb",
|
||||
)
|
||||
# TODO: change to FaissStore
|
||||
# self.qa_cache_questions_vectordb = FaissStore( {CKPT_DIR}/ 'curriculum/vectordb'
|
||||
|
||||
@classmethod
|
||||
def set_skills(cls, skills):
|
||||
cls.skills = skills
|
||||
# Check if Skill Manager's vectordb right using
|
||||
assert cls.vectordb._collection.count() == len(cls.skills), (
|
||||
f"Skill Manager's vectordb is not synced with skills.json.\n"
|
||||
f"There are {cls.vectordb._collection.count()} skills in vectordb but {len(cls.skills)} skills in skills.json.\n"
|
||||
f"Did you set resume=False when initializing the manager?\n"
|
||||
f"You may need to manually delete the vectordb directory for running from scratch."
|
||||
)
|
||||
# FIXME
|
||||
if self.check_init:
|
||||
# Check if Skill Manager's vectordb right using
|
||||
assert self.vectordb._collection.count() >= len(self.skills), (
|
||||
f"Skill Manager's vectordb is not synced with skills.json.\n"
|
||||
f"There are {self.vectordb._collection.count()} skills in vectordb but {len(self.skills)} skills in skills.json.\n"
|
||||
f"Did you set resume=False when initializing the manager?\n"
|
||||
f"You may need to manually delete the vectordb directory for running from scratch."
|
||||
)
|
||||
# Check if Skill Manager's vectordb right using
|
||||
assert self.qa_cache_questions_vectordb._collection.count() >= len(
|
||||
self.qa_cache
|
||||
), (
|
||||
f"Curriculum Agent's qa cache question vectordb is not synced with qa_cache.json.\n"
|
||||
f"There are {self.qa_cache_questions_vectordb._collection.count()} questions in vectordb "
|
||||
f"but {len(self.qa_cache)} questions in qa_cache.json.\n"
|
||||
f"Did you set resume=False when initializing the agent?\n"
|
||||
f"You may need to manually delete the qa cache question vectordb directory for running from scratch.\n"
|
||||
)
|
||||
self.check_init = False
|
||||
# TODO: change to FaissStore
|
||||
# self.qa_cache_questions_vectordb = FaissStore( {CKPT_DIR}/ 'curriculum/vectordb'
|
||||
|
||||
@classmethod
|
||||
def set_qa_cache(cls, qa_cache):
|
||||
cls.qa_cache = qa_cache
|
||||
# Check if qa_cache right using
|
||||
# Check if Skill Manager's vectordb right using
|
||||
assert cls.qa_cache_questions_vectordb._collection.count() == len(
|
||||
cls.qa_cache
|
||||
), (
|
||||
f"Curriculum Agent's qa cache question vectordb is not synced with qa_cache.json.\n"
|
||||
f"There are {cls.qa_cache_questions_vectordb._collection.count()} questions in vectordb "
|
||||
f"but {len(cls.qa_cache)} questions in qa_cache.json.\n"
|
||||
f"Did you set resume=False when initializing the agent?\n"
|
||||
f"You may need to manually delete the qa cache question vectordb directory for running from scratch.\n"
|
||||
)
|
||||
|
||||
"""Minecraft player info without any implementation details"""
|
||||
|
||||
async def run(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ class Config(metaclass=Singleton):
|
|||
self.pyppeteer_executable_path = self._get("PYPPETEER_EXECUTABLE_PATH", "")
|
||||
|
||||
self.prompt_format = self._get("PROMPT_FORMAT", "markdown")
|
||||
self.resume = self._get("RESUME", False)
|
||||
|
||||
def _init_with_config_files_and_env(self, configs: dict, yaml_file):
|
||||
"""Load from config/key.yaml, config/config.yaml, and env in decreasing order of priority"""
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# @Desc :
|
||||
from typing import Iterable, Dict, Any
|
||||
from pydantic import BaseModel, Field
|
||||
import requests
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
|
|
@ -18,6 +18,7 @@ from metagpt.roles.minecraft.minecraft_base import Minecraft
|
|||
from metagpt.environment import Environment
|
||||
from metagpt.mineflayer_environment import MineflayerEnv
|
||||
from metagpt.const import CKPT_DIR
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.actions.minecraft.control_primitives import load_skills_code
|
||||
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ class GameEnvironment(BaseModel, arbitrary_types_allowed=True):
|
|||
default="You can mine one of oak, birch, spruce, jungle, acacia, dark oak, or mangrove logs."
|
||||
)
|
||||
code: str = Field(default="")
|
||||
program_code: str = Field(default="") # write in skill/code/*.js
|
||||
program_name: str = Field(default="")
|
||||
critique: str = Field(default="")
|
||||
skills: dict = Field(default_factory=dict) # for skills.json
|
||||
|
|
@ -76,12 +78,13 @@ class GameEnvironment(BaseModel, arbitrary_types_allowed=True):
|
|||
@property
|
||||
def core_inv_items_regex(self):
|
||||
return self.mf_instance.core_inv_items_regex
|
||||
|
||||
|
||||
def set_mc_port(self, mc_port):
|
||||
self.mf_instance.set_mc_port(mc_port)
|
||||
self.set_mc_resume()
|
||||
|
||||
def set_mc_resume(self, resume: bool = False): # TODO: mv to config
|
||||
if resume:
|
||||
def set_mc_resume(self):
|
||||
if CONFIG.resume:
|
||||
logger.info(f"Loading Action Developer from {CKPT_DIR}/action")
|
||||
with open(f"{CKPT_DIR}/action/chest_memory.json", "r") as f:
|
||||
self.chest_memory = json.load(f)
|
||||
|
|
@ -91,16 +94,23 @@ class GameEnvironment(BaseModel, arbitrary_types_allowed=True):
|
|||
self.completed_tasks = json.load(f)
|
||||
with open(f"{CKPT_DIR}/curriculum/failed_tasks.json", "r") as f:
|
||||
self.failed_tasks = json.load(f)
|
||||
with open(f"{CKPT_DIR}/curriculum/qa_cache.json", "r") as f:
|
||||
self.qa_cache = json.load(f)
|
||||
|
||||
|
||||
logger.info(f"Loading Skill Manager from {CKPT_DIR}/skill\033[0m")
|
||||
with open(f"{CKPT_DIR}/skill/skills.json", "r") as f:
|
||||
self.skills = json.load(f)
|
||||
|
||||
logger.info(f"Loading Qa Cache from {CKPT_DIR}/curriculum\033[0m")
|
||||
with open(f"{CKPT_DIR}/curriculum/qa_cache.json", "r") as f:
|
||||
self.qa_cache = json.load(f)
|
||||
|
||||
def register_roles(self, roles: Iterable[Minecraft]):
|
||||
for role in roles:
|
||||
role.set_memory(self)
|
||||
for act in role.vdb_actions:
|
||||
logger.info(act)
|
||||
act.set_qa_cache_questions_vectordb(self.qa_cache_questions_vectordb)
|
||||
act.set_qa_cache(self.qa_cache)
|
||||
act.set_vectordb(self.vectordb)
|
||||
|
||||
def update_event(self, event: Dict):
|
||||
if self.event == event:
|
||||
|
|
@ -114,7 +124,10 @@ class GameEnvironment(BaseModel, arbitrary_types_allowed=True):
|
|||
|
||||
def update_context(self, context: str):
|
||||
self.context = context
|
||||
|
||||
|
||||
def update_program_code(self, program_code: str):
|
||||
self.program_code = program_code
|
||||
|
||||
def update_code(self, code: str):
|
||||
self.code = code # action_developer.gen_action_code to HERE
|
||||
|
||||
|
|
@ -335,9 +348,6 @@ class MinecraftPlayer(SoftwareCompany):
|
|||
def set_port(self, mc_port):
|
||||
self.game_memory.set_mc_port(mc_port)
|
||||
|
||||
def set_resume(self, resume: bool = False):
|
||||
self.game_memory.set_mc_resume(resume=resume)
|
||||
|
||||
def check_complete_round(self):
|
||||
complete_round = []
|
||||
for role in self.environment.roles.values():
|
||||
|
|
@ -380,12 +390,23 @@ class MinecraftPlayer(SoftwareCompany):
|
|||
async def run(self, n_round=3):
|
||||
"""Run company until target round or no money"""
|
||||
round_id = 0
|
||||
self.game_memory.mf_instance.reset(
|
||||
options={
|
||||
"mode": "soft",
|
||||
"wait_ticks": 20,
|
||||
}
|
||||
)
|
||||
if CONFIG.resume:
|
||||
# keep the inventory
|
||||
self.game_memory.mf_instance.reset(
|
||||
options={
|
||||
"mode": "soft",
|
||||
"wait_ticks": 20,
|
||||
}
|
||||
)
|
||||
else:
|
||||
# clear the inventory
|
||||
self.game_memory.mf_instance.reset(
|
||||
options={
|
||||
"mode": "hard",
|
||||
"wait_ticks": 20,
|
||||
}
|
||||
)
|
||||
|
||||
events = self.game_memory.mf_instance.step(
|
||||
code="",
|
||||
programs="",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ const Inventory = require("./lib/observation/inventory");
|
|||
const OnSave = require("./lib/observation/onSave");
|
||||
const Chests = require("./lib/observation/chests");
|
||||
const { plugin: tool } = require("mineflayer-tool");
|
||||
const { mineflayer: mineflayerViewer } = require('prismarine-viewer')
|
||||
|
||||
let bot = null;
|
||||
|
||||
|
|
@ -50,6 +51,7 @@ app.post("/start", (req, res) => {
|
|||
});
|
||||
|
||||
bot.once("spawn", async () => {
|
||||
mineflayerViewer(bot, { port: 3007, firstPerson: false })
|
||||
bot.removeListener("error", onConnectionFailed);
|
||||
let itemTicks = 1;
|
||||
if (req.body.reset === "hard") {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
# @Date : 2023/9/23 12:45
|
||||
# @Author : stellahong (stellahong@fuzhi.ai)
|
||||
# @Desc :
|
||||
import copy
|
||||
|
||||
from metagpt.logs import logger
|
||||
from metagpt.roles.minecraft.minecraft_base import Minecraft as Base
|
||||
from metagpt.schema import Message, HumanMessage, SystemMessage
|
||||
|
|
@ -40,14 +38,13 @@ class ActionDeveloper(Base):
|
|||
# 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])
|
||||
self.rollout_num_iter = 0
|
||||
self.task_max_retries = 4
|
||||
self.finish_state = len(self._actions)
|
||||
self.critic_reviewer = None # self._rc.env.roles["Task Reviewer"]
|
||||
self.critic_reviewer = None # self._rc.env.roles["Task Reviewer"]
|
||||
|
||||
def render_system_message(self, skills=[], *args, **kwargs):
|
||||
"""
|
||||
|
|
@ -208,6 +205,7 @@ class ActionDeveloper(Base):
|
|||
async def handle_add_new_skills(
|
||||
self, task, program_name, program_code, skills, *args, **kwargs
|
||||
):
|
||||
skills = self.game_memory.skills
|
||||
skill_desp = self.game_memory.skill_desp
|
||||
new_skills_info = await AddNewSkills().run(
|
||||
task, program_name, program_code, skills, skill_desp
|
||||
|
|
@ -231,11 +229,9 @@ class ActionDeveloper(Base):
|
|||
context = self.game_memory.context
|
||||
|
||||
# 更新生成的代码和对应程序名称
|
||||
code, program_name = await GenerateActionCode().run(
|
||||
program_code, code, program_name = await GenerateActionCode().run(
|
||||
human_msg, system_msg, *args, **kwargs
|
||||
)
|
||||
# logger.warning(type(code))
|
||||
# logger.info(f"Code is Here:{code}")
|
||||
|
||||
if code is not None:
|
||||
# fixme:若有独立的mc code执行入口函数,使用独立的函数
|
||||
|
|
@ -298,6 +294,8 @@ class ActionDeveloper(Base):
|
|||
"success": self.game_memory.runtime_status,
|
||||
}
|
||||
logger.info(f"info is {info}")
|
||||
|
||||
self.perform_game_info_callback(program_code, self.game_memory.update_program_code)
|
||||
self.perform_game_info_callback(code, self.game_memory.update_code)
|
||||
self.perform_game_info_callback(
|
||||
program_name, self.game_memory.update_program_name
|
||||
|
|
@ -306,11 +304,10 @@ class ActionDeveloper(Base):
|
|||
return system_msg, human_msg, 0, done, info
|
||||
|
||||
async def generate_action_code(self, human_msg, system_msg, *args, **kwargs):
|
||||
code, program_name = await GenerateActionCode().run(
|
||||
program_code, code, program_name = await GenerateActionCode().run(
|
||||
human_msg, system_msg, *args, **kwargs
|
||||
)
|
||||
# logger.warning(type(code))
|
||||
# logger.info(f"Code is Here:{code}")
|
||||
self.perform_game_info_callback(program_code, self.game_memory.update_program_code)
|
||||
self.perform_game_info_callback(code, self.game_memory.update_code)
|
||||
self.perform_game_info_callback(
|
||||
program_name, self.game_memory.update_program_name
|
||||
|
|
|
|||
|
|
@ -18,29 +18,29 @@ 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.",
|
||||
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])
|
||||
logger.info(self._actions)
|
||||
self.finish_state = len(self._actions)
|
||||
|
||||
|
||||
def render_curriculum_observation(self, *, events, chest_observation):
|
||||
"""
|
||||
Returns: observation for curriculum
|
||||
Refer to @ https://github.com/MineDojo/Voyager/blob/main/voyager/agents/curriculum.py
|
||||
"""
|
||||
|
||||
|
||||
assert events[-1][0] == "observe", "Last event must be observe"
|
||||
event = events[-1][1]
|
||||
biome = event["status"]["biome"]
|
||||
|
|
@ -54,31 +54,31 @@ class CurriculumDesigner(Base):
|
|||
equipment = event["status"]["equipment"]
|
||||
inventory_used = event["status"]["inventoryUsed"]
|
||||
inventory = event["inventory"]
|
||||
|
||||
|
||||
if not any(
|
||||
"dirt" in block
|
||||
or "log" in block
|
||||
or "grass" in block
|
||||
or "sand" in block
|
||||
or "snow" in block
|
||||
for block in voxels
|
||||
"dirt" in block
|
||||
or "log" in block
|
||||
or "grass" in block
|
||||
or "sand" in block
|
||||
or "snow" in block
|
||||
for block in voxels
|
||||
):
|
||||
biome = "underground"
|
||||
|
||||
|
||||
other_blocks = ", ".join(
|
||||
list(
|
||||
set(block_records).difference(set(voxels).union(set(inventory.keys())))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
other_blocks = other_blocks if other_blocks else "None"
|
||||
|
||||
|
||||
nearby_entities = (
|
||||
", ".join([k for k, v in sorted(entities.items(), key=lambda x: x[1])])
|
||||
if entities
|
||||
else "None"
|
||||
)
|
||||
|
||||
|
||||
completed_tasks = (
|
||||
", ".join(self.game_memory.completed_tasks)
|
||||
if self.game_memory.completed_tasks
|
||||
|
|
@ -89,18 +89,18 @@ class CurriculumDesigner(Base):
|
|||
if self.game_memory.failed_tasks
|
||||
else "None"
|
||||
)
|
||||
|
||||
|
||||
# filter out optional inventory items if required
|
||||
if (
|
||||
self.game_memory.progress
|
||||
< self.game_memory.warm_up["optional_inventory_items"]
|
||||
self.game_memory.progress
|
||||
< self.game_memory.warm_up["optional_inventory_items"]
|
||||
):
|
||||
inventory = {
|
||||
k: v
|
||||
for k, v in inventory.items()
|
||||
if self.game_memory.core_inv_items_regex.search(k) is not None
|
||||
}
|
||||
|
||||
|
||||
observation = {
|
||||
"context": "",
|
||||
"biome": f"Biome: {biome}\n\n",
|
||||
|
|
@ -118,25 +118,31 @@ class CurriculumDesigner(Base):
|
|||
"failed_tasks": f"Failed tasks that are too hard: {failed_tasks}\n\n",
|
||||
}
|
||||
return observation
|
||||
|
||||
|
||||
# --------------------------------Design Task Prepare---------------------------------------
|
||||
def render_design_task_human_message(
|
||||
self, events, chest_observation, *args, **kwargs
|
||||
async def render_design_task_human_message(
|
||||
self, events, chest_observation, *args, **kwargs
|
||||
):
|
||||
"""
|
||||
Returns: observation for curriculum
|
||||
Refer to @ https://github.com/MineDojo/Voyager/blob/main/voyager/agents/curriculum.py
|
||||
"""
|
||||
|
||||
|
||||
content = ""
|
||||
warm_up = self.game_memory.mf_instance.warm_up
|
||||
observation = self.render_curriculum_observation(
|
||||
events=events, chest_observation=chest_observation
|
||||
)
|
||||
if self.game_memory.progress >= warm_up["context"]:
|
||||
questions, answers = DesignCurriculum.generate_qa(
|
||||
# if self.game_memory.progress >= 0: # TEST ONLY
|
||||
human_msg = self.render_design_curriculum_human_message(
|
||||
events=events, chest_observation=chest_observation
|
||||
).content
|
||||
system_msg = [self.render_design_curriculum_system_message().content]
|
||||
questions, answers = await self.curriculum_design_action.generate_qa(
|
||||
events=events, human_msg=human_msg, system_msg=system_msg
|
||||
)
|
||||
logger.debug(f"Generate_qa result is HERE: Ques: {questions}, Ans: {answers}")
|
||||
i = 1
|
||||
for question, answer in zip(questions, answers):
|
||||
if "Answer: Unknown" in answer or "language model" in answer:
|
||||
|
|
@ -146,7 +152,7 @@ class CurriculumDesigner(Base):
|
|||
i += 1
|
||||
if i > 5:
|
||||
break
|
||||
|
||||
|
||||
for key in CURRICULUM_OB:
|
||||
if self.game_memory.progress >= warm_up[key]:
|
||||
if warm_up[key] != 0:
|
||||
|
|
@ -155,20 +161,20 @@ class CurriculumDesigner(Base):
|
|||
should_include = True
|
||||
if should_include:
|
||||
content += observation[key]
|
||||
|
||||
|
||||
logger.info(f"Curriculum Agent human message\n{content}")
|
||||
return HumanMessage(content=content)
|
||||
|
||||
|
||||
def render_design_task_system_message(self, *args, **kwargs):
|
||||
return SystemMessage(content=load_prompt("curriculum"))
|
||||
|
||||
def encapsule_design_task_message(self, events, chest_observation, *args, **kwargs):
|
||||
human_msg = self.render_design_task_human_message(
|
||||
|
||||
async def encapsule_design_task_message(self, events, chest_observation, *args, **kwargs):
|
||||
human_msg = await self.render_design_task_human_message(
|
||||
events=events, chest_observation=chest_observation, *args, **kwargs
|
||||
)
|
||||
system_msg = self.render_design_task_system_message(*args, **kwargs)
|
||||
return {"system_msg": [system_msg.content], "human_msg": human_msg.content}
|
||||
|
||||
|
||||
def generate_task_if_inventory_full(self, events, chest_observation):
|
||||
"""
|
||||
TODO: Try if this could be done with prompt
|
||||
|
|
@ -187,15 +193,15 @@ class CurriculumDesigner(Base):
|
|||
else:
|
||||
task = "Craft 1 chest"
|
||||
return task
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# --------------------------------Design Curriculum Prepare--------------------------------
|
||||
def render_design_curriculum_system_message(self, *args, **kwargs):
|
||||
return SystemMessage(content=load_prompt("curriculum_qa_step1_ask_questions"))
|
||||
|
||||
|
||||
def render_design_curriculum_human_message(
|
||||
self, events, chest_observation, *args, **kwargs
|
||||
self, events, chest_observation, *args, **kwargs
|
||||
):
|
||||
observation = self.render_curriculum_observation(
|
||||
events=events, chest_observation=chest_observation
|
||||
|
|
@ -204,16 +210,16 @@ class CurriculumDesigner(Base):
|
|||
for key in CURRICULUM_OB:
|
||||
content += observation[key]
|
||||
return HumanMessage(content=content)
|
||||
|
||||
|
||||
def encapsule_design_curriculum_message(
|
||||
self, events, chest_observation, *args, **kwargs
|
||||
self, events, chest_observation, *args, **kwargs
|
||||
):
|
||||
human_msg = self.render_design_curriculum_human_message(
|
||||
events=events, chest_observation=chest_observation, *args, **kwargs
|
||||
)
|
||||
system_msg = self.render_design_curriculum_system_message(*args, **kwargs)
|
||||
return {"system_msg": [system_msg.content], "human_msg": human_msg.content}
|
||||
|
||||
|
||||
def generate_context_if_inventory_full(self, events, chest_observation):
|
||||
"""
|
||||
TODO: Try if this could be done with prompt
|
||||
|
|
@ -244,9 +250,9 @@ class CurriculumDesigner(Base):
|
|||
else:
|
||||
context = "Craft 1 chest with 8 planks of any kind of wood."
|
||||
return context
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
async def handle_task_design(self, human_msg, system_msg, *args, **kwargs):
|
||||
"""
|
||||
Args:
|
||||
|
|
@ -260,7 +266,7 @@ class CurriculumDesigner(Base):
|
|||
events = self.game_memory.event
|
||||
chest_observation = self.game_memory.chest_observation
|
||||
inventoryUsed = events[-1][1]["status"]["inventoryUsed"]
|
||||
|
||||
|
||||
if self.game_memory.progress == 0:
|
||||
task = self.game_memory.current_task
|
||||
elif inventoryUsed >= 33:
|
||||
|
|
@ -270,12 +276,12 @@ class CurriculumDesigner(Base):
|
|||
else:
|
||||
task = await DesignTask().run(human_msg, system_msg, *args, **kwargs)
|
||||
logger.info(f"Handle_task_design result is Here: {task}")
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -292,7 +298,7 @@ class CurriculumDesigner(Base):
|
|||
chest_observation = self.game_memory.chest_observation
|
||||
inventoryUsed = events[-1][1]["status"]["inventoryUsed"]
|
||||
task = self.game_memory.current_task
|
||||
|
||||
|
||||
if self.game_memory.progress == 0:
|
||||
context = self.game_memory.context
|
||||
elif inventoryUsed >= 33:
|
||||
|
|
@ -300,37 +306,34 @@ class CurriculumDesigner(Base):
|
|||
self, events=events, chest_observation=chest_observation
|
||||
)
|
||||
else:
|
||||
context = await DesignCurriculum().run(
|
||||
context = await self.DesignCurriculum().run(
|
||||
task, 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}")
|
||||
self.maintain_actions(todo)
|
||||
self.maintain_actions(todo)
|
||||
|
||||
# 获取最新的游戏周边环境信息
|
||||
# events = await self._obtain_events()
|
||||
events = self.game_memory.event
|
||||
chest_observation = self.game_memory.chest_observation
|
||||
|
||||
# DesignCurriculum.set_qa_cache(self.game_memory.qa_cache)
|
||||
|
||||
# msg = self._rc.memory.get(k=1)[0]
|
||||
# query = msg.content
|
||||
|
||||
design_task_message = self.encapsule_design_task_message(
|
||||
|
||||
design_task_message = await self.encapsule_design_task_message(
|
||||
events, chest_observation
|
||||
)
|
||||
design_curriculum_message = self.encapsule_design_curriculum_message(
|
||||
events, chest_observation
|
||||
)
|
||||
|
||||
|
||||
handler_map = {
|
||||
DesignTask: self.handle_task_design,
|
||||
DesignCurriculum: self.handle_curriculum_design,
|
||||
|
|
@ -345,5 +348,5 @@ class CurriculumDesigner(Base):
|
|||
msg.round_id = self.round_id
|
||||
self._publish_message(msg)
|
||||
return msg
|
||||
|
||||
|
||||
raise ValueError(f"Unknown todo type: {type(todo)}")
|
||||
|
|
|
|||
|
|
@ -19,41 +19,40 @@ from metagpt.utils.minecraft import load_prompt
|
|||
@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.",
|
||||
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]) #AddNewSkills])#先去掉add
|
||||
self._init_actions([RetrieveSkills, GenerateSkillDescription, AddNewSkills])
|
||||
|
||||
# Set events or actions the SkillManager should watch or be aware of
|
||||
self._watch(
|
||||
[DesignCurriculum, GenerateActionCode, RetrieveSkills, GenerateSkillDescription]
|
||||
)
|
||||
|
||||
self.finish_state = len(self._actions)
|
||||
|
||||
|
||||
def encapsule_message(self, program_code, program_name, *args, **kwargs):
|
||||
system_msg = self.render_system_message(load_prompt("skill"))
|
||||
human_msg = self.render_human_message(
|
||||
program_code + "\n\n" + f"The main function is `{program_name}`."
|
||||
)
|
||||
return {"system_msg": [system_msg.content], "human_msg": human_msg.content}
|
||||
|
||||
|
||||
async def retrieve_skills(self, query, skills, *args, **kwargs):
|
||||
retrieve_skills = await RetrieveSkills().run(query, skills)
|
||||
logger.info(f"Render Action Agent system message with {len(retrieve_skills)} skills")
|
||||
self.perform_game_info_callback(retrieve_skills, self.game_memory.update_retrieve_skills)
|
||||
return Message(content=f"{retrieve_skills}", instruct_content="retrieve_skills",
|
||||
return Message(content=f"{retrieve_skills}", instruct_content="retrieve_skills",
|
||||
role=self.profile, send_to=agent_registry.entries["action_developer"]()._setting.name)
|
||||
# return Message(
|
||||
# content=f"{skills}", instruct_content="retrieve_skills", role=self.profile
|
||||
# ) # Unit test only
|
||||
|
||||
|
||||
async def generate_skill_descp(self, human_msg, system_msg, *args, **kwargs):
|
||||
program_name = self.game_memory.program_name
|
||||
desp = await GenerateSkillDescription().run(program_name, human_msg, system_msg)
|
||||
|
|
@ -63,16 +62,16 @@ class SkillManager(Base):
|
|||
instruct_content="generate_skill_descp",
|
||||
role=self.profile,
|
||||
)
|
||||
|
||||
|
||||
async def handle_add_new_skills(
|
||||
self, task, program_name, program_code, skills, *args, **kwargs
|
||||
self, task, program_name, program_code, skills, *args, **kwargs
|
||||
):
|
||||
if not self.game_memory.runtime_status:
|
||||
return Message(
|
||||
content="",
|
||||
instruct_content="handle_add_new_skills",
|
||||
role=self.profile,
|
||||
)
|
||||
content="",
|
||||
instruct_content="handle_add_new_skills",
|
||||
role=self.profile,
|
||||
)
|
||||
|
||||
skill_desp = self.game_memory.skill_desp
|
||||
new_skills_info = await AddNewSkills().run(
|
||||
|
|
@ -84,43 +83,41 @@ class SkillManager(Base):
|
|||
instruct_content="handle_add_new_skills",
|
||||
role=self.profile,
|
||||
)
|
||||
|
||||
|
||||
async def _act(self) -> Message:
|
||||
todo = self._rc.todo
|
||||
logger.debug(f"Todo is {todo}")
|
||||
self.maintain_actions(todo)
|
||||
self.maintain_actions(todo)
|
||||
# 获取最新的游戏周边信息
|
||||
|
||||
context = self.game_memory.context
|
||||
task = self.game_memory.current_task
|
||||
|
||||
code = self.game_memory.code
|
||||
self.perform_game_info_callback(self.game_memory.event, self.game_memory.summarize_chatlog)
|
||||
event_summary = self.game_memory.event_summary
|
||||
try:
|
||||
program_code = code["program_code"] # TODO: Handle code is None, cuz first round DesignCurriculum(code is None) trigger this
|
||||
except (KeyError, TypeError):
|
||||
program_code = ""
|
||||
|
||||
program_code = self.game_memory.program_code
|
||||
|
||||
program_name = self.game_memory.program_name
|
||||
skills = self.game_memory.skills
|
||||
|
||||
|
||||
# msg = self._rc.memory.get(k=1)[0]
|
||||
|
||||
|
||||
retrieve_skills_message_step1 = {"query": context, "skills": skills}
|
||||
logger.info(f"check query {context}")
|
||||
logger.info(f"check event summary {event_summary}")
|
||||
|
||||
retrieve_skills_message_step2 = {"query": context + "\n\n" + event_summary, "skills": skills}
|
||||
|
||||
|
||||
generate_skill_message = self.encapsule_message(program_code, program_name)
|
||||
|
||||
|
||||
add_new_skills_message = {
|
||||
"task": task,
|
||||
"program_name": program_name,
|
||||
"program_code": program_code,
|
||||
"skills": skills,
|
||||
}
|
||||
|
||||
|
||||
handler_map = {
|
||||
DesignCurriculum: self.retrieve_skills,
|
||||
RetrieveSkills: self.retrieve_skills,
|
||||
|
|
@ -139,10 +136,10 @@ class SkillManager(Base):
|
|||
msg = await handler(**generate_skill_message)
|
||||
else:
|
||||
msg = await handler(**add_new_skills_message)
|
||||
|
||||
|
||||
msg.cause_by = type(todo)
|
||||
msg.round_id = self.round_id
|
||||
self._publish_message(msg)
|
||||
return msg
|
||||
|
||||
|
||||
raise ValueError(f"Unknown todo type: {type(todo)}")
|
||||
|
|
|
|||
|
|
@ -11,10 +11,9 @@ 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):
|
||||
async def learn(task="Start", investment: float = 50.0, n_round: int = 50):
|
||||
mc_player = MinecraftPlayer()
|
||||
mc_player.set_port(33141) # Modify this to your Minecraft LAN port
|
||||
# mc_player.set_resume(True) # If load json from ckpt dir(include chest_memory, skills, ...)
|
||||
mc_player.set_port(30181) # Modify this to your Minecraft LAN port
|
||||
mc_player.hire(
|
||||
[
|
||||
CurriculumDesigner(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue