From c0ce28659d74014af2e31014619e2132986e3059 Mon Sep 17 00:00:00 2001 From: yzlin Date: Fri, 15 Sep 2023 22:40:22 +0800 Subject: [PATCH 1/5] basic examples --- examples/build_customized_agent.py | 136 ++++++++++++++++++++++++++ examples/debate.py | 145 ++++++++++++++++++++++++++++ examples/use_off_the_shelf_agent.py | 13 +++ 3 files changed, 294 insertions(+) create mode 100644 examples/build_customized_agent.py create mode 100644 examples/debate.py create mode 100644 examples/use_off_the_shelf_agent.py diff --git a/examples/build_customized_agent.py b/examples/build_customized_agent.py new file mode 100644 index 000000000..7122a9858 --- /dev/null +++ b/examples/build_customized_agent.py @@ -0,0 +1,136 @@ +import re +import subprocess + +from metagpt.actions import Action +from metagpt.roles import Role +from metagpt.schema import Message +from metagpt.logs import logger + +class SimpleWriteCode(Action): + + PROMPT_TEMPLATE = """ + Write a python function that can {instruction} and provide two runnnable test cases. + Return ```python your_code_here ``` with NO other texts, + example: + ```python + # function + def add(a, b): + return a + b + # test cases + print(add(1, 2)) + print(add(3, 4)) + ``` + your code: + """ + + def __init__(self, name="SimpleWriteCode", context=None, llm=None): + super().__init__(name, context, llm) + + async def run(self, instruction: str): + + prompt = self.PROMPT_TEMPLATE.format(instruction=instruction) + # logger.info(prompt) + + rsp = await self._aask(prompt) + + code_text = SimpleWriteCode.parse_code(rsp) + + return code_text + + @staticmethod + def parse_code(rsp): + pattern = r'```python(.*)```' + match = re.search(pattern, rsp, re.DOTALL) + code_text = match.group(1) if match else rsp + return code_text + +class SimpleRunCode(Action): + def __init__(self, name="SimpleRunCode", context=None, llm=None): + super().__init__(name, context, llm) + + async def run(self, code_text: str): + result = subprocess.run(["python3", "-c", code_text], capture_output=True, text=True) + code_result = result.stdout + # exec(code_text) + logger.info(f"{code_result=}") + return code_result + +class SimpleCoder(Role): + def __init__( + self, + name: str = "Alice", + profile: str = "SimpleCoder", + **kwargs, + ): + super().__init__(name, profile, **kwargs) + self._init_actions([SimpleWriteCode]) + + async def _act(self) -> Message: + logger.info(f"{self._setting}: ready to {self._rc.todo}") + todo = self._rc.todo + msg = self._rc.memory.get()[-1] + + instruction = msg.content + code_text = await SimpleWriteCode().run(instruction) + msg = Message(content=code_text, role=self.profile, cause_by=todo) + + return msg + +class RunnableCoder(Role): + def __init__( + self, + name: str = "Alice", + profile: str = "RunnableCoder", + **kwargs, + ): + super().__init__(name, profile, **kwargs) + self._init_actions([SimpleWriteCode, SimpleRunCode]) + + async def _think(self) -> None: + if self._rc.todo is None: + self._set_state(0) + return + + if self._rc.state + 1 < len(self._states): + self._set_state(self._rc.state + 1) + else: + self._rc.todo = None + + async def _act(self) -> Message: + logger.info(f"{self._setting}: ready to {self._rc.todo}") + todo = self._rc.todo + msg = self._rc.memory.get()[-1] + + if isinstance(todo, SimpleWriteCode): + instruction = msg.content + code_text = await SimpleWriteCode().run(instruction) + msg = Message(content=code_text, role=self.profile, cause_by=todo) + + elif isinstance(todo, SimpleRunCode): + code_text = msg.content + rsp = await SimpleRunCode().run(code_text) + msg = Message(content=rsp, role=self.profile, cause_by=todo) + + self._rc.memory.add(msg) + return msg + + async def _react(self) -> Message: + while True: + await self._think() + if self._rc.todo is None: + break + await self._act() + return Message(content="All job done", role=self.profile) + +if __name__ == "__main__": + import asyncio + + async def main(): + msg = "write a function that calculates the sum of a list" + # role = SimpleCoder() + role = RunnableCoder() + logger.info(msg) + result = await role.run(msg) + logger.info(result) + + asyncio.run(main()) \ No newline at end of file diff --git a/examples/debate.py b/examples/debate.py new file mode 100644 index 000000000..c98705fcc --- /dev/null +++ b/examples/debate.py @@ -0,0 +1,145 @@ +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 Shout(Action): + + 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="Shout", 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 = "Trump", + **kwargs, + ): + super().__init__(name, profile, **kwargs) + self._init_actions([Shout]) + self._watch([Shout]) + self.name = "Trump" + self.opponent_name = "Biden" + + async def _observe(self) -> int: + await super()._observe() + self._rc.news = [ + msg for msg in self._rc.news if msg.send_to == self.name + ] # only relevant msgs count as observed news + 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([Shout]) + context = [] + for m in msg_history: + context.append(str(m)) + context = "\n".join(context) + + rsp = await Shout().run(context=context, name=self.name, opponent_name=self.opponent_name) + + msg = Message( + content=rsp, + role=self.profile, + cause_by=Shout, + sent_from=self.name, + send_to=self.opponent_name, + ) + self._publish_message(msg) + + return msg + +class Biden(Role): + def __init__( + self, + name: str = "Biden", + profile: str = "Biden", + **kwargs, + ): + super().__init__(name, profile, **kwargs) + self._init_actions([Shout]) + self._watch([BossRequirement, Shout]) + self.name = "Biden" + self.opponent_name = "Trump" + + async def _observe(self) -> int: + await super()._observe() + self._rc.news = [ + msg for msg in self._rc.news if msg.send_to == self.name or msg.cause_by == BossRequirement + ] # only relevant msgs count as observed news + 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, Shout]) + context = [] + for m in msg_history: + context.append(str(m)) + context = "\n".join(context) + + rsp = await Shout().run(context=context, name=self.name, opponent_name=self.opponent_name) + + msg = Message( + content=rsp, + role=self.profile, + cause_by=Shout, + sent_from=self.name, + send_to=self.opponent_name, + ) + self._publish_message(msg) + + return msg + +async def startup(idea: str, investment: float = 3.0, n_round: int = 5, + code_review: bool = False, run_tests: bool = False): + """Run a startup of presidents. 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, code_review: bool = False, run_tests: bool = False): + """ + We are a software startup comprised of AI. By investing in us, you are empowering a future filled with limitless possibilities. + :param idea: Your innovative idea, such as "Creating a snake game." + :param investment: As an investor, you have the opportunity to contribute a certain dollar amount to this AI company. + :param n_round: + :param code_review: Whether to use code review. + :return: + """ + if platform.system() == "Windows": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + asyncio.run(startup(idea, investment, n_round, code_review, run_tests)) + + +if __name__ == '__main__': + fire.Fire(main) diff --git a/examples/use_off_the_shelf_agent.py b/examples/use_off_the_shelf_agent.py new file mode 100644 index 000000000..48fb2b19e --- /dev/null +++ b/examples/use_off_the_shelf_agent.py @@ -0,0 +1,13 @@ +import asyncio + +from metagpt.roles.product_manager import ProductManager +from metagpt.logs import logger + +async def main(): + msg = "Write a PRD for a snake game" + role = ProductManager() + result = await role.run(msg) + logger.info(result.content[:100]) + +if __name__ == '__main__': + asyncio.run(main()) From fa8eb17451696178633774947f79b179c2a3101b Mon Sep 17 00:00:00 2001 From: yzlin Date: Tue, 19 Sep 2023 19:31:25 +0800 Subject: [PATCH 2/5] add AgentCreator and some minor formatting --- examples/agent_creator.py | 99 +++++++++++++++++++++++++++++ examples/build_customized_agent.py | 5 ++ examples/debate.py | 49 +++++++------- examples/use_off_the_shelf_agent.py | 5 ++ 4 files changed, 136 insertions(+), 22 deletions(-) create mode 100644 examples/agent_creator.py diff --git a/examples/agent_creator.py b/examples/agent_creator.py new file mode 100644 index 000000000..748dc02b1 --- /dev/null +++ b/examples/agent_creator.py @@ -0,0 +1,99 @@ +''' +Filename: MetaGPT/examples/agent_creator.py +Created Date: Tuesday, September 12th 2023, 3:28:37 pm +Author: garylin2099 +''' +import re + +from metagpt.const import PROJECT_ROOT, WORKSPACE_ROOT +from metagpt.actions import Action +from metagpt.roles import Role +from metagpt.schema import Message +from metagpt.logs import logger + +with open(PROJECT_ROOT / "examples/build_customized_agent.py", "r") as f: + # use official example script to guide AgentCreator + MULTI_ACTION_AGENT_CODE_EXAMPLE = f.read() + +class CreateAgent(Action): + + PROMPT_TEMPLATE = """ + ### BACKGROUND + You are using an agent framework called metagpt to write agents capable of different actions, + the usage of metagpt can be illustrated by the following example: + ### EXAMPLE STARTS AT THIS LINE + {example} + ### EXAMPLE ENDS AT THIS LINE + ### TASK + Now you should create an agent with appropriate actions based on the instruction, consider carefully about + the PROMPT_TEMPLATE of all actions and when to call self._aask() + ### INSTRUCTION + {instruction} + ### YOUR CODE + Return ```python your_code_here ``` with NO other texts, your code: + """ + + async def run(self, example: str, instruction: str): + + prompt = self.PROMPT_TEMPLATE.format(example=example, instruction=instruction) + # logger.info(prompt) + + rsp = await self._aask(prompt) + + code_text = CreateAgent.parse_code(rsp) + + return code_text + + @staticmethod + def parse_code(rsp): + pattern = r'```python(.*)```' + match = re.search(pattern, rsp, re.DOTALL) + code_text = match.group(1) if match else "" + with open(WORKSPACE_ROOT / "agent_created_agent.py", "w") as f: + f.write(code_text) + return code_text + +class AgentCreator(Role): + def __init__( + self, + name: str = "Matrix", + profile: str = "AgentCreator", + agent_template: str = MULTI_ACTION_AGENT_CODE_EXAMPLE, + **kwargs, + ): + super().__init__(name, profile, **kwargs) + self._init_actions([CreateAgent]) + self.agent_template = agent_template + + async def _act(self) -> Message: + logger.info(f"{self._setting}: ready to {self._rc.todo}") + todo = self._rc.todo + msg = self._rc.memory.get()[-1] + + instruction = msg.content + code_text = await CreateAgent().run(example=self.agent_template, instruction=instruction) + msg = Message(content=code_text, role=self.profile, cause_by=todo) + + return msg + +if __name__ == "__main__": + import asyncio + + async def main(): + + agent_template = MULTI_ACTION_AGENT_CODE_EXAMPLE + + creator = AgentCreator(agent_template=agent_template) + + # msg = """Write an agent called SimpleTester that will take any code snippet (str) and return a testing code (str) for testing + # the given code snippet. Use pytest as the testing framework.""" + + msg = """ + Write an agent called SimpleTester that will take any code snippet (str) and do the following: + 1. write a testing code (str) for testing the given code snippet, save the testing code as a .py file in the current working diretory; + 2. run the testing code. + You can use pytest as the testing framework. + """ + result = await creator.run(msg) + + asyncio.run(main()) diff --git a/examples/build_customized_agent.py b/examples/build_customized_agent.py index 7122a9858..312ffa4d5 100644 --- a/examples/build_customized_agent.py +++ b/examples/build_customized_agent.py @@ -1,3 +1,8 @@ +''' +Filename: MetaGPT/examples/build_customized_agent.py +Created Date: Tuesday, September 19th 2023, 6:52:25 pm +Author: garylin2099 +''' import re import subprocess diff --git a/examples/debate.py b/examples/debate.py index c98705fcc..4e90edd20 100644 --- a/examples/debate.py +++ b/examples/debate.py @@ -1,3 +1,8 @@ +''' +Filename: MetaGPT/examples/debate.py +Created Date: Tuesday, September 19th 2023, 6:52:25 pm +Author: garylin2099 +''' import asyncio import platform import fire @@ -8,7 +13,8 @@ from metagpt.roles import Role from metagpt.schema import Message from metagpt.logs import logger -class Shout(Action): +class ShoutOut(Action): + """Action: Shout out loudly in a debate (quarrel)""" PROMPT_TEMPLATE = """ ## BACKGROUND @@ -21,7 +27,7 @@ class Shout(Action): craft a strong and emotional response in 80 words, in {name}'s rhetoric and viewpoints, your will argue: """ - def __init__(self, name="Shout", context=None, llm=None): + 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): @@ -37,12 +43,12 @@ class Trump(Role): def __init__( self, name: str = "Trump", - profile: str = "Trump", + profile: str = "Republican", **kwargs, ): super().__init__(name, profile, **kwargs) - self._init_actions([Shout]) - self._watch([Shout]) + self._init_actions([ShoutOut]) + self._watch([ShoutOut]) self.name = "Trump" self.opponent_name = "Biden" @@ -56,18 +62,18 @@ class Trump(Role): async def _act(self) -> Message: logger.info(f"{self._setting}: ready to {self._rc.todo}") - msg_history = self._rc.memory.get_by_actions([Shout]) + 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 Shout().run(context=context, name=self.name, opponent_name=self.opponent_name) + rsp = await ShoutOut().run(context=context, name=self.name, opponent_name=self.opponent_name) msg = Message( content=rsp, role=self.profile, - cause_by=Shout, + cause_by=ShoutOut, sent_from=self.name, send_to=self.opponent_name, ) @@ -79,12 +85,12 @@ class Biden(Role): def __init__( self, name: str = "Biden", - profile: str = "Biden", + profile: str = "Democrat", **kwargs, ): super().__init__(name, profile, **kwargs) - self._init_actions([Shout]) - self._watch([BossRequirement, Shout]) + self._init_actions([ShoutOut]) + self._watch([BossRequirement, ShoutOut]) self.name = "Biden" self.opponent_name = "Trump" @@ -98,18 +104,18 @@ class Biden(Role): async def _act(self) -> Message: logger.info(f"{self._setting}: ready to {self._rc.todo}") - msg_history = self._rc.memory.get_by_actions([BossRequirement, Shout]) + 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 Shout().run(context=context, name=self.name, opponent_name=self.opponent_name) + rsp = await ShoutOut().run(context=context, name=self.name, opponent_name=self.opponent_name) msg = Message( content=rsp, role=self.profile, - cause_by=Shout, + cause_by=ShoutOut, sent_from=self.name, send_to=self.opponent_name, ) @@ -119,7 +125,8 @@ class Biden(Role): async def startup(idea: str, investment: float = 3.0, n_round: int = 5, code_review: bool = False, run_tests: bool = False): - """Run a startup of presidents. Watch they quarrel. :) """ + """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) @@ -127,18 +134,16 @@ async def startup(idea: str, investment: float = 3.0, n_round: int = 5, await company.run(n_round=n_round) -def main(idea: str, investment: float = 3.0, n_round: int = 10, code_review: bool = False, run_tests: bool = False): +def main(idea: str, investment: float = 3.0, n_round: int = 10): """ - We are a software startup comprised of AI. By investing in us, you are empowering a future filled with limitless possibilities. - :param idea: Your innovative idea, such as "Creating a snake game." - :param investment: As an investor, you have the opportunity to contribute a certain dollar amount to this AI company. - :param n_round: - :param code_review: Whether to use code review. + :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, code_review, run_tests)) + asyncio.run(startup(idea, investment, n_round)) if __name__ == '__main__': diff --git a/examples/use_off_the_shelf_agent.py b/examples/use_off_the_shelf_agent.py index 48fb2b19e..2e10068bd 100644 --- a/examples/use_off_the_shelf_agent.py +++ b/examples/use_off_the_shelf_agent.py @@ -1,3 +1,8 @@ +''' +Filename: MetaGPT/examples/use_off_the_shelf_agent.py +Created Date: Tuesday, September 19th 2023, 6:52:25 pm +Author: garylin2099 +''' import asyncio from metagpt.roles.product_manager import ProductManager From e0381680adcb58a5c415cbb0da9f79e0cbbe9504 Mon Sep 17 00:00:00 2001 From: yzlin Date: Tue, 19 Sep 2023 23:15:58 +0800 Subject: [PATCH 3/5] minor update --- examples/build_customized_agent.py | 21 ++++++++++----------- examples/debate.py | 8 +++----- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/examples/build_customized_agent.py b/examples/build_customized_agent.py index 312ffa4d5..746c8c9fa 100644 --- a/examples/build_customized_agent.py +++ b/examples/build_customized_agent.py @@ -6,6 +6,8 @@ Author: garylin2099 import re import subprocess +import fire + from metagpt.actions import Action from metagpt.roles import Role from metagpt.schema import Message @@ -127,15 +129,12 @@ class RunnableCoder(Role): await self._act() return Message(content="All job done", role=self.profile) -if __name__ == "__main__": - import asyncio +async def main(msg="write a function that calculates the sum of a list"): + # role = SimpleCoder() + role = RunnableCoder() + logger.info(msg) + result = await role.run(msg) + logger.info(result) - async def main(): - msg = "write a function that calculates the sum of a list" - # role = SimpleCoder() - role = RunnableCoder() - logger.info(msg) - result = await role.run(msg) - logger.info(result) - - asyncio.run(main()) \ No newline at end of file +if __name__ == '__main__': + fire.Fire(main) \ No newline at end of file diff --git a/examples/debate.py b/examples/debate.py index 4e90edd20..3a9abf9bc 100644 --- a/examples/debate.py +++ b/examples/debate.py @@ -56,7 +56,7 @@ class Trump(Role): await super()._observe() self._rc.news = [ msg for msg in self._rc.news if msg.send_to == self.name - ] # only relevant msgs count as observed news + ] # accept messages sent (from opponent) to self, disregard own messages from the last round return len(self._rc.news) async def _act(self) -> Message: @@ -77,7 +77,6 @@ class Trump(Role): sent_from=self.name, send_to=self.opponent_name, ) - self._publish_message(msg) return msg @@ -97,8 +96,8 @@ class Biden(Role): async def _observe(self) -> int: await super()._observe() self._rc.news = [ - msg for msg in self._rc.news if msg.send_to == self.name or msg.cause_by == BossRequirement - ] # only relevant msgs count as observed news + msg for msg in self._rc.news if msg.cause_by == BossRequirement or msg.send_to == self.name + ] # accept the very first human instruction (the debate topic) or messages sent (from opponent) to self, disregard own messages from the last round return len(self._rc.news) async def _act(self) -> Message: @@ -119,7 +118,6 @@ class Biden(Role): sent_from=self.name, send_to=self.opponent_name, ) - self._publish_message(msg) return msg From f040c73ae99045458343ca66914bf7bb57e63a45 Mon Sep 17 00:00:00 2001 From: yzlin Date: Wed, 20 Sep 2023 11:42:41 +0800 Subject: [PATCH 4/5] formatting --- examples/agent_creator.py | 7 ++++--- examples/build_customized_agent.py | 10 +++++----- examples/debate.py | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/examples/agent_creator.py b/examples/agent_creator.py index 748dc02b1..e03a88c6b 100644 --- a/examples/agent_creator.py +++ b/examples/agent_creator.py @@ -43,7 +43,7 @@ class CreateAgent(Action): code_text = CreateAgent.parse_code(rsp) return code_text - + @staticmethod def parse_code(rsp): pattern = r'```python(.*)```' @@ -85,7 +85,8 @@ if __name__ == "__main__": creator = AgentCreator(agent_template=agent_template) - # msg = """Write an agent called SimpleTester that will take any code snippet (str) and return a testing code (str) for testing + # msg = """Write an agent called SimpleTester that will take any code snippet (str) + # and return a testing code (str) for testing # the given code snippet. Use pytest as the testing framework.""" msg = """ @@ -94,6 +95,6 @@ if __name__ == "__main__": 2. run the testing code. You can use pytest as the testing framework. """ - result = await creator.run(msg) + await creator.run(msg) asyncio.run(main()) diff --git a/examples/build_customized_agent.py b/examples/build_customized_agent.py index 746c8c9fa..dc15ff061 100644 --- a/examples/build_customized_agent.py +++ b/examples/build_customized_agent.py @@ -32,7 +32,7 @@ class SimpleWriteCode(Action): def __init__(self, name="SimpleWriteCode", context=None, llm=None): super().__init__(name, context, llm) - + async def run(self, instruction: str): prompt = self.PROMPT_TEMPLATE.format(instruction=instruction) @@ -43,7 +43,7 @@ class SimpleWriteCode(Action): code_text = SimpleWriteCode.parse_code(rsp) return code_text - + @staticmethod def parse_code(rsp): pattern = r'```python(.*)```' @@ -54,7 +54,7 @@ class SimpleWriteCode(Action): class SimpleRunCode(Action): def __init__(self, name="SimpleRunCode", context=None, llm=None): super().__init__(name, context, llm) - + async def run(self, code_text: str): result = subprocess.run(["python3", "-c", code_text], capture_output=True, text=True) code_result = result.stdout @@ -112,7 +112,7 @@ class RunnableCoder(Role): instruction = msg.content code_text = await SimpleWriteCode().run(instruction) msg = Message(content=code_text, role=self.profile, cause_by=todo) - + elif isinstance(todo, SimpleRunCode): code_text = msg.content rsp = await SimpleRunCode().run(code_text) @@ -137,4 +137,4 @@ async def main(msg="write a function that calculates the sum of a list"): logger.info(result) if __name__ == '__main__': - fire.Fire(main) \ No newline at end of file + fire.Fire(main) diff --git a/examples/debate.py b/examples/debate.py index 3a9abf9bc..05db28070 100644 --- a/examples/debate.py +++ b/examples/debate.py @@ -29,7 +29,7 @@ class ShoutOut(Action): 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) @@ -51,17 +51,16 @@ class Trump(Role): self._watch([ShoutOut]) self.name = "Trump" self.opponent_name = "Biden" - + async def _observe(self) -> int: await super()._observe() - self._rc.news = [ - msg for msg in self._rc.news if msg.send_to == self.name - ] # accept messages sent (from opponent) to self, disregard own messages from the last round + # 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] 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: @@ -92,17 +91,17 @@ class Biden(Role): self._watch([BossRequirement, ShoutOut]) self.name = "Biden" self.opponent_name = "Trump" - + async def _observe(self) -> int: await super()._observe() - self._rc.news = [ - msg for msg in self._rc.news if msg.cause_by == BossRequirement or msg.send_to == self.name - ] # accept the very first human instruction (the debate topic) or messages sent (from opponent) to self, disregard own messages from the last round + # 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: @@ -134,7 +133,8 @@ async def startup(idea: str, investment: float = 3.0, n_round: int = 5, 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 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: From 876094893ac71c6ad117bb93cfef896700dfc385 Mon Sep 17 00:00:00 2001 From: yzlin Date: Thu, 21 Sep 2023 11:14:10 +0800 Subject: [PATCH 5/5] minor update --- examples/build_customized_agent.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/examples/build_customized_agent.py b/examples/build_customized_agent.py index dc15ff061..87d7a9c76 100644 --- a/examples/build_customized_agent.py +++ b/examples/build_customized_agent.py @@ -5,6 +5,7 @@ Author: garylin2099 ''' import re import subprocess +import asyncio import fire @@ -36,7 +37,6 @@ class SimpleWriteCode(Action): async def run(self, instruction: str): prompt = self.PROMPT_TEMPLATE.format(instruction=instruction) - # logger.info(prompt) rsp = await self._aask(prompt) @@ -58,7 +58,6 @@ class SimpleRunCode(Action): async def run(self, code_text: str): result = subprocess.run(["python3", "-c", code_text], capture_output=True, text=True) code_result = result.stdout - # exec(code_text) logger.info(f"{code_result=}") return code_result @@ -75,9 +74,10 @@ class SimpleCoder(Role): async def _act(self) -> Message: logger.info(f"{self._setting}: ready to {self._rc.todo}") todo = self._rc.todo - msg = self._rc.memory.get()[-1] + msg = self._rc.memory.get()[-1] # retrieve the latest memory instruction = msg.content + code_text = await SimpleWriteCode().run(instruction) msg = Message(content=code_text, role=self.profile, cause_by=todo) @@ -110,14 +110,13 @@ class RunnableCoder(Role): if isinstance(todo, SimpleWriteCode): instruction = msg.content - code_text = await SimpleWriteCode().run(instruction) - msg = Message(content=code_text, role=self.profile, cause_by=todo) + result = await SimpleWriteCode().run(instruction) elif isinstance(todo, SimpleRunCode): code_text = msg.content - rsp = await SimpleRunCode().run(code_text) - msg = Message(content=rsp, role=self.profile, cause_by=todo) + result = await SimpleRunCode().run(code_text) + msg = Message(content=result, role=self.profile, cause_by=todo) self._rc.memory.add(msg) return msg @@ -129,11 +128,11 @@ class RunnableCoder(Role): await self._act() return Message(content="All job done", role=self.profile) -async def main(msg="write a function that calculates the sum of a list"): +def main(msg="write a function that calculates the sum of a list"): # role = SimpleCoder() role = RunnableCoder() logger.info(msg) - result = await role.run(msg) + result = asyncio.run(role.run(msg)) logger.info(result) if __name__ == '__main__':