MetaGPT/examples/debate.py

149 lines
4.8 KiB
Python
Raw Normal View History

'''
Filename: MetaGPT/examples/debate.py
Created Date: Tuesday, September 19th 2023, 6:52:25 pm
Author: garylin2099
'''
2023-09-15 22:40:22 +08:00
import asyncio
import platform
import fire
from metagpt.software_company import SoftwareCompany
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)"""
2023-09-15 22:40:22 +08:00
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):
2023-09-15 22:40:22 +08:00
super().__init__(name, context, llm)
2023-09-20 11:42:41 +08:00
2023-09-15 22:40:22 +08:00
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",
2023-09-15 22:40:22 +08:00
**kwargs,
):
super().__init__(name, profile, **kwargs)
self._init_actions([ShoutOut])
self._watch([ShoutOut])
2023-09-15 22:40:22 +08:00
self.name = "Trump"
self.opponent_name = "Biden"
2023-09-20 11:42:41 +08:00
2023-09-15 22:40:22 +08:00
async def _observe(self) -> int:
await super()._observe()
2023-09-20 11:42:41 +08:00
# 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]
2023-09-15 22:40:22 +08:00
return len(self._rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
2023-09-20 11:42:41 +08:00
msg_history = self._rc.memory.get_by_actions([ShoutOut])
2023-09-15 22:40:22 +08:00
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)
2023-09-15 22:40:22 +08:00
msg = Message(
content=rsp,
role=self.profile,
cause_by=ShoutOut,
2023-09-15 22:40:22 +08:00
sent_from=self.name,
send_to=self.opponent_name,
)
return msg
class Biden(Role):
def __init__(
self,
name: str = "Biden",
profile: str = "Democrat",
2023-09-15 22:40:22 +08:00
**kwargs,
):
super().__init__(name, profile, **kwargs)
self._init_actions([ShoutOut])
self._watch([BossRequirement, ShoutOut])
2023-09-15 22:40:22 +08:00
self.name = "Biden"
self.opponent_name = "Trump"
2023-09-20 11:42:41 +08:00
2023-09-15 22:40:22 +08:00
async def _observe(self) -> int:
await super()._observe()
2023-09-20 11:42:41 +08:00
# 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]
2023-09-15 22:40:22 +08:00
return len(self._rc.news)
async def _act(self) -> Message:
logger.info(f"{self._setting}: ready to {self._rc.todo}")
2023-09-20 11:42:41 +08:00
msg_history = self._rc.memory.get_by_actions([BossRequirement, ShoutOut])
2023-09-15 22:40:22 +08:00
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)
2023-09-15 22:40:22 +08:00
msg = Message(
content=rsp,
role=self.profile,
cause_by=ShoutOut,
2023-09-15 22:40:22 +08:00
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. :) """
2023-09-15 22:40:22 +08:00
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):
2023-09-15 22:40:22 +08:00
"""
2023-09-20 11:42:41 +08:00
: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
2023-09-15 22:40:22 +08:00
:return:
"""
if platform.system() == "Windows":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(startup(idea, investment, n_round))
2023-09-15 22:40:22 +08:00
if __name__ == '__main__':
fire.Fire(main)