From fd925eacb169a5abbd55a7d37ee51b5c596e8f5e Mon Sep 17 00:00:00 2001 From: qbc Date: Wed, 17 Jan 2024 16:52:55 +0800 Subject: [PATCH 1/4] add jupyter notebook for werewolf game and add some modifications for the game --- examples/werewolf/README.md | 2 +- examples/werewolf/prompt.py | 7 +- examples/werewolf/werewolf.py | 6 +- notebook/werewolf.ipynb | 489 ++++++++++++++++++++++++++++++++++ 4 files changed, 497 insertions(+), 7 deletions(-) create mode 100644 notebook/werewolf.ipynb diff --git a/examples/werewolf/README.md b/examples/werewolf/README.md index 04f5b128c..90e275329 100644 --- a/examples/werewolf/README.md +++ b/examples/werewolf/README.md @@ -92,7 +92,7 @@ More details please refer to the code of [`DictDialogAgent`](../.. with msghub(wolves, announcement=hint) as hub: for _ in range(MAX_WEREWOLF_DISCUSSION_ROUND): x = sequentialpipeline(wolves) - if x.agreement: + if x.get("agreement", False): break # ... ``` \ No newline at end of file diff --git a/examples/werewolf/prompt.py b/examples/werewolf/prompt.py index 5537d672e..2e16dd8bf 100644 --- a/examples/werewolf/prompt.py +++ b/examples/werewolf/prompt.py @@ -8,7 +8,7 @@ class Prompts: to_wolves = ( "{}, you are werewolves. If you are alone, eliminate a player, else " "discuss with your teammates and reach an agreement. Response in the " - "following format which can be loaded by python json.loads()" + "following format which can be loaded by python json.loads()\n" "{{\n" ' "thought": "thought",\n' ' "speak": "thoughts summary to say to others",\n' @@ -35,7 +35,7 @@ class Prompts: "{{\n" ' "thought": "thought",\n' ' "speak": "thoughts summary to say",\n' - ' "resurrect": "true/false"\n' + ' "resurrect": true/false\n' "}}" ) @@ -44,7 +44,8 @@ class Prompts: "json format which can be loaded by python json.loads()\n" "{{\n" ' "thought": "thought", \n' - ' "speak": "False or player_name"\n' + ' "speak": "thoughts summary to say",\n' + ' "eliminate": ture/false\n' "}}" ) diff --git a/examples/werewolf/werewolf.py b/examples/werewolf/werewolf.py index bb39294f2..96af8a0b2 100644 --- a/examples/werewolf/werewolf.py +++ b/examples/werewolf/werewolf.py @@ -35,7 +35,7 @@ with msghub(wolves, announcement=hint) as hub: for _ in range(MAX_WEREWOLF_DISCUSSION_ROUND): x = sequentialpipeline(wolves) - if x.agreement: + if x.get("agreement", False): break # werewolves vote @@ -56,14 +56,14 @@ {"witch_name": witch.name, "dead_name": dead_player[0]}, ), ) - if witch(hint).resurrect: + if witch(hint).get("resurrect", False): healing_used_tonight = True dead_player.pop() healing = False if poison and not healing_used_tonight: x = witch(HostMsg(content=Prompts.to_witch_poison)) - if "False" not in x.content: + if x.get("eliminate", False): dead_player.append(extract_name_and_id(x.content)[0]) poison = False diff --git a/notebook/werewolf.ipynb b/notebook/werewolf.ipynb new file mode 100644 index 000000000..ff90bf47f --- /dev/null +++ b/notebook/werewolf.ipynb @@ -0,0 +1,489 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "33be6252-0814-4f97-b4ed-06d7e68ce66b", + "metadata": {}, + "source": [ + "# Werewolf Game" + ] + }, + { + "cell_type": "markdown", + "id": "722dd171-2a2f-4ed6-b851-8154acc46b83", + "metadata": {}, + "source": [ + "This is a demo of how to use AgentScope to play the Werewolf game, where six agents play against werewolves and villagers. The details can be found in `examples/werewolf/`." + ] + }, + { + "cell_type": "markdown", + "id": "22684e1a-acf9-469c-8cee-36bd0b3efb8a", + "metadata": {}, + "source": [ + "To install AgentScope, please follow the steps in [README.md](https://github.com/alibaba/AgentScope/blob/main/README.md#installation)." + ] + }, + { + "cell_type": "markdown", + "id": "51b90378-6c48-4462-9110-c44639e57f44", + "metadata": {}, + "source": [ + "First, we need to set the model configs for the agents." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b221278f-d1b1-410c-892d-df26a0d55fb4", + "metadata": {}, + "outputs": [], + "source": [ + "model_configs = [\n", + " {\n", + " \"type\": \"openai\",\n", + " \"name\": \"gpt-3.5-turbo\",\n", + " \"api_key\": \"xxx\",\n", + " \"organization\": \"xxx\",\n", + " \"generate_args\": {\n", + " \"temperature\": 0.5\n", + " }\n", + " },\n", + " {\n", + " \"type\": \"post_api\",\n", + " \"name\": \"my_post_api\",\n", + " \"api_url\": \"https://xxx\",\n", + " \"headers\": {\n", + " },\n", + " \"json_args\": {\n", + " }\n", + " }\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "b683b8da-38ab-44eb-afc9-9e1a0ab0ec8e", + "metadata": {}, + "source": [ + "The configs for each agent are as follows. There are six agents, each playing a role in the game. Here, `DictDialogAgent` is a specific class in AgentScope. The details can be found in `src/agentscope/agents/dict_dialog_agent.py`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8a389c49-5474-40db-8b61-e595ec803b82", + "metadata": {}, + "outputs": [], + "source": [ + "agent_configs = [\n", + " {\n", + " \"class\": \"DictDialogAgent\",\n", + " \"args\": {\n", + " \"name\": \"Player1\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player1 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing werewolf in this game.\\n\",\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " \"use_memory\": True\n", + " }\n", + " },\n", + " {\n", + " \"class\": \"DictDialogAgent\",\n", + " \"args\": {\n", + " \"name\": \"Player2\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player2 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing werewolf in this game.\\n\",\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " \"use_memory\": True\n", + " }\n", + " },\n", + " {\n", + " \"class\": \"DictDialogAgent\",\n", + " \"args\": {\n", + " \"name\": \"Player3\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player3 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing villager in this game.\\n\",\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " \"use_memory\": True\n", + " }\n", + " },\n", + " {\n", + " \"class\": \"DictDialogAgent\",\n", + " \"args\": {\n", + " \"name\": \"Player4\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player4 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing villager in this game.\\n\",\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " \"use_memory\": True\n", + " }\n", + " },\n", + " {\n", + " \"class\": \"DictDialogAgent\",\n", + " \"args\": {\n", + " \"name\": \"Player5\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player5 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing seer in this game.\\n\",\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " \"use_memory\": True\n", + " }\n", + " },\n", + " {\n", + " \"class\": \"DictDialogAgent\",\n", + " \"args\": {\n", + " \"name\": \"Player6\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player6 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing witch in this game.\\n\",\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " \"use_memory\": True\n", + " }\n", + " }\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "87dad640-3fca-404a-b567-eff0fde3e42f", + "metadata": {}, + "source": [ + "We also need to set the prompts for different players in differents states." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0b7de59d-baa3-4b2d-ae41-fac1504f4277", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Used to record prompts, will be replaced by configuration\"\"\"\n", + "\n", + "\n", + "class Prompts:\n", + " \"\"\"Prompts for werewolf game\"\"\"\n", + "\n", + " to_wolves = (\n", + " \"{}, you are werewolves. If you are alone, eliminate a player, else \"\n", + " \"discuss with your teammates and reach an agreement. Response in the \"\n", + " \"following format which can be loaded by python json.loads()\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\",\\n'\n", + " ' \"speak\": \"thoughts summary to say to others\",\\n'\n", + " ' \"agreement\": \"whether the discussion reached an agreement or '\n", + " 'not(true/false)\"\\n'\n", + " \"}}\"\n", + " )\n", + "\n", + " to_wolves_vote = (\n", + " \"Which player do you vote to kill? Response in the following format \"\n", + " \"which can be loaded by python json.loads()\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\" ,\\n'\n", + " ' \"speak\": \"player_name\"\\n'\n", + " \"}}\"\n", + " )\n", + "\n", + " to_wolves_res = \"The player with the most votes is {}.\"\n", + "\n", + " to_witch_resurrect = (\n", + " \"{witch_name}, you're witch. Tonight {dead_name} is eliminated. Would \"\n", + " \"you like to resurrect {dead_name}? Response in the following format \"\n", + " \"which can be loaded by python json.loads()\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\",\\n'\n", + " ' \"speak\": \"thoughts summary to say\",\\n'\n", + " ' \"resurrect\": true/false\\n'\n", + " \"}}\"\n", + " )\n", + "\n", + " to_witch_poison = (\n", + " \"Would you like to eliminate one player? Response in the following \"\n", + " \"json format which can be loaded by python json.loads()\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\", \\n'\n", + " ' \"speak\": \"False or player_name\"\\n'\n", + " ' \"eliminate\": ture/false\\n' \n", + " \"}}\"\n", + " )\n", + "\n", + " to_seer = (\n", + " \"{}, you're seer. Which player in {} would you like to check \"\n", + " \"tonight? Response in the following json format which can be loaded \"\n", + " \"by python json.loads()\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\" ,\\n'\n", + " ' \"speak\": \"player_name\"\\n'\n", + " \"}}\"\n", + " )\n", + "\n", + " to_seer_result = \"Okay, the role of {} is {}.\"\n", + "\n", + " to_all_danger = (\n", + " \"The day is coming, all the players open your eyes. Last night, \"\n", + " \"the following player(s) has been eliminated: {}.\"\n", + " )\n", + "\n", + " to_all_peace = (\n", + " \"The day is coming, all the players open your eyes. Last night is \"\n", + " \"peaceful, no player is eliminated.\"\n", + " )\n", + "\n", + " to_all_discuss = (\n", + " \"Now the alive players are {}. Given the game rules and your role, \"\n", + " \"based on the \"\n", + " \"situation and the information you gain, to vote a player eliminated \"\n", + " \"among alive players and to win the game, what do you want to say \"\n", + " \"to others? You can decide whether to reveal your role. Response in \"\n", + " \"the following JSON format which can be loaded by python json.loads(\"\n", + " \")\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\" ,\\n'\n", + " ' \"speak\": \"thought summary to say to others\"\\n'\n", + " \"}}\"\n", + " )\n", + "\n", + " to_all_vote = (\n", + " \"Now the alive players are {}. Given the game rules and your role, \"\n", + " \"based on the situation and the information you gain, to vote a \"\n", + " \"player among alive players and to win the \"\n", + " \"game, it's time to vote one player among the alive players, please \"\n", + " \"cast your vote on who you believe is a werewolf. Response in the \"\n", + " \"following format which can be loaded by python json.loads()\\n\"\n", + " \"{{\\n\"\n", + " ' \"thought\": \"thought\",\\n'\n", + " ' \"speak\": \"player_name\"\\n'\n", + " \"}}\"\n", + " )\n", + "\n", + " to_all_res = \"{} has been voted out.\"\n", + "\n", + " to_all_wolf_win = (\n", + " \"The werewolves have prevailed and taken over the village. Better \"\n", + " \"luck next time!\"\n", + " )\n", + "\n", + " to_all_village_win = (\n", + " \"The game is over. The werewolves have been defeated, and the village \"\n", + " \"is safe once again!\"\n", + " )\n", + "\n", + " to_all_continue = \"The game goes on.\"" + ] + }, + { + "cell_type": "markdown", + "id": "f757d37a-f691-4af3-9251-a66c04ac93aa", + "metadata": {}, + "source": [ + "During the game, we also need some utility funcitons. We list them below." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0f5062d4-faad-472e-90f2-b33d6ad64cf8", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"utils.\"\"\"\n", + "import re\n", + "from typing import Union, Any, Sequence\n", + "\n", + "import numpy as np\n", + "from loguru import logger\n", + "\n", + "from agentscope.agents import AgentBase\n", + "from agentscope.message import Msg\n", + "\n", + "\n", + "def check_winning(alive_agents: list, wolf_agents: list, host: str) -> bool:\n", + " \"\"\"check which group wins\"\"\"\n", + " if len(wolf_agents) * 2 >= len(alive_agents):\n", + " msg = Msg(host, Prompts.to_all_wolf_win)\n", + " logger.chat(f\"{host}: {msg.content}\")\n", + " return True\n", + " if alive_agents and not wolf_agents:\n", + " msg = Msg(host, Prompts.to_all_village_win)\n", + " logger.chat(f\"{host}: {msg.content}\")\n", + " return True\n", + " return False\n", + "\n", + "\n", + "def update_alive_players(\n", + " survivors: Sequence[AgentBase],\n", + " wolves: Sequence[AgentBase],\n", + " dead_names: Union[str, list[str]],\n", + ") -> tuple[list, list]:\n", + " \"\"\"update the list of alive agents\"\"\"\n", + " if not isinstance(dead_names, list):\n", + " dead_names = [dead_names]\n", + " return [_ for _ in survivors if _.name not in dead_names], [\n", + " _ for _ in wolves if _.name not in dead_names\n", + " ]\n", + "\n", + "\n", + "def majority_vote(votes: list) -> Any:\n", + " \"\"\"majority_vote function\"\"\"\n", + " unit, counts = np.unique(votes, return_counts=True)\n", + " return unit[np.argmax(counts)]\n", + "\n", + "\n", + "def extract_name_and_id(name: str) -> tuple[str, int]:\n", + " \"\"\"extract player name and id from a string\"\"\"\n", + " name = re.search(r\"\\bPlayer\\d+\\b\", name).group(0)\n", + " idx = int(re.search(r\"Player(\\d+)\", name).group(1)) - 1\n", + " return name, idx\n", + "\n", + "\n", + "def n2s(agents: Sequence[Union[AgentBase, str]]) -> str:\n", + " \"\"\"combine agent names into a string, and use \"and\" to connect the last two names.\"\"\"\n", + "\n", + " def _get_name(agent_: Union[AgentBase, str]) -> str:\n", + " return agent_.name if isinstance(agent_, AgentBase) else agent_\n", + "\n", + " if len(agents) == 1:\n", + " return _get_name(agents[0])\n", + "\n", + " return (\n", + " \", \".join([_get_name(_) for _ in agents[:-1]])\n", + " + \" and \"\n", + " + _get_name(agents[-1])\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "4cbc4d91-b224-4c58-bf51-500cca9037f7", + "metadata": {}, + "source": [ + "Now we can turn our attention to the main function of the game. Run the following codes and enjoy the game." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0e1e3bcb-279b-409e-ba98-4d6ea01dcc87", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"A werewolf game implemented by agentscope.\"\"\"\n", + "from functools import partial\n", + "from agentscope.message import Msg\n", + "from agentscope.msghub import msghub\n", + "from agentscope.pipelines.functional import sequentialpipeline\n", + "import agentscope\n", + "\n", + "# default settings\n", + "HostMsg = partial(Msg, name=\"Moderator\", echo=True)\n", + "healing, poison = True, True\n", + "MAX_WEREWOLF_DISCUSSION_ROUND = 3\n", + "MAX_GAME_ROUND = 6\n", + "# read model and agent configs, and initialize agents automatically\n", + "survivors = agentscope.init(\n", + " model_configs=model_configs,\n", + " agent_configs=agent_configs,\n", + ")\n", + "roles = [\"werewolf\", \"werewolf\", \"villager\", \"villager\", \"seer\", \"witch\"]\n", + "wolves, witch, seer = survivors[:2], survivors[-1], survivors[-2]\n", + "\n", + "# start the game\n", + "for i in range(1, MAX_GAME_ROUND + 1):\n", + " # night phase, werewolves discuss\n", + " hint = HostMsg(content=Prompts.to_wolves.format(n2s(wolves)))\n", + " with msghub(wolves, announcement=hint) as hub:\n", + " for _ in range(MAX_WEREWOLF_DISCUSSION_ROUND):\n", + " x = sequentialpipeline(wolves)\n", + " if x.get(\"agreement\", False):\n", + " break\n", + "\n", + " # werewolves vote\n", + " hint = HostMsg(content=Prompts.to_wolves_vote)\n", + " votes = [extract_name_and_id(wolf(hint).content)[0] for wolf in wolves]\n", + " # broadcast the result to werewolves\n", + " dead_player = [majority_vote(votes)]\n", + " hub.broadcast(\n", + " HostMsg(content=Prompts.to_wolves_res.format(dead_player[0])),\n", + " )\n", + "\n", + " # witch\n", + " healing_used_tonight = False\n", + " if witch in survivors:\n", + " if healing:\n", + " hint = HostMsg(\n", + " content=Prompts.to_witch_resurrect.format_map(\n", + " {\"witch_name\": witch.name, \"dead_name\": dead_player[0]},\n", + " ),\n", + " )\n", + " if witch(hint).get(\"resurrect\", False):\n", + " healing_used_tonight = True\n", + " dead_player.pop()\n", + " healing = False\n", + "\n", + " if poison and not healing_used_tonight:\n", + " x = witch(HostMsg(content=Prompts.to_witch_poison))\n", + " if x.get(\"eliminate\", True):\n", + " dead_player.append(extract_name_and_id(x.content)[0])\n", + " poison = False\n", + "\n", + " # seer\n", + " if seer in survivors:\n", + " hint = HostMsg(\n", + " content=Prompts.to_seer.format(seer.name, n2s(survivors)),\n", + " )\n", + " x = seer(hint)\n", + "\n", + " player, idx = extract_name_and_id(x.content)\n", + " role = \"werewolf\" if roles[idx] == \"werewolf\" else \"villager\"\n", + " hint = HostMsg(content=Prompts.to_seer_result.format(player, role))\n", + " seer.observe(hint)\n", + "\n", + " survivors, wolves = update_alive_players(survivors, wolves, dead_player)\n", + " if check_winning(survivors, wolves, \"Moderator\"):\n", + " break\n", + "\n", + " # daytime discussion\n", + " content = (\n", + " Prompts.to_all_danger.format(n2s(dead_player))\n", + " if dead_player\n", + " else Prompts.to_all_peace\n", + " )\n", + " hints = [\n", + " HostMsg(content=content),\n", + " HostMsg(content=Prompts.to_all_discuss.format(n2s(survivors))),\n", + " ]\n", + " with msghub(survivors, announcement=hints) as hub:\n", + " # discuss\n", + " x = sequentialpipeline(survivors)\n", + "\n", + " # vote\n", + " hint = HostMsg(content=Prompts.to_all_vote.format(n2s(survivors)))\n", + " votes = [extract_name_and_id(_(hint).content)[0] for _ in survivors]\n", + " vote_res = majority_vote(votes)\n", + " # broadcast the result to all players\n", + " result = HostMsg(content=Prompts.to_all_res.format(vote_res))\n", + " hub.broadcast(result)\n", + "\n", + " survivors, wolves = update_alive_players(survivors, wolves, vote_res)\n", + "\n", + " if check_winning(survivors, wolves, \"Moderator\"):\n", + " break\n", + "\n", + " hub.broadcast(HostMsg(content=Prompts.to_all_continue))\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 3a9d4aa0fb1068114a0893236d290486df53f100 Mon Sep 17 00:00:00 2001 From: qbc Date: Wed, 17 Jan 2024 16:59:54 +0800 Subject: [PATCH 2/4] minor changes --- examples/werewolf/prompt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/werewolf/prompt.py b/examples/werewolf/prompt.py index 2e16dd8bf..ed454de44 100644 --- a/examples/werewolf/prompt.py +++ b/examples/werewolf/prompt.py @@ -45,7 +45,7 @@ class Prompts: "{{\n" ' "thought": "thought", \n' ' "speak": "thoughts summary to say",\n' - ' "eliminate": ture/false\n' + ' "eliminate": ture/false\n' "}}" ) From c19787ce02d8fd40d89c95f8d504508abdccbd8f Mon Sep 17 00:00:00 2001 From: qbc Date: Mon, 22 Jan 2024 14:49:25 +0800 Subject: [PATCH 3/4] modify according to comments --- notebook/werewolf.ipynb | 186 ++++++++-------------------------------- 1 file changed, 34 insertions(+), 152 deletions(-) diff --git a/notebook/werewolf.ipynb b/notebook/werewolf.ipynb index ff90bf47f..ee58191b4 100644 --- a/notebook/werewolf.ipynb +++ b/notebook/werewolf.ipynb @@ -13,7 +13,9 @@ "id": "722dd171-2a2f-4ed6-b851-8154acc46b83", "metadata": {}, "source": [ - "This is a demo of how to use AgentScope to play the Werewolf game, where six agents play against werewolves and villagers. The details can be found in `examples/werewolf/`." + "This is a demo of how to use AgentScope to play the Werewolf game, where six\n", + " agents play the roles of werewolves and villagers. The details can be found\n", + " in `examples/werewolf/README.md`." ] }, { @@ -21,7 +23,7 @@ "id": "22684e1a-acf9-469c-8cee-36bd0b3efb8a", "metadata": {}, "source": [ - "To install AgentScope, please follow the steps in [README.md](https://github.com/alibaba/AgentScope/blob/main/README.md#installation)." + "To install AgentScope, please follow the steps in [README.md](../README.md#installation)." ] }, { @@ -66,12 +68,12 @@ "id": "b683b8da-38ab-44eb-afc9-9e1a0ab0ec8e", "metadata": {}, "source": [ - "The configs for each agent are as follows. There are six agents, each playing a role in the game. Here, `DictDialogAgent` is a specific class in AgentScope. The details can be found in `src/agentscope/agents/dict_dialog_agent.py`." + "The configs for each agent are as follows. There are six agents, each playing a role in the game. Here, `DictDialogAgent` is a specific class in AgentScope. The details can be found in `src/agentscope/agents/dict_dialog_agent.py`. The details about `sys_prompt` for each player can be found in `examples/werewolf/configs/agent_configs`." ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 8, "id": "8a389c49-5474-40db-8b61-e595ec803b82", "metadata": {}, "outputs": [], @@ -81,7 +83,7 @@ " \"class\": \"DictDialogAgent\",\n", " \"args\": {\n", " \"name\": \"Player1\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player1 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing werewolf in this game.\\n\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player1 ...\",\n", " \"model\": \"gpt-3.5-turbo\",\n", " \"use_memory\": True\n", " }\n", @@ -90,7 +92,7 @@ " \"class\": \"DictDialogAgent\",\n", " \"args\": {\n", " \"name\": \"Player2\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player2 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing werewolf in this game.\\n\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player2 ...\",\n", " \"model\": \"gpt-3.5-turbo\",\n", " \"use_memory\": True\n", " }\n", @@ -99,7 +101,7 @@ " \"class\": \"DictDialogAgent\",\n", " \"args\": {\n", " \"name\": \"Player3\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player3 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing villager in this game.\\n\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player3 ...\",\n", " \"model\": \"gpt-3.5-turbo\",\n", " \"use_memory\": True\n", " }\n", @@ -108,7 +110,7 @@ " \"class\": \"DictDialogAgent\",\n", " \"args\": {\n", " \"name\": \"Player4\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player4 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing villager in this game.\\n\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player4 ...\",\n", " \"model\": \"gpt-3.5-turbo\",\n", " \"use_memory\": True\n", " }\n", @@ -117,7 +119,7 @@ " \"class\": \"DictDialogAgent\",\n", " \"args\": {\n", " \"name\": \"Player5\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player5 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing seer in this game.\\n\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player5 ...\",\n", " \"model\": \"gpt-3.5-turbo\",\n", " \"use_memory\": True\n", " }\n", @@ -126,7 +128,7 @@ " \"class\": \"DictDialogAgent\",\n", " \"args\": {\n", " \"name\": \"Player6\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player6 and\\nthere are totally 6 players, named Player1, Player2, Player3, Player4, Player5 and Player6.\\n\\nPLAYER ROLES:\\nIn werewolf game, players are divided into two werewolves, two villagers, one seer and one witch. Note only werewolves know who are their teammates.\\nWerewolves: They know their teammates' identities and attempt to eliminate a villager each night while trying to remain undetected.\\nVillagers: They do not know who the werewolves are and must work together during the day to deduce who the werewolves might be and vote to eliminate them.\\nSeer: A villager with the ability to learn the true identity of one player each night. This role is crucial for the villagers to gain information.\\nWitch: A character who has a one-time ability to save a player from being eliminated at night (sometimes this is a potion of life) and a one-time ability to eliminate a player at night (a potion of death).\\n\\nGAME RULE:\\nThe game is consisted of two phases: night phase and day phase. The two phases are repeated until werewolf or villager win the game.\\n1. Night Phase: During the night, the werewolves discuss and vote for a player to eliminate. Special roles also perform their actions at this time (e.g., the Seer chooses a player to learn their role, the witch chooses a decide if save the player).\\n2. Day Phase: During the day, all surviving players discuss who they suspect might be a werewolf. No one reveals their role unless it serves a strategic purpose. After the discussion, a vote is taken, and the player with the most votes is \\\"lynched\\\" or eliminated from the game.\\n\\nVICTORY CONDITION:\\nFor werewolves, they win the game if the number of werewolves is equal to or greater than the number of remaining villagers.\\nFor villagers, they win if they identify and eliminate all of the werewolves in the group.\\n\\nCONSTRAINTS:\\n1. Your response should be in the first person.\\n2. This is a conversational game. You should response only based on the conversation history and your strategy.\\n\\nYou are playing witch in this game.\\n\",\n", + " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player6 ...\",\n", " \"model\": \"gpt-3.5-turbo\",\n", " \"use_memory\": True\n", " }\n", @@ -139,12 +141,12 @@ "id": "87dad640-3fca-404a-b567-eff0fde3e42f", "metadata": {}, "source": [ - "We also need to set the prompts for different players in differents states." + "We also need to set the prompts for different players in differents states. The details can be found in `examples/werewolf/prompt.py`." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 9, "id": "0b7de59d-baa3-4b2d-ae41-fac1504f4277", "metadata": {}, "outputs": [], @@ -156,57 +158,25 @@ " \"\"\"Prompts for werewolf game\"\"\"\n", "\n", " to_wolves = (\n", - " \"{}, you are werewolves. If you are alone, eliminate a player, else \"\n", - " \"discuss with your teammates and reach an agreement. Response in the \"\n", - " \"following format which can be loaded by python json.loads()\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\",\\n'\n", - " ' \"speak\": \"thoughts summary to say to others\",\\n'\n", - " ' \"agreement\": \"whether the discussion reached an agreement or '\n", - " 'not(true/false)\"\\n'\n", - " \"}}\"\n", + " \"{}, you are werewolves. ...\"\n", " )\n", "\n", " to_wolves_vote = (\n", - " \"Which player do you vote to kill? Response in the following format \"\n", - " \"which can be loaded by python json.loads()\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\" ,\\n'\n", - " ' \"speak\": \"player_name\"\\n'\n", - " \"}}\"\n", + " \"Which player do you vote to kill? ...\"\n", " )\n", "\n", " to_wolves_res = \"The player with the most votes is {}.\"\n", "\n", " to_witch_resurrect = (\n", - " \"{witch_name}, you're witch. Tonight {dead_name} is eliminated. Would \"\n", - " \"you like to resurrect {dead_name}? Response in the following format \"\n", - " \"which can be loaded by python json.loads()\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\",\\n'\n", - " ' \"speak\": \"thoughts summary to say\",\\n'\n", - " ' \"resurrect\": true/false\\n'\n", - " \"}}\"\n", + " \"{witch_name}, you're witch. ...\"\n", " )\n", "\n", " to_witch_poison = (\n", - " \"Would you like to eliminate one player? Response in the following \"\n", - " \"json format which can be loaded by python json.loads()\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\", \\n'\n", - " ' \"speak\": \"False or player_name\"\\n'\n", - " ' \"eliminate\": ture/false\\n' \n", - " \"}}\"\n", + " \"Would you like to eliminate one player? ...\"\n", " )\n", "\n", " to_seer = (\n", - " \"{}, you're seer. Which player in {} would you like to check \"\n", - " \"tonight? Response in the following json format which can be loaded \"\n", - " \"by python json.loads()\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\" ,\\n'\n", - " ' \"speak\": \"player_name\"\\n'\n", - " \"}}\"\n", + " \"{}, you're seer. ...\"\n", " )\n", "\n", " to_seer_result = \"Okay, the role of {} is {}.\"\n", @@ -222,30 +192,11 @@ " )\n", "\n", " to_all_discuss = (\n", - " \"Now the alive players are {}. Given the game rules and your role, \"\n", - " \"based on the \"\n", - " \"situation and the information you gain, to vote a player eliminated \"\n", - " \"among alive players and to win the game, what do you want to say \"\n", - " \"to others? You can decide whether to reveal your role. Response in \"\n", - " \"the following JSON format which can be loaded by python json.loads(\"\n", - " \")\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\" ,\\n'\n", - " ' \"speak\": \"thought summary to say to others\"\\n'\n", - " \"}}\"\n", + " \"Now the alive players are {}. ...\"\n", " )\n", "\n", " to_all_vote = (\n", - " \"Now the alive players are {}. Given the game rules and your role, \"\n", - " \"based on the situation and the information you gain, to vote a \"\n", - " \"player among alive players and to win the \"\n", - " \"game, it's time to vote one player among the alive players, please \"\n", - " \"cast your vote on who you believe is a werewolf. Response in the \"\n", - " \"following format which can be loaded by python json.loads()\\n\"\n", - " \"{{\\n\"\n", - " ' \"thought\": \"thought\",\\n'\n", - " ' \"speak\": \"player_name\"\\n'\n", - " \"}}\"\n", + " \"Now the alive players are {}. ...\"\n", " )\n", "\n", " to_all_res = \"{} has been voted out.\"\n", @@ -263,87 +214,6 @@ " to_all_continue = \"The game goes on.\"" ] }, - { - "cell_type": "markdown", - "id": "f757d37a-f691-4af3-9251-a66c04ac93aa", - "metadata": {}, - "source": [ - "During the game, we also need some utility funcitons. We list them below." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "0f5062d4-faad-472e-90f2-b33d6ad64cf8", - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"utils.\"\"\"\n", - "import re\n", - "from typing import Union, Any, Sequence\n", - "\n", - "import numpy as np\n", - "from loguru import logger\n", - "\n", - "from agentscope.agents import AgentBase\n", - "from agentscope.message import Msg\n", - "\n", - "\n", - "def check_winning(alive_agents: list, wolf_agents: list, host: str) -> bool:\n", - " \"\"\"check which group wins\"\"\"\n", - " if len(wolf_agents) * 2 >= len(alive_agents):\n", - " msg = Msg(host, Prompts.to_all_wolf_win)\n", - " logger.chat(f\"{host}: {msg.content}\")\n", - " return True\n", - " if alive_agents and not wolf_agents:\n", - " msg = Msg(host, Prompts.to_all_village_win)\n", - " logger.chat(f\"{host}: {msg.content}\")\n", - " return True\n", - " return False\n", - "\n", - "\n", - "def update_alive_players(\n", - " survivors: Sequence[AgentBase],\n", - " wolves: Sequence[AgentBase],\n", - " dead_names: Union[str, list[str]],\n", - ") -> tuple[list, list]:\n", - " \"\"\"update the list of alive agents\"\"\"\n", - " if not isinstance(dead_names, list):\n", - " dead_names = [dead_names]\n", - " return [_ for _ in survivors if _.name not in dead_names], [\n", - " _ for _ in wolves if _.name not in dead_names\n", - " ]\n", - "\n", - "\n", - "def majority_vote(votes: list) -> Any:\n", - " \"\"\"majority_vote function\"\"\"\n", - " unit, counts = np.unique(votes, return_counts=True)\n", - " return unit[np.argmax(counts)]\n", - "\n", - "\n", - "def extract_name_and_id(name: str) -> tuple[str, int]:\n", - " \"\"\"extract player name and id from a string\"\"\"\n", - " name = re.search(r\"\\bPlayer\\d+\\b\", name).group(0)\n", - " idx = int(re.search(r\"Player(\\d+)\", name).group(1)) - 1\n", - " return name, idx\n", - "\n", - "\n", - "def n2s(agents: Sequence[Union[AgentBase, str]]) -> str:\n", - " \"\"\"combine agent names into a string, and use \"and\" to connect the last two names.\"\"\"\n", - "\n", - " def _get_name(agent_: Union[AgentBase, str]) -> str:\n", - " return agent_.name if isinstance(agent_, AgentBase) else agent_\n", - "\n", - " if len(agents) == 1:\n", - " return _get_name(agents[0])\n", - "\n", - " return (\n", - " \", \".join([_get_name(_) for _ in agents[:-1]])\n", - " + \" and \"\n", - " + _get_name(agents[-1])\n", - " )" - ] - }, { "cell_type": "markdown", "id": "4cbc4d91-b224-4c58-bf51-500cca9037f7", @@ -366,6 +236,18 @@ "from agentscope.pipelines.functional import sequentialpipeline\n", "import agentscope\n", "\n", + "import sys\n", + "sys.path.append('../examples/werewolf/')\n", + "from prompt import Prompts\n", + "from utils import (\n", + " check_winning,\n", + " update_alive_players,\n", + " majority_vote,\n", + " extract_name_and_id,\n", + " n2s,\n", + ")\n", + "\n", + "\n", "# default settings\n", "HostMsg = partial(Msg, name=\"Moderator\", echo=True)\n", "healing, poison = True, True\n", @@ -374,7 +256,7 @@ "# read model and agent configs, and initialize agents automatically\n", "survivors = agentscope.init(\n", " model_configs=model_configs,\n", - " agent_configs=agent_configs,\n", + " agent_configs=\"../examples/werewolf/configs/agent_configs.json\",\n", ")\n", "roles = [\"werewolf\", \"werewolf\", \"villager\", \"villager\", \"seer\", \"witch\"]\n", "wolves, witch, seer = survivors[:2], survivors[-1], survivors[-2]\n", From fff42e943b3f79d56081c31d8018a092170c5eb2 Mon Sep 17 00:00:00 2001 From: qbc Date: Thu, 25 Jan 2024 13:54:49 +0800 Subject: [PATCH 4/4] delete werewolf jupyter --- notebook/werewolf.ipynb | 371 ---------------------------------------- 1 file changed, 371 deletions(-) delete mode 100644 notebook/werewolf.ipynb diff --git a/notebook/werewolf.ipynb b/notebook/werewolf.ipynb deleted file mode 100644 index ee58191b4..000000000 --- a/notebook/werewolf.ipynb +++ /dev/null @@ -1,371 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "33be6252-0814-4f97-b4ed-06d7e68ce66b", - "metadata": {}, - "source": [ - "# Werewolf Game" - ] - }, - { - "cell_type": "markdown", - "id": "722dd171-2a2f-4ed6-b851-8154acc46b83", - "metadata": {}, - "source": [ - "This is a demo of how to use AgentScope to play the Werewolf game, where six\n", - " agents play the roles of werewolves and villagers. The details can be found\n", - " in `examples/werewolf/README.md`." - ] - }, - { - "cell_type": "markdown", - "id": "22684e1a-acf9-469c-8cee-36bd0b3efb8a", - "metadata": {}, - "source": [ - "To install AgentScope, please follow the steps in [README.md](../README.md#installation)." - ] - }, - { - "cell_type": "markdown", - "id": "51b90378-6c48-4462-9110-c44639e57f44", - "metadata": {}, - "source": [ - "First, we need to set the model configs for the agents." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b221278f-d1b1-410c-892d-df26a0d55fb4", - "metadata": {}, - "outputs": [], - "source": [ - "model_configs = [\n", - " {\n", - " \"type\": \"openai\",\n", - " \"name\": \"gpt-3.5-turbo\",\n", - " \"api_key\": \"xxx\",\n", - " \"organization\": \"xxx\",\n", - " \"generate_args\": {\n", - " \"temperature\": 0.5\n", - " }\n", - " },\n", - " {\n", - " \"type\": \"post_api\",\n", - " \"name\": \"my_post_api\",\n", - " \"api_url\": \"https://xxx\",\n", - " \"headers\": {\n", - " },\n", - " \"json_args\": {\n", - " }\n", - " }\n", - "]" - ] - }, - { - "cell_type": "markdown", - "id": "b683b8da-38ab-44eb-afc9-9e1a0ab0ec8e", - "metadata": {}, - "source": [ - "The configs for each agent are as follows. There are six agents, each playing a role in the game. Here, `DictDialogAgent` is a specific class in AgentScope. The details can be found in `src/agentscope/agents/dict_dialog_agent.py`. The details about `sys_prompt` for each player can be found in `examples/werewolf/configs/agent_configs`." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "8a389c49-5474-40db-8b61-e595ec803b82", - "metadata": {}, - "outputs": [], - "source": [ - "agent_configs = [\n", - " {\n", - " \"class\": \"DictDialogAgent\",\n", - " \"args\": {\n", - " \"name\": \"Player1\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player1 ...\",\n", - " \"model\": \"gpt-3.5-turbo\",\n", - " \"use_memory\": True\n", - " }\n", - " },\n", - " {\n", - " \"class\": \"DictDialogAgent\",\n", - " \"args\": {\n", - " \"name\": \"Player2\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player2 ...\",\n", - " \"model\": \"gpt-3.5-turbo\",\n", - " \"use_memory\": True\n", - " }\n", - " },\n", - " {\n", - " \"class\": \"DictDialogAgent\",\n", - " \"args\": {\n", - " \"name\": \"Player3\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player3 ...\",\n", - " \"model\": \"gpt-3.5-turbo\",\n", - " \"use_memory\": True\n", - " }\n", - " },\n", - " {\n", - " \"class\": \"DictDialogAgent\",\n", - " \"args\": {\n", - " \"name\": \"Player4\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player4 ...\",\n", - " \"model\": \"gpt-3.5-turbo\",\n", - " \"use_memory\": True\n", - " }\n", - " },\n", - " {\n", - " \"class\": \"DictDialogAgent\",\n", - " \"args\": {\n", - " \"name\": \"Player5\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player5 ...\",\n", - " \"model\": \"gpt-3.5-turbo\",\n", - " \"use_memory\": True\n", - " }\n", - " },\n", - " {\n", - " \"class\": \"DictDialogAgent\",\n", - " \"args\": {\n", - " \"name\": \"Player6\",\n", - " \"sys_prompt\": \"Act as a player in a werewolf game. You are Player6 ...\",\n", - " \"model\": \"gpt-3.5-turbo\",\n", - " \"use_memory\": True\n", - " }\n", - " }\n", - "]" - ] - }, - { - "cell_type": "markdown", - "id": "87dad640-3fca-404a-b567-eff0fde3e42f", - "metadata": {}, - "source": [ - "We also need to set the prompts for different players in differents states. The details can be found in `examples/werewolf/prompt.py`." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "0b7de59d-baa3-4b2d-ae41-fac1504f4277", - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"Used to record prompts, will be replaced by configuration\"\"\"\n", - "\n", - "\n", - "class Prompts:\n", - " \"\"\"Prompts for werewolf game\"\"\"\n", - "\n", - " to_wolves = (\n", - " \"{}, you are werewolves. ...\"\n", - " )\n", - "\n", - " to_wolves_vote = (\n", - " \"Which player do you vote to kill? ...\"\n", - " )\n", - "\n", - " to_wolves_res = \"The player with the most votes is {}.\"\n", - "\n", - " to_witch_resurrect = (\n", - " \"{witch_name}, you're witch. ...\"\n", - " )\n", - "\n", - " to_witch_poison = (\n", - " \"Would you like to eliminate one player? ...\"\n", - " )\n", - "\n", - " to_seer = (\n", - " \"{}, you're seer. ...\"\n", - " )\n", - "\n", - " to_seer_result = \"Okay, the role of {} is {}.\"\n", - "\n", - " to_all_danger = (\n", - " \"The day is coming, all the players open your eyes. Last night, \"\n", - " \"the following player(s) has been eliminated: {}.\"\n", - " )\n", - "\n", - " to_all_peace = (\n", - " \"The day is coming, all the players open your eyes. Last night is \"\n", - " \"peaceful, no player is eliminated.\"\n", - " )\n", - "\n", - " to_all_discuss = (\n", - " \"Now the alive players are {}. ...\"\n", - " )\n", - "\n", - " to_all_vote = (\n", - " \"Now the alive players are {}. ...\"\n", - " )\n", - "\n", - " to_all_res = \"{} has been voted out.\"\n", - "\n", - " to_all_wolf_win = (\n", - " \"The werewolves have prevailed and taken over the village. Better \"\n", - " \"luck next time!\"\n", - " )\n", - "\n", - " to_all_village_win = (\n", - " \"The game is over. The werewolves have been defeated, and the village \"\n", - " \"is safe once again!\"\n", - " )\n", - "\n", - " to_all_continue = \"The game goes on.\"" - ] - }, - { - "cell_type": "markdown", - "id": "4cbc4d91-b224-4c58-bf51-500cca9037f7", - "metadata": {}, - "source": [ - "Now we can turn our attention to the main function of the game. Run the following codes and enjoy the game." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0e1e3bcb-279b-409e-ba98-4d6ea01dcc87", - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"A werewolf game implemented by agentscope.\"\"\"\n", - "from functools import partial\n", - "from agentscope.message import Msg\n", - "from agentscope.msghub import msghub\n", - "from agentscope.pipelines.functional import sequentialpipeline\n", - "import agentscope\n", - "\n", - "import sys\n", - "sys.path.append('../examples/werewolf/')\n", - "from prompt import Prompts\n", - "from utils import (\n", - " check_winning,\n", - " update_alive_players,\n", - " majority_vote,\n", - " extract_name_and_id,\n", - " n2s,\n", - ")\n", - "\n", - "\n", - "# default settings\n", - "HostMsg = partial(Msg, name=\"Moderator\", echo=True)\n", - "healing, poison = True, True\n", - "MAX_WEREWOLF_DISCUSSION_ROUND = 3\n", - "MAX_GAME_ROUND = 6\n", - "# read model and agent configs, and initialize agents automatically\n", - "survivors = agentscope.init(\n", - " model_configs=model_configs,\n", - " agent_configs=\"../examples/werewolf/configs/agent_configs.json\",\n", - ")\n", - "roles = [\"werewolf\", \"werewolf\", \"villager\", \"villager\", \"seer\", \"witch\"]\n", - "wolves, witch, seer = survivors[:2], survivors[-1], survivors[-2]\n", - "\n", - "# start the game\n", - "for i in range(1, MAX_GAME_ROUND + 1):\n", - " # night phase, werewolves discuss\n", - " hint = HostMsg(content=Prompts.to_wolves.format(n2s(wolves)))\n", - " with msghub(wolves, announcement=hint) as hub:\n", - " for _ in range(MAX_WEREWOLF_DISCUSSION_ROUND):\n", - " x = sequentialpipeline(wolves)\n", - " if x.get(\"agreement\", False):\n", - " break\n", - "\n", - " # werewolves vote\n", - " hint = HostMsg(content=Prompts.to_wolves_vote)\n", - " votes = [extract_name_and_id(wolf(hint).content)[0] for wolf in wolves]\n", - " # broadcast the result to werewolves\n", - " dead_player = [majority_vote(votes)]\n", - " hub.broadcast(\n", - " HostMsg(content=Prompts.to_wolves_res.format(dead_player[0])),\n", - " )\n", - "\n", - " # witch\n", - " healing_used_tonight = False\n", - " if witch in survivors:\n", - " if healing:\n", - " hint = HostMsg(\n", - " content=Prompts.to_witch_resurrect.format_map(\n", - " {\"witch_name\": witch.name, \"dead_name\": dead_player[0]},\n", - " ),\n", - " )\n", - " if witch(hint).get(\"resurrect\", False):\n", - " healing_used_tonight = True\n", - " dead_player.pop()\n", - " healing = False\n", - "\n", - " if poison and not healing_used_tonight:\n", - " x = witch(HostMsg(content=Prompts.to_witch_poison))\n", - " if x.get(\"eliminate\", True):\n", - " dead_player.append(extract_name_and_id(x.content)[0])\n", - " poison = False\n", - "\n", - " # seer\n", - " if seer in survivors:\n", - " hint = HostMsg(\n", - " content=Prompts.to_seer.format(seer.name, n2s(survivors)),\n", - " )\n", - " x = seer(hint)\n", - "\n", - " player, idx = extract_name_and_id(x.content)\n", - " role = \"werewolf\" if roles[idx] == \"werewolf\" else \"villager\"\n", - " hint = HostMsg(content=Prompts.to_seer_result.format(player, role))\n", - " seer.observe(hint)\n", - "\n", - " survivors, wolves = update_alive_players(survivors, wolves, dead_player)\n", - " if check_winning(survivors, wolves, \"Moderator\"):\n", - " break\n", - "\n", - " # daytime discussion\n", - " content = (\n", - " Prompts.to_all_danger.format(n2s(dead_player))\n", - " if dead_player\n", - " else Prompts.to_all_peace\n", - " )\n", - " hints = [\n", - " HostMsg(content=content),\n", - " HostMsg(content=Prompts.to_all_discuss.format(n2s(survivors))),\n", - " ]\n", - " with msghub(survivors, announcement=hints) as hub:\n", - " # discuss\n", - " x = sequentialpipeline(survivors)\n", - "\n", - " # vote\n", - " hint = HostMsg(content=Prompts.to_all_vote.format(n2s(survivors)))\n", - " votes = [extract_name_and_id(_(hint).content)[0] for _ in survivors]\n", - " vote_res = majority_vote(votes)\n", - " # broadcast the result to all players\n", - " result = HostMsg(content=Prompts.to_all_res.format(vote_res))\n", - " hub.broadcast(result)\n", - "\n", - " survivors, wolves = update_alive_players(survivors, wolves, vote_res)\n", - "\n", - " if check_winning(survivors, wolves, \"Moderator\"):\n", - " break\n", - "\n", - " hub.broadcast(HostMsg(content=Prompts.to_all_continue))\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.18" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -}