mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-29 10:56:22 +02:00
feat: merge huggingface
This commit is contained in:
parent
4582f65cf8
commit
379b7b5820
9 changed files with 73 additions and 45 deletions
|
|
@ -94,4 +94,8 @@ 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
|
||||
|
||||
### Agent configurations
|
||||
# RAISE_NOT_CONFIG_ERROR: true # "true" if the LLM key is not configured, throw a NotConfiguredException, else "false".
|
||||
# WORKSPACE_PATH_WITH_UID: false # "true" if using `{workspace}/{uid}` as the workspace path; "false" use `{workspace}`.
|
||||
|
|
@ -27,8 +27,8 @@ class PrepareDocuments(Action):
|
|||
# Create and initialize the workspace folder, initialize the Git environment.
|
||||
project_name = CONFIG.project_name or FileRepository.new_filename()
|
||||
workdir = CONFIG.project_path
|
||||
if not workdir and CONFIG.workspace:
|
||||
workdir = Path(CONFIG.workspace) / project_name
|
||||
if not workdir and CONFIG.workspace_path:
|
||||
workdir = Path(CONFIG.workspace_path) / project_name
|
||||
workdir = Path(workdir or DEFAULT_WORKSPACE_ROOT / project_name)
|
||||
if not CONFIG.inc and workdir.exists():
|
||||
shutil.rmtree(workdir)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ Provide configuration, singleton
|
|||
1. According to Section 2.2.3.11 of RFC 135, add git repository support.
|
||||
2. Add the parameter `src_workspace` for the old version project path.
|
||||
"""
|
||||
import datetime
|
||||
import os
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from uuid import uuid4
|
||||
|
||||
import yaml
|
||||
|
||||
|
|
@ -60,7 +62,11 @@ class Config(metaclass=Singleton):
|
|||
and (not self.anthropic_api_key or "YOUR_API_KEY" == self.anthropic_api_key)
|
||||
and (not self.zhipuai_api_key or "YOUR_API_KEY" == self.zhipuai_api_key)
|
||||
):
|
||||
raise NotConfiguredException("Set OPENAI_API_KEY or Anthropic_API_KEY or ZHIPUAI_API_KEY first")
|
||||
val = self._get("RAISE_NOT_CONFIG_ERROR")
|
||||
if val is None or val.lower() == "true":
|
||||
raise NotConfiguredException("Set OPENAI_API_KEY or Anthropic_API_KEY or ZHIPUAI_API_KEY first")
|
||||
else: # for agent
|
||||
logger.warning("Set OPENAI_API_KEY or Anthropic_API_KEY or ZHIPUAI_API_KEY first")
|
||||
self.openai_api_base = self._get("OPENAI_API_BASE")
|
||||
self.openai_proxy = self._get("OPENAI_PROXY") or self.global_proxy
|
||||
self.openai_api_type = self._get("OPENAI_API_TYPE")
|
||||
|
|
@ -103,8 +109,15 @@ class Config(metaclass=Singleton):
|
|||
self.pyppeteer_executable_path = self._get("PYPPETEER_EXECUTABLE_PATH", "")
|
||||
|
||||
self.prompt_format = self._get("PROMPT_FORMAT", "markdown")
|
||||
workspace_uid = (
|
||||
self._get("WORKSPACE_UID") or f"{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}-{uuid4().hex[-8:]}"
|
||||
)
|
||||
self.workspace_path = Path(self._get("WORKSPACE_PATH", DEFAULT_WORKSPACE_ROOT))
|
||||
val = self._get("WORKSPACE_PATH_WITH_UID")
|
||||
if val and val.lower() == "true": # for agent
|
||||
self.workspace_path = self.workspace_path / workspace_uid
|
||||
self._ensure_workspace_exists()
|
||||
self.max_auto_summarize_code = self.max_auto_summarize_code or self._get("MAX_AUTO_SUMMARIZE_CODE", 1)
|
||||
|
||||
def _ensure_workspace_exists(self):
|
||||
self.workspace_path.mkdir(parents=True, exist_ok=True)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class Environment(BaseModel):
|
|||
for role in roles:
|
||||
self.add_role(role)
|
||||
|
||||
def publish_message(self, message: Message) -> bool:
|
||||
def publish_message(self, message: Message, peekable: bool = True) -> bool:
|
||||
"""
|
||||
Distribute the message to the recipients.
|
||||
In accordance with the Message routing structure design in Chapter 2.2.1 of RFC 116, as already planned
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ from metagpt.schema import (
|
|||
Documents,
|
||||
Message,
|
||||
)
|
||||
from metagpt.utils.common import any_to_str, any_to_str_set
|
||||
from metagpt.utils.common import any_to_name, any_to_str, any_to_str_set
|
||||
|
||||
IS_PASS_PROMPT = """
|
||||
{context}
|
||||
|
|
@ -83,6 +83,7 @@ class Engineer(Role):
|
|||
self.code_todos = []
|
||||
self.summarize_todos = []
|
||||
self.n_borg = n_borg
|
||||
self._next_todo = any_to_name(WriteCode)
|
||||
|
||||
@staticmethod
|
||||
def _parse_tasks(task_msg: Document) -> list[str]:
|
||||
|
|
@ -124,8 +125,10 @@ class Engineer(Role):
|
|||
if self._rc.todo is None:
|
||||
return None
|
||||
if isinstance(self._rc.todo, WriteCode):
|
||||
self._next_todo = any_to_name(SummarizeCode)
|
||||
return await self._act_write_code()
|
||||
if isinstance(self._rc.todo, SummarizeCode):
|
||||
self._next_todo = any_to_name(WriteCode)
|
||||
return await self._act_summarize()
|
||||
return None
|
||||
|
||||
|
|
@ -296,3 +299,7 @@ class Engineer(Role):
|
|||
self.summarize_todos.append(SummarizeCode(context=ctx, llm=self._llm))
|
||||
if self.summarize_todos:
|
||||
self._rc.todo = self.summarize_todos[0]
|
||||
|
||||
@property
|
||||
def todo(self) -> str:
|
||||
return self._next_todo
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from metagpt.actions import UserRequirement, WritePRD
|
|||
from metagpt.actions.prepare_documents import PrepareDocuments
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.roles import Role
|
||||
from metagpt.utils.common import any_to_name
|
||||
|
||||
|
||||
class ProductManager(Role):
|
||||
|
|
@ -55,3 +56,10 @@ class ProductManager(Role):
|
|||
|
||||
async def _observe(self, ignore_memory=False) -> int:
|
||||
return await super(ProductManager, self)._observe(ignore_memory=True)
|
||||
|
||||
@property
|
||||
def todo(self) -> str:
|
||||
if self._rc.state == 0:
|
||||
return any_to_name(WritePRD)
|
||||
else:
|
||||
return any_to_name(PrepareDocuments)
|
||||
|
|
|
|||
|
|
@ -30,10 +30,8 @@ from metagpt.config import CONFIG
|
|||
from metagpt.llm import LLM, HumanProvider
|
||||
from metagpt.logs import logger
|
||||
from metagpt.memory import Memory
|
||||
|
||||
# from metagpt.memory import LongTermMemory
|
||||
from metagpt.schema import Message, MessageQueue
|
||||
from metagpt.utils.common import any_to_str
|
||||
from metagpt.utils.common import any_to_name, any_to_str
|
||||
|
||||
PREFIX_TEMPLATE = """You are a {profile}, named {name}, your goal is {goal}, and the constraint is {constraints}. """
|
||||
|
||||
|
|
@ -191,6 +189,9 @@ class Role:
|
|||
# check RoleContext after adding watch actions
|
||||
self._rc.check(self._role_id)
|
||||
|
||||
def is_watch(self, caused_by: str):
|
||||
return caused_by in self._rc.watch
|
||||
|
||||
def subscribe(self, tags: Set[str]):
|
||||
"""Used to receive Messages with certain tags from the environment. Message will be put into personal message
|
||||
buffer to be further processed in _observe. By default, a Role subscribes Messages with a tag of its own name
|
||||
|
|
@ -213,22 +214,6 @@ class Role:
|
|||
if env:
|
||||
env.set_subscription(self, self._subscription)
|
||||
|
||||
# # Replaced by FileRepository.set_file
|
||||
# def set_doc(self, content: str, filename: str):
|
||||
# return self._rc.env.set_doc(content, filename)
|
||||
#
|
||||
# # Replaced by FileRepository.get_file
|
||||
# def get_doc(self, filename: str):
|
||||
# return self._rc.env.get_doc(filename)
|
||||
#
|
||||
# # Replaced by CONFIG.xx
|
||||
# def set(self, k, v):
|
||||
# return self._rc.env.set(k, v)
|
||||
#
|
||||
# # Replaced by CONFIG.xx
|
||||
# def get(self, k):
|
||||
# return self._rc.env.get(k)
|
||||
|
||||
@property
|
||||
def profile(self):
|
||||
"""Get the role description (position)"""
|
||||
|
|
@ -368,23 +353,6 @@ class Role:
|
|||
self._set_state(state=-1) # current reaction is complete, reset state to -1 and todo back to None
|
||||
return rsp
|
||||
|
||||
# # Replaced by run()
|
||||
# def recv(self, message: Message) -> None:
|
||||
# """add message to history."""
|
||||
# # self._history += f"\n{message}"
|
||||
# # self._context = self._history
|
||||
# if message in self._rc.memory.get():
|
||||
# return
|
||||
# self._rc.memory.add(message)
|
||||
|
||||
# # Replaced by run()
|
||||
# async def handle(self, message: Message) -> Message:
|
||||
# """Receive information and reply with actions"""
|
||||
# # logger.debug(f"{self.name=}, {self.profile=}, {message.role=}")
|
||||
# self.recv(message)
|
||||
#
|
||||
# return await self._react()
|
||||
|
||||
def get_memories(self, k=0) -> list[Message]:
|
||||
"""A wrapper to return the most recent k memories of this role, return all when k=0"""
|
||||
return self._rc.memory.get(k=k)
|
||||
|
|
@ -418,3 +386,19 @@ class Role:
|
|||
def is_idle(self) -> bool:
|
||||
"""If true, all actions have been executed."""
|
||||
return not self._rc.news and not self._rc.todo and self._rc.msg_buffer.empty()
|
||||
|
||||
async def think(self) -> Action:
|
||||
"""The exported `think` function"""
|
||||
await self._think()
|
||||
return self._rc.todo
|
||||
|
||||
async def act(self) -> ActionOutput:
|
||||
"""The exported `act` function"""
|
||||
msg = await self._act()
|
||||
return ActionOutput(content=msg.content, instruct_content=msg.instruct_content)
|
||||
|
||||
@property
|
||||
def todo(self) -> str:
|
||||
if self._actions:
|
||||
return any_to_name(self._actions[0])
|
||||
return ""
|
||||
|
|
|
|||
|
|
@ -52,13 +52,14 @@ class Team(BaseModel):
|
|||
|
||||
# Human requirement.
|
||||
self.env.publish_message(
|
||||
Message(role="Human", content=idea, cause_by=UserRequirement, send_to=send_to or MESSAGE_ROUTE_TO_ALL)
|
||||
Message(role="Human", content=idea, cause_by=UserRequirement, send_to=send_to or MESSAGE_ROUTE_TO_ALL),
|
||||
peekable=False,
|
||||
)
|
||||
|
||||
def _save(self):
|
||||
logger.info(self.json(ensure_ascii=False))
|
||||
|
||||
async def run(self, n_round=3):
|
||||
async def run(self, n_round=3, auto_archive=True):
|
||||
"""Run company until target round or no money"""
|
||||
while n_round > 0:
|
||||
# self._save()
|
||||
|
|
@ -66,6 +67,6 @@ class Team(BaseModel):
|
|||
logger.debug(f"{n_round=}")
|
||||
self._check_balance()
|
||||
await self.env.run()
|
||||
if CONFIG.git_repo:
|
||||
if auto_archive and CONFIG.git_repo:
|
||||
CONFIG.git_repo.archive()
|
||||
return self.env.history
|
||||
|
|
|
|||
|
|
@ -358,3 +358,14 @@ def is_subscribed(message, tags):
|
|||
if t in message.send_to:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def any_to_name(val):
|
||||
"""
|
||||
Convert a value to its name by extracting the last part of the dotted path.
|
||||
|
||||
:param val: The value to convert.
|
||||
|
||||
:return: The name of the value.
|
||||
"""
|
||||
return any_to_str(val).split(".")[-1]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue