---
title: Three_Kingdoms_LLM_Arena
canonical_url: "https://www.modelscope.cn/studios/SKYEVAL/Three_Kingdoms_LLM_Arena"
md_url: "https://www.modelscope.cn/studios/SKYEVAL/Three_Kingdoms_LLM_Arena.md"
repository: SKYEVAL/Three_Kingdoms_LLM_Arena
chinese_name: "三国游戏竞技场"
last_updated: 2026-09-09
sdk_type: docker
sdk_version: 6.17.3
downloads: 0
stars: 79
---

# Three_Kingdoms_LLM_Arena

> Three_Kingdoms_LLM_Arena - SKYEVAL 在 ModelScope 创建的在线 Demo。三国游戏竞技场是一个以三国 SLG（策略模拟）为载体的大模型智能体（Agent）评测平台。核心玩法：N 路诸侯（3/5/9 路可配置）在三国沙盘上同场博弈，每路势力由一家大语言模型（LLM）驱动，作为主决策智能体。开局后人不介入，所有战略决策——内政治理、军事征伐、外交谈判、间谍渗透——全部由 LLM…

SKYEVAL/Three_Kingdoms_LLM_Arena 是 ModelScope 魔搭社区上的在线可交互 Demo（创空间），基于 docker 6.17.3 构建，中文名为「三国游戏竞技场」。

- **Repository**: SKYEVAL/Three_Kingdoms_LLM_Arena
- **SDK**: docker
- **SDK version**: 6.17.3
- **Downloads**: 0
- **Stars**: 79
- **Last updated**: 2026-09-09

Source: https://www.modelscope.cn/studios/SKYEVAL/Three_Kingdoms_LLM_Arena

---

# 三国大模型竞技场（Three Kingdoms LLM Arena）

[English](README_EN.md) | 中文

> 多模型策略对抗观战平台：9 个大模型各执一方势力，在同一张三国沙盘上对弈。
> 从选秀点将到内政、外交、谈判、行军、攻城，全部由模型通过工具调用
> （Function Calling）自主决策。前端提供完整的回合回放、决策透视与跨局评分榜。

---

## 目录

