适用场景
这套方案适合想亲手跑通一个"能自己打游戏"的智能体的开发者:用多模态大模型看画面做决策,用 agent-wow 负责抓屏、记忆和执行键鼠动作。典型用途是长时任务智能体的研究、多模态决策链路的验证,以及"视觉输入 → 动作输出"闭环的工程练习。
需要提前说清楚一件事:不要把自动化脚本接到暴雪官方服务器上。自动操作违反游戏用户协议,账号可能被永久封禁。所有实验请在自建的本地私服、单人离线环境或官方允许的测试环境里做。下面的步骤默认走本地私服。
环境与前置条件
| 项目 | 建议 |
|---|---|
| 操作系统 | Windows 10/11 64 位(游戏客户端与输入注入在这个平台上最省事);agent-wow 本体也可跑在 Linux/macOS,只是动作执行需要另接一层 |
| Python | 3.10 及以上,具体最低版本以 agent-wow 官方文档为准 |
| 内存 | 16 GB 起,32 GB 更稳(游戏客户端 + 抓屏缓冲 + Python 进程) |
| 显存 | 走云端 API 时可忽略;若本地跑视觉模型,建议 12 GB 以上 |
| 磁盘 | SSD,预留 30 GB 以上,录像回放很占空间 |
| 网络 | 能稳定访问模型 API,建议有线网络,避免抖动导致动作错位 |
| 其他 | 一个可用的私服/离线客户端;一个 ASTRA_API_KEY(写进环境变量,不要进代码库) |
合规与安全边界(先做这一步):把动作空间限制在"移动、选目标、攻击、拾取、吃喝"这类低风险操作上。交易、邮件、删除物品、公开发言、退出游戏这些动作,直接写进黑名单,不让模型有权限碰。
分步骤部署
第 1 步:起一个本地测试环境
把私服跑起来,客户端用窗口化或无边框窗口模式,分辨率固定成 1280×720 或 1920×1080 之一,不要用独占全屏。固定分辨率是后面视觉链路能稳定工作的前提——模型看到的画面比例变了,动作坐标就全错。
客户端里新建一个角色,放到新手村附近,确保周围有可攻击的低等级怪。
第 2 步:准备 Python 环境与目录
```bash
mkdir agent-wow-lab && cd agent-wow-lab
python3 -m venv .venv
Windows PowerShell:
.venv\Scripts\Activate.ps1
macOS / Linux:
source .venv/bin/activate
python -m pip install --upgrade pip
```
目录结构建议这样分,后面回放和日志才好整理:
```
agent-wow-lab/
├── config/
│ ├── agent.yaml # 模型、感知、执行配置
│ └── actions.yaml # 动作白名单/黑名单
├── tasks/
│ └── grind.yaml # 任务定义
├── data/
│ ├── screenshots/ # 单帧截图
│ └── replays/ # JSONL 回放记录
└── logs/
```
第 3 步:安装并初始化 agent-wow
用官方仓库给出的安装方式(源码安装或 pip 包),版本号以官方文档当前版本为准。装完先跑一次自检:
```bash
python -m agent_wow --help
python -m agent_wow doctor
```
doctor 通常会检查:抓屏权限、输入注入权限、配置文件能否解析、API Key 是否存在。看到全绿或 "all checks passed" 才算这一步成功。如果 agent-wow 的 CLI 参数名与本文不同,以 --help 输出为准。
第 4 步:接入 GPT-6 Astra
先把密钥放进环境变量,别写进 YAML:
```bash
Windows PowerShell(当前会话生效)
$env:ASTRA_API_KEY = "<你的 key>"
macOS / Linux
export ASTRA_API_KEY="<你的 key>"
```
然后写 config/agent.yaml:
```yaml
model:
provider: astra
model: <以官方文档当前模型名为准>
api_key_env: ASTRA_API_KEY
base_url: <以官方文档提供的接入地址为准>
max_output_tokens: 1024
timeout_seconds: 60
max_retries: 3
temperature: 0.2
perception:
capture_mode: window
window_title_contains: "World of Warcraft"
capture_interval_ms: 1000
downscale_width: 1280
save_frames: true
actuator:
backend: input
action_delay_ms: 400
max_actions_per_minute: 60
```
几个参数的含义:capture_interval_ms 控制模型看画面的频率,1000ms 是"一秒决策一次",长时任务下足够;max_actions_per_minute 是节流阀,防止模型连续输出动作把客户端点乱;temperature 调低是为了让决策稳定。
单独验证模型连通性,写个最小脚本:
```python
import base64, json, os
from openai import OpenAI # 若 Astra 提供兼容接口;否则用官方 SDK
client = OpenAI(
api_key=os.environ["ASTRA_API_KEY"],
base_url=os.environ.get("ASTRA_BASE_URL"), # 以官方文档为准
)
def decide(image_path: str, state: dict) -> dict:
with open(image_path, "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = client.chat.completions.create(
model=os.environ["ASTRA_MODEL"], # 模型名以官方文档为准
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": [
{"type": "text", "text": json.dumps(state, ensure_ascii=False)},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}},
]},
],
temperature=0.2,
response_format={"type": "json_object"}, # 结构化输出支持情况以官方文档为准
)
return json.loads(resp.choices[0].message.content)
```
AI 词典:系统提示词">系统提示词是整个项目里最该反复打磨的东西,第一版可以这样写:
```
你是《魔兽世界》的操作代理。你会收到一张游戏截图和当前状态(血量、目标、坐标)。
只输出 JSON,不要输出任何其他文字:
{"reasoning": "一句话推理", "action": "动作名", "args": {}, "confidence": 0.0~1.0}
可用动作只能从白名单里选:move_to / turn_left / turn_right / target_nearest /
attack / use_ability / loot / eat_food / wait
规则:
1) 血量低于 40% 时优先 eat_food 或后退;
2) 没有目标时先 target_nearest;
3) 画面信息不足或置信度低于 0.5 时输出 wait;
4) 永远不要输出交易、邮件、删除物品、公开发言类动作。
```
第 5 步:配动作白名单
config/actions.yaml 里把动作和键位绑定写清楚,白名单之外的动作一律不执行:
```yaml
whitelist:
target_nearest: {type: key, key: "TAB"}
attack: {type: key, key: "1"}
use_ability: {type: key, key: "{slot}"} # slot 由模型给出,需做范围校验
loot: {type: key, key: "F"}
eat_food: {type: key, key: "2"}
move_to: {type: click_world, coord: "{x,y}"}
turn_left: {type: key, key: "A", hold_ms: 300}
turn_right: {type: key, key: "D", hold_ms: 300}
wait: {type: noop}
blacklist: [trade, mail, delete_item, chat_say, logout, use_item_quality_high]
```
use_ability 这类带参数的动作用之前一定要做范围校验(比如 slot 只能是 1~9),否则模型偶尔给个越界值就可能触发意料之外的操作。
第 6 步:定义第一个任务
tasks/grind.yaml —— 目标很简单:在半径 30 码内找怪、打死、拾取,循环 30 分钟。
```yaml
name: grind_nearby_mobs
duration_minutes: 30
goal: 击杀附近的低等级怪物并拾取掉落,血量低于 40% 时恢复
success_criteria:
min_kills: 20
stop_conditions:
- hp_below_percent: 20
- no_progress_steps: 60 # 连续 60 步位置无变化就停
- consecutive_errors: 5
```
第 7 步:先干跑,再放开
干跑模式只决策不执行,用来确认"看到的画面"和"想做的动作"对得上:
```bash
python -m agent_wow run --config config/agent.yaml --task tasks/grind.yaml --dry-run
```
观察日志里每一步的 action 是否合理:怪在右边却一直输出 turn_left,说明坐标映射有问题;一直输出 wait,说明提示词或截图质量有问题。
确认无误后去掉 --dry-run 正式跑:
```bash
python -m agent_wow run --config config/agent.yaml --task tasks/grind.yaml --replay data/replays/session-001.jsonl
```
验证部署是否成功
按顺序跑这三条,全部通过就说明链路是通的:
```bash
1. 环境自检
python -m agent_wow doctor
2. 抓一帧画面,确认不是黑屏
python -m agent_wow capture --config config/agent.yaml --out data/screenshots/check.png
3. 单步决策,不执行动作
python -m agent_wow step --config config/agent.yaml --task tasks/grind.yaml
```
预期结果:
- 第 1 条:各项检查通过,没有红色项。
- 第 2 条:
data/screenshots/check.png打开后是清晰的游戏画面,能看到角色、地面、怪物,不是纯黑或纯桌面壁纸。 - 第 3 条:终端打印出一步完整的 JSON 决策,包含
reasoning、action、confidence,且action落在白名单里。
再进一步,让它在离线环境里真的打 30 分钟,然后统计 data/replays/session-001.jsonl 的行数与动作分布:
```bash
wc -l data/replays/session-001.jsonl
python -m agent_wow replay stats --file data/replays/session-001.jsonl
```
如果击杀数达到 min_kills、中途没有触发停止条件,说明端到端闭环跑通了。
常见报错与解决
1. 截图全黑或截到的是桌面
原因:游戏处于独占全屏,或者抓屏工具没有拿到正确的窗口句柄。
解决:把客户端改成窗口化/无边框窗口,并在配置里明确窗口标题关键字,然后用第 2 步的 capture 命令复验。
```bash
python -m agent_wow capture --config config/agent.yaml --out data/screenshots/check.png
```
2. 429 Too Many Requests 或请求超时
原因:决策频率过高,或者失败重试没有退避。
解决:把 capture_interval_ms 调大到 1500~2000,降低截图分辨率,并确认 max_retries 已开启指数退避。
```yaml
perception:
capture_interval_ms: 2000
downscale_width: 960
model:
max_retries: 3
```
3. 模型返回的内容不是合法 JSON,解析报 JSONDecodeError
原因:模型输出了解释性文字或 Markdown 代码块。
解决:在提示词里强调"只输出 JSON",启用结构化输出(支持情况以官方文档为准),并在解析层加兜底——解析失败就当 wait 处理,不要抛异常中断任务。
```python
try:
action = json.loads(text)
except json.JSONDecodeError:
action = {"action": "wait", "args": {}, "confidence": 0.0}
```
4. 动作发出去了,游戏没反应
原因:游戏以管理员权限运行,而 agent-wow 不是;或者当前是中文输入法,按键被输入法截走。
解决:用管理员权限启动终端再跑;跑之前把输入法切到英文。Windows 下还可以改用游戏内插件通道下发指令,稳定性通常好于模拟键鼠。
```powershell
以管理员身份打开 PowerShell 后
.venv\Scripts\Activate.ps1
python -m agent_wow run --config config/agent.yaml --task tasks/grind.yaml
```
5. 任务跑几分钟后卡住,角色原地不动
原因:模型陷入循环,反复输出同一个动作;或者目标名物已死亡但状态没更新。
解决:确认 stop_conditions.no_progress_steps 已生效;缩短记忆窗口,只保留最近若干步;定期把当前状态重新喂给模型做一次"重新规划"。
```yaml
memory:
window_steps: 12
replan_every_steps: 20
```
后续维护
备份:config/、tasks/ 和回放文件是核心资产。配置文件用 Git 管理(密钥走环境变量,不进仓库),回放数据按日期归档到对象存储或本地冷盘。
升级:升级 agent-wow 或切换模型名之前,先读官方 changelog,注意动作接口和配置字段是否变化。升级后至少重跑一次 doctor 和 --dry-run 干跑,再放长时任务。
日志:给日志加轮转,避免长时任务把磁盘写满。建议保留的字段包括:时间戳、步骤序号、动作、置信度、token 消耗、耗时。
```bash
简易轮转(Linux/macOS)
python -m agent_wow run --config config/agent.yaml --task tasks/grind.yaml \
>> logs/run-$(date +%F).log 2>&1
```
监控:长时任务至少盯这几个指标——动作成功率、每分钟 token 消耗与成本、连续 wait 的次数、位置是否长期不变。任何一个异常都可以触发自动停止,别让它在无人看管时一直烧额度。
回放复盘:replays/*.jsonl 里每行是"截图路径 + 状态 + 模型输出 + 实际执行动作",出错时按时间轴回看,通常一眼就能看出是感知错了、提示词没覆盖到、还是动作映射写反了。
安全复盘:每月检查一次黑名单是否仍覆盖高风险动作,确认没有人为了"让它更聪明"而把交易、邮件、公开发言权限放开。
