返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

全网爆火的AI狼人杀:开源了

[复制链接]
链载Ai 显示全部楼层 发表于 前天 10:01 |阅读模式 打印 上一主题 下一主题

近期网上疯狂流传了一个人类与AI参与的VR狼人杀游戏,十分有趣。通过对游戏内容的分析,我发现游戏VR的表现形式十分吸引人,但其中的AI对话部分并不复杂。于是小智使用LangGraph实现了一个文字版本,今天将代码开源(文末获取),希望大家能喜欢。

AI狼人杀,人类一败涂地

首先给没看过视频的小伙伴们介绍下:

一个名为 Tore Knabe 的网友在 X 平台发布了一个视频,展示了一个有趣的实验:

这是一次反向图灵测试,几个全球最先进的大模型坐在一起,坐着火车唱着歌,但其中混进了人类:

参与者扮演历史知名人物,古希腊巨哲 —— 亚里士多德(GPT4 Turbo),维也纳古典乐派代表人物 —— 莫扎特(Claude3 Opus),意大利文艺复兴时期画家 —— 列奥纳多・达・芬奇(Llama3),埃及艳后 —— 克利奥帕特拉七世(Gemini Pro)。其中蒙古军事家 —— 成吉思汗由人类扮演。

游戏规则要求,参与者通过提问和回答来分辨人类与 AI,最后通过投票确定谁是人类。

人类扮演者因缺乏深度和逻辑性的回答,在第一轮的投票中就被3票淘汰,人类一败涂地

代码实现

接下来,我们来看看如何用LangGraph把这个游戏做出来吧!

游戏过程

游戏的过程很简单,主要包括以下三个环节。小智使用主持人Agent来将整个流程串起来。

  • 第一环节:提问与回答,各个游戏角色之间进行互相提问,并回复问题。
defask_for_speak(state:GameState):
#如果待发言池为空,则进入投票阶段
iflen(state['waiting'])==0:
state['waiting']=state['roles'].copy()
state['stage']='vote'
print(f"主持人:游戏结束,请进行投票。请大家耐心等待投票结果!")
returnask_for_vote(state)
chat_history=state['chat_history']
last_chat=chat_history[-1]
last_chat_str=last_chat[0]+':'+last_chat[1]
waiting_roles_str=','.join(state['waiting'])
llm=ChatOpenAI(model="glm-4",temperature=0.01)
choose_prompt=ChatPromptTemplate.from_template(load_prompt("prompt/choose_speaker.prompt"))
chain=choose_prompt|llm|StrOutputParser()
role_chosen=chain.invoke({"history":last_chat_str,"waitings":waiting_roles_str})
ifrole_choseninstate['waiting']:
state['waiting'].remove(role_chosen)
state['next_speaker']=role_chosen
else:
next=random.choice(state['waiting'])
state['next_speaker']=next
state['waiting'].remove(next)
returnstate
  • 第二环节:投票:在所有角色依次发言后,玩家将根据之前的互动和提问环节的表现,进行相互投票以确定谁是人类。
defask_for_vote(state:GameState):
iflen(state['waiting'])==0:
human_role=state['human_role']
round=state['round']
#统计票数决定是否结束游戏
vote_store=state['vote_store']
human_vote_count=0
forvoteinvote_store:
vote_role=vote[1]['vote']
ifvote_role==human_role:
human_vote_count+=1
totle_votes=len(state['roles'])
#如果人类角色票数超过一半,结束游戏
ifhuman_vote_count>totle_votes/2:
state['stage']='end'
print("AIwin!")
print("投票详情如下:"+json.dumps(vote_store,ensure_ascii=False))
elifround==3:
state['stage']='end'
print("Human存活超过3轮,Humanwin!")
else:
print("Human存活,游戏继续!")
print("上轮投票详情如下:"+json.dumps(vote_store,ensure_ascii=False))
state=gen_and_dispatch_role(state)
returnstate
next=random.choice(state['waiting'])
state['next_speaker']=next
state['waiting'].remove(next)
returnstate
  • 最后:结果揭晓,基于投票判断人类扮演者是否被发现。

游戏角色

有了主持人Agent控场,那么其他角色就很好设计了,由于AI除了扮演角色不一样外,所执行的逻辑是一致的,我们可以统一抽象为AI角色扮演Agent,再就是用于人类输出的人类Agent

  • AI角色扮演Agent:由四个AI NPC扮演历史知名人物,发表演讲,并在投票阶段进行投票。
defspeak(state:GameState):
role=state['next_speaker']
roles_str=','.join(state['roles'])
chat_history=state['chat_history']
history=""
forchatinchat_history:
history+=f"{chat[0]}:{chat[1]}\n"
llm=ChatOpenAI(model="glm-4",temperature=0.8)
role_prompt=ChatPromptTemplate.from_template(load_prompt("prompt/role.prompt"))
chain=role_prompt|llm|StrOutputParser()
rsp=chain.stream({"role":role,"roles":roles_str,"history":history})
output=''
print(role+':',end='',flush=True)
fortokeninrsp:
output+=token
print(token,end='',flush=True)
print()
print("---------------------------")
state['chat_history'].append((role,output))
returnstate

defvote(state:GameState):
role=state['next_speaker']
roles_str=','.join(state['roles'])
chat_history=state['chat_history']
history=""
forchatinchat_history:
history+=f"{chat[0]}:{chat[1]}\n"
llm=ChatOpenAI(model="glm-4",temperature=0.01)
vote_prompt=ChatPromptTemplate.from_template(load_prompt("prompt/vote.prompt"))
chain=vote_prompt|llm|JsonOutputParser()
output=chain.invoke({"role":role,"roles":roles_str,"history":history})
state['vote_store'].append((role,output))
returnstate
  • 人类Agent : 人类Agent的逻辑相比AI更加简单只需要在恰当的阶段,提示人类玩家进行输出。
defspeak(state:GameState):
role=state['next_speaker']
print("你当前的角色是:"+role)
user_input=input("请输入你的对话内容:")
state['chat_history'].append((role,user_input))
returnstate

defvote(state:GameState):
role=state['next_speaker']
roles_str=','.join(state['roles'])
print("你当前的角色是:"+role)
print("可供投票的选项有:"+roles_str)
user_vote=input("请输入你的投票选择:")
user_reason=input("请输入你的投票原因:")
state['vote_store'].append((role,{"vote":user_vote,"reason":user_reason}))
returnstate

实现效果及完整代码

最终实现效果如下所示

游戏的完整代码已上传github开源,感兴趣的小伙伴可以拉取到自己本地玩一玩:https://github.com/q2wxec/langgraph-demo/tree/master/werewolf

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