🌟 项目特点
- 🤖 智能AI:基于文心一言大模型,具有强大的推理能力
- 🎯 实时思考:展示AI的思考过程,让你了解AI是如何推理的
- 🎮 互动性强:通过简单的"是/否"问答,让游戏更加有趣
- 📊 计分系统:记录AI和人类的得分,增加游戏竞技性
- 🎨 精美界面:采用现代化的UI设计,提供流畅的游戏体验
🎯 游戏规则
- 玩家在心中想一个物体
- AI会通过最多20个"是/否"问题来猜测这个物体
- 玩家需要诚实回答每个问题
- 如果AI在20个问题内猜对,AI得1分
- 如果AI没有猜对,人类得1分
- 游戏结束后可以重新开始,继续挑战
💡 特色功能
- 实时思考展示:AI会展示它的思考过程,让你了解它是如何推理的
- 智能问题生成:AI会根据之前的回答,生成更有针对性的问题
- 容错机制:考虑到玩家可能回答错误的情况,AI会进行更全面的推理
- 分数统计:记录游戏得分,增加竞技性
- 轮数显示:清晰显示当前问题轮数,让游戏进度一目了然
🎮 如何开始
- 在输入框中输入你想让AI猜的物体
- 点击"设置目标物体"按钮开始游戏
- 回答AI提出的"是/否"问题
- 等待AI的最终猜测
- 查看结果并开始新的游戏
🎯 游戏技巧
- 选择具体的物体,避免抽象概念
- 诚实回答每个问题
- 观察AI的思考过程,了解它的推理方式
- 尝试选择一些不常见的物体,增加游戏难度
🎨 界面预览
游戏界面采用现代化的设计风格,包含:
- 清晰的游戏标题和说明
- 醒目的轮数计数器
- 实时更新的分数显示
- 优雅的输入框和按钮
- 流畅的动画效果
import os
import gradio as gr
from openai import OpenAI
import time# 初始化OpenAI客户端
client = OpenAI(api_key="填写你的密钥",base_url="https://aistudio.baidu.com/llm/lmapi/v3"
)# 游戏状态
class GameState:def __init__(self):self.questions_asked = 0self.max_questions = 20self.game_history = []self.target_object = Noneself.is_game_over = Falseself.current_question = Noneself.is_game_started = Falseself.ai_score = 0self.human_score = 0game_state = GameState()def stream_response(response, history_text):"""流式输出响应"""full_response = ""for chunk in response:if chunk.choices[0].delta.content:full_response += chunk.choices[0].delta.contentyield full_response, history_textreturn full_response, history_textdef set_target_object(target):"""设置目标物体并开始游戏"""if not target.strip():return "请输入目标物体!", "", "", "0/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""game_state.target_object = target.strip()game_state.is_game_started = Truegame_state.questions_asked = 0game_state.game_history = []game_state.is_game_over = Falsegame_state.current_question = None# 让AI提出第一个问题prompt = """你正在玩20问游戏。请提出第一个问题来猜测玩家心中的物体。
问题应该是一个简单的"是/否"问题,比如"它是活物吗?"、"它比汽车大吗?"等。
请先思考一下,然后只输出问题,不要输出其他内容。"""try:yield "游戏开始!", "\n".join(game_state.game_history), "", "0/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", "AI正在思考第一个问题..."response = client.chat.completions.create(model="ernie-x1-turbo-32k",messages=[{"role": "user", "content": prompt}],temperature=0.7,max_tokens=100,stream=True)first_question = ""thinking_process = "AI正在思考第一个问题...\n\n"for chunk in response:if hasattr(chunk.choices[0].delta, 'reasoning_content') and chunk.choices[0].delta.reasoning_content:thinking_process += chunk.choices[0].delta.reasoning_contentyield "游戏开始!", "\n".join(game_state.game_history), "", "0/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", thinking_processif chunk.choices[0].delta.content:first_question += chunk.choices[0].delta.contentgame_state.current_question = first_question.strip()game_state.game_history.append(f"AI问题 {game_state.questions_asked + 1}: {first_question.strip()}")yield f"游戏开始!\nAI的第一个问题:{first_question.strip()}", "\n".join(game_state.game_history), "", "0/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", thinking_process + "\n\n思考完成!"except Exception as e:yield f"发生错误: {str(e)}", "", "", "0/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""def answer_question(answer):"""处理玩家的回答"""if not game_state.is_game_started:return "请先设置目标物体!", "", "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""if game_state.is_game_over:return "游戏已结束,请开始新游戏!", "", "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""if not answer.strip():return "请输入你的回答!", "", "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""# 记录玩家的回答game_state.game_history.append(f"玩家回答: {answer}")game_state.questions_asked += 1# 如果是最后一轮,让AI进行最终猜测if game_state.questions_asked >= game_state.max_questions:game_state.is_game_over = True# 让AI进行最终猜测guess_prompt = f"""基于之前的对话:
{chr(10).join(game_state.game_history)}这是最后一轮了,请根据所有信息,给出你的最终猜测。
请先分析一下已有的信息,然后给出你的猜测。
只输出一个具体的物体名称,不要输出其他内容。"""try:yield "游戏即将结束...", "\n".join(game_state.game_history), "", "20/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", "AI正在分析所有信息并做出最终猜测..."guess_response = client.chat.completions.create(model="ernie-x1-turbo-32k",messages=[{"role": "user", "content": guess_prompt}],temperature=0.7,max_tokens=50,stream=True)guess = ""thinking_process = "AI正在分析所有信息并做出最终猜测...\n\n"for chunk in guess_response:if hasattr(chunk.choices[0].delta, 'reasoning_content') and chunk.choices[0].delta.reasoning_content:thinking_process += chunk.choices[0].delta.reasoning_contentyield "游戏即将结束...", "\n".join(game_state.game_history), "", "20/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", thinking_processif chunk.choices[0].delta.content:guess += chunk.choices[0].delta.contentguess = guess.strip()game_state.game_history.append(f"AI最终猜测: {guess}")# 判断AI的猜测是否正确if guess.lower().strip() == game_state.target_object.lower().strip():game_state.ai_score += 1result = f"AI猜对了!目标物体就是:{game_state.target_object}\nAI得1分!"else:game_state.human_score += 1result = f"AI猜错了!目标物体是:{game_state.target_object}\n人类得1分!"history_text = "\n".join(game_state.game_history)yield result, history_text, "", "20/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", thinking_process + "\n\n思考完成!"returnexcept Exception as e:yield f"发生错误: {str(e)}", "", "", "20/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""return# 如果不是最后一轮,让AI继续提问next_prompt = f"""基于之前的对话:
{chr(10).join(game_state.game_history)}请分析这些问答,提出下一个问题来猜测玩家心中的物体。
问题应该是一个简单的"是/否"问题,要基于之前的回答来缩小范围,但也要注意,有时玩家并不知道这个物体应该选是还是否,可能会出现回答错误,因此要考虑这种情况。
请先思考一下,然后只输出问题,不要输出其他内容。"""try:yield "AI正在思考...", "\n".join(game_state.game_history), "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", f"AI正在分析第{game_state.questions_asked}轮的回答并思考下一个问题..."next_response = client.chat.completions.create(model="ernie-x1-turbo-32k",messages=[{"role": "user", "content": next_prompt}],temperature=0.7,max_tokens=100,stream=True)next_question = ""thinking_process = f"AI正在分析第{game_state.questions_asked}轮的回答并思考下一个问题...\n\n"for chunk in next_response:if hasattr(chunk.choices[0].delta, 'reasoning_content') and chunk.choices[0].delta.reasoning_content:thinking_process += chunk.choices[0].delta.reasoning_contentyield "AI正在思考...", "\n".join(game_state.game_history), "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", thinking_processif chunk.choices[0].delta.content:next_question += chunk.choices[0].delta.contentnext_question = next_question.strip()game_state.current_question = next_questiongame_state.game_history.append(f"AI问题 {game_state.questions_asked + 1}: {next_question}")history_text = "\n".join(game_state.game_history)yield f"AI的问题 {game_state.questions_asked + 1}/20: {next_question}", history_text, "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", thinking_process + "\n\n思考完成!"except Exception as e:yield f"发生错误: {str(e)}", "", "", f"{game_state.questions_asked}/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", ""def reset_game():"""重置游戏"""game_state.questions_asked = 0game_state.game_history = []game_state.is_game_over = Falsegame_state.target_object = Nonegame_state.current_question = Nonegame_state.is_game_started = Falsereturn "游戏已重置!请设置新的目标物体。", "", "", "0/20", f"AI: {game_state.ai_score} - 人类: {game_state.human_score}", "游戏已重置,等待开始新游戏..."# 自定义CSS样式
custom_css = """
.round-counter {font-size: 24px !important;font-weight: bold !important;color: #4a90e2 !important;padding: 10px 20px !important;background-color: #f5f5f5 !important;border-radius: 10px !important;box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;margin-left: auto !important;
}.score-counter {font-size: 20px !important;font-weight: bold !important;color: #2c3e50 !important;padding: 8px 16px !important;background-color: #ecf0f1 !important;border-radius: 8px !important;box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;margin-left: 20px !important;
}.thinking {color: #666 !important;font-style: italic !important;
}.ai-thinking {font-family: 'Courier New', monospace !important;background-color: #f8f9fa !important;padding: 15px !important;border-radius: 8px !important;border-left: 4px solid #4a90e2 !important;margin: 10px 0 !important;white-space: pre-wrap !important;font-size: 14px !important;line-height: 1.5 !important;
}
"""# 创建Gradio界面
with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:with gr.Row():gr.Markdown("# 🎮 知你所想")round_counter = gr.Markdown("0/20", elem_classes=["round-counter"])score_counter = gr.Markdown("AI: 0 - 人类: 0", elem_classes=["score-counter"])gr.Markdown("### 20个问题,猜中你所想的东西,来挑战一下吧!")with gr.Row():with gr.Column(scale=1):target_input = gr.Textbox(label="输入你想让AI猜的物体",placeholder="例如:长颈鹿",lines=2)set_target_button = gr.Button("设置目标物体", variant="primary")with gr.Column(scale=1):answer_input = gr.Textbox(label="回答AI的问题",placeholder="输入:是、否、或不知道",lines=2)answer_button = gr.Button("回答", variant="primary")with gr.Row():reset_button = gr.Button("开始新游戏", variant="stop")with gr.Row():ai_thinking = gr.Textbox(label="AI思考过程",lines=5,elem_classes=["ai-thinking"],interactive=False)with gr.Row():output = gr.Textbox(label="游戏状态", lines=10)history = gr.Textbox(label="游戏历史", lines=10)error = gr.Textbox(label="错误信息", lines=10)# 设置事件处理set_target_button.click(set_target_object,inputs=[target_input],outputs=[output, history, error, round_counter, score_counter, ai_thinking],queue=True)answer_button.click(answer_question,inputs=[answer_input],outputs=[output, history, error, round_counter, score_counter, ai_thinking],queue=True)reset_button.click(reset_game,outputs=[output, history, error, round_counter, score_counter, ai_thinking])if __name__ == "__main__":demo.queue().launch()