2023-11-01 20:08:58 +08:00
"""
2023-09-19 19:31:25 +08:00
Filename : MetaGPT / examples / debate . py
Created Date : Tuesday , September 19 th 2023 , 6 : 52 : 25 pm
Author : garylin2099
2023-11-08 21:38:52 +08:00
@Modified By : mashenquan , 2023 - 11 - 1. In accordance with Chapter 2.1 .3 of RFC 116 , modify the data type of the ` send_to `
2023-11-09 11:14:05 +08:00
value of the ` Message ` object ; modify the argument type of ` get_by_actions ` .
2023-11-01 20:08:58 +08:00
"""
2023-09-15 22:40:22 +08:00
import asyncio
import platform
2023-12-27 15:03:34 +08:00
from typing import Any
2023-11-01 20:08:58 +08:00
2023-09-15 22:40:22 +08:00
import fire
2023-11-20 11:24:46 +08:00
from metagpt . actions import Action , UserRequirement
2023-11-01 20:08:58 +08:00
from metagpt . logs import logger
2023-09-15 22:40:22 +08:00
from metagpt . roles import Role
from metagpt . schema import Message
2023-11-28 18:16:50 +08:00
from metagpt . team import Team
2023-11-01 20:08:58 +08:00
2023-09-15 22:40:22 +08:00
2023-11-08 19:42:30 +08:00
class SpeakAloud ( Action ) :
""" Action: Speak out aloud in a debate (quarrel) """
2023-09-15 22:40:22 +08:00
2023-12-27 15:03:34 +08:00
PROMPT_TEMPLATE : str = """
2023-09-15 22:40:22 +08:00
## 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:
"""
2023-12-27 15:03:34 +08:00
name : str = " SpeakAloud "
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
2023-11-01 20:08:58 +08:00
2023-11-08 19:42:30 +08:00
class Debator ( Role ) :
2023-12-27 15:03:34 +08:00
name : str = " "
profile : str = " "
opponent_name : str = " "
def __init__ ( self , * * data : Any ) :
super ( ) . __init__ ( * * data )
2024-01-10 17:54:13 +08:00
self . set_actions ( [ SpeakAloud ] )
2023-11-20 11:24:46 +08:00
self . _watch ( [ UserRequirement , SpeakAloud ] )
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
2023-12-27 14:00:54 +08:00
self . rc . news = [ msg for msg in self . rc . news if msg . send_to == { self . name } ]
return len ( self . rc . news )
2023-09-15 22:40:22 +08:00
async def _act ( self ) - > Message :
2023-12-27 14:00:54 +08:00
logger . info ( f " { self . _setting } : to do { self . rc . todo } ( { self . rc . todo . name } ) " )
todo = self . rc . todo # An instance of SpeakAloud
2023-09-20 11:42:41 +08:00
2023-11-08 19:42:30 +08:00
memories = self . get_memories ( )
context = " \n " . join ( f " { msg . sent_from } : { msg . content } " for msg in memories )
# print(context)
2023-09-15 22:40:22 +08:00
2023-11-08 19:42:30 +08:00
rsp = await todo . 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 ,
2023-11-08 19:42:30 +08:00
cause_by = type ( todo ) ,
2023-11-08 20:56:05 +08:00
sent_from = self . name ,
send_to = self . opponent_name ,
2023-09-15 22:40:22 +08:00
)
2023-12-27 14:00:54 +08:00
self . rc . memory . add ( msg )
2023-09-15 22:40:22 +08:00
return msg
2023-11-01 20:08:58 +08:00
2023-11-08 19:42:30 +08:00
async def debate ( idea : str , investment : float = 3.0 , n_round : int = 5 ) :
2023-11-28 18:16:50 +08:00
""" Run a team of presidents and watch they quarrel. :) """
2023-11-08 19:42:30 +08:00
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 )
2023-11-28 18:16:50 +08:00
team . run_project ( idea , send_to = " Biden " ) # send debate topic to Biden and let him speak first
2023-11-08 19:42:30 +08:00
await team . run ( n_round = n_round )
2023-09-15 22:40:22 +08:00
2023-09-19 19:31:25 +08:00
def main ( idea : str , investment : float = 3.0 , n_round : int = 10 ) :
2023-09-15 22:40:22 +08:00
"""
2023-11-01 20:08:58 +08:00
: param idea : Debate topic , such as " Topic: The U.S. should commit more in climate change fighting "
2023-09-20 11:42:41 +08:00
or " Trump: Climate change is a hoax "
2023-09-19 19:31:25 +08:00
: 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 ( ) )
2023-11-08 19:42:30 +08:00
asyncio . run ( debate ( idea , investment , n_round ) )
2023-09-15 22:40:22 +08:00
2023-11-01 20:08:58 +08:00
if __name__ == " __main__ " :
2023-09-15 22:40:22 +08:00
fire . Fire ( main )