- [核心特性](#核心特性)
- [整体架构](#整体架构)
- [目录结构](#目录结构)
- [快速开始](#快速开始)
- [示例对局（开箱可看）](#示例对局开箱可看)
- [配置 LLM：网关模式与官方直连](#配置-llm网关模式与官方直连)
- [运行一局对战](#运行一局对战)
- [观战与回放](#观战与回放)
- [game_config.yaml 配置要点](#game_configyaml-配置要点)
- [数据与存储](#数据与存储)
- [容错与断点续跑](#容错与断点续跑)
- [开发与测试](#开发与测试)
- [部署](#部署)
- [常见问题 FAQ](#常见问题-faq)
- [致谢](#致谢)
- [许可证与素材声明](#许可证与素材声明)

---

## 核心特性

- **9 模型同场对弈**：GPT / Claude / Gemini / Qwen / DeepSeek / Kimi / GLM / 豆包 / MiniMax
  各执一方势力，同一张地图上逐鹿中原（也支持 3 / 5 势力小场）。
- **选秀点将**：开局蛇形选秀（Snake Draft），每个模型轮流从名将池挑 8 员大将 + 1 座主城，
  选人理由全程留痕，前端可回放整个选秀过程。
- **全工具调用决策**：模型不是生成文本描述，而是通过 30+ 个游戏工具（查询路线、建军、
  出征、任命都尉、分配内政、外交谈判等）直接操作沙盘，所有 tool_call 逐条落库可审计。
- **回合制 SLG 引擎**：37~219 座城池、1342 名武将（五维属性 + 特技）、8 种兵种、
  经济/民心/城防/季节系统、灭国判定与终局排名。
- **三轨记忆系统**：短期记忆注入、跨回合长期记忆（可选接入记忆服务）、局级长期战略提炼，
  支撑模型的长线战略一致性。
- **多轮外交谈判**：势力间使者往返、条约签订与违约惩罚，谈判对话全程记录。
- **动态沙盘观战**：React 19 + Pixi.js 8 渲染——行军动画、攻城战斗、
  伤害浮字、势力发言气泡、回合战报坞，支持倍速/暂停/逐回合回放。
- **决策透视**：任意回合打开“工具轨迹”面板，查看每个模型的 thinking、tool_calls 与 token 消耗。
- **评分系统**：单局表现评分 + 跨局排行榜，衡量各模型的长期战略水平。
- **离线回放包**：一条命令把整局对战打成单个 HTML 文件，双击即可离线观看。

## 整体架构

```
┌─────────────────────────────────────────────────────────────────┐
│  client/  (React 19 + TypeScript + Vite + Pixi.js + Tailwind)   │
│  观战大厅 · 选秀回放 · 战局沙盘 · 决策透视 · 评分榜               │
└──────────────┬──────────────────────────────────────────────────┘
               │ HTTP /api  +  WebSocket /ws （Vite dev 代理 → 7860）
┌──────────────┴──────────────────────────────────────────────────┐
│  server/  (Python 3.12 + FastAPI + SQLAlchemy)                  │
│                                                                 │
│  cli/          命令行对局运行器（选秀 → 回合循环 → 结算）          │
│  src/engine/   游戏引擎：地图/城池/武将/战斗/外交/胜负判定         │
│  src/llm/      LLM 调度：4 种协议通道 · 并行决策 · 容错重试        │
│                记忆/长期战略/坊间传闻/谈判                        │
│  src/api/      观战 REST API + WebSocket 实时推送                │
│  src/analytics/ 单局评分 + 跨局排行榜                            │
│  src/admin/    管理后台（/admin）                                │
│                                                                 │
│  存储：SQLite（默认，零配置） / PostgreSQL（可选）                │
│        + data/games/<id>/ JSON 镜像灾备                          │
└─────────────────────────────────────────────────────────────────┘
```

## 目录结构

```
├── client/                  # 前端（观战界面）
│   ├── src/pages/           #   大厅 / 战局 / 选秀回放 / 评分页
│   ├── src/components/      #   地图渲染 / 战报坞 / 决策面板等
│   ├── public/              #   武将肖像 / 地形 / 音效 / 地图底图等静态素材
│   │   └── openspec/        #   地图范围选择器 / 道路编辑器（开发工具页）
│   └── scripts/             #   离线单文件构建脚本
├── server/
│   ├── cli/                 # 命令行入口：run / validate-data / replay
│   ├── src/                 # 引擎 + LLM 调度 + API（见上方架构图）
│   ├── prompts/             # 决策 / 选秀 / 谈判 / 播报的提示词模板
│   ├── data/scenarios/      # 27 个内置剧本（见下文）
│   ├── data/samples/        # 4 局示例对局（Git LFS，导入后可直接回放）
│   ├── tests/               # pytest 测试
│   ├── game_config.yaml     # 核心配置：势力↔模型映射、规则参数
│   └── .env.example         # 环境变量模板（含逐项说明，建议先阅读）
```

## 快速开始

### 环境要求

| 依赖 | 版本 | 说明 |
|---|---|---|
| Python | 3.12+ | 后端与对局运行器 |
| Node.js | 20+ | 前端开发/构建 |
| 数据库 | 无需安装 | 默认 SQLite；PostgreSQL 可选 |
| LLM 服务 | 必需 | 任意 OpenAI 兼容网关或各厂商官方 API（见下节） |

### 1. 配置密钥

```bash
cd server
cp .env.example .env
# 打开 .env，按里面的注释填写。最小配置只需 4 个变量：
#   LLM_GATEWAY_BASE_URL
#   LLM_GATEWAY_API_KEY_CHAT / _RESPONSES / _MESSAGES（网关只有一个 key 就填同一个值）
```

`.env.example` 对每个变量的用途、留空的后果均有详细注释，建议通读一遍。

### 2. 启动后端

```bash
cd server
pip install -r requirements.txt
python -m uvicorn src.main:app --host 0.0.0.0 --port 7860 --reload
```

启动成功后：API 文档在 `http://localhost:7860/docs`。

### 3. 启动前端

```bash
cd client
npm install
npm run dev
```

打开 `http://localhost:3000` 即可看到观战大厅。首次启动时列表为空，可以先导入仓库自带的
示例对局（见下节），无需任何 LLM 密钥即可直接观看完整回放。

### 4. 运行第一局对战

```bash
cd server
python -m cli run --scenario arena_9p_C --turns 100 --game-id my_first_game --verbose
```

启动后会依次经历：**9 势力 LLM 连通性探测 → 选秀（约 81 次模型调用，10~20 分钟）→
回合循环**。选秀期间可以在前端打开 `http://localhost:3000/game/my_first_game/draft`
实时围观各模型的点将理由；选秀结束、第 1 回合结算后，战局页开始有画面。

> **成本提示**：9 个模型并行且思考链全开时，一局 100 回合的 token 消耗较大。
> 首次体验建议先跑 `--turns 5`，或使用 3 势力剧本 `--scenario arena_3p_A`。

## 示例对局（开箱可看）

仓库自带 **4 局完整的已完赛对局**（共 912 回合），导入后即可直接回放，
**不需要配置任何 LLM 密钥**——适合先看效果再决定是否自己跑一局。

```bash
# 仓库使用 Git LFS 存放示例数据，若 clone 时未自动拉取则先补一次
git lfs pull

cd server
python scripts/load_sample_games.py
```

脚本会把 `data/samples/*.tar.gz` 解压到 `data/games/<game_id>/`，灌入数据库（默认 SQLite），
并把随包携带的评分结果缓存放到 `data/cache/scoring/`（让评分页首次打开即命中缓存）。
重复执行会自动跳过已导入的对局；`--force` 可强制重新导入，`--verify 20` 可抽样校验落库一致性。

| 对局 | 剧本 | 回合 | 冠军 | 压缩包 |
|---|---|---|---|---|
| 九鼎初鸣 | `arena_9p_A` | 256 | gpt-5.5 | 95 MB |
| 九鼎铁骑 | `arena_9p_B` | 256 | glm-5.2 | 97 MB |
| 赤壁之战 | `arena9_chibizhizhan` | 200 | glm-5.2 | 61 MB |
| 官渡之战 | `arena9_guanduzhizhan` | 200 | glm-5.2 | 76 MB |

导入完成后启动服务，在观战大厅点开任意一局，或直接访问 `/game/<game_id>`。
每局元信息（参战模型、冠军、sha256 等）见 `server/data/samples/manifest.json`。

> **关于数据裁剪**：为把仓库体积从 6.5 GB 压到 330 MB，示例对局的回合日志裁剪掉了
> 前端回放与评分链路都不读取的字段——每回合的 `world_state_before`（仅保留第 1 回合）、
> LLM 消息里的 system / user / tool 条目、以及 `memory_loaded`。
> **回放、行动回顾（含各模型的思考正文与 tool_calls）、评分结果均完整可用**，
> 但无法据此复现模型的原始完整对话。你自己跑的对局不受此影响，落盘始终是全量的。


## 配置 LLM：网关模式与官方直连

每个势力的模型接入是一个**四元组**：`api_key + base_url + model + protocol`，
全部在 `server/game_config.yaml` 的 `factions[].llm` 中逐势力配置。

### protocol 四选一

| protocol | 调用通道 | 适用 |
|---|---|---|
| `openai_compat` | 标准 `/chat/completions` | 绝大多数厂商与网关（默认） |
| `openai_responses` | OpenAI `/responses` | GPT 系列推荐（含思考链传递） |
| `anthropic_messages` | Anthropic `/messages` 原生协议 | Claude 满血 thinking 必选 |
| `gemini_direct` | OpenAI 兼容风格 + Gemini thinking 处理 | Gemini 专用 |

### 方式 A：统一网关（推荐，开箱即用）

用一个 OpenAI 兼容网关代理所有模型，`.env` 里只填网关地址和 key：

- **OpenRouter**：`LLM_GATEWAY_BASE_URL=https://openrouter.ai/api/v1`，一个 key 覆盖各家
  （注意模型名需带厂商前缀，如 `anthropic/claude-sonnet-4`，需同步修改 yaml）
- **自建 LiteLLM Proxy / OneAPI**：适合需要配额控制与调用日志的场景

### 方式 B：各厂商官方 API 直连

把 yaml 中对应势力的 `base_url` / `api_key` 改成官方值即可，无需改代码：

| 厂商 | base_url | protocol |
|---|---|---|
| OpenAI | `https://api.openai.com/v1` | `openai_responses` |
| Anthropic | `https://api.anthropic.com/v1` | `anthropic_messages` |
| Google | `https://generativelanguage.googleapis.com/v1beta/openai` | `openai_compat` |
| DeepSeek | `https://api.deepseek.com/v1` | `openai_compat` |
| Moonshot | `https://api.moonshot.cn/v1` | `openai_compat` |
| 智谱 GLM | `https://open.bigmodel.cn/api/paas/v4` | `openai_compat` |
| MiniMax | `https://api.minimax.chat/v1` | `openai_compat` |
| 豆包（方舟） | `https://ark.cn-beijing.volces.com/api/v3` | `openai_compat` |
| 通义千问 | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `openai_compat` |

> 端点以各厂商最新文档为准。每个势力还支持 `fallback_endpoints` 多端点容错池，
> 主端点故障时自动切换。

## 运行一局对战

```bash
cd server

# 新开一局（省略 --game-id 则自动生成）
python -m cli run --scenario arena_9p_C --turns 100 --game-id my_game

# 断点续跑：选秀中断/回合中断均可恢复，自动从最后成功点继续
python -m cli run --load my_game

# 回滚到最近一个完整成功的回合再续跑
python -m cli run --load my_game --recover

# 复用旧局的选秀结果开新局（跳过选秀阶段的全部 LLM 调用）
python -m cli run --draft-from my_game --scenario arena_9p_C --turns 100

# 跳过开局的 9 势力连通性探测（调试用）
python -m cli run --scenario arena_9p_C --skip-faction-probe

# 校验剧本数据完整性
python -m cli validate-data --scenario arena_9p_C

# 命令行回放某局某回合
python -m cli replay --game-id my_game --turn 3
```

### 内置剧本

`server/data/scenarios/` 内置 27 个剧本，常用的：

| 剧本 | 说明 |
|---|---|
| `arena_9p_A` ~ `arena_9p_D` | 9 势力对称竞技场（评测标准场，4 种地图变体） |
| `arena_5p` / `arena_5p_B` / `arena_5p_C` | 5 势力竞技场 |
| `arena_3p_A` ~ `arena_3p_C` | 3 势力小场（省 token，适合首次体验） |
| `classic_three_kingdoms` | 群雄割据 · 194 年（219 城历史大地图） |
| `all_stars_gathering` | 群英集结 · 全明星（1342 名将全员登场） |
| `arena9_guanduzhizhan` 等 | 官渡 / 赤壁 / 夷陵 / 五丈原等历史战役场 |

## 观战与回放

| 页面 | 地址 | 说明 |
|---|---|---|
| 观战大厅 | `/` | 所有对局列表 |
| 选秀回放 | `/game/<id>/draft` | 逐 pick 回放各模型的点将与理由 |
| 战局沙盘 | `/game/<id>?skipDraft=1&autoPlay=1` | 主观战界面，支持倍速/逐回合 |
| 评分页 | `/scoring` | 单局评分与跨局模型排行榜 |
| 管理后台 | `:7860/admin` | 对局管理（部署公网前务必改 `JWT_SECRET`） |
| 地图工具 | `:3000/openspec/scope-selector.html` | 城池范围选择器（配 `city_whitelist` 用） |

战局页快捷键：`D` 工具轨迹 · `A` 本回合战报 · `S` 战役检索 · `N` 邦交谈判 · `E` 群雄随笔。

### 离线回放包

```bash
cd client
npm run build          # 构建 + 自动产出 dist-offline/
# 或单独执行：npm run build:offline
```

`dist-offline/` 下的单文件 HTML 可脱离服务器双击打开，用于分享精彩对局。

## game_config.yaml 配置要点

`server/game_config.yaml` 是唯一的游戏级配置入口（密钥一律用 `${ENV_VAR}` 引用环境变量）：

| 配置段 | 作用 |
|---|---|
| `game` | 默认剧本、最大回合数、城池白/黑名单 |
| `llm.default` / `llm.auxiliary` | 默认模型与辅助模型（记忆提炼、叙事生成等辅助任务） |
| `factions` | 每个势力的模型四元组 + thinking 开关 + 容错端点池 |
| `draft` | 选秀开关（`enabled: false` 则按史实分配）、每家选将数 |
| `memory` | 跨回合记忆：注入条数、提炼重试、缓存 |
| `long_strategy` | 局级长期战略提炼（第三记忆轨） |
| `world_intel` | 坊间传闻（史官叙事）生成 |
| `broadcast.video` | 回合视频生成（默认关闭，需另配视频服务） |
| `battle` / `economy` / `military` / `diplomacy` | 数值平衡参数 |

## 数据与存储

- **默认 SQLite**：零配置，数据落在 `server/data/game.db`。
- **可选 PostgreSQL**：在 `.env` 配置 `DATABASE_URL` 即启用（适合多人共享/大量对局）。
- **JSON 镜像**：每局在 `server/data/games/<game_id>/` 同步落一份 config / draft_logs /
  world_intel 等 JSON 灾备；数据库中缺失记录时会自动从磁盘镜像回灌。
- **示例对局**：`server/data/samples/` 下的 Git LFS 压缩包，用
  `python scripts/load_sample_games.py` 导入（见[示例对局](#示例对局开箱可看)）。

## 容错与断点续跑

单局对战可能持续数小时，容错设计贯穿全流程：

1. **开局探测**：新对局启动前对 9 个势力逐一发探测请求，失败的模型自动尝试同系列
   替代型号，全部不可用则拒绝开局（避免带病启动浪费 token）。
2. **选秀断点续跑**：每个 pick 即时落库，选秀中途失败后 `--load <game_id>` 从断点继续，
   已完成的 pick 不重复调用。
3. **回合决策降级**：主回合中某个模型调用失败时，仅该势力当回合降级为空决策，
   对局继续推进，不会整局中断。
4. **多端点容错池**：`fallback_endpoints` 支持一个势力配多个端点，自动故障切换。

## 开发与测试

```bash
# 后端测试
cd server && python -m pytest tests/ -x -q

# 前端类型检查 + 构建
cd client && npm run build

# 前端 Lint
cd client && npm run lint
```

## 部署

### 单进程部署（推荐）

前端构建产物会被后端自动托管，只需跑一个进程：

```bash
cd client && npm run build        # 产出 client/dist/
cd ../server
python -m uvicorn src.main:app --host 0.0.0.0 --port 7860
# 直接访问 http://<host>:7860/ 即是完整站点（API + 前端 + admin）
```

> 提示：若部署在无法访问外网的内网环境，启动前请运行 `python server/download_vendor.py`
> 下载 Admin 后台依赖的本地 vendor 文件（`tailwindcss.js` / `htmx.min.js`）。
> 外网环境无需执行，页面会自动回退到 CDN。

### 部署到魔搭创空间（ModelScope Studio）

本项目是“FastAPI 后端 + 静态前端”的标准形态，适合以**自定义镜像**方式部署创空间：

1. 按上面“单进程部署”构建出 `client/dist/`；
2. 编写 Dockerfile：基于 `python:3.12-slim`，安装 `server/requirements.txt`，
   启动命令即上面的 uvicorn 单进程命令，暴露 `7860` 端口；
3. 在创空间配置中将服务端口指向 `7860`，并把 `.env` 中的密钥改为通过
   创空间的环境变量/密钥管理注入（**切勿把 .env 打进镜像**）；
4. LLM 网关需选择创空间网络可访问的服务（如各厂商官方 API 或公网网关）。

> 提示：对局运行器（`python -m cli run`）是长任务，建议在创空间中仅做**观战服务**，
> 对局本身在本地或独立服务器上跑，数据库/数据目录共享给观战服务即可。

## 常见问题 FAQ

**Q：启动对局时部分势力探测失败（Connection error）？**
A：先看启动日志里有无 `环境变量 ${LLM_GATEWAY_*} 未定义` 的 WARNING——通常是
`.env` 未配置或变量名拼写错误，导致 base_url 仍为字面量占位符。

**Q：战局页一直转圈（"典籍卷起 · 地图徐展"）？**
A：说明该局还在选秀阶段、尚未产生任何世界状态。去 `/game/<id>/draft` 看选秀进度，
选秀结束并跑完第 1 回合后战局页自动出画面。

**Q：日志刷 `connection to server at "localhost", port 5432 failed`？**
A：`.env` 里配了 PostgreSQL 但数据库没启动。注释掉 `DATABASE_URL` / `POSTGRES_*`
即回退到零配置的 SQLite。

**Q：想省 token 快速验证全流程？**
A：`--scenario arena_3p_A --turns 5`；或者用 `--draft-from <已有局>` 跳过选秀；
再或者把 yaml 中各势力的 `thinking_enabled` 关掉。

**Q：如何只用一个厂商的 key 跑起来？**
A：把 `factions` 里 9 个势力的 llm 段全部指向同一 base_url/key，仅 `model` 不同
（比如全走 OpenRouter）。竞技性下降，但流程完全可用。

## 致谢

- 本项目的游戏机制与地图路网设计参考了开源项目
  [ZHSAN3（中華三國志重製版 3.0）](https://github.com/luiges90/ZHSAN3)，
- 地形与战棋机制设计同时参考了社区项目 game-sanguo。
- 在此向原作者及社区致谢。

## 许可证与素材声明

- 代码采用 [MIT License](LICENSE) 开源，可自由使用、修改与分发。
- **图像与音乐素材（AI 生成）**：武将肖像（`client/public/portraits/`）、背景音乐
  （`client/public/bgm/`）、建筑 / 兵种 / 特效 / 地形 / 背景等（`architecture` /
  `troops` / `effects` / `terrain` / `units` / `backgrounds`）均由 AI 生成。
- **界面音效**（`client/public/sounds/`）：来自 [Mixkit](https://mixkit.co/free-sound-effects/)
  免费素材（Mixkit Sound Effects Free License，可免费商用、无需署名），
  逐文件来源见 `client/public/sounds/README.md`。
- **字体**：站酷小薇（ZCOOL XiaoWei），采用 SIL Open Font License。
- **各大模型名称与 Logo**（`client/public/logos/`）归属各自厂商所有，仅用于标识
  对局参与方，不表示任何合作或背书关系。

---

欢迎提交 Issue 与 Pull Request。
