Skip to content

v0.1.20 · 规则全面审查 + 采纳外部贡献

Choose a tag to compare

@Rapace7 Rapace7 released this 07 Oct 14:19
· 51 commits to main since this release

v0.1.20:规则全面审查(对照 KataGo)+ 采纳外部贡献 + 推荐落点交互澄清

一、规则审查:揪出并修掉三个规则错误

这一版把围棋规则对着权威实现逐条核了一遍(KataGo 的规则引擎 + 开源围棋软件 KaTrain)。

① 让 3 子的位置错了。 第三子原来摆在左上,通行摆法是右上。
(KataGo 的 place_free_handicap 3 输出 D4 Q16 Q4 可印证。)2/4~9 子都是对的,只有 3 子这一档错。

② 座子制(明清规则)的黑白放反了。 原来是「左上/右下 = 黑」,
正确是「黑子在右上角 + 左下角,白子在左上角 + 右下角」
(依据:座子制通行规则原文「黑座子放置于右上角和左下角的四四位,白座子依此类推」)。
这个错影响整套明清规则 —— 古谱摆出来黑白是反的。

③ 打劫判据用的是我自己琢磨的启发式,会误禁合法棋。 换成开源围棋软件 KaTrain 的判据:
「上一手是否只提了 1 子、且提的正是这一手要下的那一点」+「这一手是否也只提 1 子」。
它不预判未来,天然避开倒扑和"提掉一个本来就只剩 1 气的子"这两类误判。
(我前后错了四版,全错在"预判未来"上。)

顺手还改了两处我们自己代码的问题:

  • rebuildCapAt 的棋盘索引语义搞错(boardAt(i) 是"走完第 i 手",我按"走了 i 手"取,
    整个错开一手)→ 悔棋后打劫判据形同失效。这正是您之前报的"悔棋后能直接提劫"的根子之一。
  • _cdp_ko.mjs 里一条测试期望值写错了(写的是"倒扑回提应合法"),
    拿 KataGo 实测那个形,它判 illegal move —— 是断言错、代码对。

核对无误的:贴目(用空盘 final_score 反推:中 7.5 / 日韩 6.5 / 明清 0)、
还棋头(同局面只改块数,ancient-area 差 2 目 → tax=ALL 生效且我们没有重复计算)、
规则名映射、2~9 子让子摆法、星位(9/13/19 路)、坐标(GTP 跳 I / SGF 含 i)、
停一手与终局、SGF 导出。

二、采纳外部贡献(感谢 jerry barbarrossasky)

