Skip to content

Repository files navigation

warplay

战争势态可视化:在现代地图上按时间轴回放一场战争中各作战单位的运动、 编制变化与主要战斗。从解放战争(1945–1949)起步,但引擎本身与具体战争无关。

项目背景

传统战史地图是静态的:几张要图、几条红蓝箭头,看不到势态随时间的演化。 warplay 想做的是把"某支部队某天在哪里、处于什么状态、为什么往那里去" 变成可以拖动时间轴逐日回放、可以点击追问、可以跨战役检索的东西。

这依赖大量历史文献——多数是没有文字层的扫描书籍。项目用 AI 管线 (OCR → 分块 → 抽取代理 → 地名解析 → 装配校验)把这些文献转成结构化、 带页码溯源、可跨源交叉验证的数据,再由数据驱动渲染。人工只做小而关键的 部分(单位谱系映射、冲突裁决),其余环节可重复运行。

解放战争是第一个语料充分的目标;引擎不含任何关于它的知识。


一、系统设计规则

战场与战争分离

这是本项目最重要的设计约束:

  • 战场(引擎):地图渲染、时间轴插值、单位符号系统(简化 APP-6)、 编年史视图、跨战役检索、API。不含任何具体战争的知识。
  • 战争(数据):战役文件(data/scenarios/)、事实库(data/facts/)、 部队权威名录(data/registry/)。引擎渲染的一切都来自这里。

data/scenarios/ 放一个符合 docs/SCENARIO_FORMAT.md 的 JSON 文件,新战役就上线了。同一引擎可以承载任何有史料支撑的战争。

战争优先,战役为镜头:一场战争的数据归一后,战役(辽沈、淮海、平津) 不再是独立数据集,而是战争场景内的聚焦跳转(campaigns 字段:时段 + 视口), 点击即飞至战区并定位到战役开始日。同一份数据换读法还有部队编年史/chronicle):按部队(阵营→层级树)、人物(任职 + 全部相关条目)、 命令(按发令方分组)、序列(任意日期的战斗序列树)四个维度浏览,相互穿透。

军事单元的字段设计

部队名录(data/registry/units.json)的字段设计针对军史数据的几个固有难点:

  • 跨史料身份。同一支部队在不同书、不同时期番号不同 ("东北民主联军第3纵队" = "东野3纵" = 后来的"第40军")。每个单位一个 registry id,names 收录各时期番号变体,抽取归并时据此对齐。
  • 生命周期lifecycle 记录创建、改称、合并、分解、易帜、覆灭—— 单位不允许凭空出现或凭空消失。起义部队改编(如 60 军→50 军)用 side-changed 表达,而不是删一个建一个。恒番号重建(覆灭后同番号 另建新部队)建模为"化身分段",谱系不混同。
  • 带时间区间的隶属关系。师、团一级同样是独立条目;subordination 是带起止日期的关系列表而非静态 parent 字段,因为隶属会变 (师在纵队间调动、纵队改隶兵团)。编制层级是随时间变化的关系,不是一棵 静态树——战斗序列视图正是按查询日期展开这些关系窗口。
  • 指挥员带任期。同一将领先后指挥多支部队,严禁按人名做无任期的静态映射。
  • 日期是区间不是点。史料只说"中旬",就诚实记 {earliest, latest}; 上下文能收窄时收窄("四平失守后三日内")。
  • 决策文件是动机层。作战电报、战役指示以 type: "command" 入事实层, 附着到发令/受令单位——把"部队怎么动"和"为什么这样动"放在一起。

渲染诚实规则(宁缺毋错)

数据有多可靠,图上就画多确定;不确定必须看得见:

  • 推测位置的 keyframe 带 inferred: true,渲染为半透明虚线,弹窗注明;
  • 史料空白超过 30 天停止插值;空白 120 天且无结局记录的单位下图, 而不是永远钉在最后一个已知位置;
  • 被歼/投诚标记同样在结局 120 天后过期消失;
  • 控制点一年无事实再确认即降级"待考"样式(治单侧记载偏差);
  • 冲突事实在弹窗中并列各源原文,不掩盖分歧。

二、战争记录的获取与校验规则

引擎之外,数据侧遵循一条严格单向的流水线(详见 docs/DATA_ARCHITECTURE.md):

