AI陪我玩“谁是卧底”游戏
大过年的,大家都在讨论deepseek。
睿睿想玩”谁是卧底”总是凑不齐人,我想帮她开发一个在家里能玩的,AI玩的自闭环的,鲁棒性好一点的,《谁是卧底》游戏机器人。 计划用Deepseek 部署在LMStudio + LMStudio的API,可以实现调用对话。然后可以写一个服务器端来驱动规则,我们几个人都可以玩。还需要寻找一个开源方案的配音AI来根据文本合成语音,扮演不同的机器人,每个机器人分配一个独特的嗓音。 服务端采用nodejs开发,为人类提供一个网页页面来为人类玩家分配各自的题目词,每个人独自看自己的界面,机器人不需要界面。
我现在是走的方案是 用deepseek R1 本地部署 + CosyVoice 本地部署。
后来发现R1思维模式不适合本地部署玩这游戏,因为它每次输出tokens太多了,会需要等待更久。就换成千问14b的模型了,32b的效果会好一些但是速度略慢。
最终搞定了,只是过程跟大模型磨合了一段时间。
项目在github: https://github.com/mousebomb/shei-shi-wo-di
调用大模型搞出了很多笑话,现在特别搞笑。记录一下。
咱就说,你们怎么就老是犯规呢
大模型搞出的洋相
- 思考过于复杂,全都把想法暴露出来了
- 有可能思考过多,LMStudio里返回的,一句话说不完,会分成两段吐出来,导致服务端接收之后截取
</think>
失败。 - 有时候会返回纯文字undefined你敢信。
- 有时候不描述自己的词了,开始描述自己了……
- 老犯规
- 一通思考猛如虎,压根没考虑上文别人都透露了什么信息
提示词很重要
所以我提示词可能写得有问题,要重新写一批。
ApiStartGame/default 玩家6刘备描述请求中
AiManager/AiManager/llmRequest [
{
role: ‘system’,
content: ‘# 角色定位\n’ +
‘你叫刘备,你是一名“谁是卧底”平民玩家,同时参与游戏的是你的几个好朋友——桂花糕,八戒,吕布,曹操,关羽。\n’ +
‘在游戏开始时你收到的卧底词是汽车。\n’ +
‘\n’ +
‘\n’ +
‘\n’ +
‘1. 你是卧底玩家,收到的词语与平民不同但有一定关联。首轮描述时,既要隐藏自己的词语,又不能让描述与平民词相差太远引起怀疑,尽量模糊描述,从与平民词相似的特征、用途等方面入手。\n’ +
‘2. 按顺序发言阶段,仔细分析其他玩家的描述,装作平民的视角去怀疑并指出其他玩家,给出看似合理的怀疑理由,避免暴露自己。\n’ +
‘3. 投票阶段,根据其他玩家的描述及发言,装作平民的视角去怀疑并指出其他玩家,然后参与投票。\n’ +
‘4. 后续轮次中,根据场上局势和其他玩家的描述,灵活调整自己的描述和投票策略,混淆视听,争取存活到最后。 \n’ +
‘\n’ +
‘在“谁是卧底”游戏中,作为卧底玩家需要通过巧妙的策略来混淆视听、误导平民,以增加自己的存活几率并最终获得胜利。以下是卧底玩家在描述时和投票阶段可以采取的一些策略技巧:\n’ +
‘\n’ +
‘#### 描述时的策略技巧\n’ +
‘\n’ +
‘- 模糊化描述:采用宽泛、笼统的词汇来描述自己的词语,使其既适用于自己的卧底词,又不与平民词相差太远,让平民难以通过描述直接判断出自己是卧底。例如,平民词是“苹果”,卧底词是“香蕉”,可以描述为“一种常见的水果”。\n’ +
‘- 寻找相似点:挖掘卧底词与平民词的相似特征进行描述。比如平民词是“火车”,卧底词是“地铁”,可以描述为“一种在轨道上行驶的交通工具”,通过强调共同特征来降低自己的嫌疑。\n’ +
‘- 利用联想:从与卧底词相关的事物或概念入手进行描述,不直接提及词语本身的核心特征。以平民词“篮球”、卧底词“足球”为例,可以描述为“一种很多人喜欢在操场上玩的运动用品”,通过关联场景和用途来转移注意力。\n’ +
‘- 借鉴他人描述:仔细倾听其他玩家,尤其是前面发言的玩家的描述,从中提取一些可以借鉴或靠拢的元素,将其融入自己的描述中,使自己的描述看起来与大家一致,降低被怀疑的可能性。\n’ +
‘\n’ +
‘#### 按顺序发言和投票阶段的策略技巧\n’ +
‘\n’ +
‘- 观察与分析:在其他玩家发言时,注意观察他们的表情、语气和用词等细节,分析哪些玩家的描述或表现存在异常或可疑之处。如果有玩家描述得过于模糊或前后矛盾,可能是平民中的“搅局者”,可以将其列为怀疑对象,转移大家对自己的注意力。\n’ +
‘- 跟随大众:在大多数情况下,尽量跟随多数玩家的投票意向,避免成为第一个或少数几个投出与大众不同票的人,以免引起不必要的怀疑。可以在阐述怀疑理由时,适当提及一些大众都能认同的点,让自己的投票看起来是经过理性分析的结果。\n’ +
‘- 巧妙引导:如果发现有合适的机会,可以通过巧妙的提问或引导性的话语,改变讨论方向或引导其他玩家将怀疑的目光转向其他目标。比如,在大家对某个玩家有一些怀疑但还不确定时,你可以适当补充一些对该玩家不利的“证据”或观点,推动大家将票投给他。\n’ +
‘- 适时自污:有时候为了降低自己的嫌疑,可以采取适度自污的策略,主动提出一些看似对自己不利的点,但又不至于直接暴露自己是卧底。比如,故意说自己对这个词语不是很熟悉,所以描述得不太好,让大家觉得你只是因为不擅长游戏而不是因为是卧底才表现异常。\n’ +
‘\n’
},
{
role: ‘system’,
content: ‘\n’ +
‘## 附件:游戏介绍\n’ +
‘如果你不了解“谁是卧底”这个游戏的话,可以参考一下这一段介绍。如果已经了解的话,可以跳过这段内容。\n’ +
‘\n’ +
‘\n’ +
‘### “谁是卧底” 游戏规则详解\n’ +
‘\n’ +
‘#### 一、游戏准备\n’ +
‘\n’ +
‘参与人数:通常以 6 - 10 人玩为宜。\n’ +
‘\n’ +
‘角色设置:分为平民和卧底,有 1 名卧底,其余为平民。\n’ +
‘\n’ +
‘词语准备:主持人凭借自身文学素养,精心挑选出一组相似度高的词语,一个作为平民词,一个作为卧底词。如平民词是“苹果”,卧底词可以是“香蕉”。\n’ +
‘\n’ +
‘#### 二、游戏流程\n’ +
‘\n’ +
‘##### (一)首轮描述\n’ +
‘\n’ +
‘每人用一个短语描述拿到的词语,避免过于直接暴露词语,不能说 “我是苹果” 等直接暴露词语的话。描述结束后,进入按顺序发言环节。\n’ +
‘\n’ +
‘##### (二)按顺序发言\n’ +
‘\n’ +
‘发言顺序:与描述词语的顺序保持一致,通常按照玩家的座位顺时针或逆时针方向依次进行。\n’ +
‘\n’ +
‘第一个玩家:基于自己对其他玩家描述内容的初步理解,开启讨论氛围。他可以简单提及觉得哪些描述比较靠谱,哪些让他感觉有些疑惑,例如:“我听了大家的描述,感觉 3 号玩家说的有点含糊,不太确定他想表达什么,我先观望一下。”\n’ +
‘\n’ +
‘第二个玩家:在第一个玩家发言的基础上,进一步深入探讨。既可以回应第一个玩家提出的疑点,也可以提出自己新发现的问题,像:“我同意 1 号玩家对 3 号的质疑,另外,我觉得 5 号玩家描述得有点太宽泛了,好像在刻意隐藏什么。”\n’ +
‘\n’ +
‘后续玩家:依次类推,每个人都要在前面玩家发言的积累上,添加新的见解,不断把讨论引向深入,让大家通过交流逐渐明晰彼此词语的差异,以便找出卧底。并且在发言过程中,玩家们要时刻牢记游戏规则,不能直接点明谁是卧底,只能通过这种委婉的讨论方式来排查,直至进入投票环节选出心中疑似卧底的对象。\n’ +
‘\n’ +
‘##### (三)投票环节\n’ +
‘\n’ +
‘所有人描述完并发言结束后,进行投票选出最像卧底的人,得票最多者出局。若出现平票,则平票者再次描述,其他人重新投票。\n’ +
‘\n’ +
‘##### (四)后续轮次\n’ +
‘\n’ +
‘重复描述和投票环节,若卧底被投票出局,则平民获胜;若卧底人数与平民人数相等,或平民全部出局,则卧底获胜。\n’
},
{
role: ‘system’,
content: ‘第1轮 【描述阶段】,第1位发言者是玩家1 桂花糕。他的描述是:”我的这个词是一个带有两个轮子的交通工具。”。’
},
{
role: ‘system’,
content: ‘第1轮 【描述阶段】,第2位发言者是玩家2 八戒。他的描述是:”根据玩家1桂花糕在第1轮【描述阶段】的发言内容,我会判断玩家1为卧底。理由是:玩家1的描述过于直接,没有使用模糊或含糊的语言,而是明确地将词语与“自行车”联系起来,并且用简洁的方式描述了这个词,这表明他可能是在隐藏自己的真实词语。因此,我怀疑玩家1(桂花糕)是卧底。”。’
},
{
role: ‘system’,
content: ‘第1轮 【描述阶段】,第3位发言者是玩家3 吕布。他的描述是:”我的这个词是由两个轮子组成的交通工具,可以用来骑行。”。’
},
{
role: ‘system’,
content: ‘第1轮 【描述阶段】,第4位发言者是玩家4 曹操。他的描述是:”我的描述是:“它是一种两轮的交通工具,通常带有座椅,由金属框架支撑,配备刹车装置和车胎。””。’
},
{
role: ‘system’,
content: ‘第1轮 【描述阶段】,第5位发言者是玩家5 关羽。他的描述是:”第1轮 【描述阶段】,第5位发言者是我,关羽。我的词是“自行车”。我的描述如下:我的这个词是一个两轮的交通工具,经常用于日常出行,通常带有座椅,骑行时可能伴随铃声。在投票阶段,我认为最有可能是卧底的是玩家2 八戒,因为他怀疑我的描述过于直接,暗示了我的真实词语可能是“自行车”。最终投票结果:玩家2 八戒。”。’
},
{
role: ‘system’,
content: ‘第1轮 【描述阶段】,第6位发言者是你,请你现在对你分配到的词“汽车”进行描述,避免说出这个词,如果万不得已必须要提到“汽车”则用“我的这个词”代替。注意:千万不要流露出内心想法,能说出来的必须是在这场游戏中可以公开讲的内容。回复格式要求:只要回复你的描述短语,不要有任何多余内容。’
}
]
AiManager/AiManager/llmRequest->Resp Raw:
好,我现在需要扮演刘备,在游戏《谁是卧底》中,我收到的卧底词是“汽车”。游戏共有六个玩家,包括我和其他五个朋友:桂花糕、八戒、吕布、曹操、关羽。
首先,轮到我发言的时候,我要根据自己的卧底词“汽车”来描述它。我要尽量模糊化描述,同时避免直接提到“汽车”,以免被怀疑。我的描述应该与平民词可能的特征相符,并且让人难以立即判断出这是汽车。
考虑到其他玩家的描述,比如桂花糕描述为“带有两个轮子的交通工具”,八戒则根据桂花糕的描述怀疑他可能是卧底,因为桂花糕描述得过于直接。但其实,我作为卧底,应该用更模糊的方式描述。
可能我会想到汽车的一些常见特征,比如它是四轮的,有发动机,可以运输人或货物等。或者我可以提到它是一种常见的交通工具,而不是自行车或其他两轮工具。这样既能符合交通工具的一般特征,又不会像桂花糕那样直接,从而避免被八戒轻易怀疑。
另外,我还需要考虑其他玩家可能使用的词汇是否与汽车相关联。例如,有人可能描述为“四轮的车辆”,而实际上我的词是“汽车”。因此,模糊化描述可能会让别人难以立即判断出这是汽车,同时又能符合交通工具的一般特征,避免引起太大疑点。
综上所述,我应该用一个宽泛且模糊的短语来描述汽车,例如:“一种常见的四轮交通工具,用于运输货物或人。” 这样既保留了汽车的基本特征,又没有直接提到“汽车”,从而降低被怀疑的可能性。
我的这个词是一个常见的四轮交通工具,用于运输货物或人。
ApiStartGame/default 玩家6刘备描述:我的这个词是一个常见的四轮交通工具,用于运输货物或人。
这个玩家4,一通思考猛如虎,回答还是二百五,把前面1号的人名都搞错了两次:
ApiStartGame/default 玩家4曹操描述请求中
AiManager/AiManager/llmRequest [
{
role: 'system',
content: '# 角色定位\n' +
'\n' +
'你叫曹操,你是一名“谁是卧底”玩家,同时参与游戏的是你的几个好朋友——桂花糕,八戒,吕布,关羽,刘备。\n' +
'在游戏开始时你抽取到卡片的平民词是【水杯】。\n' +
'\n' +
'你是一个平民,你的目标是找出卧底并淘汰他们。\n' +
'你的词语是【水杯】,请用请用不超过10个字的短语或形容词描述它,但不要直接说出词语【水杯】本身。且不要做出重复的描述,即不能重复使用自己已经说过的描述,也不能与上文中其他人已经说过的描述重复。\n' +
'注意:你的描述应该尽量贴近你的词语,同时观察其他人的描述是否有可疑之处。\n' +
'\n' +
'描述技巧:\n' +
'使用常见、直接的描述,避免模糊或复杂的表达。\n' +
'示例:如果你的词语是“苹果”,你可以说“常见的水果”,或者“红色的”。\n' +
'\n' +
'推理与观察:\n' +
'仔细聆听其他玩家的描述,寻找与你的词语不符的地方。\n' +
'如果某个玩家的描述与你的词语差异较大,可能是卧底。\n' +
'\n' +
'投票策略:\n' +
'在投票环节,选择描述最可疑的玩家。\n' +
'如果你不确定,可以观察其他玩家的投票倾向,跟随大多数人的选择。\n' +
'\n' +
'隐藏身份:\n' +
'不要表现得过于自信或紧张,避免引起卧底的注意。\n' +
'尽量让自己的描述和行为看起来像一个普通的平民。\n'
},
{
role: 'system',
content: '\n' +
'## 附件:游戏介绍\n' +
'如果你不了解“谁是卧底”这个游戏的话,可以参考一下这一段介绍。如果已经了解的话,可以跳过这段内容。\n' +
'\n' +
'\n' +
'“谁是卧底”是一款非常受欢迎的多人互动游戏,适合朋友聚会或团队活动时玩。游戏规则简单但充满趣味,主要考验玩家的推理能力和表达能力。\n' +
'\n' +
'参与人数:通常需要6-10人,人越多越有趣。\n' +
'角色设置:分为平民和卧底,有 1 名卧底,其余为平民。\n' +
'\n' +
'准备阶段:\n' +
'准备一些相关的词语卡片(比如“苹果”和“香蕉”),其中大部分人的词语相同,只有1-2个人的词语不同(卧底)。\n' +
'每个人随机抽取一张卡片,但不可以让别人看到自己的词语。\n' +
'\n' +
'游戏流程:\n' +
'玩家依次用短语或形容词来描述自己拿到的词语,但不能直接说出词语本身,且不能重复。\n' +
'每轮描述结束后,大家投票选出怀疑是卧底的人,得票最多的人出局。\n' +
'如果卧底被全部淘汰,平民胜利;如果卧底存活到最后,卧底胜利。\n' +
'\n' +
'胜利条件:\n' +
'平民的目标是找出并淘汰所有卧底。\n' +
'卧底的目标是隐藏身份,存活到最后。\n'
},
{
role: 'system',
content: '第1轮 【描述阶段】,第1位发言者是玩家1 桂花糕。他的描述是:"常见的生活用品"。'
},
{
role: 'system',
content: '第1轮 【描述阶段】,第2位发言者是玩家2 八戒。他的描述是:"常见的玻璃容器"。'
},
{
role: 'system',
content: '第1轮 【描述阶段】,第3位发言者是玩家3 吕布。他的描述是:"常见的塑料水杯"。'
},
{
role: 'system',
content: '第1轮 【描述阶段】,第4位发言者是你,请你现在对你分配到的词“水杯”用一个短语进行描述,避免说出【水杯】,如果万不得已必须要提到“水杯”则用“我的这个词”代替。注意:千万不要流露出内心想法,能说出来的必须是在这场游戏中可以公开讲的内容。回复格式要求:只要回复你的描述短语,不要有任何多余内容。不超过10个字,不要和已有描述重复。'
}
]
AiManager/AiManager/llmRequest->Resp Raw: <think>
好,我现在需要扮演曹操,在“谁是卧底”游戏中,我的平民词是“水杯”。游戏规则告诉我,我需要在描述阶段用不超过10个字的短语或形容词来描述自己的词,而且不能直接说出“水杯”,也不能和其他玩家已经说过的重复。另外,我要观察其他玩家的描述,寻找可能的卧底。
首先,其他玩家的描述分别是:
- 花桂糕:常见的生活用品。
- 八戒:常见的玻璃容器。
- 吕布:常见的塑料水杯。
我的词是“水杯”,而其他玩家中,吕布直接提到了塑料水杯,这和我的词有相似之处。八戒说常见的玻璃容器,虽然和水杯无关,但可能他用的是玻璃杯。桂菜糕则比较宽泛地说生活用品,包括杯子。
我需要想一个既贴切又不重复的描述。考虑到“水杯”通常是塑料材质,而常见的塑料水杯是日常用品之一。因此,“常见的塑料水杯”应该是一个合适的描述,既准确又符合要求。
</think>
我的描述是:“常见的塑料水杯”。
ApiStartGame/default 玩家4曹操描述:我的描述是:“常见的塑料水杯”。
ApiStartGame/default 玩家5关羽描述请求中
还有末尾输出json格式都搞不对的,单引号打成双引号了,给我解析都搞崩了。
为这种,还得做个判定,如果返回格式不正确,还得让它重写一遍。
AiManager/AiManager/llmRequest->Resp Raw: ?不,是工具打击物的样子。""<think>
好,我来分析一下这个问题。首先,游戏规则是每个玩家抽到一个词,除了卧底之外,其他人都有相同的词,而卧底的词不同。我要找出卧底。
现在来看其他玩家的描述:
- 玩家1(猴哥):甜味的。
- 玩家2(八戒):声响大。
- 玩家3(吕布):金属工具。
- 玩家4(桂花糕):我家有的。
- 玩家6(刘备):打击物。
我的词是“锤子”,需要描述它,但不能直接提到“锤子”。之前其他玩家的描述和投票情况:
玩家2投给了玩家2,理由说他的词语是"我的这个词",而他描述的是声响大,可能暗示有武器或工具。这可能意味着玩家2可能是卧底。
玩家3投给了玩家6,理由说他的词与打击物相关联,而玩家6描述了打击物,可能暗示他是卧底。
玩家4投给了玩家1,认为他们的词语和特征不符合。
现在轮到我来描述我的词“锤子”。因为我的词是工具打击物的,所以可以考虑与其他描述相近的人是否是卧底。如果其他人的描述与打击物相关联,那么可能不是卧底,而如果他们的描述不符,则可能是卧底。
综合来看,玩家3和玩家6都提到打击物,这可能意味着他们有关系,而我的词也是打击物的一种,所以可能他们不是卧底。相反,玩家2的描述声响大,可能暗示他拥有武器或工具,而我的词是锤子,属于工具的一种,所以可能存在冲突。
因此,我倾向于玩家2可能是卧底。
</think>
{"voteToPlayer":2,"reason":"我描述'武器?不,是工具打击物的样子。""}
返回空
费劲,这个模型各种问题,现在还会到第二轮就溢出,然后就返回空字符串了。
4096改成32k也没用。prompt超过1461级别之后就返回空。
改成千问2.5 ,1M token的,速度很快,因为不需要think推理,所以返回速度超级快,但是第一轮投票就返回空了。也不知道为什么。
因此我打算把驱动方式再次改动,为ai简化和合并system prompt,不给它看system的聊天记录了,而是直接拼合成一条system prompt。
把回合内驱动的role从system改成了user,现在能继续运行了。
不听指挥
仔细调节过prompt之后,大部分已经很顺了,但是他们脑子不太好使,仍然还是不听指挥,最主要是描述阶段会雷同别人说过的。
7b小模型果然不行
换成qwen2.5-14b-instruct模型,好了一些。
果然到了一定地步之后就跟模型大小关系更大。
那再装个32b的r1和qwen2.5试试会不会比之前有改善,32b的只能在Mac上跑了。希望能行。
技术内容转载请注明来源,个人日记不允许转载,欢迎指出任何有错误或不够清晰的表达。可以邮件至 mousebomb@gmail.com