★ 按 SGF 的 SZ 属性读棋盘大小(原 PR #3)
原来 parseSGF 把「节点」当「属性」访问(t.id / t.vals),而节点结构是 {props, at, end} ——
于是 SZ 永远读不到,9 路和 13 路的棋谱全被按 19 路打开。改用现成的 firstProp('SZ') 读取。

★ 推荐落点交互改进(原 PR #6)
把「棋盘上的实时推荐」和「点击生成的讲解快照」明确分开,快照上方标明对应手数,
局面变化时提示「当前局面已变化」。

这一项我们做了调整(作者误会的根源)

作者做这个交互的起因是:他以为 LoGos 的讲解和 KataGo 的推荐是两套不同的点。
实际上点全部来自 KataGo,LoGos 只负责解释(prompt 里点名讲哪一点,还校验它有没有讲错点)。
所以「LoGos 推荐落点」这个名字本身就在强化误解,已改成:
标题「推荐落点讲解」+ 小字「KataGo 选点 · LoGos 讲道理」,
并且删掉了卡片里那个重复的「实时推荐落点」开关 ——
用「显示」菜单里那一个就行(快捷键 T),两处重复只会让人搞不清该信哪个。
他真正治好的那个病(实时推荐与旧快照会分歧、却没提示)保留了。

三、没采纳的

设置里可选「启动时自动加载引擎」(原 PR #4)—— 代码本身没问题,但它改的是
2026-10-05 已经定过的事(默认不加载任何引擎,因为开软件常常只是想摆棋打谱,
一开就吃几 GB 显存没道理)。这一版不并入。


v0.1.19:推荐点卡住的真根因 + 轻量化(撤掉调试日志、给引擎日志设上限)

一、修「推荐点永远不出来 / 那行『计算中… N』定住不动」

根因:悔棋时会清掉"这批选点作废"的记号,但另一个记号没跟着清。

if (state.candAt > len) state.candAt = -1;   // 这批选点废了
if (shownAt > len) shownAt = -1;             // ← 只管了"大于新长度"这一种情况

悔棋退到某一手时会出现:candAt(比如 6)> len(2)→ 清成 -1;
但 shownAt 恰好等于 2(≤ len)→ 原样留着。

于是**「这批选点废了」与「这个局面显示过了」同时成立**,成了死结:

  • runAnalysis 判 shownAt !== cur → 为假 → 跳过当前局面,不重算
  • scheduleAnalysis 又因 history[cur] 有值 → 不入队

两头都不动手 → 那个局面永远不再分析。修法:这两个记号是同一批结果的一对,
要废一起废。

怎么找到的:前两版都没修对(我先判成"记在了没上屏的结果上"——那条本身对,
但没打到这个问题;我加的自愈网还被自己写坏、只试一次就放弃)。
最后是让它把分析链路的关键决定写进日志文件,从日志里直接看到:

schedule at=2 入队=否(history已有→不入队) q=[] shownAt=2 candAt=-1 busy=true hist[2]=有
★ run 认为已算过但 candAt=-1 ≠ viewAt=2

验证:单元(截断时两个记号都要清 / candAt 有效时不误清);
场景(落 8 手 → 回看第 2 手 → 回最新 → 悔棋退到第 2 手 → 116ms 选点重新上屏);
猛捶 80 轮后日志里那个异常从 2 次降到 0 次。用户实测:不卡了。

二、轻量化:不做"一直产生垃圾文件"的软件

用户要求:「软件要尽量轻量化,尽量不像手机 APP 一样一直产生垃圾文件」。

  • 撤掉上面那个分析链路日志:它实测玩 20 秒写 63.8 KB(约 11 MB/小时),
    而且是同步写盘。它是排查偶发问题的临时手段,问题解决后就该撤。
  • 引擎日志自动限量:每次启动引擎,KataGo 会写自己的日志(2 个文件,几 KB),
    会无限累积。现在启动时自动只留最近 20 个。
    (实测:造 30 个 → 启动一次 → 剩 20 个,删的是最旧的。)
  • Chromium 磁盘缓存上限 32 MB + 媒体缓存 8 MB(本软件不联网,只当保险绳)。

现在的写盘清单(都审过,没有会无限涨的)

写什么 增长情况
settings.json 固定一个文件
records\ 棋谱 / 复盘 / 讲解 同名覆盖,不涨
records\*.sgf.bak 每份棋谱最多 1 个(第一次编辑解说词时留的备份)
engine-logs\ 只留最近 20 个
userdata\(GPU/着色器缓存) 约 8 MB 后稳定,另设了磁盘缓存上限

三、这个版本还包含(它们没有单独发 Release)

applyAnalysis 如实报告有没有真上屏、shownAt 只在真上屏时才记、
自愈网(卡住时每 6 秒重试一次、且自己续排,不依赖用户再操作)、
Ctrl+Shift+D 自检键修好(原来被上面一道 Ctrl 总闸挡成死代码)。


v0.1.17:查「选点卡住」的过程(这些都没有单独发 Release,留作记录)

怎么找到的(这次不是猜的)

用户报「AI 落子后很短时间内点悔棋,选点推荐和形势分析就卡住不显示,有时候会有时候不会」。
我在两台机器上做了三轮压力测试(共 100 轮、含 AI 思考中悔棋、悔棋延迟随机 0~400ms),
一次都复现不出来。

于是给软件加了一个自检键(Ctrl+Shift+D),让用户在自己那台出问题的机器上按一下。
他读出来这一行:

分析自检·局面: 2手·看第2手·选点: 还没算过·搜索量: 200·请求: 空闲·引擎: 就绪·链路: 轮30/成功19/空跑0

这一行就把病灶锁定了:

读数 说明
选点: 还没算过 candAt = -1,候选点从未上屏
搜索量: 200 请求发出去过、也回过进度(所以不是"没发请求")
请求: 空闲、空跑0 队列空了、没有待办、也没有请求失败

三个事实合起来只有一个解释:软件认为「这个局面已经算过了」,所以永远不再算它。

真根因(一行代码)

applyAnalysis(res, at);   // ← 内部有提前 return(报文与当前局面不符 / 搜索量太低时直接返回)
shownAt = at;             // ← 但它**无条件**标记"已上屏"

applyAnalysis 提前返回时候选点根本没画上去,可 shownAt 已经记成"这个局面显示过了"。
而 runAnalysis 的判据是 shownAt !== cur —— 于是这个局面永远不再重算:
棋盘上方那行「计算中… N」定住,推荐点永远不出现。

为什么"有时候会有时候不会":at !== state.viewAt 那条判断 ——
报文回来时局面刚好又变了(AI 刚落子、或用户刚落子),这一趟结果被当成
"补历史欠账"处理:只记走势、不画选点。这是个竞态,只在特定时序成立,所以偶发。

修法

  1. applyAnalysis 现在如实报告有没有真上屏(返回布尔):
    报文与当前局面不符 → false;搜索量太低(<20)→ false;真画上去了 → true。
  2. runAnalysisOnce 只有真上屏才记 shownAt —— 没上屏就留着重算,死结解开。
  3. 再加一道自愈网:若出现「算过但没上屏」这个不一致状态(shownAt === viewAt
    但 candAt !== viewAt),6 秒后自己重算一次。万一还有别的路径造成同样不一致,
    也不会再卡住等用户"再落一手"来撞开。
  4. Ctrl+Shift+D 自检键修好了(原来写在 switch 里,被上面一道 Ctrl 总闸提前 return
    挡成死代码,按了没反应)+ 加了分析链路计数。

验证

项 结果
applyAnalysis 四种入参的返回值 正常→true / 局面不符→false / 搜索量太低→false / 空结果→false ✅
人为造出用户那个卡住状态,自愈网 6 秒救回,候选点上屏,路径记进埋点 ✅
强制重算后 shownAt 与 candAt 一致 ✅
综合回归(悔棋/回看/涨跌/刷新/一致性) 全绿 ✅
打劫回归(悔棋×打劫,用那份 GN[打劫BUG] 棋谱) 全绿 ✅
倒扑仍合法(没被误判成劫) ✅
极限压力 40 轮(独立调试实例、rank_3d、极短延迟悔棋) 恢复 1.3~1.5 秒,无卡住 ✅

说明

这次有用户的实测读数做判据,不再是"我读代码猜出来的漏洞" —— 所以这一版可以说
根因是确定的。但请留意:如果那个竞态的触发条件还有我没覆盖到的分支,
自愈网(第 3 条)会兜住它,最多晚 6 秒,不会再永久卡住。


一、悔棋之后能无视禁着点直接提劫(用户报的,附了他自己存的棋谱)

现象:白提劫 → 黑被禁 → 黑在他处走一手 → 白补劫 → 黑悔棋回到「白提完劫」
→ 这时黑能直接提回去(禁着点凭空消失)。

根因:悔棋那段有一句 state.koPoint = null;。
注释写的只对一半 —— 退掉「提劫那一手」时它确实该失效,
但退到「刚提完劫」那个局面时它必须重新成立。
反方向也错:悔棋退掉一个「在别处走」的手之后,劫其实又成立,禁着点本该回来。

修法:悔棋后按新局面重算(新增 koFromBoard()),判据与 tryPlay 里那段逐条一致
(上一手提 1 子 + 落子是孤子 + 只剩一口气)—— 单一来源,避免两处规则跑偏。
因为沿用了「孤子」那条判据,上次修好的倒扑误判不会回退(已回归验证)。

验证(用那份棋谱逐手重下 32 手走到「白提完劫」):

步骤 结果
提劫后生成禁着点 R17 ✓
立刻回提 被拒 ✓
走别处后禁着点清空 ✓
悔棋回到提劫那一刻 禁着点重新成立 = R17 ✓
此时直接回提(报的那一手) 被拒 ✓
别处仍可正常落子 ✓(没把局面锁死)

二、分析链路两处「卡住不会自愈」的隐患

用户报「AI 落子后马上悔棋,选点/形势有时卡住不显示,有时候会有时候不会」。
我按那个时序做了压力测试(60 轮、悔棋延迟随机 0~400ms、含 AI 思考中悔棋),
测试环境里 0 轮卡住,但翻代码找到了两个真实的机制漏洞:

  1. shownAt 悔棋后没有跟着退。它是「屏幕上这批结果算的是第几手」,
    悔棋把局面变短之后如果它还指着一个已不存在的手数,
    runAnalysis 的判据 shownAt !== cur 就变成永远为假 ——
    它以为当前局面已算过,于是永远不再重算:候选点 / 胜率 / 形势雾停在旧值。
    原来只退了 candAt / ownAt,漏了 shownAt(它是模块级变量,不在 state 上,
    所以前几次审查都没扫到)。
  2. 被 cancel 的那条路没有重排。分析请求被掐掉(比如数子时 runScore 会 cancel)
    返回 false 之后,anaBusy 放开了,但「重算当前局面」这个意图没人再触发 ——
    如果这一刻正好没有落子/回看,分析就停在那儿不动了。现在会主动重排一次。

另外给 Ctrl+Shift+D 自检加了一组分析链路计数(启动轮数 / 成功次数 / 空跑次数 /
提前 return 的原因),下次再遇到卡住,按一下就能看出它卡在哪一步。

三、顺带:测试跑在「活目录」上,动到了用户的棋谱

做这些测试时发现用户那份 20261007-155056-34手.sgf 从他的棋谱库里消失了。
已从备份快照完整恢复(内容逐字节一致,时间戳 15:51:39 对得上),
并新增 dev\_guard_records.ps1:跑任何端到端测试之前把用户 records 整个收起来、
跑完原样放回。以后测试再也碰不到用户的棋谱库。

打劫那份棋谱也复制成了仓库内 fixture(dev\fixtures\打劫BUG-34手.sgf),
测试不再依赖用户目录。


v0.1.15:修「悔棋之后能无视禁着点直接提劫」+ 分析链路两处卡死隐患

一、悔棋之后能无视禁着点直接提劫(用户报的,附了他自己存的棋谱)

现象(用户报的,附了他自己存的棋谱 GN[打劫BUG])

白提劫 → 黑被禁着 → 黑在他处走一手 → 白补上劫空 → 黑悔棋…
悔到「白提完劫」那个局面时,黑能直接提回去 —— 也就是禁着点凭空消失了。

根因

悔棋那一段里有一句:

state.koPoint = null;          // 局面变了,打劫禁着点随之失效

注释说的只对了一半:

  • 退掉提劫那一手时,禁着点确实该失效 ✅
  • 退到**「刚提完劫」那个局面时,禁着点必须重新成立** ❗ ← 这里丢了

于是悔棋之后禁着点永远是 null,等于把劫禁手放行了。
反方向也错:悔棋退掉一个「在别处走」的手之后,劫其实又成立了,禁着点本该回来,却也是 null。

修法

悔棋后按新局面重算禁着点,而不是清空:

state.koPoint = koFromBoard(boardAt(state.moves.length), state.moves);

koFromBoard() 的判据与 tryPlay 里那段逐条一致(单一来源,避免两处规则跑偏):
上一手提了恰好 1 子、落下的那颗是孤子、且它只剩一口气 → 那口气就是禁着点。

为什么必须带「孤子」那条:倒扑时落子连着自己人,对方回提会一口气提走 ≥2 子、
局面并不重复,那是合法的好手 —— 这条判据是 2026-10-06 修倒扑误判时定下来的,
这次原样沿用,所以倒扑仍然不会被误判成劫(已回归验证)。

验证

用用户自己那份棋谱(records\20261007-155056-34手.sgf)逐手重下 32 手,走到「白提完劫」:

步骤 结果
① 提劫后生成禁着点 R17 ✓
② 立刻回提 被拒 ✓
③ 在别处走一手 禁着点清空 ✓
④ 悔棋回到提劫那一刻 禁着点重新成立 = R17 ✓
⑤ 此时直接回提(用户报的那一手) 被拒 ✓
⑥ 别处仍可正常落子 ✓(没把局面锁死)
⑦ 再撤一手后再试回提 仍被拒 ✓

同时回归:倒扑仍合法(提走 2 子、不误判为劫)、静态三件套全绿、综合回归
(悔棋 / 回看 / 涨跌数字 / 刷新按钮 / 界面一致性)全绿。

说明

顺带查清一件事:那份棋谱里 32 手全部合法、没有任何一手违反禁着点。
棋谱第 33 手 B[R17](黑提回)是合法的 —— 因为在那之前白还下过一手自杀手,
棋盘没变也没提子,所以不产生新劫。所以这份棋谱本身没问题,是悔棋把禁着点弄丢了。


v0.1.13:修「引擎版本旧了吃不下新权重」+ 仓库目录整理 + Mac/显卡指引

现象

用户反馈(转来的原话):「训练站最新的分析权重需要更高版本的 katago,旧版引擎会直接退出」。

根因(查证过,不是猜测)

KataGo 的权重是分代际的,引擎只认自己那一代和更早的:

权重代际 需要引擎
transformer(kata1-tf3-…,训练站现在最新的一批都是这个) v1.17.0 以上
b28 系列 v1.14.0 以上
b18c384nbt 系列 v1.13.0 以上

两条硬证据:

  1. 训练站首页公告(原文):2026-09-15 — Support for versions prior to v1.18.0 has been retired.
    (前一条 2026-08-25:transformer 权重已上传,没升到 v1.18.0+ 的请尽快升)
  2. katago.exe 里自带的报错文案:

    This neural net requires a newer KataGo version. Obtain a newer KataGo at https://github.com/...
    This neural net is from an extremely old version of KataGo and is no longer supported by the engine.

版本对不上时引擎加载权重失败后直接退出,于是软件里只显示「引擎异常 / 分析失败」——
用户看不出原因,只会觉得软件坏了。

本软件的实际情况(实测)

我们打包的引擎是能用的。本机实测:

KataGo v1.18.1 + 训练站最新 transformer 权重(kata1-tf3-b11c768-s12252M-d6398M)
  → Model version 17 · Model name: kata1-tf3-… (nbt transformer, 70442025 params)
  → Loaded model ✓

所以问题不在包,在"引擎版本 ↔ 权重代际"的搭配。

修法

  1. 打包的引擎升到最新:v1.18.1 → v1.18.2(官方 2026-08-30,最后一个稳定版)
  2. 把引擎的原话透到界面上(这条最要紧):main.js 现在监听引擎 stderr,
    命中「requires a newer KataGo version」这类文案就把它转写成一句能照着做的话,
    显示在棋盘中央的提示框和右侧胜率卡上 —— 而不是只说「引擎异常」。
  3. 文档写清楚代际对应表:README 与帮助面板都加了「引擎版本与权重代际」一节,
    并推荐「引擎和权重都从 KataGo 的 Release 页拿,那里附带的必定配套」。

顺带:仓库根目录整理

反馈"GitHub 页面上文件太多,要拉很久才看到产品介绍"。查了一下:
根目录 67 个文件里有 51 个是我的开发脚本(_cdp_*.mjs 测试脚本等)。

现在全部搬进 dev/,根目录只剩 16 个(README、LICENSE、程序本体、renderer/、assets/…)。
同时写了 dev/README.md 说明那堆脚本怎么用,并把脚本里写死的盘符路径改成按自身位置推导。

验证

  • v1.18.2 + 最新 transformer 权重:加载成功、分析输出正常(退出码 0)
  • 旧权重(b11c768nbt)与 human 权重:同样正常
  • 静态三件套(DOM / hidden / IPC)全部「无 ✓」
  • 回归套件(悔棋 / 回看 / 涨跌数字 / 刷新按钮 / 界面一致性)全绿

说明

A 卡 / Intel 显卡的路径我没有实测(本机是 NVIDIA RTX 4070)。
README 里那张「显卡品牌 → 下哪个 KataGo」的对应表来自 KataGo 官方发布的资产清单,
但"OpenCL 版在 A 卡上到底跑多快"要用户那边验证。


v0.1.12:修「手数后面的涨跌数字会自己跳」+ 顶栏加「刷新」按钮

现象

一、涨跌数字会变。 下完一手,手数列表里那一手右边显示一个数字(比如「−2.4%」),
过一会儿再点回去看,变成另一个数(比如「−16.8%」)—— 原本算是亏的,再看看就不亏了。

二、引擎像是卡住了。 偶尔出现:棋盘上推荐选点不出来,棋盘上方那行「计算中… 320」
定在一个数字上不动,点悔棋、回看、落子都没反应,只能重启软件。

根因

一、同一手被算了十几遍

引擎每 0.25 秒推一次「算到一半」的中间报告,每一份都往走势数据里写一次,
而列表读的是最后一次写的值。实测(连落 6 手):

同一手 被写了几次 各次搜索量 胜率极差
第 1 手 6 次 151 / 298 / 463 / 515 / 515 / 515 0.62%
第 4 手 4 次 152 / 312 / 471 / 514 1.63%
第 5 手 5 次 168 / 340 / 515 / 515 / 515 1.69%
第 6 手 14 次 165 / 326 / 480 / 514 / 515 … 8.06%

第 6 手那一行就是您看到的现象:27.7% → 19.7% → 32.9%,来回跳。
不是"算得太短",是"算了十几遍、而且用最早那份粗算覆盖了收敛后的结果"。

二、分析请求有一条"回不来"的路

分析链路上每发一次请求都要等引擎回话。万一那一次等待永远不返回,
「一次只允许一个分析在跑」那道闸门就永远占着 → 整个分析停摆:
选点不刷新、胜率条冻住、那行「计算中… N」定住不动 —— 三条现象同时成立。

修法

一、涨跌数字改成「算准了才出现,出现后不再变」

  • 搜索量不到「计算深度」90% 的结果,只允许填空、不许覆盖已记的数据;
  • 达标的结果才允许覆盖,而且不许用更少搜索量的结果改写更多的那一份;
  • 没算准的那一格显示「…」(占位),算准了才变成数字。

试过一版「新结果比旧结果搜索量高 1.25 倍就允许覆盖」——形同虚设:
中间报告的访问量是 122 → 294 → 489 → 515 逐级涨的,每一级都比上一级高 2.4 倍,
于是每一级都过了那道门,数字照跳。必须用目标值的绝对比例当门槛。

二、请求回不来的路,两头都兜住

  • 渲染端加 25 秒超时:超时就放弃这一次、主动重排一次(连续 3 次仍超时才停手并提示);
  • 顶栏状态灯旁边加一个「刷新」按钮:卡住时点一下 —— ①放开卡住的分析并重排;
    ②重新查一遍引擎真实状态;③引擎真挂了就卸载再加载(等于重启引擎)。

三、顺手加固两处

  • 补账队列加上限(40 条):连点几十手之后,引擎不会再长时间忙于补很久以前的数据;
  • 新增 Ctrl+Shift+D:把分析链路的内部状态打到状态栏上(自检用,排查"点不出来")。

验证

  • 涨跌数字:刚落显示「…」→ 收敛后出数字 → 之后连续采样 5~6 次一个字都不变 ✅
  • 悔棋 ×3:选点跟上新局面耗时中位 121ms,队列不残留、走势数据长度正确 ✅
  • 回看旧手 → 回最新 → 连悔两次 ×3:每次都在 200ms 内收敛、零欠账、不卡 ✅
  • 刷新按钮:正常点=重算当前局面;把闸门人为卡住后点=立刻放开、清队列、恢复分析 ✅
  • 补账会不会拖慢选点(专门量过):有欠账时选点延迟中位 377ms,
    无欠账 470ms —— 选点排在补账前面,补账不拖慢选点 ✅
  • 顺带量到一个反直觉的:计算深度 200 / 500 / 1000 三档,推荐点出现快慢几乎一样
    (都在 0.49 秒)—— 因为推荐点在引擎吐出第一份结果时就画上去了。已写进帮助。

说明

第二条(卡住)我在测试环境里反复捣了几十轮没能复现,
所以那两个修法属于「把已知的机制漏洞堵上 + 给你一个立刻能自救的按钮」,
不是"确认修好了那个 bug"。下次再遇到,请按一下 Ctrl+Shift+D,
状态栏会打出当时分析链路的状态,把那一行发我就能定位。


关于「三大目录」的分工(维护者备查,也免得自己混)

位置 是什么 里面该有什么
RapaceGo\(开发目录) 改代码、跑测试的地方 源码 + node_modules + 一堆 _ 开头的开发脚本
dist\ 只放要传 GitHub 的东西 只有 RapaceGo.zip(win-unpacked 是中间产物,同步完自动删)
玄清围弈\ 本地自用的免解压版(唯一一个) 可直接双击运行的完整程序
桌面 RapaceGo懒人包\ 给别人下载用的整包(传网盘,不传 GitHub) 程序 + KataGo + LoGos,解压即用、零配置

为什么懒人包不上 GitHub:它 8.2 GB,而 GitHub Release 单个附件上限 2 GB,
且大头(4.4GB 的 .gguf 模型、296MB 的 .bin.gz 权重)本身就是压缩格式,
再打 zip 也压不动。GitHub 那份走轻量路线(146MB + 首次运行自动下模型)。

★ 懒人包的目录约定(做包时最容易搞错的一条)

main.js 里打包态的「引擎位置」是和 RapaceGo.exe 平级,不是上一级:

BASE_DIR = IS_PACKAGED ? path.dirname(process.execPath) : __dirname;  // 打包后 = exe 目录
const up = IS_PACKAGED ? BASE_DIR : path.join(__dirname, '..');        // 打包后 up 就是 exe 目录本身
katago: path.join(up, 'KataGo', 'engine', 'katago.exe')

所以懒人包的布局必须是:

RapaceGo懒人包\
├─ RapaceGo.exe      ← 和下面两个目录平级
├─ KataGo\engine\katago.exe + weights\
└─ LoGos\llama-server.exe + *.gguf

别把程序本体再套一层 RapaceGo\ —— 那样软件会去找 懒人包\RapaceGo\KataGo\...,
而文件在 懒人包\KataGo\...,结果引擎永远起不来(实测 settings.check 五项全 false)。

重建懒人包:powershell -File _build_lazy.ps1(已含"删掉 settings.json / records"等铁律)。

下载

只有一个文件:

文件 大小 说明
RapaceGo.zip 约 146 MB 解压一次,之后从文件夹里双击启动 —— 启动最快,也最便携

包名固定不带版本号(这样每次下载地址都一样)。要知道自己装的是哪一版:
打开软件 → 左上角「帮助」,标题右边写着版本号。

完全不会用 GitHub 也能装(四步)

① 打开下载页:https://github.com/Rapace7/RapaceGo/releases

② 往下滑,找到最上面那条发布(标题写着版本号和日期,GitHub 的下载文件都放在「发布」里)

③ 那个区块下面有一栏 Assets

⚠️ Assets 不是一个文件夹,是这次发布附带的下载文件清单。
小白最容易在这儿绕晕 —— 你要找的就是这份清单里的文件。

④ 点清单里的 RapaceGo.zip 下载

  • ⚠️ 别下页面最下面的 Source code (zip) —— 那是 GitHub 自动生成的源码压缩包,
    解压出来不能双击运行

⑤ 下载完右键「全部解压缩」,打开文件夹,双击 RapaceGo.exe —— 软件就起来了。

认准三样东西就行:① 最上面那条发布 → ② 它下面的 Assets 清单 → ③ 蓝色的 RapaceGo.zip

更新到新版本

把新包解压到原来那个文件夹、覆盖同名文件就行 —— 棋谱和设置不会丢。

  1. 打开软件 → 左上角「帮助」,记下当前版本号
  2. 到这个页面看最上面那条是不是更新了
  3. 关掉软件(重要:程序开着文件被占用,覆盖会失败或只覆盖一半)
  4. 下载新的 RapaceGo.zip → 解压到你现在用的那个文件夹 → 问是否覆盖时选「替换」
  5. 重新双击 RapaceGo.exe

为什么不会丢东西:包里只有程序本体,records/(你的棋谱和讲解)、settings.json
(引擎路径)、KataGo/、LoGos/(引擎与模型)都不在包里,所以原样保留。

保险做法:更新前把 records 文件夹复制一份到别处 —— 那是唯一丢了找不回来的东西。

⚠️ 引擎要自己准备一次(包里不含)

下载包里只有软件本体(约 570KB 的代码 + Electron 运行时),两个引擎是别人的项目:

① KataGo(必需,不装就没有 AI 下棋和数据分析)

② 讲解模型(可选,4.4GB)

解压后的文件夹里有一个 下载讲解模型.bat —— 双击它就行。
它会自动下载、合并模型、装好推理运行时,全程中文提示;
中途断了重新双击会接着下(按精确字节数判断,没下全的续传)。

👉 已经自己下载了那三个 .part 分卷(part01/02/03)?
那就不用管 bat 了 —— 往下翻到 ▶ 点这里展开 那段,一行命令就能合并。

▶ 点这里展开:已经自己下好那三个 .part 分卷了?手动合并也行(不用 bat)

下载 LoGos-7B-Q4_K_M.gguf.part01 / .part02 / .part03 之后,任选一种方式合并成
LoGos-7B-Q4_K_M.gguf(三个文件放在同一个文件夹里):

① 命令提示符一行

copy /b LoGos-7B-Q4_K_M.gguf.part01+LoGos-7B-Q4_K_M.gguf.part02+LoGos-7B-Q4_K_M.gguf.part03 LoGos-7B-Q4_K_M.gguf

② PowerShell(流式拷贝,内存占用低)

$out = [System.IO.File]::Create("LoGos-7B-Q4_K_M.gguf")
foreach ($p in "part01","part02","part03") {
  $i = [System.IO.File]::OpenRead("LoGos-7B-Q4_K_M.gguf.$p")
  $i.CopyTo($out); $i.Close()
}
$out.Close()

③ 7-Zip / WinRAR 不行 —— 压缩工具没有「合并分卷」功能。

⚠️ 合并后务必核对:应该是 4,683,071,328 字节(约 4.36 GB)。
不对就是没下全,删掉重下。核对完可以把三个 .part 删掉(省 4.4GB)。
然后回软件「设置」→ LoGos 组分别选 llama-server.exe 和合并出来的 .gguf。

为什么要分卷:GitHub 单个文件硬上限 2GB,而这模型 4.4GB —— 平台限制,
不是故意折腾你。三个分卷就是纯二进制切片,合并结果和原文件逐字节一致
(开发时用 sha256 验过)。

合并完还需要推理运行时(llama-server.exe)—— 上面那个 bat 会帮你装。

▶ 点这里展开:完全手动装(不用 bat、不用管分卷)

模型:YichuanMa/LoGos-7B 转的 GGUF Q4_K_M;
运行时:llama.cpp 的 Windows CUDA 版。
⚠️ 官方主包不含 CUDA 运行时,要另下同版本的 cudart-*.zip 放同目录。

装完之后文件夹长什么样

解压出来不止 RapaceGo.exe 一个文件,还有一堆 .dll、.pak、locales\ 之类 ——
那些都是软件自带的运行库(Electron 框架),不用管、也不要删(一共约 368 MB)。

下面把「你加进去的」和「软件自带的」分开写:

RapaceGo/                          ← 解压出来的文件夹(名字随便,拷到哪都能用)
│
├─ ★ 你自己准备的 ──────────────────────────
│  ├─ KataGo/                      ① 下 KataGo 的 Windows 版解压进来,改名成 KataGo
│  │  ├─ katago.exe
│  │  ├─ …(同目录还有一堆 .dll,一起放着别删)
│  │  └─ weights/                  ② 新建这个文件夹,放两个权重
│  │     ├─ b11c768nbt.bin.gz              算胜率 / 推荐点 / 形势
│  │     └─ b18c384nbt-humanv0.bin.gz      当 AI 对手(带 human 的那个)
│  └─ LoGos/                       ③ 双击「下载讲解模型.bat」之后自动出现(可选)
│     ├─ llama-server.exe
│     └─ LoGos-7B-Q4_K_M.gguf
│
├─ ★ 软件自带的(别删)─────────────────────
│  ├─ RapaceGo.exe                 ← 双击这个启动(245 MB,程序+框架都在里面)
│  ├─ 下载讲解模型.bat              ← 要讲解功能就双击它(会自动建上面的 LoGos/)
│  ├─ start.bat                    ← 双击没反应时的备用启动方式
│  ├─ resources/  locales/         ← 程序代码、界面、语言包
│  ├─ *.dll(7 个)                 ← 图形 / 视频 / 编译器等运行库
│  ├─ *.pak / *.bin / *.dat        ← 界面资源
│  └─ LICENSE.electron.txt · LICENSES.chromium.html  ← 开源许可声明
│
└─ ★ 自动生成的(随时可删)─────────────────
   ├─ settings.json                ← 你在「设置」里填的引擎路径(**删了要重填**)
   ├─ records/                     ← 你的棋谱 + 复盘报告 + 逐手讲解(**别删**)
   └─ userdata/                    ← 页面缓存(删了自动重建,不心疼)

一句话:只有 RapaceGo.exe 和那一堆自带的 dll/pak 是"程序本体",其余要么是你放进去的引擎、
要么是它自己生成的数据。看不懂的文件不要删 —— 真正该动的只有 KataGo/、LoGos/ 和「设置」。
想彻底卸载:把整个文件夹删掉就行(棋谱想留就先复制 records/ 出来)。

装好后在软件左上角「设置」里指一下路径(选 katago.exe 时它会自动帮你填权重),
再点左上角(顶栏左侧)的引擎灯 →「加载」。

硬件:显存是主要门槛

实测(RTX 4070 Laptop / 8GB,nvidia-smi):

组件 显存
KataGo 分析引擎 ≈ 350 MB
KataGo 对弈引擎 ≈ 170 MB
LoGos 讲解模型(Q4_K_M) ≈ 4.9 GB
三个全开 ≈ 5.5 GB

6GB 显存的卡能用但别全开;4GB 或核显只能用 KataGo 部分功能。
软件默认一个引擎都不加载,用不到就不占显存。

说明

  • 本项目代码 MIT;KataGo MIT;LoGos 授权为「仅研究、非商业」
  • 讲解由本地小模型 LoGos 生成,只输出中文(训练数据是中文标注)。
    看不懂中文的话:把讲解文字选起来丢进翻译工具就行(软件里允许选中复制)。
  • 代码几乎全部由 AI Agent 编写(对话由 DeepSeek V4.1 Flash 驱动),
    完整的决策过程见仓库里的 开发记录.md