┌─ 来源层 sources ─────────────────────────────────────────────┐
│ reference/*.pdf (git-ignored) → OCR → 逐书抽取记录            │
│ tools/chronicle-pipeline/                                    │
└──────────────────────────┬───────────────────────────────────┘
                           ▼
┌─ 事实层 facts + registry ────────────────────────────────────┐
│ data/registry/units.json   部队权威名录(谱系/改称/易帜/指挥员)│
│ data/registry/places.json  地名辞典(变体 → 坐标)             │
│ data/facts/<doc>/records.jsonl  单源记录(每条带页码)         │
│ data/facts/facts.jsonl     跨源核对后的事实(含冲突裁决)      │
└──────────────────────────┬───────────────────────────────────┘
                           ▼
┌─ 表现层 scenarios ───────────────────────────────────────────┐
│ data/scenarios/*.json  战役文件(v2),从事实层选取、成文      │
└──────────────────────────────────────────────────────────────┘

原始扫描件永不进入渲染层;战役文件不得发明事实。

获取

  • 扫描书籍:Vision OCR(自动处理旋转页)→ 分块 → LLM 逐块抽取为 带页码的结构化记录。批量抽取走成本可控的模型,主模型只做 10% 抽样审计 与判断性工作;审计标准是"忠实优先"——不许编造,页码必须准确。
  • 公开史料库:marxists.org 文电、维基百科战斗序列(仅作结构化底稿, 一律回中文军史核校)、地方志与公开战史。
  • 逐案考证:审计工具持续产出可疑案例批次(大位移机动、无头无尾单位、 控制矛盾、终局缺失),交研究代理蜂群逐案查证。问题必须自带我方原文 摘录(出处仅作溯源)——考证方无法访问我方书库,绝不出"查某书某页" 这种题;答复格式在出题时预先约定(日期、主体、控制方三要素), 契约见 data/facts/kimi_batches_v2/README.md

校验

进入事实表前,每条记录要过四道防线:

  1. 跨源归并与权威裁决——同单位、同时段、同地点的多源记录聚簇; 各源一致则互证(corroborated),分歧则标记冲突(conflicted),由 《全国解放战争史》作最终信源裁决,除非 ≥2 个独立其他来源联合反对。 任何裁决都不删除落选主张,各源分歧原样保留在 conflict 字段。 同一研究代理的多轮回答算一个来源族,既不互证也不互冲。
  2. 物理合理性——行军速度上限(陆路 120 km/日)、出生区域锚定 (军区部队必须在辖区内起步)、同名异地劫持检测(候选坐标与部队前后 活动云对比)、区域一致性(控制区内的敌方孤点默认可疑)。 不可达的位置下图进复核队列,绝不硬画。
  3. 语义防线——控制点攻占方从句义推断而非记录主语("西安解放, 胡宗南放弃西安"的主语是败方);重建判定识别否定句("此非某部番号 恢复")并要求主语匹配;军区所属部队编出不等于军区终结。
  4. 人工终审——冲突批量呈报用户裁决(裁决以签名键持久化,重构不失效); AI 产出一律抽样复核后方可入库。

原则一以贯之:宁缺毋错——不确定的信息宁可不上图,也不给一个看起来 确定的错误答案。


当前内容

公共版对外只有一个战争大类:

  • 全国解放战争(1945–1950)——战争级视图,内置辽沈/淮海/平津战役 聚焦镜头;303 个事件(含各战役手工整理的叙述)、90 支部队 1,600+ 关键帧、 400 个控制点,全部由事实库生成

早期的独立战役文件与东北全程场景已折叠进战争视图(事件经去重注入、 记录层本就同源),归档于 data/scenarios/archive/。太平洋战场(中途岛 1942)本版下线(美方史料尚未达标准),恢复开关见 tools/factstore/merge.py。 数据仍在整理校核中,欢迎在 GitHub Issues 指正史实、定位或谱系错误。

参考材料

完整目录见 reference/解放战争史料总目录.md。 本项目实际引用的文献分类如下。

大陆官方战史(编制、番号、沿革的主干)

  • 军事科学院军事历史研究部《中国人民解放军全国解放战争史》(全五卷), 军事科学出版社——本项目冲突裁决的最终信源
  • 军事科学院《中国人民解放军战史》,军事科学出版社
  • 《中国人民解放军第二野战军战史》,解放军出版社
  • 《东北解放战争大事记》,中共党史资料出版社,1987

专题与文电(决策动机层)

  • 刘统《决战:华东解放战争 1945–1949》,上海人民出版社,2017
  • 《淮海战役史料选》《三大战役统一战线文件选》《第一野战军文选编》 《毛泽东军事文电》(十三卷本)——marxists.org 中文库直链 PDF
  • 《中国人民解放军将帅名录》,解放军出版社(USC Scalar OCR 版)

外文史料(交叉校核)

  • Gary J. Bjorge, Moving the Enemy: Operational Art in the Chinese PLA's Huai Hai Campaign, US Army CGSC Combat Studies Institute, 2004
  • Michael Lynch, The Chinese Civil War 1945–49, Osprey, 2010
  • CIA ORE 77-48 及 Order of Battle Handbook(CIA FOIA 阅览室)
  • FRUS 1946–1949 中国各卷;Wilson Center CWIHP 苏联档案研究

可抓取底稿

  • 中/英文维基百科战役与战斗序列条目——仅作结构化底稿,一律回中文军史核校

版权边界:扫描书籍原件不入库(reference/ 为 git-ignored),仓库只含 结构化事实、页码引用与自撰摘要文本。

致谢

本项目站在大量前人工作之上:

  • 史料著作者与出版机构——军事科学院军事历史研究部及《全国解放战争史》 编写组、各野战军战史编委会、刘统先生、Gary J. Bjorge 等(完整书目见上节 "参考材料")。数据层的每一条事实都带页码回指这些著作。
  • 公开史料库——marxists.org 中文文库、USC 数字图书馆、CIA FOIA 阅览室、 中/英文维基百科及维基共享资源;太平洋战区数据源 combinedfleet.com(逐舰 TROM)、NavWeaps、JANAC 战损表。
  • 开源软件——LeafletOpenStreetMap 及 CyclOSM / OpenTopoMap 图层贡献者、FastAPI / uvicorn、Nominatim 地理编码。
  • AI 协作者——本项目是人机协作实验:Claude(Anthropic)承担工程与数据 架构,DeepSeek 承担批量文献抽取,Kimi(月之暗面)代理蜂群承担逐案史料 考证(机动节点、控制易手、部队存亡)。所有 AI 产出均经跨源核验、物理 合理性校验与人工抽样后方可入库;冲突由人工终审。

协议

本仓库的原创部分(代码、结构化事实数据、文档)以 CC BY-NC 4.0 (署名—非商业性使用 4.0 国际)协议发布,详见 LICENSE。 引用数据时请保留事实条目所附的史料出处。

源自第三方的数据与文档遵循其原有共享协议,不受上述协议覆盖:

  • 引自维基百科的内容(如人物任职记录)依 CC BY-SA 4.0 共享;
  • OpenStreetMap 数据依 ODbL 共享; 地图底图版权归各图层提供方所有;
  • 史料著作版权归原著作权人所有,本仓库不含扫描原件,仅含结构化事实 与页码引用。

若您认为本仓库任何内容侵犯了您的权利,请在 GitHub Issues 提交说明(注明具体文件/条目及权利依据),我们会及时处理。

快速开始

uv run --with-requirements requirements.txt uvicorn app.main:app --port 8080
# 测试(校验所有战役文件的格式、日期序、引用完整性)
uv run --with-requirements requirements.txt --with pytest --with httpx pytest -q

或 Docker:docker build -t warplay . && docker run -p 8080:8080 warplay

API:

  • GET /health
  • GET /api/scenarios — 战役列表(元数据)
  • GET /api/scenarios/{id} — 完整战役文件
  • GET /api/search?q= — 跨战役检索战斗/单位
  • GET /api/chronicle/units[/{id}] — 部队索引 / 单部队编年史
  • GET /api/chronicle/people[/{name}] — 人物索引 / 单人相关条目
  • GET /api/chronicle/orders — 全库命令流(按发令方分组)
  • GET /api/chronicle/oob?date= — 指定日期的战斗序列树

部署:vinyard real-project class(vinyard.toml,port 42090),POST /api/deploy

Releases

Packages

Contributors

Languages