# AI 陪玩系统需求与技术方案
更新时间:2026-08-18
文档状态:需求确认完成,方案待实施
> 本文结合已确认的产品需求与当前项目源码编写。
>
> 文中“当前系统”表示仓库已经存在并已核对的行为;“拟新增”表示本次 AI 陪玩系统的设计方案,尚未实现。实时牌局规则始终以当前 `game` 服务为唯一权威。
## 1. 文档目的与适用对象
本文用于统一 AI 陪玩系统的产品口径、业务边界、技术架构、后台配置、策略能力、开源选型和验收标准,适用于:
- 产品与运营:确认 AI 如何配置、何时生效、如何统计和排查。
- 游戏服务研发:确认 AI 在现有牌局中的接入点和安全边界。
- AI 服务研发:确认决策输入、输出、策略组成和性能目标。
- 后台研发:确认管理页面、数据模型和权限范围。
- 测试与验收:确认公平性、异常兜底、强度校准和回归范围。
本文不改变当前比赛报名、分桌、盲注、筹码、淘汰、排名、奖励和结算规则。
## 2. 已确认的核心结论
| 主题 | 已确认口径 |
| --- | --- |
| AI 角色 | AI 使用普通参赛账号,直接坐桌并自动打牌 |
| 账号来源 | 复用现有用户账号创建方式,AI 页面只绑定已有账号 |
| 生效范围 | 账号启用 AI 绑定后,参加任何线上德州扑克赛事时均由 AI 接管操作 |
| 业务影响 | AI 只影响打牌和下注决策,不影响报名、分桌、淘汰、排名和奖励 |
| 旧 Bot | 新系统独立建设,不复用旧 Bot 字段、规则、策略或控制链路 |
| 公平模式 | AI 只读取真人在相同位置可以看到的信息,不读取其他玩家底牌、牌堆或未来公共牌 |
| 桌型 | 遵循当前项目规则,单桌最多 9 人;同桌 AI 数量不限制 |
| 实时规则 | 合法动作、加注上下限、边池和轮次推进均由当前 `game` 服务计算 |
| 策略绑定 | 每个 AI 账号固定绑定一个策略档案 |
| 强度配置 | 使用 1~5 档强度,不允许直接填写或保证任意胜率 |
| 打法配置 | 松紧度、激进度、诈唬频率、风险偏好、对手适应程度、下注尺度和思考时间 |
| 对手分析 | 只统计同一场比赛内的简单对手数据,不建立跨比赛长期画像 |
| 随机策略 | 采用可控随机混合策略,并记录随机种子用于复盘 |
| 聊天能力 | 首版不接入大模型聊天、语音或语言人格 |
| 玩家展示 | 玩家端不显示 AI 标识;内部后台、日志和审计记录需要可识别 |
| 配置入口 | 在现有 `poker-web` 管理后台新增配置页面 |
| 配置生效 | 策略修改、更换或关闭绑定从下一手牌开始生效 |
| 异常兜底 | AI 决策失败时重试一次;仍失败则可过牌时过牌,否则弃牌 |
| 首版锦标赛策略 | 使用筹码深度、比赛阶段和剩余人数的简化策略 |
| 后续锦标赛能力 | 完整 ICM、泡沫期和奖励结构计算后续迭代 |
| 校准方式 | 固定 9 人基准环境中统计第一名率、平均名次、BB/100 和样本数 |
| 性能目标 | 同时约 100 个 AI,峰值约 20 次决策/秒 |
| AI 技术栈 | 独立 Python 3.11 + FastAPI 服务 |
## 3. 核心业务概览
### 3.1 AI 账号是什么
AI 账号首先是现有系统中的普通用户账号。运营人员在后台将该账号绑定到一个 AI 策略档案后,账号的报名、分桌、筹码和奖励身份保持不变;只有轮到该账号行动时,系统才将决策交给独立 AI 服务。
AI 账号关闭绑定后恢复为普通真人账号,不需要迁移用户资料,也不改变其历史比赛记录。
### 3.2 AI 策略档案是什么
策略档案是一组可复用的 AI 打法配置。多个 AI 账号可以绑定同一个策略档案,但由于使用混合策略和独立随机种子,它们在相同局面下不必做出完全相同的动作。
一个策略档案包含:
- 1~5 档强度等级。
- 松紧度、激进度、诈唬频率和风险偏好。
- 对手适应程度。
- 下注尺度风格。
- 最短和最长思考时间。
- 启用状态和配置版本。
### 3.3 “胜率配置”的业务口径
公平模式下不能为 AI 保证单局或单场比赛结果。运营人员配置的是强度和打法,系统通过标准化对局测量其长期表现。
后台展示的参考结果包括:
- 固定 9 人测试环境中的第一名率。
- 平均最终名次。
- 每百手筹码收益 `BB/100`。
- 对局样本数。
- 使用的基准对手和盲注场景版本。
这些结果是只读的校准数据,不是实时控牌或结果干预参数。
## 4. 当前系统实现基础
### 4.1 当前管理端
当前 `poker-web` 是 Laravel 6 + Poppy Framework 的赛事业务后台和 API 项目,已经具备:
- `/mgr-page` 管理后台。
- Poker 模块菜单和权限配置。
- 列表、表单、路由、模型和数据库迁移的既有开发模式。
- 赛事、盲注、奖池、报名、牌桌和比赛记录等管理能力。
因此 AI 配置页面应直接放入 `poker-web/modules/poker`,不新建另一套运营后台。
### 4.2 当前实时牌局
当前 `game` 服务基于 PHP/Hyperf/Swoole,已经负责:
- 单桌最多 9 人及比赛分桌。
- 翻牌前、翻牌、转牌、河牌和摊牌阶段。
- 过牌、跟注、加注、全下和弃牌。
- 盲注、前注、筹码、主池和边池。
- 合法动作、最小加注和最大加注计算。
- 操作倒计时、超时自动过牌或弃牌。
- 比赛阶段、盲注等级、淘汰、排名和牌局记录。
AI 不重新实现上述规则,只消费当前牌局提供的公开状态和合法动作集合。
### 4.3 当前可复用的接入能力
当前轮到用户操作时,系统会先计算:
- 当前动作时间点。
- 允许执行的动作。
- 跟注所需筹码。
- 最小和最大加注额。
- 快捷下注参考值。
普通用户提交动作后,现有动作处理链会再次校验并推进牌局。因此新 AI 系统可以复用同一执行入口,无需模拟一个 WebSocket 客户端。
## 5. 产品目标与非目标
### 5.1 首版目标
- 让普通参赛账号在绑定后能够自动完成整场比赛。
- 支持一桌任意数量 AI,并允许 9 个 AI 全自动对局。
- 支持运营配置可辨识的打法和 5 档强度。
- 使用公平可见信息作出决策。
- 支持同场比赛内的轻量对手适应。
- 提供决策日志和标准化强度校准。
- AI 服务异常时不阻塞牌桌,也不会在故障状态下冒险下注。
- 在约 100 个同时参赛 AI、峰值 20 次决策/秒下稳定运行。
### 5.2 首版非目标
- 不控制发牌、牌堆或最终输赢。
- 不读取其他玩家底牌或未来公共牌。
- 不复用或迁移旧 Bot 策略。
- 不允许运营输入任意目标胜率并要求系统保证结果。
- 不实现完整 ICM、泡沫期和奖励结构计算。
- 不引入 CFR、Deep CFR、深度强化学习或在线模型训练。
- 不接入大模型聊天、语音或自动话术。
- 不保存跨比赛的长期玩家打法画像。
- 不在玩家端增加 AI 标识或专属交互。
- 不让 Python AI 服务直接读取当前游戏 Redis 中的隐藏牌局数据。
## 6. 总体架构
```mermaid
flowchart LR
OPS["poker-web 管理后台
AI账号、策略、日志、校准"] --> DB["现有 MySQL
新增独立 AI 表"]
DB --> GAME["game / Hyperf
AI接入适配器"]
GAME -->|"公平状态 + 合法动作 + 策略快照"| AI["ai-player-service
Python 3.11 + FastAPI"]
AI --> PHE["PokerHandEvaluator
牌型与蒙特卡洛计算"]
AI --> AIR["AI Redis 命名空间
单场对手统计、幂等缓存"]
AI -->|"动作 + 下注额 + 决策元数据"| GAME
GAME -->|"现有 Action Handler"| TABLE["当前牌局状态机"]
TABLE -->|"操作完成事件"| GAME
GAME -->|"异步公开动作事件"| AI
BENCH["校准命令行工具"] --> AI
BENCH --> DB
```
### 6.1 `poker-web` 职责
- 管理策略档案。
- 将已有普通用户账号绑定为 AI。
- 启用、关闭或更换账号策略。
- 查看决策记录和异常记录。
- 发起或查看标准化校准结果。
- 管理菜单、权限和操作审计。
### 6.2 `game` 职责
- 继续作为实时牌局唯一权威。
- 在每手牌开始时生成 AI 策略快照。
- 轮到账号操作时检查独立 AI 绑定。
- 组装公平可见的 AI 决策输入。
- 调用 Python AI 服务并控制思考延迟。
- 校验返回动作仍属于当前合法动作。
- 使用现有动作处理链执行动作。
- 记录决策日志和异常兜底结果。
- 将公开动作事件异步发送给 AI 服务用于单场统计。
### 6.3 `ai-player-service` 职责
- 校验决策请求格式和幂等键。
- 计算手牌胜率、底池赔率和筹码压力。
- 执行翻牌前范围、翻牌后规则和混合策略。
- 维护当前比赛内的对手统计。
- 根据策略档案和强度等级返回动作。
- 返回结构化决策原因、随机种子和耗时。
- 不负责发牌、合法性最终判断、底池结算或比赛状态推进。
### 6.4 数据存储原则
- AI 配置和审计记录使用新增独立表,不修改旧 Bot 表和字段。
- Python 服务不直接访问游戏运行态 Redis Key。
- 当前比赛的对手统计使用独立 `ai-player:` Redis 前缀;可先复用现有 Redis 集群,后续按容量拆分实例。
- 策略配置由 `game` 读取并作为版本化快照发送给 AI 服务,减少 Python 服务对主业务数据库的耦合。
## 7. 核心业务流程
### 7.1 账号绑定
```text
运营选择已有普通用户账号
→ 选择一个已启用策略档案
→ 保存 AI 绑定
→ 账号后续正常报名和参赛
→ 下一手牌开始时由游戏服务识别为 AI
```
业务规则:
- 同一用户账号只能存在一个有效 AI 绑定。
- 一个策略档案可以绑定多个 AI 账号。
- 被禁用的策略档案不能新增绑定。
- 账号绑定不改变用户资料、报名资格、筹码或奖励资格。
- 玩家端不展示 AI 身份。
### 7.2 每手牌策略快照
每手牌开始时,游戏服务为当前参赛 AI 账号保存:
- AI 绑定 ID。
- 策略档案 ID。
- 策略版本。
- 本手牌使用的完整策略参数。
同一手牌中始终使用同一版本。运营在牌局中修改策略、更换档案或关闭绑定时,从下一手牌开始生效。
### 7.3 AI 决策
```text
轮到某账号操作
→ 当前项目计算合法动作和下注范围
→ 检查本手牌 AI 策略快照
→ 组装公平决策状态
→ 请求 Python AI 服务
→ AI 返回动作和下注额
→ 等待配置的思考时间
→ 再次校验动作时间点和合法范围
→ 调用现有动作处理链
→ 记录决策结果
```
### 7.4 对手统计更新
每次玩家完成公开动作后,游戏服务异步发送:
- 比赛、房间和手牌标识。
- 当前阶段。
- 玩家位置。
- 公开动作和下注额。
- 当时底池、盲注和有效筹码。
- 是否到达摊牌,以及摊牌公开结果。
AI 服务按比赛维度更新对手数据。比赛结束或数据超过有效期后自动清理。
### 7.5 关闭 AI
- 普通关闭:当前手牌继续使用已有快照,下一手牌恢复真人操作。
- 全局紧急停用:立即停止新的 AI 决策请求;轮到 AI 时直接执行安全兜底。
- 已经返回但动作时间点过期的结果必须丢弃,不能作用于新一轮操作。
## 8. 后台配置方案
### 8.1 菜单规划
建议在 `在线选拔` 下新增 `AI 陪玩` 分组:
- AI 账号
- 策略档案
- 决策记录
- 校准结果
### 8.2 AI 账号页面
列表字段建议:
| 字段 | 说明 |
| --- | --- |
| 用户 ID | 现有普通用户账号 ID |
| 昵称/手机号 | 用于运营检索与确认账号 |
| 策略档案 | 当前绑定的策略名称和版本 |
| 强度等级 | 1~5 档 |
| 状态 | 启用或关闭 |
| 最近决策时间 | 判断账号是否正在被 AI 接管 |
| 最近异常 | 最近一次超时、非法返回或兜底信息 |
| 更新时间/操作人 | 审计信息 |
支持操作:
- 绑定已有账号。
- 更换策略档案。
- 启用或关闭 AI。
- 查看账号决策记录。
- 查看当前策略的校准结果。
首版不在此页面创建普通用户账号。
### 8.3 策略档案页面
固定配置字段:
| 字段 | 范围 | 业务含义 |
| --- | ---: | --- |
| 策略名称 | 文本 | 运营识别名称,如“稳健型” |
| 强度等级 | 1~5 | 决策质量和允许误差的总体档位 |
| 松紧度 | 0~100 | 起手范围和边缘牌参与程度 |
| 激进度 | 0~100 | 主动下注和加注倾向 |
| 诈唬频率 | 0~100 | 满足牌面条件后的诈唬概率上限 |
| 风险偏好 | 0~100 | 面对大底池和筹码压力时的承受程度 |
| 对手适应程度 | 0~100 | 当前比赛对手统计对决策的影响权重 |
| 下注尺度 | 枚举 | 小注、标准、大注、混合 |
| 最短思考时间 | 毫秒 | 玩家端看到的最短等待时间 |
| 最长思考时间 | 毫秒 | 玩家端看到的最长等待时间 |
| 状态 | 开关 | 是否允许新增绑定和后续使用 |
| 备注 | 文本 | 运营说明 |
页面提供预设:
- 稳健型
- 松凶型
- 紧凶型
- 娱乐型
- 大师型
预设只负责填充固定参数,保存后仍形成普通策略档案,不引入独立逻辑分支。
### 8.4 决策记录页面
建议支持按比赛、房间、用户、策略、动作、异常类型和时间筛选。
详情包括:
- 当时合法动作及加注范围。
- AI 可见的公共状态。
- 手牌胜率、底池赔率和有效筹码 BB。
- 对手统计摘要。
- 候选动作权重和最终动作。
- 随机种子。
- 策略 ID、版本和参数摘要。
- 请求、计算和整体耗时。
- 是否重试、是否兜底、失败原因。
底牌和完整决策详情仅在该手牌结束后允许展示。
### 8.5 权限建议
| 权限 | 作用 |
| --- | --- |
| `backend:poker.ai_player.manage` | 管理 AI 账号绑定 |
| `backend:poker.ai_strategy.manage` | 管理策略档案 |
| `backend:poker.ai_decision.view` | 查看决策记录 |
| `backend:poker.ai_benchmark.run` | 发起校准任务 |
| `backend:poker.ai_emergency.disable` | 全局紧急停用 AI |
## 9. 拟新增数据模型
### 9.1 策略档案表 `poker_ai_strategy_profile`
| 字段 | 类型建议 | 说明 |
| --- | --- | --- |
| `id` | bigint | 主键 |
| `name` | varchar | 策略名称 |
| `strength_level` | tinyint | 1~5 档强度 |
| `looseness` | tinyint | 松紧度 0~100 |
| `aggression` | tinyint | 激进度 0~100 |
| `bluff_frequency` | tinyint | 诈唬频率 0~100 |
| `risk_tolerance` | tinyint | 风险偏好 0~100 |
| `opponent_adaptation` | tinyint | 对手适应程度 0~100 |
| `bet_sizing_style` | varchar | small/standard/large/mixed |
| `think_time_min_ms` | int | 最短思考时间 |
| `think_time_max_ms` | int | 最长思考时间 |
| `version` | int | 每次有效修改递增 |
| `enabled` | tinyint | 是否启用 |
| `remark` | varchar/text | 备注 |
| `created_by/updated_by` | bigint | 操作人 |
| `created_at/updated_at` | datetime | 时间 |
### 9.2 AI 账号绑定表 `poker_ai_player_binding`
| 字段 | 类型建议 | 说明 |
| --- | --- | --- |
| `id` | bigint | 主键 |
| `user_id` | bigint unique | 已有普通用户账号 |
| `strategy_profile_id` | bigint | 绑定策略档案 |
| `enabled` | tinyint | 是否启用 AI 接管 |
| `created_by/updated_by` | bigint | 操作人 |
| `created_at/updated_at` | datetime | 时间 |
### 9.3 决策记录表 `poker_ai_decision_log`
关键字段建议:
- 唯一请求 ID、比赛 ID、房间 ID、手牌序号和动作时间点。
- AI 用户 ID、策略 ID 和策略版本。
- 阶段、位置、底池、盲注、有效筹码和公共牌。
- 合法动作、加注上下限和输入快照。
- 估算胜率、底池赔率、候选动作权重。
- 最终动作、下注额和随机种子。
- 服务耗时、是否重试、是否兜底和错误码。
- 创建时间。
输入快照可以使用 JSON 存储,但必须由后台权限控制展示,并配置保留周期。
### 9.4 校准结果表 `poker_ai_benchmark_result`
关键字段建议:
- 策略 ID 和策略版本。
- 基准场景版本。
- 基准对手集合版本。
- 样本手数和比赛场数。
- 第一名率、平均名次、BB/100。
- 开始时间、完成时间和任务状态。
- 运行环境、代码版本和备注。
### 9.5 AI Redis 数据
建议使用独立前缀:
```text
ai-player:race:{raceId}:player:{userId}:stats
ai-player:race:{raceId}:recent-actions
ai-player:decision:{requestId}
ai-player:emergency-disabled
```
对手统计只在当前比赛内有效,比赛结束时清理,并额外设置 TTL 防止异常残留。
## 10. 决策接口契约
### 10.1 决策请求
建议内部接口:
```http
POST /v1/decisions
```
请求结构示例:
```json
{
"request_id": "r123:42:pre_flop:1:10001",
"race_id": 9001,
"room_id": "r123",
"hand_id": 42,
"action_time_point": "42pre_flop1",
"street": "pre_flop",
"hero": {
"user_id": 10001,
"seat": 5,
"position": "CO",
"hole_cards": ["As", "Kd"],
"stack": 18200,
"round_bet": 400
},
"table": {
"max_players": 9,
"active_players": 7,
"small_blind": 200,
"big_blind": 400,
"ante": 50,
"pot": 1650,
"side_pots": [],
"board": []
},
"players": [],
"action_history": [],
"legal_actions": {
"actions": ["fold", "call", "raise", "allin"],
"call_amount": 800,
"raise_min": 1600,
"raise_max": 18200
},
"tournament": {
"remaining_players": 51,
"hero_rank": 23,
"phase": "middle"
},
"strategy": {
"profile_id": 7,
"version": 12,
"strength_level": 3,
"looseness": 45,
"aggression": 60,
"bluff_frequency": 18,
"risk_tolerance": 42,
"opponent_adaptation": 50,
"bet_sizing_style": "mixed"
}
}
```
`game` 应在适配层将当前内部对象转换为稳定契约,避免 Python 服务直接依赖 PHP 类结构或 Redis 序列化格式。
### 10.2 决策响应
```json
{
"request_id": "r123:42:pre_flop:1:10001",
"action": "raise",
"amount": 2000,
"random_seed": "5d17...",
"equity": 0.612,
"pot_odds": 0.327,
"reason_codes": ["POSITION_RANGE", "EQUITY_EDGE", "MIXED_RAISE"],
"compute_ms": 146
}
```
玩家端不展示 `reason_codes`。它们只用于后台排查、策略调优和验收。
### 10.3 游戏服务的最终校验
收到响应后必须再次确认:
- `request_id` 与当前请求一致。
- `action_time_point` 仍然有效。
- 当前操作者仍是该 AI 账号。
- 返回动作属于当前合法动作集合。
- 跟注、加注或全下金额符合当前项目的最新范围。
- 重复响应不会重复执行动作。
任何校验失败都视为 AI 决策失败,不允许绕过现有动作处理链。
## 11. 公平信息边界
### 11.1 允许提供给 AI 的信息
- AI 自己的两张底牌。
- 已公开的公共牌。
- 玩家位置、剩余筹码和本轮下注。
- 当前底池和公开边池。
- 盲注、前注和当前阶段。
- 已公开的动作历史。
- 当前合法动作及下注范围。
- 当前比赛剩余人数、AI 自己的排名和简化比赛阶段。
- 当前比赛内形成的对手公开行为统计。
### 11.2 禁止提供给 AI 的信息
- 其他未摊牌玩家的底牌。
- 牌堆剩余顺序。
- 尚未发出的公共牌。
- 发牌随机数、内部控牌字段或隐藏运营信息。
- 当前项目旧 Bot 的配置、命中结果或控制字段。
- 其他正常玩家无法获得的服务端隐含状态。
建议为 AI 决策输入建立独立 DTO 和自动化测试,避免直接序列化完整房间、用户或发牌对象。
## 12. 首版策略引擎
### 12.1 翻牌前策略
翻牌前使用 9 人桌位置范围和有效筹码分层:
- 位置:UTG、UTG+1、MP、HJ、CO、BTN、SB、BB。
- 局面:无人入池、有人平跟、面对一次加注、面对多次加注、面对全下。
- 有效筹码:短筹码、中短筹码、中筹码、深筹码。
- 动作:弃牌、跟注、加注、再加注、全下。
松紧度控制起手牌范围宽度;激进度和诈唬频率控制主动加注与轻量再加注概率;风险偏好控制边缘全下和大底池参与程度。
### 12.2 翻牌后策略
翻牌后综合:
- 蒙特卡洛胜率。
- 底池赔率。
- 有效筹码和 SPR。
- 公共牌结构,如同花、顺子、成对牌面和高张压力。
- 对手数量和位置。
- 当前比赛内的对手统计。
- 当前合法下注范围。
候选下注额使用有限尺度,再裁剪到当前项目给出的合法范围:
- 小注。
- 标准注。
- 大注。
- 最小合法加注。
- 全下。
首版不生成任意连续下注公式,避免运营配置和策略调试复杂化。
### 12.3 简化锦标赛策略
首版纳入:
- 以大盲为单位的筹码深度。
- 短筹码 push/fold 倾向。
- 比赛前期、中期和后期的风险调整。
- 剩余人数和自身相对排名的轻量修正。
首版不纳入:
- 完整 ICM。
- 泡沫期精确计算。
- 奖励阶梯和奖金跳跃计算。
- 跨桌全部玩家筹码分布求解。
### 12.4 强度等级
| 等级 | 定位 | 策略能力 |
| ---: | --- | --- |
| 1 | 入门 | 基础起手范围、较高决策噪声、弱对手适应 |
| 2 | 休闲 | 基础位置意识、简单胜率和底池赔率判断 |
| 3 | 稳健 | 完整首版规则、正常混合策略和单场对手统计 |
| 4 | 高手 | 更细范围、更低误差、更强下注尺度和对手调整 |
| 5 | 大师 | 使用首版规则引擎的最佳参数、最低人为误差和更充分计算 |
蒙特卡洛样本数、误差注入和动作混合范围属于内部调优参数,不直接暴露给运营。具体值以容量测试和校准结果确定。
### 12.5 可控随机混合策略
AI 不以固定阈值机械地选择唯一动作,而是为合法候选动作生成权重后抽样。
随机种子至少包含:
- 比赛 ID。
- 房间 ID。
- 手牌序号。
- 动作时间点。
- AI 用户 ID。
- 策略 ID 和版本。
每次决策保存最终种子,使同一输入能够在测试环境中重放。
## 13. 单场对手分析
### 13.1 首版指标
| 指标 | 业务含义 |
| --- | --- |
| VPIP | 翻牌前主动投入筹码的手牌比例 |
| PFR | 翻牌前主动加注比例 |
| 加注频率 | 各阶段主动下注或加注倾向 |
| 面对加注弃牌率 | 遇到压力后弃牌的倾向 |
| 摊牌率 | 进入摊牌的比例 |
| 摊牌胜率 | 已公开摊牌中的获胜比例 |
| 近期激进度 | 最近若干手的动作趋势 |
### 13.2 使用规则
- 只使用当前比赛内数据。
- 样本不足时向默认人群参数收缩,不能因一两手牌形成极端判断。
- `opponent_adaptation` 决定统计对最终决策的最大影响权重。
- Redis 不可用时降级为基础策略,不阻塞牌局。
- 比赛结束后清理;不写入长期玩家画像。
## 14. 思考时间与异常兜底
### 14.1 思考时间
AI 计算时间和玩家端思考时间分开:
1. Python 服务尽快完成计算。
2. 游戏服务根据策略档案随机生成展示等待时间。
3. 等待时间不得超过当前操作倒计时的安全余量。
4. 等待结束前再次确认动作时间点有效。
### 14.2 失败处理
| 场景 | 处理方式 |
| --- | --- |
| AI 服务超时 | 短暂重试一次 |
| 第二次仍超时 | 可以过牌则过牌,否则弃牌 |
| 返回非法动作 | 记录异常并执行安全兜底 |
| 返回金额越界 | 不自动修正为冒险下注,执行安全兜底 |
| 动作时间点已变化 | 丢弃结果,不执行 |
| 策略配置缺失 | 告警并执行安全兜底 |
| 对手统计 Redis 故障 | 使用无对手适应的基础策略 |
| 决策日志写入失败 | 记录服务错误,但不阻塞合法动作执行 |
| 全局紧急停用 | 停止新请求并执行安全兜底 |
错误情况下绝不自动跟注、加注或全下。
## 15. 性能与部署目标
### 15.1 首版容量
- 同时参赛 AI:约 100 个。
- 决策峰值:约 20 次/秒。
- 单桌 AI 数量:不限制,最多可为 9 个。
- AI 决策服务:多进程 worker,允许后续水平扩容。
### 15.2 性能原则
- 请求链路中不执行模型训练、CFR 求解或大模型调用。
- 预先加载翻牌前范围和固定规则表。
- 复用牌型查表和牌组编码。
- 蒙特卡洛样本数按强度、阶段和剩余时间自适应。
- CPU 密集计算使用多进程隔离,不依赖单个 Python 事件循环吞吐。
- 建议首版以单次正常计算 P95 小于 500 毫秒为目标,并设置独立硬超时。
- 服务可以通过无状态实例扩容;当前比赛对手统计保存在 Redis。
### 15.3 部署建议
```text
ai-player-service
├── FastAPI API 层
├── 策略与范围模块
├── 胜率计算模块
├── 对手统计模块
├── 决策解释与日志模块
└── 校准命令行工具
```
首版可以单独部署一组 Python 服务实例,与 `game` 通过内网 HTTP 通信。接口应配置:
- 服务间认证。
- 请求签名或短期令牌。
- 内网访问控制。
- 请求 ID 和幂等校验。
- 健康检查和就绪检查。
## 16. 决策日志、监控与排查
### 16.1 关键监控指标
- 决策请求总量、成功率和失败率。
- P50/P95/P99 计算耗时。
- 重试率和安全兜底率。
- 非法返回和过期响应数量。
- 各策略档案动作分布。
- 各强度等级的校准结果变化。
- AI Redis 命中率和故障次数。
- 游戏服务因 AI 产生的额外等待时间。
### 16.2 运营排查顺序
当出现“AI 操作异常”反馈时:
1. 确认账号在该手牌是否存在有效 AI 策略快照。
2. 检查当时合法动作、加注范围和动作时间点。
3. 查看 AI 输入中是否只包含公平信息。
4. 查看策略版本、胜率、底池赔率和候选动作权重。
5. 查看随机种子并在测试环境重放。
6. 确认是否发生超时、重试、兜底或过期响应。
7. 最后核对现有动作处理链是否拒绝或修改了动作。
## 17. 强度校准方案
### 17.1 校准原则
- 实际线上牌局规则以当前 `game` 服务为准。
- 主要集成校准应使用测试环境中的当前游戏服务和普通 AI 账号完成。
- PokerKit 可以用于离线场景生成、快速回归和策略单元测试,但不替代线上规则。
- 每次校准固定策略版本、基准对手版本、盲注结构和代码版本。
- 校准结果只描述历史样本,不自动控制后续比赛结果。
### 17.2 标准基准场景
建议至少建立:
- 固定 9 人单桌场景。
- 固定初始筹码和盲注结构。
- 多组基准对手:入门、休闲、稳健和混合对手。
- 足够数量的随机种子和比赛样本。
- 5 个强度等级之间的交叉对局。
### 17.3 结果展示
后台显示:
- 第一名率。
- 平均最终名次。
- BB/100。
- 比赛场数和手牌数。
- 基准场景版本。
- 置信区间或波动提示。
- 最近一次完成时间。
验收重点是不同强度在足够样本下形成稳定区分,而不是要求每档达到一个被保证的固定胜率。
## 18. 开源项目调研与选型
调研时间:2026-08-18。仓库活跃度和许可证以调研时 GitHub 信息为准。
### 18.1 推荐结论
| 项目 | 许可证 | 适用部分 | 首版结论 |
| --- | --- | --- | --- |
| [PokerHandEvaluator](https://github.com/HenryRLee/PokerHandEvaluator) | Apache-2.0 | 5~7 张牌型评估、蒙特卡洛底层计算 | **直接采用** Python 包 `phevaluator` |
| [PokerKit](https://github.com/uoftcprg/pokerkit) | MIT | 多变体模拟、牌型评估、离线测试 | **用于离线模拟与回归**,不接管线上规则 |
| [PyPokerEngine](https://github.com/ishikota/PyPokerEngine) | MIT | AI 回调格式、合法动作与牌局状态输入设计 | **借鉴接口设计**,不直接嵌入当前牌局 |
| [rosbo/texas-holdem-poker-ai](https://github.com/rosbo/texas-holdem-poker-ai) | MIT | 手牌强度、翻牌前模拟、简单对手建模 | **借鉴轻量策略思路**,不直接复制架构 |
| [OpenSpiel](https://github.com/google-deepmind/open_spiel) | Apache-2.0 | CFR、强化学习、自博弈和研究评估 | **后续研究**,首版不引入 |
| [RLCard](https://github.com/datamllab/rlcard) | MIT | 卡牌强化学习环境、动作抽象和训练示例 | **后续研究**,与当前 9 人锦标赛状态不直接匹配 |
| [PokerRL](https://github.com/EricSteinberger/PokerRL) | MIT | 多智能体 Deep RL、Deep CFR 框架 | **后续研究**,依赖和训练复杂度过高 |
| [Slumbot2019](https://github.com/ericgjackson/slumbot2019) | MIT | CFR+/MCCFR、部分多人支持 | **算法参考**,不进入首版运行链路 |
| [River Poker Solver](https://github.com/noambrown/poker_solver) | MIT | 河牌子博弈 CFR 变体 | **专项参考**,范围不足以支持完整 9 人实时 AI |
| [TexasSolver](https://github.com/bupticybee/TexasSolver) | AGPL-3.0/商业许可说明 | 高性能德州扑克 GTO 求解 | **不直接集成**,许可证和求解复杂度不适合首版服务 |
| [postflop-solver](https://github.com/b-inary/postflop-solver) | AGPL-3.0 | Rust 翻牌后 DCFR 求解 | **不直接集成**,开源开发已暂停且许可证限制较强 |
### 18.2 用户提供链接的具体判断
#### PokerKit
优点:
- Python 3.11+ 纯 Python 库。
- 支持无限注德州扑克及多种扑克变体。
- 提供牌局模拟、牌型评估和统计分析能力。
- MIT 许可证,测试覆盖和维护活跃度较好。
使用方式:
- 用于策略单元测试和离线场景生成。
- 用于校验某些公开牌局序列和策略回归。
- 不用它替换当前 `game` 服务的发牌、下注或底池规则。
#### OpenSpiel
优点:
- 支持多玩家、不完全信息游戏和多种 CFR/RL 算法。
- C++ 核心并提供 Python 接口。
- 研究生态成熟,适合后续自博弈和算法评估。
首版不采用原因:
- 当前目标是可配置、低复杂度、可快速接入的 9 人锦标赛 AI。
- 需要重新适配当前项目状态、下注树和锦标赛流程。
- 训练、评估和部署成本显著高于规则策略方案。
#### PokerHandEvaluator
优点:
- 支持 5、6、7 张牌评估。
- Python 包可直接安装。
- 牌型查表速度适合作为蒙特卡洛核心。
- Apache-2.0 许可证。
使用方式:
- 首版 Python AI 服务直接依赖 `phevaluator`。
- 在服务启动和 CI 中固定版本并执行牌型回归测试。
#### GitHub `poker-ai` Topic
Topic 页面适合发现项目,但不能直接作为选型依据。调研中发现部分近期仓库存在以下情况:
- 没有明确许可证。
- 只有说明、演示或商业联系方式,缺少完整实现。
- Star 和使用样本很少。
- 声称支持实时强 AI,但缺少测试、训练数据和可复现实验。
因此 Topic 中的新项目只能进入候选池,必须逐个核对源码、测试、许可证和可复现性后再采用。
## 19. 实施阶段
### 阶段 1:数据与管理后台
- 新增策略档案、账号绑定、决策记录和校准结果表。
- 新增后台菜单、权限、列表和表单。
- 支持选择已有普通用户账号并绑定策略。
- 实现配置版本和下一手牌生效机制。
### 阶段 2:AI 服务最小闭环
- 创建 Python 3.11 + FastAPI 服务。
- 集成 PokerHandEvaluator。
- 实现翻牌前范围、基础翻牌后胜率和底池赔率策略。
- 实现 5 档强度、固定参数和混合随机策略。
- 实现健康检查、幂等和结构化日志。
### 阶段 3:当前游戏服务接入
- 新增独立 AI 绑定检查和手牌策略快照。
- 组装公平决策 DTO。
- 调用 AI 决策接口。
- 复用现有合法动作计算和动作处理链。
- 实现思考延迟、重试、安全兜底和决策记录。
- 保证真人用户原有操作链不受影响。
### 阶段 4:对手统计与校准
- 基于公开动作事件维护单场对手统计。
- 实现标准 9 人校准命令。
- 建立基准对手和场景版本。
- 在后台展示校准结果和决策详情。
- 完成 100 AI、20 决策/秒容量验证。
### 后续迭代
- 完整 ICM、泡沫期和奖励结构计算。
- 更精细的范围推断和牌面抽象。
- CFR/子博弈求解或强化学习策略实验。
- 长期模型评估体系。
- 如产品需要,再独立评估大模型聊天和语音能力。
## 20. 验收标准
### 20.1 业务验收
- 已有普通账号可绑定和关闭 AI,不改变账号其他业务行为。
- AI 账号正常报名、分桌、淘汰、排名和领奖。
- 同桌可存在任意数量 AI,包括 9 个 AI。
- 玩家端不显示 AI 标识。
- 策略修改和关闭绑定从下一手牌生效。
### 20.2 公平性验收
- 决策请求中不存在其他玩家隐藏底牌、未来公共牌或牌堆顺序。
- AI 返回动作只能在当前合法动作和金额范围内执行。
- AI 服务不能直接读取游戏运行态隐藏 Redis 数据。
- 决策日志可以追溯实际输入、策略版本和随机种子。
### 20.3 策略验收
- 调整松紧度、激进度、诈唬率等参数后,动作分布存在可测差异。
- 同一策略在相同局面中允许按权重做出不同动作。
- 5 档强度在足够样本的固定基准环境中形成稳定区分。
- 单场对手统计会影响高适应度策略,但不会跨比赛保留。
### 20.4 稳定性验收
- AI 服务超时、非法返回和 Redis 故障不会阻塞牌桌。
- 失败后只执行过牌或弃牌的安全兜底。
- 过期响应和重复响应不会重复执行动作。
- 支持约 100 个同时参赛 AI 和峰值 20 次决策/秒。
- AI 日志故障不会破坏正常牌局推进。
### 20.5 回归验收
- 未绑定 AI 的真人账号操作行为与改造前一致。
- 当前项目的合法动作、加注、全下、边池和轮次测试继续通过。
- 旧 Bot 代码和数据不作为新 AI 的依赖。
## 21. 主要风险与控制措施
| 风险 | 控制措施 |
| --- | --- |
| 决策输入误带隐藏信息 | 独立公平 DTO、字段白名单和自动化测试 |
| Python 计算耗时过高 | PHE 查表、有限蒙特卡洛、缓存、多进程和硬超时 |
| AI 动作与当前状态过期 | 使用动作时间点、请求 ID 和执行前二次校验 |
| 多个 AI 行为过于一致 | 混合策略、独立种子和策略参数扰动 |
| 策略参数难以解释 | 固定参数、结构化原因码和决策日志 |
| 强度等级名不副实 | 固定基准场景、大样本校准和版本化结果 |
| 对手小样本误判 | 最小样本门槛和向默认值收缩 |
| AI 服务故障拖慢牌桌 | 非阻塞调用、一次重试和安全兜底 |
| 开源许可证风险 | 首版仅直接采用 Apache-2.0/MIT 组件;AGPL 项目只作研究参考 |
| 配置中途变化导致行为不一致 | 每手牌策略快照和版本记录 |
## 22. 当前代码依据
以下文件用于确认当前实现,不表示其中已经存在本方案的新 AI 能力。
| 当前事实 | 代码依据 |
| --- | --- |
| 单桌人数上限为 9 | `game/app/Service/User/Calculator.php:13`、`game/app/Service/Constants/PositionConst.php:14` |
| 比赛包含盲注、报名截止等级、结束等级和初始筹码 | `game/app/Model/PokerRace.php:15`、`:26`、`:27`、`:31` |
| 当前模型记录国际扑克玩法 | `game/app/Model/PokerRace.php:20`、`:70` |
| 牌局阶段包含翻牌前、翻牌、转牌、河牌和摊牌 | `game/app/Service/Constants/RoundConst.php:15` 至 `:19` |
| 动作包含过牌、加注、跟注、全下和弃牌 | `game/app/Service/Constants/ActionConst.php:11` 至 `:15` |
| 轮到用户时计算合法动作并安排超时过牌/弃牌 | `game/app/Service/Action/Policy/NormalProcessorPolicy.php:32`、`:45`、`:48` |
| 合法动作结果带动作时间点和权限集合 | `game/app/Service/Privilege/Calculator.php:184` 至 `:185` |
| 加注权限提供最小和最大加注额 | `game/app/Service/Privilege/Raise.php:93` 至 `:94` |
| 用户动作通过统一 Handler 执行并推进牌局 | `game/app/Service/Action/Handler.php:56`、`:87` 至 `:102` |
| 房间信息包含公共牌、底池和筹码信息 | `game/app/Service/Information/RoomInformation.php:26` 至 `:29` |
| 用户信息包含自己的手牌、筹码和操作权限 | `game/app/Service/Information/UserInformation.php:124`、`:157`、`:184` |
| 操作完成后存在统一事件对象 | `game/app/Event/AfterAction.php` |
| 操作完成后保存房间、用户和公开动作记录 | `game/app/Listener/AfterAction/DataSaveListener.php` |
| 当前管理后台采用 Poker 模块菜单、权限、路由、列表和表单模式 | `poker-web/modules/poker/configurations/menus.yaml`、`permissions.yaml`、`src/http/routes/backend.php` |
| 管理后台技术栈和模块结构 | `poker-web/README.md` |
## 23. 最终方案结论
首版采用“当前 PHP 牌局权威 + 独立 Python 决策服务 + 现有管理后台配置”的组合:
```text
普通账号和现有赛事流程保持不变
+ 独立 AI 账号绑定与策略档案
+ 当前项目输出公平状态和合法动作
+ Python 规则策略与蒙特卡洛决策
+ 当前项目最终校验并执行动作
+ 单场对手统计、决策审计和标准化校准
```
该方案优先保证规则一致、公平可审计和较低实现复杂度,同时为后续 ICM、CFR、强化学习和更高级策略保留清晰扩展边界。