如何让机器人学会打牌?陪伴机器人接入牌类AI决策API的技术方案
陪伴机器人是近两年硬件赛道的热门方向,尤其是面向老年人的陪伴场景。其中一个高频需求是**"陪老人打牌"**——麻将、掼蛋、斗地主是中国老年人最常见的娱乐活动。
但让机器人"会打牌"不是一个简单的问题。本文分享我们为机器人陪伴场景设计的牌类AI决策API方案,包括技术架构、接口设计、端云协同策略和实际部署经验。
一、机器人打牌的技术挑战
| 挑战 | 具体问题 |
|---|---|
| 决策能力 | 机器人需要实时计算最优出牌,不能只随机出 |
| 多品类 | 不同老人喜欢不同牌:麻将、掼蛋、斗地主 |
| 算力限制 | 机器人端侧算力有限(通常是 ARM 芯片) |
| 延迟要求 | 出牌不能太慢(>2秒用户体验差),也不能太快(<0.5秒不像人) |
| 难度适配 | AI太强老人没兴趣,太弱没挑战 |
核心矛盾:高质量的博弈AI需要 GPU 推理,但机器人端侧没有 GPU。
二、端云协同架构
我们的方案是端侧识别 + 云端决策:
┌──────────────────────────────┐
│ 陪伴机器人(端侧) │
│ │
│ 摄像头 → 牌面识别(本地CV) │
│ 麦克风 → 语音交互 │
│ 机械臂 → 出牌执行 │
│ │
│ 状态管理器:维护当前对局状态 │
│ ↓ HTTP/WebSocket │
└──────────────────────────────┘
↓
┌──────────────────────────────┐
│ 云端AI决策服务 │
│ │
│ POST /api/v1/decision │
│ 输入:game_state │
│ 输出:最优出牌 + 置信度 │
│ │
│ 延迟:<300ms │
│ 支持:麻将×8 + 掼蛋 + 斗地主 │
└──────────────────────────────┘
为什么不做端侧推理?
我们测试过在 RK3588(机器人常用芯片)上跑 ONNX 推理:
| 方案 | 延迟 | 准确率 | 部署难度 |
|---|---|---|---|
| 端侧 FP32 | 1200ms | 100% | 高(每台都要部署) |
| 端侧 INT8 量化 | 450ms | 92% | 高 |
| 云端 API | 180ms + 80ms网络 = 260ms | 100% | 低(一次集成) |
云端方案在延迟、准确率和部署成本上都更优。端侧只需要做牌面识别和状态维护。
三、API 调用流程
3.1 一次出牌的完整流程
import requests
import time
API_URL = "https://api.example.com/api/v1/decision"
API_KEY = "your_api_key"
def robot_play_turn(game_state):
"""机器人出牌:调用云端API获取决策"""
# 1. 调用决策API
resp = requests.post(API_URL, json={
"game_type": "sichuan_mahjong",
"game_state": game_state,
"options": {
"temperature": 1.5, # 中等难度,让老人能赢
"top_k": 3,
"include_analysis": False # 机器人场景不需要分析
}
}, headers={"Authorization": f"Bearer {API_KEY}"})
result = resp.json()
action = result["action"]
# 2. 模拟思考时间(太快不像人)
think_time = random.uniform(1.0, 3.0)
time.sleep(think_time)
# 3. 控制机械臂出牌
robot_arm.play_tile(action["tile"])
# 4. 可选:语音播报
if action["type"] == "hu":
tts.speak("我胡啦!")
elif action["type"] == "peng":
tts.speak("碰!")
return action
3.2 难度自适应
一个重要的产品细节:AI 不能一直赢。我们通过动态调整 temperature 实现难度自适应:
class DifficultyAdapter:
"""根据老人的胜率动态调整AI难度"""
def __init__(self, target_win_rate=0.45):
self.target = target_win_rate # 目标:老人赢45%
self.history = [] # 近20局胜负记录
self.temperature = 1.5 # 初始中等难度
def update(self, human_won: bool):
self.history.append(human_won)
if len(self.history) > 20:
self.history.pop(0)
current_rate = sum(self.history) / len(self.history)
# 老人赢太少 → 降低AI强度(升高temperature)
if current_rate < self.target - 0.1:
self.temperature = min(self.temperature + 0.3, 5.0)
# 老人赢太多 → 提高AI强度(降低temperature)
elif current_rate > self.target + 0.1:
self.temperature = max(self.temperature - 0.2, 0.5)
def get_temperature(self):
return self.temperature
四、WebSocket 方案(低延迟场景)
对于延迟敏感的实时对局,HTTP 轮询不够高效。我们也支持 WebSocket 长连接:
import asyncio
import websockets
import json
async def robot_game_session():
"""WebSocket 长连接方案"""
async with websockets.connect("wss://api.example.com/ws/game") as ws:
# 认证
await ws.send(json.dumps({"type": "auth", "api_key": API_KEY}))
# 创建对局
await ws.send(json.dumps({
"type": "create_game",
"game_type": "guandan",
"players": 4
}))
# 游戏循环
async for message in ws:
data = json.loads(message)
if data["type"] == "your_turn":
# 轮到机器人出牌
decision = data["suggested_action"]
await asyncio.sleep(random.uniform(1, 3))
await ws.send(json.dumps({
"type": "play",
"action": decision
}))
elif data["type"] == "game_over":
print(f"Game ended. Winner: {data['winner']}")
break
五、实际部署数据
我们与某款陪伴机器人做了小批量测试(50台设备,持续2个月):
| 指标 | 数据 |
|---|---|
| 日均对局次数 | 3.2 局/台 |
| API 平均延迟 | 187ms |
| API P99 延迟 | 340ms |
| 用户满意度 | 82%(满意/非常满意) |
| 最受欢迎品类 | 四川麻将 > 长沙麻将 > 掼蛋 |
核心发现:老人更在意"机器人像不像真人"而非"AI强不强"。模拟思考时间和语音播报对体验的影响大于决策质量。
六、踩坑记录
- 网络中断处理:机器人 WiFi 不稳定时 API 调用超时。解决:端侧缓存一个简单的规则引擎做 fallback,网络恢复后切回云端
- 牌面识别准确率:摄像头角度和光线影响 OCR。解决:加了牌面状态校验,识别结果与历史不一致时请求用户确认
- 出牌速度:AI 秒出让老人感觉"不真实"。加了 1-3 秒随机延迟后用户满意度提升了 15 个百分点
七、小结
机器人陪打牌的技术核心是端云协同:端侧做感知和交互,云端做决策。关键 takeaway:
- 云端 API 比端侧推理在延迟、准确率、部署成本上都更优
- 难度自适应比固定难度的用户体验好得多
- "像人"比"AI强"更重要——模拟思考时间和语音播报是关键
作者团队:长沙赢麻哒文化传播 | malinguo.com