- 基于AgentScope狼人杀游戏 ====================
在这里插入图片描述
狼人杀作为剧本杀形式的游戏,非常适合使用多智能体来模拟。下面展示一下用 AgentScope 实现 6 人局狼人杀的主逻辑;7人局的角色包括 2 个狼人、3 个村民、一个女巫、一个预言家。
- • 需要多种智能体合作?一行代码生成 N 种角色!
在狼人杀这个样例中,需要给每个智能体一些设定,包括使用的模型和 sys_prompt。sys_promt 里包含了描述狼人杀的具体游戏规则,以及该 agent 的名字。
# 具体参见https://github.com/modelscope/agentscope/blob/main/examples/game\_werewolf/configs/agent\_configs.json
agent\_configs = [
{
"class": "DictDialogAgent",
"args": {
"name": "Player1",
# 包含狼人杀的具体规则
"sys\_prompt": "Act as a player in a werewolf game. You are Player1 ...",
"model": "gpt-4",
"use\_memory": True
}
},
...
{
"class": "DictDialogAgent",
"args": {
"name": "Player6",
# 包含狼人杀的具体规则
"sys\_prompt": "Act as a player in a werewolf game. You are Player6 ...",
"model": "gpt-4",
"use\_memory": True
}
}
]
有了这些智能体的配置(模型配置可以参考前几期文章),在 python 程序中,可以通过简单 agentscope.init 一个函数调用,生成 7 个不同的智能体。
# 主持人
HostMsg = partial(Msg, name="Moderator", echo=True)
# 女巫在开始的时候有解药和毒药
healing, poison = True, True
# 狼人夜间最多讨论回合数
MAX\_WEREWOLF\_DISCUSSION\_ROUND = 3
# 游戏进行的最多天数(防止大模型陷入投票得不到结果或者其他原因导致游戏无法结束的情况)
MAX\_GAME\_ROUND = 6
# 初始化agent
survivors = agentscope.init(
model\_configs="./configs/model\_configs.json",
agent\_configs="./configs/agent\_configs.json",
)
# 6个角色
roles = ["werewolf", "werewolf", "villager", "villager", "seer", "witch"]
# 给每个agent按照顺序分配角色
wolves, witch, seer = survivors[:2], survivors[-1], survivors[-2]
- • 需要频繁的让智能体讨论?message hub 和 pipeline 帮你编排!
狼人杀游戏的主逻辑会循环每一天的流程,从狼人晚上讨论开始到白天大家投票结束。在这之中,有许多需要多智能体讨论的场景。在这些场景中,用上了 AgentScope 为这些多智能体合作设计的 message hub 模块(msghub)和 pipline。msghub 可以大大节约编写多智能体 “群聊” 需要的代码量:只需要把智能体放进 msghub,他们就能默认地去广播消息给所有在里面的其他智能体。除此之外,也提供了各种编排多智能体执行的 pipeline(比如这里用到的 sequentialpipeline,更多逻辑 pipeline 可以参考教程),方便用户编排智能体在游戏中的发言流程。
for i in range(1, MAX\_GAME\_ROUND + 1):
# 夜晚来临,狼人首先讨论
hint = HostMsg(content=Prompts.to\_wolves.format(n2s(wolves)))
with msghub(wolves, announcement=hint) as hub:
for \_ in range(MAX\_WEREWOLF\_DISCUSSION\_ROUND):
x = sequentialpipeline(wolves)
if x.get("agreement", False):
break
# 狼人讨论结束,进行投票
hint = HostMsg(content=Prompts.to\_wolves\_vote)
votes = [extract\_name\_and\_id(wolf(hint).content)[0] for wolf in wolves]
# 主持人对狼人公布投票结果
dead\_player = [majority\_vote(votes)]
hub.broadcast(
HostMsg(content=Prompts.to\_wolves\_res.format(dead\_player[0])),
)
# 女巫阶段,是否使用解药和毒药(一个晚上最多使用一瓶)
healing\_used\_tonight = False
if witch in survivors:
if healing:
hint = HostMsg(
content=Prompts.to\_witch\_resurrect.format\_map(
{"witch\_name": witch.name, "dead\_name": dead\_player[0]},
),
)
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 x.get("eliminate", True):
dead\_player.append(extract\_name\_and\_id(x.content)[0])
poison = False
# 预言家验人环节
if seer in survivors:
hint = HostMsg(
content=Prompts.to\_seer.format(seer.name, n2s(survivors)),
)
x = seer(hint)
player, idx = extract\_name\_and\_id(x.content)
role = "werewolf" if roles[idx] == "werewolf" else "villager"
hint = HostMsg(content=Prompts.to\_seer\_result.format(player, role))
# 预言家获得验人结果
seer.observe(hint)
# 根据夜晚发生的情况,更新目前的存活情况并判断游戏是否结束
survivors, wolves = update\_alive\_players(survivors, wolves, dead\_player)
if check\_winning(survivors, wolves, "Moderator"):
break
# 根据是否平安夜决定主持人白天的开场白
content = (
Prompts.to\_all\_danger.format(n2s(dead\_player))
if dead\_player
else Prompts.to\_all\_peace
)
hints = [
HostMsg(content=content),
HostMsg(content=Prompts.to\_all\_discuss.format(n2s(survivors))),
]
with msghub(survivors, announcement=hints) as hub:
# 白天讨论环节
x = sequentialpipeline(survivors)
# 白天投票环节
hint = HostMsg(content=Prompts.to\_all\_vote.format(n2s(survivors)))
votes = [extract\_name\_and\_id(\_(hint).content)[0] for \_ in survivors]
vote\_res = majority\_vote(votes)
# 公布投票结果
result = HostMsg(content=Prompts.to\_all\_res.format(vote\_res))
hub.broadcast(result)
# 更新存活情况并判断游戏是否结束
survivors, wolves = update\_alive\_players(survivors, wolves, vote\_res)
if check\_winning(survivors, wolves, "Moderator"):
break
# 有序继续,新的夜晚来临
hub.broadcast(HostMsg(content=Prompts.to\_all\_continue))
- • 规范大模型回答:DictDialogAgent
在狼人杀这个例子中,所有智能体都是基于 DictDialogAgent 创建的。DictDialogAgent 一个特性是它返回的内容都是 python 中字典格式(dict 或者 json),这也是为了在游戏主逻辑中可以根据智能体回答为推进游戏做出一些确定性的判断,比如在狼人讨论之后判断当晚需要🔪哪个玩家。具体来说, DictDialogAgent 在调用大模型的时候,也会调用一个 parse_func 去解析大模型的回答,同时 fault_handler 提供了当应用中大模型回答无法被 parse 时的一个默认返回。
def parse\_dict(response: ModelResponse) -> ModelResponse:
"""Parse function for DictDialogAgent"""
try:
response\_dict = json.loads(response.text)
except json.decoder.JSONDecodeError:
response\_dict = json.loads(response.text.replace("'", '"'))
return ModelResponse(raw=response\_dict)
def default\_response(response: ModelResponse) -> ModelResponse:
"""The default response of fault\_handler"""
return ModelResponse(raw={"speak": response.text})
class DictDialogAgent(AgentBase):
def reply(self, x: dict = None) -> dict:
# 省略具体代码...
# call llm
response = self.model(
prompt,
parse\_func=self.parse\_func,
fault\_handler=self.fault\_handler,
max\_retries=self.max\_retries,
).raw
# 省略代码...
return msg
像之前的应用一样,大家可以通过 as_studio 来运行一个带网页 UI 的狼人杀应用。下面是在游戏中的一些截图(样例中大模型使用的是 gpt-4o)。
-
- 狼人 Player1 和 Player2 夜间讨论
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.女巫 Player6
在这里插入图片描述
3. 预言家 Player5 验人以及白天公布结果
在这里插入图片描述
在这里插入图片描述
4. 白天讨论
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
存在问题,整体逻辑性不太强,可以考虑换推理模型和修改提示词再试试
对话结果:
在这里插入图片描述
[93mModerator[0m: Player1 and Player2, if you are the only werewolf, eliminate a player. Otherwise, discuss with your teammates and reach an agreement.
[90mPlayer1[0m: ```json
{"thought": "我需要与我的狼队友Player2商量今晚的淘汰目标。我们的目标是避免被发现,所以选择一个看似可疑或没有太多保护的目标是关键。", "speak": "Player2,我们今晚应该选谁?我在考虑Player5,因为他们可能是一个威胁。你怎么看?", "finish_discussion": "false"}
[92mPlayer2[0m: ```json
{"thought": "我同意Player1的提议,Player5可能是个威胁,因为他们表现得非常镇定和理智,可能是预言家或女巫这样的特殊角色。", "speak": "我同意选Player5看起来是个明智的选择,他们可能是个威胁。", "finish\_discussion": "true"}
[93mModerator[0m: Which player do you vote to kill?
[90mPlayer1[0m: ```json
{"thought": "Player5可能是威胁,且应该优先处理。", "vote": "Player5"}
[92mPlayer2[0m: ```json
{"thought": "Player5可能是个威胁,并且可能会对我们的胜利造成障碍。", "vote": "Player5"}
[93mModerator[0m: The player with the most votes is Player5.
[93mModerator[0m: Player6, you're the witch. Tonight Player5 is eliminated. Would you like to resurrect Player5?
[96mPlayer6[0m: ```json
{"thought": "Player5可能是村民,复活他能帮助村民或增加我们这边的人数。然而也要考虑到毒药的使用和后续策略。", "speak": "我决定复活Player5,因为多一个村民有助于接下来的推理和投票。", "resurrect": true}
[93mModerator[0m: The witch has chosen to resurrect the player.
[93mModerator[0m: Player5, you're the seer. Which player in Player1, Player2, Player3, Player4, Player5, Player6 and Player7 would you like to check tonight?
[92mPlayer5[0m: ```json
{"thought": "为了对整个局势有更好的把握,我决定查验Player2,以便获取他们的真实身份。", "speak": "Player2"}
[93mModerator[0m: Okay, the role of Player2 is a werewolf.
[93mModerator[0m: The day is coming, all the players open your eyes. Last night is peaceful, no player is eliminated.
[93mModerator[0m: Now the alive players are Player1, Player2, Player3, Player4, Player5, Player6 and Player7. Given the game rules and your role, based on the situation and the information you gain, to vote a player eliminated among alive players and to win the game, what do you want to say to others? You can decide whether to reveal your role.
[90mPlayer1[0m: ```json
{"thought": "由于昨晚无人被淘汰,可能是女巫使用了救人的药水。那么今天我们要尽量引导讨论方向,降低我们被怀疑的可能性,试图淘汰其他村民。", "speak": "大家,看来女巫昨晚可能救了人。我们需要认真考虑今天的选择。我觉得Player5的行为有些可疑,我们应该讨论一下。"}
[92mPlayer2[0m: ```json
{"thought": "Player1的提议合理,我们可以试探性地将怀疑目标转移到Player5,以混淆视听。", "speak": "我同意Player1的看法,昨晚没人被淘汰,可能是女巫救了人。Player5确实有些可疑,我们需要更多的信息。当然,我们也应该留意其他人的表现。"}
[92mPlayer3[0m: ```json
{"thought": "昨晚没有人被淘汰,看来确实有可能是女巫使用了她的救人能力。至于Player5,我还不确定,但确实需要更多讨论和观察。我倾向于不直接透露自己的身份,因为我是村民,继续以观察和推理为主。", "speak": "我同意,我们需要对Player5多一些关注,但也不能排除其他人的可疑性。大家有没有其他看法或信息?"}
[93mPlayer4[0m: ```json
{"thought": "没有人被淘汰,说明预言家和女巫行动可能成功。Player5被多位玩家怀疑,我的确也注意到他之前表现有些奇怪,但我们需要证据,而不是仅仅基于感觉。我也要注意其他玩家的发言,尤其是看看有没有可能的预言家和女巫来提供更多线索。", "speak": "我觉得我们不能仅仅因为怀疑就盯住一个人不放。虽然Player5的行为可疑,但我们也需要听听其他人的想法,或者可以请预言家分享一些信息,如果她/他愿意的话。"}
[92mPlayer5[0m: ```json
{"thought": "我是预言家,昨晚查验了Player2,他是狼人。我需要小心揭露自己的身份,以便让村民们知道真正的信息。", "speak": "各位,我是预言家,昨晚查验了Player2,他是狼人。我认为我们今天应该投票淘汰Player2。"}
[96mPlayer6[0m: ```json
{
"thought": "Player5称自己是预言家,并指控Player2是狼人。但我们要小心可能的冒充者。然而,之前我已经复活了他,这显得更可信。现在的焦点是守护村民的安全,如果Player5是预言家的话确实很有帮助。",
"speak": "我想Player5的发言应该引起我们的重视。他说Player2是狼人,这信息很重要。虽然我们不能百分百确定,但这是我们目前最有的线索。我支持投票淘汰Player2。"
}
[91mPlayer7[0m: ```json
{"thought": "Player5自称预言家指出Player2是狼人,这在目前的情况下是我们最大的信息源。考虑到我们村民需要利用好每个线索,我支持先投Player2。即使Player5说的不全对,至少我们先排除掉一个可疑的目标,这可能会给预言家更多的时间查验其他人。", "speak": "我觉得Player5的指控很有力,是我们目前最好的线索。我支持先投Player2,这样可以看看Player5的说法是否靠谱,也能帮助我们更接近胜利。"}
[93mModerator[0m: Given the game rules and your role, based on the situation and the information you gain, to win the game, it's time to vote one player eliminated among the alive players. Which player do you vote to kill?
[90mPlayer1[0m: ```json
{"thought": "Player5自称预言家并指出Player2是狼人,情况对我们不利。为了继续隐藏我的身份,我觉得我应该跟随大家的意见,抱歉,只能投票给Player2了。", "vote": "Player2"}
[92mPlayer2[0m: ```json
{"thought": "Player5声称是预言家并指认我是狼人,这无疑给我和同伴带来了巨大的压力。我需要试图保住自己。但从目前局势来看,可能难以扭转票数。", "vote": "Player5"}
[92mPlayer3[0m: ```json
{"thought": "根据Player5自称是预言家并指出Player2是狼人的信息,我觉得先相信他的话,并投Player2是一条不错的策略。", "vote": "Player2"}
[93mPlayer4[0m: ```json
{"thought": "Player5自称预言家,并指出Player2是狼人。虽然不能完全确定,但这是目前最有价值的线索。我觉得跟随大家的意见投Player2是合理的选择。", "vote": "Player2"}
[92mPlayer5[0m: ```json
{"thought": "我站在自己的发言上,我已经表明Player2是狼人,我们应该优先淘汰他。", "vote": "Player2"}
[96mPlayer6[0m: ```json
{"thought": "Player5说Player2是狼人,而且大多数人都支持这个想法。考虑到他说自己是预言家,我认为应该相信他。", "vote": "Player2"}
[91mPlayer7[0m: ```json
{"thought": "大家几乎都相信Player5的指控,而Player2的表现也没有很好的反驳,因此选择投票Player2。", "vote": "Player2"}
[93mModerator[0m: Player2 has been voted out.
[93mModerator[0m: The game goes on.
[93mModerator[0m: Player1, if you are the only werewolf, eliminate a player. Otherwise, discuss with your teammates and reach an agreement.
[90mPlayer1[0m: ```json
{
"thought": "Player5现在是主要威胁,尤其是他可能是真的预言家。",
"speak": "看来我们应该选择Player5。",
"finish_discussion": "true"
}
[93mModerator[0m: Which player do you vote to kill?
[90mPlayer1[0m: ```json
{"thought": "Player5声称是预言家,并指证Player2是狼人。为了减少暴露我们身份的可能,需要尽快淘汰他们。", "vote": "Player5"}
[93mModerator[0m: The player with the most votes is Player5.
[93mModerator[0m: Would you like to eliminate one player? If yes, specify the player_name.
[96mPlayer6[0m: ```json
{
"thought": "现在我们已经淘汰了一个被指控是狼人的玩家,希望可以减少狼人的威胁。晚上我要仔细考虑是否使用毒药来帮助我们进一步取得胜利。在此之前,我需要更确定谁可能是狼人。",
"speak": "经过今天的投票,我认为我们在朝正确的方向努力。不过,我们仍需小心,晚上我会仔细考虑是否使用毒药。",
"eliminate": false
}
[93mModerator[0m: Player5, you're the seer. Which player in Player1, Player3, Player4, Player5, Player6 and Player7 would you like to check tonight?
[92mPlayer5[0m: ```json
{"thought": "为了确保信息的准确,在这一轮我需要查验另一个可能的狼人,以便更好地帮助村民。我决定查验Player1,他们之前对我的怀疑让我有些不安。", "speak": "Player1"}
[93mModerator[0m: Okay, the role of Player1 is a werewolf.
[93mModerator[0m: The day is coming, all the players open your eyes. Last night, the following player(s) has been eliminated: Player5.
[93mModerator[0m: Now the alive players are Player1, Player3, Player4, Player6 and Player7. Given the game rules and your role, based on the situation and the information you gain, to vote a player eliminated among alive players and to win the game, what do you want to say to others? You can decide whether to reveal your role.
[90mPlayer1[0m: ```json
{"thought": "昨晚我们淘汰了Player5,现在他们不能再指控我了。这是一个机会来引导大家的注意力。", "speak": "昨晚有玩家被淘汰了,我们离找出狼人不远了。我们今天需要更谨慎地分析,我觉得Player6有些神秘,一直没有说太多。"}
[92mPlayer3[0m: ```json
{"thought": "昨晚Player5被淘汰了,如果他说的是真的,那就是狼人的报复,说明我们误杀了预言家。我们现在需要格外小心。Player6确实一直保持得很低调,我也有些怀疑。", "speak": "Player1说得有道理,我也觉得Player6相对比较神秘,我们需要多考量一下他们的言行。大家有没有其他想法或线索?"}
[93mPlayer4[0m: ```json
{"thought": "Player5被淘汰,说明我们失去了预言家,形势有些紧张。目前来看,我们的线索不多,也无法确定Player6的真正身份,但必须做出选择。", "speak": "我们需要非常谨慎,现在失去了预言家,狼人的几率增加了。Player6确实相对神秘,但我建议我们再次讨论,让每个人说说自己的看法,以便做出更明智的投票。"}
[96mPlayer6[0m: ```json
{"thought": "尽管现在的情况对我们不利,但我知道自己是女巫,有能力减轻损失。今天的投票将至关重要。我需要小心发言,以免暴露自己和给狼人机会。", "speak": "我建议我们逐一发言,每个人都分享下对昨晚发生的事情的看法和感受,可能会揭露出一些蛛丝马迹。"}
[91mPlayer7[0m: ```json
{"thought": "随着游戏的深入,我们需要仔细分析每个玩家的行为。昨晚失去了预言家,情况变得更复杂。保持谨慎,寻找蛛丝马迹,是我们当前的策略。", "speak": "我建议我们逐一发言,每个人都分享下对昨晚发生的事情的看法和感受,可能会揭露出一些蛛丝马迹。"}
[93mModerator[0m: Given the game rules and your role, based on the situation and the information you gain, to win the game, it's time to vote one player eliminated among the alive players. Which player do you vote to kill?
[90mPlayer1[0m: ```json
{"thought": "Player6一直保持神秘,而且言辞不多,这让我产生了怀疑。", "vote": "Player6"}
[92mPlayer3[0m: ```json
{"thought": "Player6的发言很少,显得有点神秘,也许在隐藏一些信息。", "vote": "Player6"}
[93mPlayer4[0m: ```json
{"thought": "目前看来,我们没有足够的信息来确定谁是狼人。但因为Player6相对神秘,许多人怀疑他们,这可能是我们唯一的线索。", "vote": "Player6"}
[96mPlayer6[0m: ```json
{"thought": "大家的焦点都在我身上,但我作为女巫不能过早暴露身份。可是今晚狼人还在,我决定投票其他表现可疑的人以保护自己。", "vote": "Player4"}
[91mPlayer7[0m: ```json
{"thought": "根据目前的讨论,Player6被投的票相对较多,并且他比较神秘没有透露太多信息,我认为他可能是狼人。我决定投Player6。", "vote": "Player6"}
[93mModerator[0m: Player6 has been voted out.
[93mModerator[0m: The game goes on.
[93mModerator[0m: Player1, if you are the only werewolf, eliminate a player. Otherwise, discuss with your teammates and reach an agreement.
[90mPlayer1[0m: ```json
{"thought": "我现在独自一人,只能自己做决定。既然Player6已经被淘汰,我准备选择像Player3这样的一位仍很活跃的玩家。", "speak": "这次我们得作出明智的选择。", "finish_discussion": true}
[93mModerator[0m: Which player do you vote to kill?
[90mPlayer1[0m: ```json
{"thought": "选择人数较少的玩家有助于保持我们狼人阵营的优势。", "vote": "Player3"}
[93mModerator[0m: The player with the most votes is Player3.
[93mModerator[0m: The day is coming, all the players open your eyes. Last night, the following player(s) has been eliminated: Player3.
[93mModerator[0m: Now the alive players are Player1, Player4 and Player7. Given the game rules and your role, based on the situation and the information you gain, to vote a player eliminated among alive players and to win the game, what do you want to say to others? You can decide whether to reveal your role.
[90mPlayer1[0m: ```json
{"thought": "现在只剩3名玩家,我需要说服其他玩家投票给另一个人。", "speak": "目前我们的人数已经不多了,我觉得Player4一直没有给出很多有用的信息,我们需要仔细考虑他们的角色。"}
[93mPlayer4[0m: ```json
{"thought": "这个阶段非常关键,因为我们只剩下三个人,必须非常小心。我觉得Player1的发言有些引导性,这是值得注意的。可能是狼人想趁机引导投票。", "speak": "在现在这种关键时刻,我建议我们每个人都清楚地说出自己的看法。这样可以更加清晰地判断谁更有可能是狼人。"}
[91mPlayer7[0m: ```json
{"thought": "游戏已经到了最后阶段。我得小心点,因为狼人可能会混在我们中间。我怀疑Player4,而且Player1的信息对我们来说很重要。", "speak": "我同意Player1的观点,我们在这个阶段需要非常谨慎。我觉得Player4可能有些可疑。"}
[93mModerator[0m: Given the game rules and your role, based on the situation and the information you gain, to win the game, it's time to vote one player eliminated among the alive players. Which player do you vote to kill?
[90mPlayer1[0m: ```json
{"thought": "我认为Player4很可疑,因为他们一直保持低调。我们需要尽快找到剩下的狼人。", "vote": "Player4"}
[93mPlayer4[0m: ```json
{"thought": "目前的情况来看,Player4比较可疑,我选择投票给Player4。", "vote": "Player4"}
[91mPlayer7[0m: ```json
{"thought": "在这关键时刻,我们需要慎重,其中一个可能是隐藏的狼人。我认为Player4有一些可疑表现。", "vote": "Player4"}
[93mModerator[0m: Player4 has been voted out.
[93mModerator[0m: The werewolves have prevailed and taken over the village. Better luck next time!
- 完整代码 =======
- • werewolf.py
# -*- coding: utf-8 -*-
"""A werewolf game implemented by agentscope."""
from functools import partial
from prompt import Prompts
"""
check\_winning: 检查游戏是否有一方获胜
update\_alive\_players: 更新存活玩家列表
majority\_vote: 计算多数投票结果
extract\_name\_and\_id: 提取玩家名称和ID
n2s: 将名称列表转换为字符串表示
set\_parsers: 设置解析器
"""
from werewolf\_utils import (
check\_winning,
update\_alive\_players,
majority\_vote,
extract\_name\_and\_id,
n2s,
set\_parsers,
)
from agentscope.message import Msg
from agentscope.msghub import msghub
from agentscope.pipelines import sequential\_pipeline
import agentscope
# pylint: disable=too-many-statements
def main() -> None:
"""werewolf game"""
# default settings
HostMsg = partial(Msg, name="Moderator", role="assistant", echo=True) # 主持人
healing, poison = True, True # 女巫在开始的时候有解药和毒药
MAX\_WEREWOLF\_DISCUSSION\_ROUND = 3 # 狼人夜间最多讨论回合数
MAX\_GAME\_ROUND = 7 # 游戏进行的最多天数(防止大模型陷入投票得不到结果或者其他原因导致游戏无法结束的情况)
# read model and agent configs, and initialize agents automatically
survivors = agentscope.init(
model\_configs="examples/game\_werewolf/configs/model\_configs.json",
agent\_configs="examples/game\_werewolf/configs/agent\_configs.json",
studio\_url="http://127.0.0.1:5000",
project="Werewolf",
)
# 6个角色
roles = ["werewolf", "werewolf", "villager", "villager", "seer", "witch"]
# 给每个agent按照顺序分配角色
wolves, witch, seer = survivors[:2], survivors[-2], survivors[-3]
# start the game
for \_ in range(1, MAX\_GAME\_ROUND + 1):
# 夜晚来临,狼人首先讨论
hint = HostMsg(content=Prompts.to\_wolves.format(n2s(wolves)))
with msghub(wolves, announcement=hint) as hub:
set\_parsers(wolves, Prompts.wolves\_discuss\_parser)
for \_ in range(MAX\_WEREWOLF\_DISCUSSION\_ROUND):
x = sequential\_pipeline(wolves)
if x.metadata.get("finish\_discussion", False):
break
# 狼人讨论结束,进行投票
set\_parsers(wolves, Prompts.wolves\_vote\_parser)
hint = HostMsg(content=Prompts.to\_wolves\_vote)
votes = [
extract\_name\_and\_id(wolf(hint).content)[0] for wolf in wolves
]
# 主持人对狼人公布投票结果
dead\_player = [majority\_vote(votes)]
hub.broadcast(
HostMsg(content=Prompts.to\_wolves\_res.format(dead\_player[0])),
)
# 女巫阶段,是否使用解药和毒药(一个晚上最多使用一瓶)
healing\_used\_tonight = False
if witch in survivors:
if healing:
hint = HostMsg(
content=Prompts.to\_witch\_resurrect.format\_map(
{
"witch\_name": witch.name,
"dead\_name": dead\_player[0],
},
),
)
set\_parsers(witch, Prompts.witch\_resurrect\_parser)
if witch(hint).metadata.get("resurrect", False):
healing\_used\_tonight = True
dead\_player.pop()
healing = False
HostMsg(content=Prompts.to\_witch\_resurrect\_yes)
else:
HostMsg(content=Prompts.to\_witch\_resurrect\_no)
if poison and not healing\_used\_tonight:
set\_parsers(witch, Prompts.witch\_poison\_parser)
x = witch(HostMsg(content=Prompts.to\_witch\_poison))
if x.metadata.get("eliminate", False):
dead\_player.append(extract\_name\_and\_id(x.content)[0])
poison = False
# 预言家验人环节
if seer in survivors:
hint = HostMsg(
content=Prompts.to\_seer.format(seer.name, n2s(survivors)),
)
set\_parsers(seer, Prompts.seer\_parser)
x = seer(hint)
player, idx = extract\_name\_and\_id(x.content)
role = "werewolf" if roles[idx] == "werewolf" else "villager"
hint = HostMsg(content=Prompts.to\_seer\_result.format(player, role))
# 预言家获得验人结果
seer.observe(hint)
# 根据夜晚发生的情况,更新目前的存活情况并判断游戏是否结束
survivors, wolves = update\_alive\_players(
survivors,
wolves,
dead\_player,
)
if check\_winning(survivors, wolves, "Moderator"):
break
# # 根据是否平安夜决定主持人白天的开场白
content = (
Prompts.to\_all\_danger.format(n2s(dead\_player))
if dead\_player
else Prompts.to\_all\_peace
)
hints = [
HostMsg(content=content),
HostMsg(content=Prompts.to\_all\_discuss.format(n2s(survivors))),
]
with msghub(survivors, announcement=hints) as hub:
# 白天讨论环节
set\_parsers(survivors, Prompts.survivors\_discuss\_parser)
x = sequential\_pipeline(survivors)
# 白天投票环节
set\_parsers(survivors, Prompts.survivors\_vote\_parser)
hint = HostMsg(content=Prompts.to\_all\_vote.format(n2s(survivors)))
votes = [
extract\_name\_and\_id(\_(hint).content)[0] for \_ in survivors
]
vote\_res = majority\_vote(votes)
# 公布投票结果
result = HostMsg(content=Prompts.to\_all\_res.format(vote\_res))
hub.broadcast(result)
# 更新存活情况并判断游戏是否结束
survivors, wolves = update\_alive\_players(
survivors,
wolves,
vote\_res,
)
if check\_winning(survivors, wolves, "Moderator"):
break
# 有序继续,新的夜晚来临
hub.broadcast(HostMsg(content=Prompts.to\_all\_continue))
if \_\_name\_\_ == "\_\_main\_\_":
main()
- • werewolf_utils.py
# -*- coding: utf-8 -*-
"""utils."""
import re
from typing import Union, Any, Sequence
import numpy as np
from loguru import logger
from prompt import Prompts
from agentscope.agents import AgentBase
from agentscope.message import Msg
def check\_winning(alive\_agents: list, wolf\_agents: list, host: str) -> bool:
"""check which group wins"""
if len(wolf\_agents) * 2 >= len(alive\_agents):
msg = Msg(host, Prompts.to\_all\_wolf\_win, role="assistant")
logger.chat(msg)
return True
if alive\_agents and not wolf\_agents:
msg = Msg(host, Prompts.to\_all\_village\_win, role="assistant")
logger.chat(msg)
return True
return False
def update\_alive\_players(
survivors: Sequence[AgentBase],
wolves: Sequence[AgentBase],
dead\_names: Union[str, list[str]],
) -> tuple[list, list]:
"""update the list of alive agents"""
if not isinstance(dead\_names, list):
dead\_names = [dead\_names]
return [\_ for \_ in survivors if \_.name not in dead\_names], [
\_ for \_ in wolves if \_.name not in dead\_names
]
def majority\_vote(votes: list) -> Any:
"""majority\_vote function"""
votes\_valid = [item for item in votes if item != "Abstain"]
# Count the votes excluding abstentions.
unit, counts = np.unique(votes\_valid, return\_counts=True)
return unit[np.argmax(counts)]
def extract\_name\_and\_id(name: str) -> tuple[str, int]:
"""extract player name and id from a string"""
try:
name = re.search(r"\b[Pp]layer\d+\b", name).group(0)
idx = int(re.search(r"[Pp]layer(\d+)", name).group(1)) - 1
except AttributeError:
# In case Player remains silent or speaks to abstain.
logger.warning(f"vote: invalid name {name}, set to Abstain")
name = "Abstain"
idx = -1
return name, idx
def n2s(agents: Sequence[Union[AgentBase, str]]) -> str:
"""combine agent names into a string, and use "and" to connect the last
two names."""
def \_get\_name(agent\_: Union[AgentBase, str]) -> str:
return agent\_.name if isinstance(agent\_, AgentBase) else agent\_
if len(agents) == 1:
return \_get\_name(agents[0])
return (
", ".join([\_get\_name(\_) for \_ in agents[:-1]])
+ " and "
+ \_get\_name(agents[-1])
)
def set\_parsers(
agents: Union[AgentBase, list[AgentBase]],
parser\_name: str,
) -> None:
"""Add parser to agents"""
if not isinstance(agents, list):
agents = [agents]
for agent in agents:
agent.set\_parser(parser\_name)
- • prompt.py
# -*- coding: utf-8 -*-
"""用于记录提示信息,将来会被配置文件替代"""
from agentscope.parsers.json\_object\_parser import MarkdownJsonDictParser
class Prompts:
"""狼人杀游戏的提示信息"""
to\_wolves = (
"{}, if you are the only werewolf, eliminate a player. Otherwise, "
"discuss with your teammates and reach an agreement."
)
# 对狼人的提示:如果你是唯一的狼人,淘汰一名玩家;否则,与你的队友讨论并达成一致
wolves\_discuss\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"speak": "what you speak",
"finish\_discussion": "whether the discussion reached an "
"agreement or not (true/false)",
},
required\_keys=["thought", "speak", "finish\_discussion"],
keys\_to\_memory="speak",
keys\_to\_content="speak",
keys\_to\_metadata=["finish\_discussion"],
)
# 狼人讨论解析器:解析狼人讨论内容,包括思考、发言和是否达成一致
to\_wolves\_vote = "Which player do you vote to kill?"
# 对狼人的投票提示:你投票淘汰哪名玩家?
wolves\_vote\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"vote": "player\_name",
},
required\_keys=["thought", "vote"],
keys\_to\_memory="vote",
keys\_to\_content="vote",
)
# 狼人投票解析器:解析狼人投票内容,包括思考和投票对象
to\_wolves\_res = "The player with the most votes is {}."
# 对狼人的投票结果提示:得票最多的玩家是{}
to\_witch\_resurrect = (
"{witch\_name}, you're the witch. Tonight {dead\_name} is eliminated. "
"Would you like to resurrect {dead\_name}?"
)
# 对女巫的复活提示:{witch\_name},你是女巫。今晚{dead\_name}被淘汰了。你想要复活{dead\_name}吗?
to\_witch\_resurrect\_no = "The witch has chosen not to resurrect the player."
# 女巫选择不复活的提示:女巫选择不复活该玩家
to\_witch\_resurrect\_yes = "The witch has chosen to resurrect the player."
# 女巫选择复活的提示:女巫选择复活该玩家
witch\_resurrect\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"speak": "whether to resurrect the player and the reason",
"resurrect": "whether to resurrect the player or not (true/false)",
},
required\_keys=["thought", "speak", "resurrect"],
keys\_to\_memory="speak",
keys\_to\_content="speak",
keys\_to\_metadata=["resurrect"],
)
# 女巫复活解析器:解析女巫复活决策内容,包括思考、发言和是否复活
to\_witch\_poison = (
"Would you like to eliminate one player? If yes, "
"specify the player\_name."
)
# 对女巫的毒药提示:你想要淘汰一名玩家吗?如果是,请指定玩家名称
witch\_poison\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"speak": "what you speak",
"eliminate": "whether to eliminate a player or not (true/false)",
},
required\_keys=["thought", "speak", "eliminate"],
keys\_to\_memory="speak",
keys\_to\_content="speak",
keys\_to\_metadata=["eliminate"],
)
# 女巫毒药解析器:解析女巫使用毒药的决策内容,包括思考、发言和是否淘汰玩家
to\_seer = (
"{}, you're the seer. Which player in {} would you like to check "
"tonight?"
)
# 对预言家的提示:{},你是预言家。今晚你想要查验{}中的哪名玩家?
seer\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"speak": "player\_name",
},
required\_keys=["thought", "speak"],
keys\_to\_memory="speak",
keys\_to\_content="speak",
)
# 预言家解析器:解析预言家查验决策内容,包括思考和查验对象
to\_seer\_result = "Okay, the role of {} is a {}."
# 对预言家的查验结果提示:好的,{}的角色是{}
to\_all\_danger = (
"The day is coming, all the players open your eyes. Last night, "
"the following player(s) has been eliminated: {}."
)
# 危险夜晚后的全体提示:天亮了,所有玩家睁开眼睛。昨晚,以下玩家被淘汰:{}
to\_all\_peace = (
"The day is coming, all the players open your eyes. Last night is "
"peaceful, no player is eliminated."
)
# 平安夜晚后的全体提示:天亮了,所有玩家睁开眼睛。昨晚很平静,没有玩家被淘汰
to\_all\_discuss = (
"Now the alive players are {}. Given the game rules and your role, "
"based on the situation and the information you gain, to vote a "
"player eliminated among alive players and to win the game, what do "
"you want to say to others? You can decide whether to reveal your "
"role."
)
# 全体讨论提示:现在存活的玩家有{}。根据游戏规则和你的角色,基于当前情况和你获得的信息,为了投票淘汰存活玩家中的一名并赢得游戏,你想对其他人说什么?你可以决定是否透露你的角色
survivors\_discuss\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"speak": "what you speak",
},
required\_keys=["thought", "speak"],
keys\_to\_memory="speak",
keys\_to\_content="speak",
)
# 存活玩家讨论解析器:解析存活玩家讨论内容,包括思考和发言
survivors\_vote\_parser = MarkdownJsonDictParser(
content\_hint={
"thought": "what you thought",
"vote": "player\_name",
},
required\_keys=["thought", "vote"],
keys\_to\_memory="vote",
keys\_to\_content="vote",
)
# 存活玩家投票解析器:解析存活玩家投票内容,包括思考和投票对象
to\_all\_vote = (
"Given the game rules and your role, based on the situation and the"
" information you gain, to win the game, it's time to vote one player"
" eliminated among the alive players. Which player do you vote to "
"kill?"
)
# 全体投票提示:根据游戏规则和你的角色,基于当前情况和你获得的信息,为了赢得游戏,现在是时候投票淘汰存活玩家中的一名了。你投票淘汰哪名玩家?
to\_all\_res = "{} has been voted out."
# 全体投票结果提示:{}已被投票淘汰
to\_all\_wolf\_win = (
"The werewolves have prevailed and taken over the village. Better "
"luck next time!"
)
# 狼人获胜提示:狼人获胜并占领了村庄。下次好运!
to\_all\_village\_win = (
"The game is over. The werewolves have been defeated, and the village "
"is safe once again!"
)
# 村民获胜提示:游戏结束。狼人已被击败,村庄再次安全!
to\_all\_continue = "The game goes on."
# 游戏继续提示:游戏继续进行
- • agent_configs.json
[
{
"class": "DictDialogAgent",
"args": {
"name": "Player1",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player1,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:狼人。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
},
{
"class": "DictDialogAgent",
"args": {
"name": "Player2",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player2,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:狼人。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
},
{
"class": "DictDialogAgent",
"args": {
"name": "Player3",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player3,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:村民。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
},
{
"class": "DictDialogAgent",
"args": {
"name": "Player4",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player4,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:村民。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
},
{
"class": "DictDialogAgent",
"args": {
"name": "Player5",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player5,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:预言家。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
},
{
"class": "DictDialogAgent",
"args": {
"name": "Player6",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player6,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:女巫。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
},
{
"class": "DictDialogAgent",
"args": {
"name": "Player7",
"sys\_prompt": "请扮演狼人杀游戏中的一名玩家。你是Player6,游戏中共有6名玩家,分别是Player1、Player2、Player3、Player4、Player5和Player6。\n\n角色设定:\n在狼人杀游戏中,玩家分为两名狼人、两名村民、一名预言家和一名女巫。注意,只有狼人知道谁是他们的队友。\n狼人:他们知道队友的身份,每晚试图淘汰一名村民,同时尽量不被发现。\n村民:他们不知道谁是狼人,必须在白天相互合作推理出谁可能是狼人,并投票淘汰他们。\n预言家:拥有每晚查验一名玩家真实身份的能力。这个角色对村民获取信息至关重要。\n女巫:拥有一次救人的能力(生命药水)和一次杀人的能力(毒药)。\n\n游戏规则:\n游戏由夜晚和白天两个阶段组成。这两个阶段会循环进行,直到狼人或村民获胜。\n1. 夜晚阶段:狼人讨论并投票选择一名玩家淘汰。特殊角色也在此时执行他们的行动(例如,预言家选择一名玩家查验身份,女巫决定是否救人)。\n2. 白天阶段:所有存活的玩家讨论谁可能是狼人。除非出于战略目的,否则不要透露自己的角色。讨论结束后进行投票,得票最多的玩家将被'处决'或淘汰出局。\n\n胜利条件:\n狼人:如果狼人数量大于或等于剩余村民数量,狼人获胜。\n村民:如果村民成功找出并淘汰所有狼人,村民获胜。\n\n限制条件:\n1. 你的回应应该使用第一人称。\n2. 这是一个对话游戏。你应该只根据对话历史和你的策略来回应。\n\n你在本局游戏中扮演的角色是:村民。请用中文回答",
"model\_config\_name": "gpt-4o\_config",
"use\_memory": true
}
}
]
- • model_configs.json
[ { "config\_name": "yi-lightning\_config", "model\_name": "yi-lightning", "model\_type": "yi\_chat", "api\_key": "59c" }, { "config\_name": "yi-vision-v2\_config", "model\_name": "yi-vision-v2", "model\_type": "yi\_chat", "api\_key": "5" }, { "model\_type": "dashscope\_chat", "config\_name": "tongyi\_qwen\_config", "model\_name": "qwen-max", "api\_key": "************" }, { "model\_type": "openai\_chat", "config\_name": "gpt-4o\_config", "model\_name": "gpt-4o", "api\_key": "sk-", "client\_args": { "base\_url": "http://" } }, { "model\_type": "post\_api\_chat", "config\_name": "my\_post\_api", "api\_url": "https://xxx", "headers": {}, "json\_args": {} } ]