mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-26 15:49:42 +02:00
update code
This commit is contained in:
parent
f70ba27d35
commit
37a7a96bbe
13 changed files with 255 additions and 215 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue