mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-26 01:06:27 +02:00
157 lines
5.1 KiB
Python
157 lines
5.1 KiB
Python
"""
|
|
Filename: MetaGPT/examples/debate.py
|
|
Created Date: Tuesday, September 19th 2023, 6:52:25 pm
|
|
Author: garylin2099
|
|
@Modified By: mashenquan, 2023-11-1. In accordance with Chapter 2.2.1 and 2.2.2 of RFC 116, modify the data
|
|
type of the `cause_by` value in the `Message` to a string, and utilize the new message distribution
|
|
feature for message filtering.
|
|
"""
|
|
import asyncio
|
|
import platform
|
|
|
|
import fire
|
|
|
|
from metagpt.actions import Action, BossRequirement
|
|
from metagpt.logs import logger
|
|
from metagpt.roles import Role
|
|
from metagpt.schema import Message
|
|
from metagpt.software_company import SoftwareCompany
|
|
|
|
|
|
class ShoutOut(Action):
|
|
"""Action: Shout out loudly in a debate (quarrel)"""
|
|
|
|
PROMPT_TEMPLATE = """
|
|
## BACKGROUND
|
|
Suppose you are {name}, you are in a debate with {opponent_name}.
|
|
## DEBATE HISTORY
|
|
Previous rounds:
|
|
{context}
|
|
## YOUR TURN
|
|
Now it's your turn, you should closely respond to your opponent's latest argument, state your position, defend your arguments, and attack your opponent's arguments,
|
|
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):
|
|
super().__init__(name, context, llm)
|
|
|
|
async def run(self, context: str, name: str, opponent_name: str):
|
|
prompt = self.PROMPT_TEMPLATE.format(context=context, name=name, opponent_name=opponent_name)
|
|
# logger.info(prompt)
|
|
|
|
rsp = await self._aask(prompt)
|
|
|
|
return rsp
|
|
|
|
|
|
class Trump(Role):
|
|
def __init__(
|
|
self,
|
|
name: str = "Trump",
|
|
profile: str = "Republican",
|
|
**kwargs,
|
|
):
|
|
super().__init__(name, profile, **kwargs)
|
|
self._init_actions([ShoutOut])
|
|
self._watch([ShoutOut])
|
|
self.name = "Trump"
|
|
self.opponent_name = "Biden"
|
|
|
|
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.contain_any({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([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,
|
|
msg_from=self.name,
|
|
msg_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
|
|
message_filter = {BossRequirement, self.name}
|
|
self._rc.news = [msg for msg in self._rc.news if msg.contain_any(message_filter)]
|
|
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,
|
|
msg_from=self.name,
|
|
msg_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)
|
|
|
|
|
|
def main(idea: str, investment: float = 3.0, n_round: int = 10):
|
|
"""
|
|
:param idea: Debate topic, such as "Topic: The U.S. should commit more in climate change fighting"
|
|
or "Trump: Climate change is a hoax"
|
|
:param investment: contribute a certain dollar amount to watch the debate
|
|
:param n_round: maximum rounds of the debate
|
|
:return:
|
|
"""
|
|
if platform.system() == "Windows":
|
|
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
asyncio.run(startup(idea, investment, n_round))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
fire.Fire(main)
|