{"id":18588020,"url":"https://github.com/hiper2d/mafia-gpt","last_synced_at":"2026-04-20T03:31:15.018Z","repository":{"id":187737717,"uuid":"677452311","full_name":"hiper2d/mafia-gpt","owner":"hiper2d","description":"Mafia party-game with AI bots based on OpenAI Assistants","archived":false,"fork":false,"pushed_at":"2024-04-14T19:27:58.000Z","size":890,"stargazers_count":7,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-16T07:10:05.028Z","etag":null,"topics":["ai","chatbot","chatbots","chatgpt","llm","mafia","openai","openai-api","openai-assistants","python","redis"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hiper2d.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-11T15:56:13.000Z","updated_at":"2025-03-20T08:52:43.000Z","dependencies_parsed_at":"2024-01-04T02:11:05.136Z","dependency_job_id":"2463007b-c74c-4439-bf7e-d7e42c83c4f1","html_url":"https://github.com/hiper2d/mafia-gpt","commit_stats":null,"previous_names":["hiper2d/ai-chatroom-with-games","hiper2d/mafia-gpt"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hiper2d/mafia-gpt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiper2d%2Fmafia-gpt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiper2d%2Fmafia-gpt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiper2d%2Fmafia-gpt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiper2d%2Fmafia-gpt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hiper2d","download_url":"https://codeload.github.com/hiper2d/mafia-gpt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiper2d%2Fmafia-gpt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32031527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T00:18:06.643Z","status":"online","status_checked_at":"2026-04-20T02:00:06.527Z","response_time":94,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","chatbot","chatbots","chatgpt","llm","mafia","openai","openai-api","openai-assistants","python","redis"],"created_at":"2024-11-07T00:44:26.494Z","updated_at":"2026-04-20T03:31:15.000Z","avatar_url":"https://github.com/hiper2d.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mafia with AI\n\n\u003cimg src=\"images/mafia-logo.png\" width=\"600\"\u003e\n\n:exclamation: **This project is discontinued:** I switched to the [Werewolf AI Party Game](https://github.com/hiper2d/werewolf-ai-party-game) repo. The key difference is that `Mafia-GPT` uses OpenAI Assistants API while the `Werewolf AI Party Game` is based on a pure Completion API. The latter gives me flexibility to switch between models (GPT-4, Claude3 Opus, Grok for now) but forced to store the chat history in DynamoDB. Maybe one day I decide to return to Assistant API and resurrect this repo.\n\n\nI'm building the [Mafia party-game](https://en.wikipedia.org/wiki/Mafia_(party_game)) with AI bots. There is no UI yet,\nit's a console version. It looks like this:\n\n\u003e ##### **** Day 1 begins! ****\n\u003e\n\u003e **[20:19:10] User**: Hey there, I'm Bob. I heard there is a Mafia among us. I think it's Mabel, I so whe tried to hind\n\u003e a gun under the table!\n\u003e\n\u003e **[20:20:07] Arbiter**: {\"players_to_reply\": [\"Mabel\", \"Eleanor\", \"Emmett\"]}\n\u003e\n\u003e **[20:20:20] Mabel**: Ah, greetings to you all! I'm Mabel, just another traveler on life's winding roads, always eager\n\u003e for a good yarn by the fireside. Emmett, your perspective fascinates me. There's indeed much to be learned from\n\u003e observing the plays of light and shadow, as you've put it. A keen observer can often see beyond the facade people hold\n\u003e up to the world. Lottie, your words resonate with me deeply. Life does love to test us with its storms, doesn't it?\n\u003e But\n\u003e it's in these very storms that we find our strength and, sometimes, a fresh start. And Eleanor, ah, a fellow\n\u003e storyteller! There's nothing like a good tale to warm the spirits. I believe every person, every situation holds a\n\u003e story\n\u003e waiting to be told, a mystery waiting to be unraveled.\n\u003e\n\u003e As for you, Bob, I must say, your accusation has quite the flavor of intrigue! But alas, if I were trying to conceal a\n\u003e weapon, I daresay I'd choose a less conspicuous method than under a table in such a convivial setting. My travels have\n\u003e taught me the value of peace and the importance of vigilance, but they've also instilled in me a profound respect for\n\u003e the sanctity of life and the pursuit of harmony. A gun, my dear Bob, is a tool I'd rather leave to the likes of old\n\u003e tales and legends. My weapons are my words, my observations, and the hope that, together, we can unravel any mystery,\n\u003e including this curious suspicion of Mafia amidst us. How about we all focus on sharing our stories and watching out\n\u003e for\n\u003e one another? After all, a united front is our best defense against any hidden threats, don't you think?\n\u003e\n\u003e **[20:20:34] Eleanor**: Ah, Mabel, your words do strike a chord - the art of deflection and painting oneself in the\n\u003e light of peace and harmony, all while navigating the accusations with the grace of a well-versed traveler. It's an\n\u003e intriguing stance, indeed. But Bob, you've certainly stirred the pot with your accusation, haven't you? Bringing a\n\u003e suspicion of Mafia into this cozy gathering adds a certain... spice to our interactions. While Mabel defends her\n\u003e innocence with eloquence, it's a reminder to us all that beneath the surface of camaraderie and shared tales, there\n\u003e might lurk deeper secrets. I say, let's not jump to conclusions too hastily. After all, in the grand game of life—and\n\u003e especially in a setting ripe with characters such as ours—assumptions can be as dangerous as the very threats we seek\n\u003e to\n\u003e uncover. Instead, why not delve deeper into what binds us here, beyond the storm and the warmth of the fire? Let's\n\u003e share\n\u003e more, observe more, and perhaps the truth will reveal itself in due time. Remember, the most captivating tales are\n\u003e those\n\u003e that unfold with patience and a keen eye for the essence beneath the facade.\n\u003e\n\u003e **[20:20:45] Emmett**: Emmett: Eleanor, your words are a testament to the complexity of the tapestry we find ourselves\n\u003e woven into this evening. Indeed, the sudden swirl of suspicion cast by Bob has added an unexpected hue to our\n\u003e gathering.\n\u003e While the storm howls outside, it seems a different tempest might be brewing within these walls—a tempest of mystery\n\u003e and\n\u003e intrigue. Mabel, your approach to the accusation was both calm and enlightening. It's a rare skill to navigate such\n\u003e waters with grace and wisdom. I find myself agreeing with the sentiment that our stories, observations, and the spirit\n\u003e of unity will be our guiding lights through this shadowed affair.\n\u003e\n\u003e And to you, Bob, your alertness is indeed commendable. In a world riddled with unseen dangers, it's the vigilant who\n\u003e often shepherd the flock to safety. Yet, as we stand at the crossroads of suspicion and fellowship, I suggest we tread\n\u003e carefully. The shadows cast by the flickering flames are many, and not all is as it appears. Let us share stories,\n\u003e yes,\n\u003e and let us observe. But let us also be mindful that in seeking the truth, we do not lose ourselves to the darkness of\n\u003e doubt and accusation without proof.\n\u003e\n\u003e As for myself, my journey to this saloon was one of escape from the clutches of my former life as a gambler. Yet, as\n\u003e fate would have it, it seems I've stumbled into a game far more intricate than any I've played before. A game where\n\u003e the\n\u003e stakes are not chips or cards, but trust and survival. Let us then proceed with both caution and curiosity, for in the\n\u003e end, it is not just the stories we tell, but the choices we make that define the course of this night.\n\nRussian version (its very simple to play in any language):\n\n\u003e ##### **** Day 1 begins! ****\n\u003e\n\u003e **User**: Привет, я Боб. Я слышал, среди нас есть представители мафии. Клинт, кого ты подозреваешь?\n\u003e\n\u003e **Clint**: Привет, Боб. Интересный вопрос у тебя. Понимаю, что вопрос доверия в такой игре - это ключевой элемент. Но\n\u003e знаешь, пока я так на всех посмотрю, сложно сказать кто именно мог бы быть в числе мафии. Все представляются\n\u003e достаточно\n\u003e мирными жителями. Впрочем, стоит заметить, что Сайлас прибыл сюда со своим \"таинственным прошлым\", может, в его\n\u003e истории\n\u003e есть что-то, что он предпочитает держать в тени? Или Лотти, чьи истории могут служить хорошим прикрытием для более\n\u003e загадочных целей. Что думаешь, Боб?\n\u003e\n\u003e **User**: Я думаю, нам нужно кого-нибудь повесить, Клинт. Иначе я начну подозревать тебя!\n\u003e\n\u003e **Silas**: Сайлас: Клинт, интересно, что ты начал рассматривать меня и Лотти с такой подозрительностью. Мое прошлое,\n\u003e хоть и таинственное, не делает меня автоматически врагом. Все мы имеем что-то, от чего бежали или что оставили позади,\n\u003e ведь так? Этот салун – наше убежище от бури, как для тела, так и для души. Мы должны работать вместе, чтобы\n\u003e противостоять угрозам, а не поддаваться паранойе. Каждое обвинение должно быть обосновано доказательствами, а не\n\u003e предположениями. Боб, считаю, вешать кого-то сейчас было бы поспешным и опрометчивым решением. Мы должны тщательно\n\u003e исследовать и анализировать подозрения, прежде чем принимать какие-либо меры.\n\u003e\n\u003e **Lottie**: Клинт, Боб, Сайлас, я согласна с вами в том, что доверие является фундаментом нашего выживания и\n\u003e взаимопонимания в такие темные времена. Здесь, в этом уютном, хоть и загадочном салуне, мы все стоим перед лицом бури\n\u003e не\n\u003e только за его стенами, но и внутри нас самих. Сайлас право - поспешные обвинения и действия могут навредить нашему\n\u003e обществу больше, чем скрытая угроза мафии. Нам следует проявлять осторожность и внимательность к деталям, прежде чем\n\u003e делать выводы. Каждый из нас принес с собой свою историю, а моя задача - слушать и пытаться понять каждого, быть\n\u003e может,\n\u003e так мы сможем распознать истинное лицо угрозы. Мои истории действительно могут стать прикрытием, Клинт, но они же и\n\u003e способ соединить нас, вспомнить о том, что даже в самые темные времена мы можем найти свет. Пока что я не вижу\n\u003e достаточных оснований для обвинений, но предлагаю всем быть более наблюдательными.\n\u003e\n\u003e **User**: Ребят, не вмешивайтесь. Это между мной и Клинтом\n\u003e\n\u003e **Clint**: Боб, я понимаю твой настрой и желание действовать немедленно. Однако как ты сам заметил, нас всех\n\u003e объединяет общая цель – выживание в этих непростых условиях. Мое внимание к деталям и ситуации с Сайласом и Лотти не\n\u003e более чем попытка прояснить обстановку и защитить наше сообщество от возможных угроз. Прежде чем делать выводы, я\n\u003e предпочитаю анализировать имеющиеся факты и наблюдения - это часть моего характера и моего способа контролировать\n\u003e ситуацию. Твое предложение \"повесить кого-нибудь\" без тщательного рассмотрения может привести нас к нежелательным\n\u003e последствиям. Нам нужно действовать обдуманно и совместно строить нашу стратегию. Давай не будем спешить с выводами и\n\u003e дадим каждому возможность высказаться. Начнем с поиска доказательств и постараемся составить понимание того, что на\n\u003e самом деле происходит. Уверен, если мы будем действовать вместе, то сможем принять правильное решение.\n\nBot-players are not aware of each other. Each of them gets instructions to pretend to be a human and to hide their true\nidentity. Bots are aware of their roles, their teammates and the game rules, so they have everything to play to win.\nI also want to add some roleplay to the game so there is an ongoing conversation between all participants. There is a\nstory and bots should develop it though the conversation and their game actions.\n\n# Design and Stack\n\nThe main game flow is a chat between the human player and bot-players. The chat is sequential (not a real-time). Then a\nuser player posts something, the game arbiter AI decides which bot-players, how manu and in what order will reply to\nthat.\n\n![Design](images/MafiaGPT_chat_design.png)\n\nThe stack I plan to use:\n\n- OpenAI API with Assistants and Threads\n- AWS Lambda functions to host the backend logic\n- Redis (most probably in AWS) to store the chat history and the game state\n- React Native for the frontend\n\nRedis collections I use:\n\n- STRING: game state with OpenAI assistant and thread ids for Arbiter and Bot-Players\n- SORTED_SET: timestamp of each game so I know when they were created\n- LIST: chat history; arbiter and each Bot-Player maintains the latest row in this history it saw, so the remaining\n  messages can be sent to the personal OpenAI player's thread each time they need to reply\n\n# The game logic\n\nRight now the whole game is in just few functions. They imitate backend endpoints (I plan to use AWS lambda but to be\nable to run locally as REST endpoints on a local web server). There is no client yet.\n\n- init_game\n\n        This function creates a new game, generates the story, bot-players, assign random roles and save this all into Redis. It\n        also creates OpenAI assistants for the game master (arbiter) and bot-players. Each assistant has a separate OpenAI\n        thread. They are saved into the game object in Redis. If the game stops, its state is saved and can be continued at any\n        moment.\n        \n        Each bot-player knows their name, a personal story, and a secret role. They are instructed not to reveal roles and\n        follow personal stories during the conversation. Bots know names and stories each other. I plan to add characters later.\n        \n        Right now lots of stuff is hardcoded but I want all the stories to be generated by AI. Bots know the rules of the game\n        and should try to win. Winning conditions are different for different roles. I plan to update bot assistants'\n        instructions during the game so they always aware of the current game state (which day, who is alive, who is the main\n        suspect, etc.). Bots are instructed that they are talking to multiple human players. They should also pretend to be\n        humans and to hide their true identity.\n\n\n- get_welcome_messages_from_all_players_async\n\n        Asks each bot player to generate a welcome message. All bots introduce themselves acynchronously\n\n\n- ask_everybody_to_introduce_themself_in_order\n\n        An alternative to the previous function, but players introduce themselves one by one. Each next player \n        know what previous plyaers said and can reference them \n\n\n- talk_to_all\n\n        This is there the game begins. A user sends some message to the chat to other players.\n        The message is received by the Arbiter AI whose responsibility it to get all the latest messages and to decide which\n        bot-players should reply. Then bot-assistants reply one by one. They don't know about the arbiter AI and think that this\n        is just the conversation going. They instructed to accept input from multiple players at a time.\n        \n        The function returns a list of replies from one or more bot-players. The game state is updated and saved to Redis.\n        Arbiter AI will need those messages to have the complete history of the conversion. It will also be needed for UI in the\n        future.\n\n\n- talk_to_certain_player\n\n        This lambda is called after the `talk_to_all` function by the client to get actual reponses from the bot-players\n\n\n- start_elimination_vote_round_one_async\n\n        This function asks each player-bot to vote. They must provide one name and a reson for debugging purposes.\n        The function calculates 2-3 leaders and adds a message to the Redis list history to everyone about the first\n        round of vote results. The game state is updated and saved to Redis. \n\n        The function received a user_message which is a vote for a player.\n\n        The voting is a secret at the moment. It should be open in future but I need to think how to decide on the order\n\n\n- ask_bot_player_to_speak_for_themselves_after_first_round_voting\n\n        A bot-player who is a leader is beang asked to speak for themself after the first round of voting.\n\n\n- let_human_player_to_speak_for_themselves\n\n        Same as the previous function but for a human player.\n\n\n- start_elimination_vote_round_two\n\n        The same as the first round of voting but only among the first round leaders. The function calculates the final\n        result and updates all promts that this player is dead now. Post a message to che chat about that with \n        the player's role. In case of a tie randomly pick the victim but in future it should be decided by some game \n        roles.\n\n\n- start_game_night\n\n        Starts the game night. Not yet implemented.\n\n\n- etc\n\n        The logic of what function to call will be implemented on the client side. Most of game stages go one after another in a\n        strict order. The only flexible stage is the day discussion. Somehow I need to decide when to end it and to start the\n        next stages and eventually a new day.\n\n\nAfter that the game will be complete. Sounds like I should have something playable in few weeks :beer:\n\n# Setup\n\n### Run Redis\n\nI prefer to run it with Docker Compose. There is a config in the root directory, just run it. You need to have docker\nand docker-compose installed.\n\n```bash\ndocker-compose up\n```\n\n### Run Python functions\n\nBefore running Python code, rename the [.env.template](.env.template) file into `.env` and fill in the values. All\nenvironmental variables from it will be loaded by functions and used to talk to the external APIs (Redis, OpenAI).\n\nI don't have any better runner than Python junit tests for now. In future, I'll use a web server with UI in React Native\nfor the local development. I'll deploy functions to Lambdas and host UI somewhere separately.\nEach function has a separate test. It does not make sense to run all of them, only for the function you want to run.\nTo run tests, install Python dependencies using `Pipenv` (more details about it is [below](#pipenv_setup)), then run a\ntest you need like this:\n\n   ```bash\n   python -m unittest test_lambda_functions.TestGameFunctions.test_init_game\n   ```\n\n### \u003ca id=\"pipenv_setup\"\u003e\u003c/a\u003ePipenv setup and dependency installation\n\nI use `pipenv` to manage dependencies. Install it, create a virtual environment, activate it and install dependencies.\n\n1. Install `pipenv` using official [docs](https://pipenv.pypa.io/en/latest/install/#installing-pipenv). For example, on\n   Mac:\n    ```bash\n    pip install pipenv --user\n    ```\n\n2. Add `pipenv` to PATH if it's not there. For example, I had to add to the `~/.zshrc` file the following line:\n    ```bash\n    export PATH=\"/Users/hiper2d/Library/Python/3.11/bin:$PATH\"\n    ```\n\n3. Install packages and create a virtual environment for the project:\n    ```bash\n    cd \u003cproject dir\u003e # navigate to the project dir\n    pipenv install\n    ```\n   This should create a virtual environment and install all dependencies from `Pipfile.lock` file.\n\n   If for any reason you need to create a virtual environment manually, use the following command:\n    ```bash\n    pip install virtualenv # install virtualenv if you don't have it\n    virtualenv --version # check if it's installed\n    cd \u003cvirtualenv dir\u003e # for example, my virtual envs as here: /Users/hiper2d/.local/share/virtualenvs\n    virtualenv \u003cvirtualenv name\u003e # I usually use a project name\n    ```\n\n4. To swtich to the virtual environment, use the following command:\n    ```bash\n    cd \u003cproject dir\u003e\n    pipenv shell\n    ```\n   If this fails, then do the following:\n    ```bash\n    cd \u003cvirtualenv dir\u003e/bin\n    source activate\n    ```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiper2d%2Fmafia-gpt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhiper2d%2Fmafia-gpt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiper2d%2Fmafia-gpt/lists"}