change PROJECT_ROOT setting & SoftwareCompany -> Team

This commit is contained in:
garylin2099 2023-11-08 19:42:30 +08:00
parent c6350efd7f
commit 56c2a162ac
10 changed files with 54 additions and 90 deletions

View file

@ -270,12 +270,12 @@ ### Usage
### Code walkthrough
```python
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from metagpt.roles import ProjectManager, ProductManager, Architect, Engineer
async def startup(idea: str, investment: float = 3.0, n_round: int = 5):
"""Run a startup. Be a boss."""
company = SoftwareCompany()
company = Team()
company.hire([ProductManager(), Architect(), ProjectManager(), Engineer()])
company.invest(investment)
company.start_project(idea)

View file

@ -190,12 +190,12 @@ ### 使用
### 代码实现
```python
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from metagpt.roles import ProjectManager, ProductManager, Architect, Engineer
async def startup(idea: str, investment: float = 3.0, n_round: int = 5):
"""运行一个创业公司。做一个老板"""
company = SoftwareCompany()
company = Team()
company.hire([ProductManager(), Architect(), ProjectManager(), Engineer()])
company.invest(investment)
company.start_project(idea)

View file

@ -270,12 +270,12 @@ ### 使用方法
### コードウォークスルー
```python
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from metagpt.roles import ProjectManager, ProductManager, Architect, Engineer
async def startup(idea: str, investment: float = 3.0, n_round: int = 5):
"""スタートアップを実行する。ボスになる。"""
company = SoftwareCompany()
company = Team()
company.hire([ProductManager(), Architect(), ProjectManager(), Engineer()])
company.invest(investment)
company.start_project(idea)

View file

@ -7,14 +7,14 @@ import asyncio
import platform
import fire
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from metagpt.actions import Action, BossRequirement
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.logs import logger
class ShoutOut(Action):
"""Action: Shout out loudly in a debate (quarrel)"""
class SpeakAloud(Action):
"""Action: Speak out aloud in a debate (quarrel)"""
PROMPT_TEMPLATE = """
## BACKGROUND
@ -27,7 +27,7 @@ class ShoutOut(Action):
craft a strong and emotional response in 80 words, in {name}'s rhetoric and viewpoints, your will argue:
"""
def __init__(self, name="ShoutOut", context=None, llm=None):
def __init__(self, name="SpeakAloud", context=None, llm=None):
super().__init__(name, context, llm)
async def run(self, context: str, name: str, opponent_name: str):
@ -39,96 +39,55 @@ class ShoutOut(Action):
return rsp
class Trump(Role):
class Debator(Role):
def __init__(
self,
name: str = "Trump",
profile: str = "Republican",
name: str,
profile: str,
opponent_name: str,
**kwargs,
):
super().__init__(name, profile, **kwargs)
self._init_actions([ShoutOut])
self._watch([ShoutOut])
self.name = "Trump"
self.opponent_name = "Biden"
self._init_actions([SpeakAloud])
self._watch([BossRequirement, SpeakAloud])
self.name = name
self.opponent_name = opponent_name
async def _observe(self) -> int:
await super()._observe()
# accept messages sent (from opponent) to self, disregard own messages from the last round
self._rc.news = [msg for msg in self._rc.news if msg.send_to == self.name]
self._rc.news = [msg for msg in self._rc.news if msg.send_to == self.name]
return len(self._rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
todo = self._rc.todo # An instance of SpeakAloud
msg_history = self._rc.memory.get_by_actions([ShoutOut])
context = []
for m in msg_history:
context.append(str(m))
context = "\n".join(context)
memories = self.get_memories()
context = "\n".join(f"{msg.sent_from}: {msg.content}" for msg in memories)
# print(context)
rsp = await ShoutOut().run(context=context, name=self.name, opponent_name=self.opponent_name)
rsp = await todo.run(context=context, name=self.name, opponent_name=self.opponent_name)
msg = Message(
content=rsp,
role=self.profile,
cause_by=ShoutOut,
cause_by=type(todo),
sent_from=self.name,
send_to=self.opponent_name,
)
return msg
class Biden(Role):
def __init__(
self,
name: str = "Biden",
profile: str = "Democrat",
**kwargs,
):
super().__init__(name, profile, **kwargs)
self._init_actions([ShoutOut])
self._watch([BossRequirement, ShoutOut])
self.name = "Biden"
self.opponent_name = "Trump"
async def _observe(self) -> int:
await super()._observe()
# accept the very first human instruction (the debate topic) or messages sent (from opponent) to self,
# disregard own messages from the last round
self._rc.news = [msg for msg in self._rc.news if msg.cause_by == BossRequirement or msg.send_to == self.name]
return len(self._rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
msg_history = self._rc.memory.get_by_actions([BossRequirement, ShoutOut])
context = []
for m in msg_history:
context.append(str(m))
context = "\n".join(context)
rsp = await ShoutOut().run(context=context, name=self.name, opponent_name=self.opponent_name)
msg = Message(
content=rsp,
role=self.profile,
cause_by=ShoutOut,
sent_from=self.name,
send_to=self.opponent_name,
)
return msg
async def startup(idea: str, investment: float = 3.0, n_round: int = 5,
code_review: bool = False, run_tests: bool = False):
"""We reuse the startup paradigm for roles to interact with each other.
Now we run a startup of presidents and watch they quarrel. :) """
company = SoftwareCompany()
company.hire([Biden(), Trump()])
company.invest(investment)
company.start_project(idea)
await company.run(n_round=n_round)
async def debate(idea: str, investment: float = 3.0, n_round: int = 5):
"""Run a team of presidents and watch they quarrel. :) """
Biden = Debator(name="Biden", profile="Democrat", opponent_name="Trump")
Trump = Debator(name="Trump", profile="Republican", opponent_name="Biden")
team = Team()
team.hire([Biden, Trump])
team.invest(investment)
team.start_project(idea, send_to="Biden") # send debate topic to Biden and let him speak first
await team.run(n_round=n_round)
def main(idea: str, investment: float = 3.0, n_round: int = 10):
@ -141,7 +100,7 @@ def main(idea: str, investment: float = 3.0, n_round: int = 10):
"""
if platform.system() == "Windows":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(startup(idea, investment, n_round))
asyncio.run(debate(idea, investment, n_round))
if __name__ == '__main__':

View file

@ -6,7 +6,7 @@
@File : const.py
"""
from pathlib import Path
from loguru import logger
def get_project_root():
"""Search upwards to find the project root directory."""
@ -17,10 +17,14 @@ def get_project_root():
or (current_path / ".project_root").exists()
or (current_path / ".gitignore").exists()
):
# use metagpt with git clone will land here
return current_path
parent_path = current_path.parent
if parent_path == current_path:
raise Exception("Project root not found.")
# use metagpt with pip install will land here
cwd = Path.cwd()
logger.info(f"RPOJECT_ROOT set to current working directory: {str(cwd)}")
return cwd
current_path = parent_path

View file

@ -207,6 +207,7 @@ class Engineer(Role):
async def _act(self) -> Message:
"""Determines the mode of action based on whether code review is used."""
logger.info(f"{self._setting}: ready to WriteCode")
if self.use_code_review:
return await self._act_sp_precision()
return await self._act_sp()

View file

@ -16,10 +16,10 @@ from metagpt.schema import Message
from metagpt.utils.common import NoMoneyException
class SoftwareCompany(BaseModel):
class Team(BaseModel):
"""
Software Company: Possesses a team, SOP (Standard Operating Procedures), and a platform for instant messaging,
dedicated to writing executable code.
Team: Possesses one or more roles (agents), SOP (Standard Operating Procedures), and a platform for instant messaging,
dedicated to perform any multi-agent activity, such as collaboratively writing executable code.
"""
environment: Environment = Field(default_factory=Environment)
investment: float = Field(default=10.0)
@ -42,10 +42,10 @@ class SoftwareCompany(BaseModel):
if CONFIG.total_cost > CONFIG.max_budget:
raise NoMoneyException(CONFIG.total_cost, f'Insufficient funds: {CONFIG.max_budget}')
def start_project(self, idea):
def start_project(self, idea, send_to: str = ""):
"""Start a project from publishing boss requirement."""
self.idea = idea
self.environment.publish_message(Message(role="BOSS", content=idea, cause_by=BossRequirement))
self.environment.publish_message(Message(role="Human", content=idea, cause_by=BossRequirement, send_to=send_to))
def _save(self):
logger.info(self.json())

View file

@ -11,7 +11,7 @@ from metagpt.roles import (
ProjectManager,
QaEngineer,
)
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
async def startup(
@ -23,7 +23,7 @@ async def startup(
implement: bool = True,
):
"""Run a startup. Be a boss."""
company = SoftwareCompany()
company = Team()
company.hire(
[
ProductManager(),

View file

@ -2,7 +2,7 @@
# @Date : 2023/7/22 02:40
# @Author : stellahong (stellahong@fuzhi.ai)
#
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
from metagpt.roles import ProductManager
from tests.metagpt.roles.ui_role import UI
@ -15,7 +15,7 @@ def test_add_ui():
async def test_ui_role(idea: str, investment: float = 3.0, n_round: int = 5):
"""Run a startup. Be a boss."""
company = SoftwareCompany()
company = Team()
company.hire([ProductManager(), UI()])
company.invest(investment)
company.start_project(idea)

View file

@ -8,12 +8,12 @@
import pytest
from metagpt.logs import logger
from metagpt.software_company import SoftwareCompany
from metagpt.team import Team
@pytest.mark.asyncio
async def test_software_company():
company = SoftwareCompany()
async def test_team():
company = Team()
company.start_project("做一个基础搜索引擎,可以支持知识库")
history = await company.run(n_round=5)
logger.info(history)