在一场由两名人类和一名机器组成的模拟图灵测试对局中,人类审讯者需在五分钟的文字交谈中分辨出与自己所交流的哪一名证人才是真正的人类,机器人则尽力模拟人类对话。
- 引入 MBTI 16 人格(含 A/T 共 32 种)作为 AI 证人的提示词集合,匹配前玩家可选择 8-32 种人格缩小范围
- 支持 Grok3、ChatGPT 与 DeepSeek 三种不同的 AI 客户端
- 实时 WebSocket 聊天系统
- ELO 评分系统追踪玩家水平
- Redis 实现消息队列和实时消息分发
- 框架:FastAPI (异步 Web 框架)
- ORM:SQLAlchemy (异步版本)
- 数据库驱动:asyncpg (PostgreSQL 异步驱动)
- 缓存与消息队列:Redis (异步客户端)
- 认证:OAuth2 + JWT (python-jose, bcrypt)
- WebSocket:websockets (实时通信)
- 数据迁移:Alembic
- HTTP 客户端:httpx (用于调用 AI API)
- 数据库:PostgreSQL
- 框架:Next.js 15 (React 19)
- UI 组件库:Material-UI (MUI) 7
- 状态管理:Zustand + React Query
- 样式:TailwindCSS + CSS Modules
- 国际化:i18next
- HTTP 客户端:Axios
- WebSocket:原生 WebSocket API
- DeepSeek:deepseek-chat 模型
- Grok3:grok-3 模型
- ChatGPT:通过统一 API 接口支持
- 容器化:Docker + Docker Compose
- Web 服务器:Uvicorn (ASGI)
- 反向代理:Nginx (可选)
.
├── README.md
├── alembic.ini # Alembic 配置文件
├── requirements.txt # Python 依赖
├── docker-compose.yml # Docker Compose 配置
├── docker/ # Docker 构建文件
│ ├── api.Dockerfile
│ └── web.Dockerfile
├── prompts/ # AI 提示词配置
│ ├── system.json # 系统提示词
│ └── personas/ # MBTI 人格提示词 (32 个 JSON 文件)
│ ├── ENFJ-A.json
│ ├── ENFJ-T.json
│ └── ...
├── api/ # 后端 API 服务
│ ├── main.py # FastAPI 应用入口
│ ├── core/ # 核心配置
│ │ ├── config.py # 应用配置(环境变量)
│ │ ├── database.py # 数据库连接
│ │ └── redis.py # Redis 连接
│ ├── dao/ # 数据访问层(ORM 模型)
│ │ ├── base.py
│ │ ├── user.py # 用户模型
│ │ ├── game.py # 游戏模型
│ │ ├── message.py # 消息模型
│ │ ├── guess.py # 猜测模型
│ │ └── sender.py # 发送者角色枚举
│ ├── dto/ # 数据传输对象(请求/响应模型)
│ │ ├── auth.py
│ │ ├── user.py
│ │ └── message.py
│ ├── routers/ # API 路由
│ │ ├── auth.py # 认证路由(注册/登录)
│ │ ├── ws_match.py # WebSocket 匹配路由
│ │ ├── chat.py # WebSocket 聊天路由
│ │ └── message.py # HTTP 消息路由
│ ├── service/ # 业务逻辑层
│ │ ├── game_service.py # 游戏服务
│ │ ├── user_service.py # 用户服务
│ │ ├── llm_service.py # AI 服务(DeepSeek/Grok3/ChatGPT)
│ │ └── prompt_builders/ # 提示词构建器
│ │ ├── prompt_builder.py
│ │ ├── make_prompt_builder.py
│ │ └── file_prompt_builder.py
│ ├── utils/ # 工具函数
│ │ ├── auth.py # JWT 工具
│ │ ├── lifespan.py # 应用生命周期
│ │ └── process_reply.py # AI 回复后处理
│ └── migrations/ # Alembic 数据库迁移
│ ├── env.py
│ └── versions/
│ ├── 03216c9751cb_initial_create.py
│ ├── 234099a5f8e6_separate_match_vs_game_status.py
│ └── 9c0e8f3e3b0a_add_ai_persona_pool.py
└── web/ # 前端 Web 应用
├── package.json
├── next.config.ts
├── tsconfig.json
├── app/ # Next.js App Router
│ ├── page.tsx # 首页
│ ├── queue/ # 匹配队列页面
│ ├── rooms/ # 游戏房间页面
│ │ └── [game_id]/
│ │ └── [role]/
│ └── else/ # 其他页面(FAQ、规则等)
├── components/ # React 组件
│ ├── ui/ # UI 组件
│ │ ├── AuthDialog.tsx
│ │ ├── MatchDialog.tsx
│ │ ├── PersonaSelectDialog.tsx
│ │ ├── InterrogatorUI.tsx
│ │ ├── WitnessUI.tsx
│ │ ├── ChatBubble.tsx
│ │ └── ...
│ └── pages/ # 页面级组件
│ ├── CaughtPage.tsx
│ ├── FooledPage.tsx
│ └── ...
├── hooks/ # React Hooks
│ ├── useAuth.ts
│ ├── useMatch.ts
│ ├── useGame.ts
│ └── useChatTimer.ts
├── lib/ # 工具库
│ ├── auth.ts
│ ├── socket.ts
│ ├── personas.ts
│ └── types.ts
├── styles/ # CSS 模块样式
├── types/ # TypeScript 类型定义
└── public/ # 静态资源
├── locales/ # 国际化文件
└── assets/
启动 PostgreSQL 使用自定义端口:
:: 启动 PostgreSQL(端口改为 15432)
docker run -d --name turing_postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=iammm -e POSTGRES_DB=turing_test -p 15432:5432 postgres启动 Redis 容器 使用自定义端口:
:: 启动 Redis(端口改为 16379)
docker run -d --name turing_redis -p 16379:6379 redisPostgreSQL 容器内登录:
docker exec -it turing_postgres bash然后在容器里执行:
psql -U postgres -d turing_test进入 Redis 容器内:
docker exec -it turing_redis redis-cli1.克隆代码:
git clone https://.../turing-test.git
cd turing-test- 环境变量配置:
在项目根目录创建 .env 文件,填写以下配置:
# 数据库配置(支持 DATABASE_URL 或拆分式配置)
DATABASE_URL=postgresql+asyncpg://postgres:iammm@localhost:15432/turing_test
# 或使用拆分式配置
POSTGRES_HOST=localhost
POSTGRES_PORT=15432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=iammm
POSTGRES_DB=turing_test
# Redis 配置
REDIS_URL=redis://localhost:16379/0
# AI 服务 API Key
DEEPSEEK_API_KEY=sk-xxx
GROK3_API_KEY=sk-xxx
CHATGPT_API_KEY=sk-xxx
# 前端环境变量(可选)
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
NEXT_PUBLIC_WS_BASE=ws://localhost:8000/api- 后端依赖安装与启动:
cd api
pip install -r ../requirements.txt
alembic upgrade head # 运行数据库迁移
uvicorn main:app --reload --host 0.0.0.0 --port 8000后端服务启动后,访问 http://localhost:8000/docs 查看 Swagger API 文档。
- 前端依赖安装与启动:
cd web
npm install
npm run dev # 开发模式(支持 Turbopack)前端服务默认运行在 http://localhost:3000。
-
用户注册:
POST /api/auth/register- 邮箱唯一性校验
- 密码哈希存储(bcrypt)
-
用户登录:
POST /api/auth/login- JWT Token 生成(有效期 1 小时,可在代码中调整)
- Token 存储在 localStorage,用于后续请求认证
-
用户模型:
- ELO 评分系统(初始 1000 分)
- 支持匿名玩家(email 可为空)
-
WebSocket 连接:
ws://127.0.0.1:8000/api/ws/match?token=<access_token> -
匹配流程:
1. 客户端发送 join → 加入匹配队列 2. 系统匹配两名玩家 → 发送 match_found 3. 玩家选择 accept/decline → 等待对方响应(60 秒超时) 4. 双方都 accept → 发送 matched,创建游戏,跳转到游戏房间 -
匹配特性:
- FIFO 队列匹配
- 随机分配角色(审讯者 I / 人类证人 W)
- 支持自定义 AI 人格池(8-32 种 MBTI 人格)
- 匹配超时自动取消
-
游戏状态流转:
CHATTING → JUDGING → ENDEDCHATTING:5 分钟聊天阶段(审讯者与两位证人对话)JUDGING:聊天结束,等待审讯者提交猜测ENDED:游戏结束,记录猜测结果
-
游戏角色:
- I (Interrogator):审讯者,与两个证人对话并猜测
- H (Human Witness):人类证人,真实玩家扮演
- A (AI Witness):AI 证人,由 LLM 扮演,使用随机选择的 MBTI 人格
-
AI 证人系统:
- 从玩家选择的人格池中随机选择一种
- 使用对应的 JSON 提示词文件定义 AI 行为
- 支持 32 种 MBTI 人格(16 种 × 2 种亚型:A/T)
-
WebSocket 房间连接:
- 审讯者:
ws://127.0.0.1:8000/api/ws/rooms/<game_id>/I?token=<token> - 人类证人:
ws://127.0.0.1:8000/api/ws/rooms/<game_id>/H?token=<token> - AI 证人:
ws://127.0.0.1:8000/api/ws/rooms/<game_id>/A(无需 token)
- 审讯者:
-
消息路由:
- 审讯者可与 AI/人类证人分别对话(双通道)
- 消息通过 Redis Pub/Sub 实时分发
- 所有消息持久化到 PostgreSQL
-
AI 自动回复:
- 审讯者向 AI 发送消息时,触发 LLM 生成回复
- 支持上下文对话(基于历史消息构建提示)
- 回复经过后处理(如长度限制、格式调整)
-
猜测提交:
- 审讯者在 JUDGING 阶段提交猜测
- 需要指定哪个证人是 AI,哪个是人类
- 系统自动判断正确性
-
结果记录:
- 猜测结果存储在
guesses表 - 游戏结果更新到
games表 - 支持 ELO 评分更新(待实现)
- 猜测结果存储在
| 方法 | 路径 | 描述 | 请求体 | 响应 |
|---|---|---|---|---|
| POST | /api/auth/register |
用户注册 | {email, display_name, password} |
UserOut |
| POST | /api/auth/login |
用户登录 | {email, password} |
{access_token, token_type} |
| 方法 | 路径 | 描述 | 认证 |
|---|---|---|---|
| GET | /api/messages/{game_id} |
获取游戏所有消息 | 需要 Token |
连接地址:
ws://127.0.0.1:8000/api/ws/match?token=<access_token>
客户端 → 服务端消息:
- 加入匹配队列:
{
"action": "join",
"persona_pool": ["INTP-A.json", "ENFP-T.json", ...] // 可选,默认全部 32 种
}- 接受匹配:
{
"action": "accept",
"match_id": "uuid-string"
}- 拒绝匹配:
{
"action": "decline",
"match_id": "uuid-string"
}服务端 → 客户端消息:
- 匹配成功:
{
"action": "match_found",
"match_id": "uuid-string",
"role": "I" | "W",
"window": 60 // 确认超时时间(秒)
}- 匹配确认:
{
"action": "matched",
"game_id": "uuid-string"
}- 错误消息:
{
"action": "error",
"detail": "错误描述"
}连接地址:
# 审讯者
ws://127.0.0.1:8000/api/ws/rooms/<game_id>/I?token=<access_token>
# 人类证人
ws://127.0.0.1:8000/api/ws/rooms/<game_id>/H?token=<access_token>
# AI 证人(系统自动连接,无需 token)
ws://127.0.0.1:8000/api/ws/rooms/<game_id>/A
客户端 → 服务端消息:
- 发送聊天消息:
{
"action": "message",
"sender": "I" | "H" | "A",
"recipient": "I" | "H" | "A",
"body": "消息内容",
"ts": "2024-01-01T00:00:00Z" // ISO 格式时间戳
}- 提交猜测(仅审讯者):
{
"action": "guess",
"guessed_ai_id": "uuid-string", // 猜测的 AI 证人用户 ID
"guessed_human_id": "uuid-string" // 猜测的人类证人用户 ID
}服务端 → 客户端消息:
- 聊天消息广播:
{
"action": "message",
"sender": "I" | "H" | "A",
"recipient": "I" | "H" | "A",
"body": "消息内容",
"ts": "2024-01-01T00:00:00Z"
}- 游戏状态更新:
{
"action": "status_update",
"status": "CHATTING" | "JUDGING" | "ENDED",
"game_id": "uuid-string"
}- 猜测结果(仅审讯者):
{
"action": "guess_result",
"is_correct": true | false,
"actual_ai_id": "uuid-string",
"actual_human_id": "uuid-string"
}- 错误消息:
{
"action": "error",
"detail": "错误描述"
}id(UUID, 主键)email(String, 唯一,可为空)display_name(String, 可为空)password_hash(String, 可为空)elo(Integer, 默认 1000)created_at(DateTime)
id(UUID, 主键)interrogator_id(UUID, 外键 → User)witness_human_id(UUID, 外键 → User)witness_ai_id(UUID, 外键 → User, 可为空)status(Enum: CHATTING, JUDGING, ENDED)ai_persona(String, AI 使用的人格文件名)ai_persona_pool(String, 玩家选择的人格池,逗号分隔)started_at(DateTime)ended_at(DateTime, 可为空)success(Boolean, 可为空:猜对/猜错/未猜)
id(Integer, 主键,自增)game_id(UUID, 外键 → Game)sender(Enum: I, H, A)recipient(Enum: I, H, A)body(String, 最大 1000 字符)ts(DateTime)
game_id(UUID, 复合主键,外键 → Game)interrogator_id(UUID, 复合主键,外键 → User)guessed_ai_id(UUID, 外键 → User)guessed_human_id(UUID, 外键 → User)is_correct(Boolean)guessed_at(DateTime)
- 创建
.env文件并配置环境变量 - 启动服务:
docker-compose up -d这将启动:
- PostgreSQL 服务(端口 15432)
- Redis 服务(端口 16379)
- 后端和前端仍需单独运行,或使用提供的 Dockerfile 构建镜像
cd api
alembic upgrade head # 应用迁移
alembic revision --autogenerate -m "描述" # 生成新迁移项目使用 MBTI(16 型人格)× 2 种亚型(A: Assertive / T: Turbulent),共 32 种 AI 人格。
每个人格对应 prompts/personas/ 目录下的一个 JSON 文件,定义:
- 表达风格(简短/详细、理性/感性等)
- 行为特征
- 示例句式
- 其他个性化设定
玩家在匹配前可选择 8-32 种人格缩小范围,系统会从中随机选择一种作为 AI 证人的行为模板。