From 0221028de2fd7060ec4274a30ec89c5621e7119f Mon Sep 17 00:00:00 2001 From: kevin-meng Date: Mon, 25 Sep 2023 00:13:27 +0800 Subject: [PATCH 1/5] add guard --- examples/werewolf_game/actions/__init__.py | 2 + .../werewolf_game/actions/guard_actions.py | 24 ++++++++++ examples/werewolf_game/roles/__init__.py | 2 + examples/werewolf_game/roles/guard.py | 44 +++++++++++++++++++ examples/werewolf_game/start_game.py | 5 ++- 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 examples/werewolf_game/actions/guard_actions.py create mode 100644 examples/werewolf_game/roles/guard.py diff --git a/examples/werewolf_game/actions/__init__.py b/examples/werewolf_game/actions/__init__.py index 7c5af46df..3c69b3c99 100644 --- a/examples/werewolf_game/actions/__init__.py +++ b/examples/werewolf_game/actions/__init__.py @@ -1,8 +1,10 @@ from examples.werewolf_game.actions.moderator_actions import InstructSpeak from examples.werewolf_game.actions.common_actions import Speak from examples.werewolf_game.actions.werewolf_actions import Hunt +from examples.werewolf_game.actions.guard_actions import Protect ACTIONS = { "Speak": Speak, "Hunt": Hunt, + "Protect": Protect, } \ No newline at end of file diff --git a/examples/werewolf_game/actions/guard_actions.py b/examples/werewolf_game/actions/guard_actions.py new file mode 100644 index 000000000..419bd0330 --- /dev/null +++ b/examples/werewolf_game/actions/guard_actions.py @@ -0,0 +1,24 @@ +from metagpt.actions import Action + +class Protect(Action): + """Action: choose a player to protect""" + + PROMPT_TEMPLATE = """ + It's a werewolf game and you are a guard, + this is game history: + {context}. + Attention: you can not protect the same player in a row. + Now, choose one to portect, you will: + """ + + def __init__(self, name="Speak", context=None, llm=None): + super().__init__(name, context, llm) + + async def run(self, context: str): + + prompt = self.PROMPT_TEMPLATE.format(context=context) + + rsp = await self._aask(prompt) + # rsp = "Protect Player 1" + + return rsp diff --git a/examples/werewolf_game/roles/__init__.py b/examples/werewolf_game/roles/__init__.py index 464563344..52cbec1f9 100644 --- a/examples/werewolf_game/roles/__init__.py +++ b/examples/werewolf_game/roles/__init__.py @@ -2,3 +2,5 @@ from examples.werewolf_game.roles.base_player import BasePlayer from examples.werewolf_game.roles.moderator import Moderator from examples.werewolf_game.roles.villager import Villager from examples.werewolf_game.roles.werewolf import Werewolf +from examples.werewolf_game.roles.guard import Guard + diff --git a/examples/werewolf_game/roles/guard.py b/examples/werewolf_game/roles/guard.py new file mode 100644 index 000000000..5a3bc55ff --- /dev/null +++ b/examples/werewolf_game/roles/guard.py @@ -0,0 +1,44 @@ +from examples.werewolf_game.roles.base_player import BasePlayer +from examples.werewolf_game.actions import Speak, Hunt +from metagpt.schema import Message +from metagpt.logs import logger + +class Werewolf(BasePlayer): + def __init__( + self, + name: str = "", + profile: str = "Werewolf", + team: str = "werewolves", + special_action_names: list[str] = ["Hunt"], + **kwargs, + ): + super().__init__(name, profile, team, special_action_names, **kwargs) + + async def _act(self): + # todo为_think时确定的,有两种情况,Speak或Hunt + todo = self._rc.todo + logger.info(f"{self._setting}: ready to {str(todo)}") + + # 可以用这个函数获取该角色的全部记忆 + memories = self.get_all_memories() + print("*" * 10, f"{self._setting}'s current memories: {memories}", "*" * 10) + + # 根据自己定义的角色Action,对应地去run,run的入参可能不同 + if isinstance(todo, Speak): + rsp = await todo.run(profile=self.profile, context=memories) + msg = Message( + content=rsp, role=self.profile, sent_from=self.name, + cause_by=Speak, send_to="", restricted_to="", + ) + + elif isinstance(todo, Hunt): + rsp = await todo.run(context=memories) + msg = Message( + content=rsp, role=self.profile, sent_from=self.name, + cause_by=Hunt, send_to="", + restricted_to=f"Moderator,{self.profile}", # 给Moderator及狼阵营发送要杀的人的加密消息 + ) + + logger.info(f"{self._setting}: {rsp}") + + return msg diff --git a/examples/werewolf_game/start_game.py b/examples/werewolf_game/start_game.py index 98d76aa9d..0b10a0a86 100644 --- a/examples/werewolf_game/start_game.py +++ b/examples/werewolf_game/start_game.py @@ -3,7 +3,7 @@ import platform import fire from examples.werewolf_game.werewolf_game import WerewolfGame -from examples.werewolf_game.roles import Moderator, Villager, Werewolf +from examples.werewolf_game.roles import Moderator, Villager, Werewolf, Guard DEFAULT_PLAYER_SETUP = """ Game setup: @@ -11,6 +11,8 @@ Player1: Villager, Player2: Villager, Player3: Werewolf, Player4: Werewolf. +Player5: Guard. + """ async def start_game(idea: str = DEFAULT_PLAYER_SETUP, investment: float = 3.0, n_round: int = 5): @@ -21,6 +23,7 @@ async def start_game(idea: str = DEFAULT_PLAYER_SETUP, investment: float = 3.0, Villager(name="Player2"), Werewolf(name="Player3"), Werewolf(name="Player4"), + Guard(name="Player5"), ]) game.invest(investment) game.start_project(idea) From 02cc5c274d3d573cb3f592cfd070404270a77e28 Mon Sep 17 00:00:00 2001 From: kevin-meng Date: Mon, 25 Sep 2023 00:26:33 +0800 Subject: [PATCH 2/5] add guard --- .../werewolf_game/actions/guard_actions.py | 5 +++-- examples/werewolf_game/roles/guard.py | 20 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/examples/werewolf_game/actions/guard_actions.py b/examples/werewolf_game/actions/guard_actions.py index 419bd0330..98dfc3b32 100644 --- a/examples/werewolf_game/actions/guard_actions.py +++ b/examples/werewolf_game/actions/guard_actions.py @@ -5,9 +5,10 @@ class Protect(Action): PROMPT_TEMPLATE = """ It's a werewolf game and you are a guard, + you can choose to protect a player, including yourself, then the protected player will not be killed by the Werewolves this night. this is game history: {context}. - Attention: you can not protect the same player in a row. + Attention: you can not protect the same player two nights in a row. Now, choose one to portect, you will: """ @@ -21,4 +22,4 @@ class Protect(Action): rsp = await self._aask(prompt) # rsp = "Protect Player 1" - return rsp + return rsp \ No newline at end of file diff --git a/examples/werewolf_game/roles/guard.py b/examples/werewolf_game/roles/guard.py index 5a3bc55ff..94b5b46dc 100644 --- a/examples/werewolf_game/roles/guard.py +++ b/examples/werewolf_game/roles/guard.py @@ -1,21 +1,21 @@ from examples.werewolf_game.roles.base_player import BasePlayer -from examples.werewolf_game.actions import Speak, Hunt +from examples.werewolf_game.actions import Speak, Protect from metagpt.schema import Message from metagpt.logs import logger -class Werewolf(BasePlayer): +class Guard(BasePlayer): def __init__( self, name: str = "", - profile: str = "Werewolf", - team: str = "werewolves", - special_action_names: list[str] = ["Hunt"], + profile: str = "Guard", + team: str = "good guys", + special_action_names: list[str] = ["Protect"], **kwargs, ): super().__init__(name, profile, team, special_action_names, **kwargs) async def _act(self): - # todo为_think时确定的,有两种情况,Speak或Hunt + # todo为_think时确定的,有两种情况,Speak或Protect todo = self._rc.todo logger.info(f"{self._setting}: ready to {str(todo)}") @@ -31,14 +31,16 @@ class Werewolf(BasePlayer): cause_by=Speak, send_to="", restricted_to="", ) - elif isinstance(todo, Hunt): + elif isinstance(todo, Protect): rsp = await todo.run(context=memories) msg = Message( content=rsp, role=self.profile, sent_from=self.name, - cause_by=Hunt, send_to="", - restricted_to=f"Moderator,{self.profile}", # 给Moderator及狼阵营发送要杀的人的加密消息 + cause_by=Protect, send_to="", + restricted_to=f"Moderator,{self.profile}", # 给Moderator发送守卫要保护的人加密消息 ) logger.info(f"{self._setting}: {rsp}") return msg + + From 1a7f415fa933c2e6f944d9538e06a0e64bf9faaa Mon Sep 17 00:00:00 2001 From: kevin-meng Date: Mon, 25 Sep 2023 23:27:12 +0800 Subject: [PATCH 3/5] modify pronunciation --- examples/werewolf_game/actions/guard_actions.py | 4 ++-- examples/werewolf_game/start_game.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/werewolf_game/actions/guard_actions.py b/examples/werewolf_game/actions/guard_actions.py index 98dfc3b32..10e550a49 100644 --- a/examples/werewolf_game/actions/guard_actions.py +++ b/examples/werewolf_game/actions/guard_actions.py @@ -9,10 +9,10 @@ class Protect(Action): this is game history: {context}. Attention: you can not protect the same player two nights in a row. - Now, choose one to portect, you will: + Now, choose one to protect, you will: """ - def __init__(self, name="Speak", context=None, llm=None): + def __init__(self, name="Protect", context=None, llm=None): super().__init__(name, context, llm) async def run(self, context: str): diff --git a/examples/werewolf_game/start_game.py b/examples/werewolf_game/start_game.py index 0b10a0a86..eeb4dbf21 100644 --- a/examples/werewolf_game/start_game.py +++ b/examples/werewolf_game/start_game.py @@ -1,6 +1,8 @@ import asyncio import platform import fire +import sys +sys.path.append("../../") from examples.werewolf_game.werewolf_game import WerewolfGame from examples.werewolf_game.roles import Moderator, Villager, Werewolf, Guard From be2580f5db1596160fe90beaa8482630220de384 Mon Sep 17 00:00:00 2001 From: kevin-meng Date: Tue, 26 Sep 2023 01:20:29 +0800 Subject: [PATCH 4/5] add arbiter prompt for evaluate --- metagpt/prompts/arbiter.py | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 metagpt/prompts/arbiter.py diff --git a/metagpt/prompts/arbiter.py b/metagpt/prompts/arbiter.py new file mode 100644 index 000000000..d8e0d0781 --- /dev/null +++ b/metagpt/prompts/arbiter.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@Time : 2023/9/26 1:12 +@Author : kevin-meng +@File : arbiter.py +""" + + +ARBITER = """ +As an experienced Arbiter, you possess the necessary competence, sound judgment, and absolute objectivity. you promise that you will officiate in games with complete impartiality, respecting and adhering to the rules that govern them, in the true spirit of sportsmanship. + +Please always remember the general duties of the Arbiters in a competition: +a. Ensure fair play and adhere to the Anti-cheating regulations. +b. Supervise the progress of the competition. +c. Observe the game and enforce decisions made, imposing penalties on players where appropriate. +d. Ensure that the Laws of the game are observed. + +The rules governing this competition are as follows: +=== +{rules} +=== + +The scoring dimensions for judging in this game are as follows: +=== +{dimensions} +=== + +After the end of the competition, the Arbiter should submit a report, which includes: +a. A summary report for the game. +b. The final standings. +c. Each player and their final score for each assessment category, along with the reasons for the ratings. +d. Any other important information +for example: + +## Summary + ...... + +## Results and Standings (Top3) + Top 1: player 1 + Top 2: player 2 + Top 2: player 3 + +## Scoring and Assessment Dimensions + - player 1 : socre + - dimension 1 + score: xx + reason: xx + - dimension 2 + score: xx + reason: xx + ...... + - player 2 + ...... + +## Conclusion + ...... + +""" + + From f9179c377d626ea974b8e93188faa900b6c2e490 Mon Sep 17 00:00:00 2001 From: Kevin Meng Date: Tue, 26 Sep 2023 20:15:27 +0800 Subject: [PATCH 5/5] Update start_game.py delete two lines of local testing code --- examples/werewolf_game/start_game.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/werewolf_game/start_game.py b/examples/werewolf_game/start_game.py index eeb4dbf21..0b10a0a86 100644 --- a/examples/werewolf_game/start_game.py +++ b/examples/werewolf_game/start_game.py @@ -1,8 +1,6 @@ import asyncio import platform import fire -import sys -sys.path.append("../../") from examples.werewolf_game.werewolf_game import WerewolfGame from examples.werewolf_game.roles import Moderator, Villager, Werewolf, Guard