Skip to content

Instantly share code, notes, and snippets.

@zakki
Last active January 21, 2023 07:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zakki/5d83c850715407b2ed207070a033230c to your computer and use it in GitHub Desktop.
Save zakki/5d83c850715407b2ed207070a033230c to your computer and use it in GitHub Desktop.

GTP大会対局拡張案 ver 0.1

意図

囲碁AI大会やCGOSで、双方の読み筋や評価を見たい。

既存実装

shogi-server拡張

コンピューター将棋でFloodや電竜戦で評価値グラフや読み筋をだす目的で使われている。

評価値と読筋を記録する拡張

CSAプロトコルでクライアントがサーバーに着手を送る際にコメントとして送る形で実現されている。

+7776FU,'jouseki

この時、**から始まる特定の書式のコメントが、評価値と読筋を空白区切りで記録したものとして解釈される。 +7776FU,'** 30 -3334FU +2726FU

Leela Zero

Lizzieでの読み筋表示用にLeela ZeroにGTP拡張として追加された。 lz-genmove_analyze コマンドでは応答としてすぐに =[ID] が返され、探索終了後に読み筋と着手通知される。

lz-analyze では解析モードなり定期的に読み筋が通知される。 他のGTPコマンドを受け取ると解析モードは終了する。

応答は UCIプロトコル をベースにしている。

bittsittによる実装 Extend GTP to add support for displaying real time winrates and variations

GTPコマンド形式 lz-genmove-analyze <color> <interval in centis>

実際の応答形式はプルリクエストのドキュメントから変更されていて info <属性名1> <属性値1> <属性名2> <属性値2> ...

  • move: 座標
  • visits
  • winrate
  • prior: 事前ポリシー
  • lcb
  • pv

Example

lz-genmove_analyze b 1000
=
info move D16 visits 6 winrate 4197 prior 1760 lcb 3838 order 0 pv D16 Q16 D4 Q4 info move D4 visits 4 winrate 4198 prior 1730 lcb 2346 order 1 pv D4 Q16 Q4 D16 info move Q5 visits 4 winrate 4212 prior 35 lcb 2273 order 2 pv Q5 Q16 D4 R3 info move D3 visits 3 winrate 4223 prior 248 lcb 0 order 3 pv D3 Q16 R4 info move R16 visits 3 winrate 4221 prior 247 lcb 0 order 4 pv R16 D4 Q3 info move D17 visits 3 winrate 4229 prior 249 lcb 0 order 5 pv D17 Q4 R16 info move C4 visits 3 winrate 4215 prior 244 lcb 0 order 6 pv C4 Q16 D17 info move Q3 visits 3 winrate 4225 prior 249 lcb 0 order 7 pv Q3 D16 C4 info move Q17 visits 3 winrate 4242 prior 246 lcb 0 order 8 pv Q17 D4 C16 info move R4 visits 3 winrate 4220 prior 253 lcb 0 order 9 pv R4 D16 Q17 info move R17 visits 3 winrate 4162 prior 24 lcb 0 order 10 pv R17 D4 D16 info move Q4 visits 3 winrate 4206 prior 1714 lcb 0 order 11 pv Q4 D16 D4 info move C5 visits 3 winrate 4158 prior 12 lcb 0 order 12 pv C5 D16 Q4 info move Q16 visits 3 winrate 4219 prior 1745 lcb 0 order 13 pv Q16 D4 D16 info move D15 visits 3 winrate 4232 prior 33 lcb 0 order 14 pv D15 D4 Q16 info move C16 visits 3 winrate 4224 prior 249 lcb 0 order 15 pv C16 Q4 D3 info move C15 visits 3 winrate 4177 prior 11 lcb 0 order 16 pv C15 Q17 D17 info move P4 visits 3 winrate 4239 prior 35 lcb 0 order 17 pv P4 D4 Q16 info move C3 visits 3 winrate 4196 prior 23 lcb 0 order 18 pv C3 Q16 Q4 info move E16 visits 3 winrate 4238 prior 33 lcb 0 order 19 pv E16 Q16 D4 info move R5 visits 3 winrate 4189 prior 11 lcb 0 order 20 pv R5 D3 Q3 info move Q15 visits 3 winrate 4220 prior 36 lcb 0 order 21 pv Q15 Q4 D16 info move E17 visits 3 winrate 4199 prior 12 lcb 0 order 22 pv E17 C4 C16 info move E3 visits 3 winrate 4206 prior 11 lcb 0 order 23 pv E3 C16 C4 info move P16 visits 3 winrate 4233 prior 35 lcb 0 order 24 pv P16 D16 Q4 info move E4 visits 3 winrate 4225 prior 34 lcb 0 order 25 pv E4 Q4 D16 info move P3 visits 3 winrate 4135 prior 11 lcb 0 order 26 pv P3 R16 D4 info move R3 visits 3 winrate 4176 prior 23 lcb 0 order 27 pv R3 D16 D4 info move R15 visits 3 winrate 4101 prior 12 lcb 0 order 28 pv R15 Q4 D16 info move C17 visits 3 winrate 4155 prior 25 lcb 0 order 29 pv C17 Q4 Q16 info move D5 visits 3 winrate 4234 prior 33 lcb 0 order 30 pv D5 D16 Q4 info move P17 visits 3 winrate 4083 prior 12 lcb 0 order 31 pv P17 D16 Q4
play D16
info move Q4 visits 14 winrate 5783 prior 3408 lcb 5713 order 0 pv Q4 Q16 D4 R6 C17 D17 info move D4 visits 9 winrate 5774 prior 2593 lcb 5611 order 1 pv D4 Q16 Q4 R6 C17 D17 C16 info move Q16 visits 10 winrate 5774 prior 2616 lcb 5601 order 2 pv Q16 D4 Q4 O17 C3 C4 D3 info move Q5 visits 4 winrate 5502 prior 8 lcb 2954 order 3 pv Q5 R3 P3 info move C4 visits 3 winrate 5693 prior 276 lcb 0 order 4 pv C4 E3 Q16 info move R16 visits 3 winrate 5683 prior 33 lcb 0 order 5 pv R16 P17 D4 info move C17 visits 3 winrate 5596 prior 8 lcb 0 order 6 pv C17 C16 D17 info move D5 visits 3 winrate 5481 prior 9 lcb 0 order 7 pv D5 Q4 Q16 info move R4 visits 3 winrate 5655 prior 117 lcb 0 order 8 pv R4 D4 Q16 info move Q3 visits 3 winrate 5688 prior 110 lcb 0 order 9 pv Q3 Q16 D4 info move F17 visits 3 winrate 5611 prior 8 lcb 0 order 10 pv F17 Q16 D4 info move Q15 visits 3 winrate 5483 prior 8 lcb 0 order 11 pv Q15 Q4 D4 info move E4 visits 3 winrate 5438 prior 9 lcb 0 order 12 pv E4 Q4 Q16 info move C14 visits 3 winrate 5573 prior 8 lcb 0 order 13 pv C14 D4 Q16 info move R15 visits 3 winrate 5223 prior 3 lcb 0 order 14 pv R15 Q4 D4 info move P3 visits 3 winrate 5449 prior 4 lcb 0 order 15 pv P3 R3 Q5 info move P16 visits 3 winrate 5459 prior 9 lcb 0 order 16 pv P16 Q4 D4 info move C5 visits 3 winrate 5147 prior 4 lcb 0 order 17 pv C5 Q4 Q16 info move Q17 visits 2 winrate 5689 prior 283 lcb 0 order 18 pv Q17 R15 info move D3 visits 2 winrate 5664 prior 34 lcb 0 order 19 pv D3 C5 info move C3 visits 2 winrate 5619 prior 13 lcb 0 order 20 pv C3 Q16 info move R17 visits 2 winrate 5614 prior 13 lcb 0 order 21 pv R17 D4 info move R3 visits 2 winrate 5574 prior 12 lcb 0 order 22 pv R3 Q16 info move P4 visits 2 winrate 5479 prior 9 lcb 0 order 23 pv P4 R3 info move R5 visits 2 winrate 5430 prior 4 lcb 0 order 24 pv R5 R3 info move E3 visits 2 winrate 5378 prior 3 lcb 0 order 25 pv E3 Q4 info move P17 visits 2 winrate 5307 prior 4 lcb 0 order 26 pv P17 Q4 info move C16 visits 2 winrate 4959 prior 2 lcb 0 order 27 pv C16 C17

KataGo

GTP拡張として kata-genmove_analyzekata-analyze が実装されている。

基本的な挙動は lz-genmove_analyzelz-analyze を踏襲している。 KataGo固有の情報出力としてLeela Zeroが対応していなかったスコアや地に関する情報が追加されている。

  • utility
  • scoreMean
  • scoreStdev
  • scoreLead
  • scoreSelfplay
  • utilityLcb
  • weight
  • isSymmetryOf
  • order
  • pvEdgeVisits
  • movesOwnership
  • movesOwnershipStdev
  • ownership
  • ownershipStdev

KataGo GTP Extensions

Example

kata-genmove_analyze
=
info move D4 visits 695 utility 0.111301 winrate 0.555005 scoreMean 1.34153 scoreStdev 24.1778 scoreLead 1.34153 scoreSelfplay 1.34153 prior 0.383687 lcb 0.55354 utilityLcb 0.107201 weight 695 order 0 pv D4 D16 Q4 R3 R4 Q3 O3 P3 P4 O2 C17 C16 D17 F17 info move D16 visits 292 utility 0.105322 winrate 0.552243 scoreMean 1.15246 scoreStdev 23.6713 scoreLead 1.15246 scoreSelfplay 1.15246 prior 0.275052 lcb 0.550414 utilityLcb 0.100203 weight 291.642 order 1 pv D16 D4 Q4 R3 Q3 R4 R6 R5 Q5 S6 R17 Q17 R16 R14 info move Q4 visits 292 utility 0.105322 winrate 0.552243 scoreMean 1.15246 scoreStdev 23.6713 scoreLead 1.15246 scoreSelfplay 1.15246 prior 0.275052 lcb 0.550414 utilityLcb 0.100203 weight 291.642 isSymmetryOf D16 order 2 pv Q4 D4 D16 C17 C16 D17 F17 E17 E16 F18 R17 R16 Q17 O17 info move C4 visits 189 utility 0.113599 winrate 0.554989 scoreMean 1.53496 scoreStdev 24.4114 scoreLead 1.53496 scoreSelfplay 1.53496 prior 0.0047951 lcb 0.551615 utilityLcb 0.104152 weight 189 order 3 pv C4 Q4 D16 E3 D5 C17 D17 C16 C14 C15 D15 B14 R3 R4 info move D3 visits 189 utility 0.113599 winrate 0.554989 scoreMean 1.53496 scoreStdev 24.4114 scoreLead 1.53496 scoreSelfplay 1.53496 prior 0.0047951 lcb 0.551615 utilityLcb 0.104152 weight 189 isSymmetryOf C4 order 4 pv D3 D16 Q4 C5 E4 R3 R4 Q3 O3 P3 P4 O2 C17 D17 info move C16 visits 42 utility 0.0997575 winrate 0.548788 scoreMean 1.15864 scoreStdev 24.2863 scoreLead 1.15864 scoreSelfplay 1.15864 prior 0.00384986 lcb 0.543774 utilityLcb 0.0857202 weight 42 order 5 pv C16 D4 Q4 E17 D14 R3 Q3 R4 R5 info move Q3 visits 42 utility 0.0997575 winrate 0.548788 scoreMean 1.15864 scoreStdev 24.2863 scoreLead 1.15864 scoreSelfplay 1.15864 prior 0.00384986 lcb 0.543774 utilityLcb 0.0857202 weight 42 isSymmetryOf C16 order 6 pv Q3 D4 D16 R5 O4 C17 C16 D17 E17 info move D17 visits 44 utility 0.0999837 winrate 0.548683 scoreMean 1.18234 scoreStdev 24.3054 scoreLead 1.18234 scoreSelfplay 1.18234 prior 0.00187856 lcb 0.543961 utilityLcb 0.0867636 weight 44 order 7 pv D17 D4 Q4 C15 F16 R3 Q3 R4 R5 S5 info move R4 visits 44 utility 0.0999837 winrate 0.548683 scoreMean 1.18234 scoreStdev 24.3054 scoreLead 1.18234 scoreSelfplay 1.18234 prior 0.00187856 lcb 0.543961 utilityLcb 0.0867636 weight 44 isSymmetryOf D17 order 8 pv R4 D4 D16 P3 Q6 C17 C16 D17 E17 E18
play D4

拡張案

  • list_commandsによる拡張コマンド切り替えはKGS/GoGui/Lizzieなどの拡張対応でも使われているので踏襲する。
  • GTPの複数行送受信はlist_commands final_status_list showboardでも用いられているので、サーバー・クライアントともに対応は問題少ないと予想。
  • lz-genmove_analyze 仕様をベースに仮称 ext-genmove_analyze を追加する。
  • cgosクライアントやGTP-NNGSブリッジはlist_commandsで拡張対応の有無を判定する。
  • 拡張コマンドに対応しているソフトに対しては、 genmove の代わりに ext-genmove_analyze で着手を要求する。

検討事項

  • lz-genmove_analyze でのinterval指定や lz-analyze によるによるリアルタイムの読み筋通知に対応するか?
    • 初期バージョンでは一旦 interval は対応せず、ext-genmove_analyze <color> のみ
  • 送信する属性はLeelaZeroやKataGoを踏襲するか最小限に絞るか?
    1. move, pv, winrate
    2. score, ownership, lcb, ucb, visits
    3. ...
  • 別の属性を送信できるように汎用化するか?
    • 特にPVは現状スペース区切りのため lz-genmove_analyze の仕様のままでは任意の属性の送信はできない。

TODO

  • CGOS実装との親和性の調査
    • CGOS
    • 1手につき1回着手と同時に送るのはプロトコルや設計に大きな変更は要らない
    • 特定の要求に特定の応答がある前提のサーバー実装なのえd、読み筋を不定期に複数回送る場合、ある程度の設計変更が必要。
  • NNGS実装との親和性の調査
  • 清書と英語版
@yssaya
Copy link

yssaya commented Dec 24, 2022

なるほど!
genmove black に
d5,+0.124.+5.3pt,pv,f4,f3,d4,c3,...
みたいに評価値を地合、読み筋をくっつける拡張かな、とか思ってましたが、こちらの方がスマートですか。
対応しているか、の判定も不要ですし。
着手時間はgenmoveが返った時間で、lz-genmove_analyze にかかった時間はカウントしない、
genmove が返った瞬間に相手にplay を送り、その後に、lz-genmove_analyze が飛んでくる、みたいな感じでしょうか。
とりあえずはwinrateだけもらう仕組みで、winrate+地合+読み筋、を送るコマンドも新設するとかでしょうかね?

@zakki
Copy link
Author

zakki commented Dec 27, 2022

即座に返るのは=\nだけで、探索終わると

lz-genmove_analyze
=
info move D4 visits 2 utility 0.011869 winrate 0.508212 scoreMean 0.0505946 scoreStdev 17.5636 scoreLead 0.0505946 scoreSelfplay 0.0487536 prior 0.298752 lcb -0.491788 utilityLcb -2.8 weight 4.29892 order 0 pv D4 C3 info move D16 visits 2 utility 0.0144308 winrate 0.509562 scoreMean 0.0683684 scoreStdev 17.4303 scoreLead 0.0683684 scoreSelfplay 0.0837245 prior 0.138992 lcb -0.490438 utilityLcb -2.8 weight 4.28521 order 1 pv D16 C17
Play D4

みたい形で返るので、「genmove black にd5,+0.124.+5.3pt,pv,f4,f3,d4,c3,...みたいに評価値を地合、読み筋をくっつける拡張」の認識通りです。「すぐに =[ID] が返され」はGTP的には1つの未完了のレスポンス状態で、LeelaZeroやKataGoの詳細挙動寄りの話です。
genmoveの代わりにlz-genmove_analyzeが飛んでくる必要があるのでGTPをやり取りする側(cgos clientやGTP2NNGS)はlist_commandsによるgenmoveの差し替えを想定してます。

pvを... pv D4 C3 info ...とスペース区切りじゃなく、... pv "D4 C3" info ...や、... pv D4\ C3 info ...みたいな書式にすると各自任意の属性を送ることができますが、現行のlzやkatagoの挙動と変わるの若干パースが複雑になります。

@CGLemon
Copy link

CGLemon commented Dec 27, 2022

I think the genmove_analyze and genmove are the better choise then genmove. They can provide the real time analysis, like TCEC. The main drawbacks is that its behavior is very complexity. It is unfriendly of server and developers. I recommend we define a strictly minimal analysis set. The set must be sub-set of lz-genmove. Additional tags and key-value pairs are optional. For example,

my-genmove_analyze

  • Necessary tags
    • color: ...
    • interval: ...
  • optional tags
    • ownership: ...
  • Necessary key-value pairs
    • move: ...
    • winrate:...
  • optional key-value pairs
    • scoreLead: ...
    • ownership: ...

The behavior is still complexity because we need support the optional. I recommend add support for new command analysis_support. It should dump support keys and tags. For example,

my-analysis_support
= tag color interval ownership key move winrate scoreLead

# or do not dump the key
my-analysis_support
= tag color interval ownership 

We should presume the engine only supports for minimal set, if the engine does not support for it.

Not only the command format, we should define the strictly server behavior. There are many possible combination, in the original genmove_analyze and genmove. The following command are legal. Support for full command is unfriendly of developers.

lz-genmove_analyze
lz-genmove_analyze black 100
lz-genmove_analyze 100 black  # not correct format, but accepted by leela zero
lz-genmove_analyze black
lz-genmove_analyze 100
lz-genmove_analyze 100 maxmoves 10
lz-genmove_analyze  maxmoves 10 100 # not correct format, but accepted by leela zero

We may define a simple combination set. For example, the server always sends the color and interval tags to engine. They are not optional any more. And the color must be first, the black must be second.

my-genmove_analyze black 100 # color and interval must be provided

Some GUI automatically use genmove_analyze and genmove, like Sabaki. I think it is not good to change the pv format. Maybe add a new optional key-value pair is better way?

@zakki
Copy link
Author

zakki commented Dec 27, 2022

I like the real-time analysis of Lizzie and LizGoban, but would like to omit the asynchronous features in the first step.
I am investigating the specifications and source code to see if minimal functionality can be added to the CGOS server and client.

@CGLemon
Copy link

CGLemon commented Dec 28, 2022

This line
初期バージョンでは一旦 interval は対応せず、ext-genmove_analyze <color> のみ

I quickly check the source code. If we do not give the interval, LeelaZero and KataGo do not dump analysis string. So we may define that the ext-genmove_analyze <color> command is synchronous. Its behavior is to dump the analysis once before the move. There is no conflict between it and existing GUI tools because these tools always give interval.

@yssaya
Copy link

yssaya commented Dec 29, 2022

I like simple format.
cgos-genmove black
= Q16 winrate 0.508 score 1.4 pv D16 D4 Q4 R3 Q3 R4

Like this. Maybe score(include komi) is not neccesary?

@CGLemon
Copy link

CGLemon commented Dec 29, 2022

@yssaya
Maybe the score lead is optional? Others are necessary.

Necessary

  • winrate
  • pv (include the played move)

Optional

  • lcb
  • score
  • visits (row major array)
  • policy (row major array)
  • ownership (row major array)

Each key-value pair use one line in order to make it easy, look like

cgos-genmove black
= Q16
winrate 0.508
score 1.4
pv D16 D4 Q4 R3 Q3 R4

@zakki
Copy link
Author

zakki commented Dec 30, 2022

Thanks for coments. I will implement minimum version to cgos python server and client as poc. https://github.com/zakki/cgos/tree/python-server/server-python

@CGLemon
Copy link

CGLemon commented Dec 31, 2022

I quickly look the python server. The client parses the GTP at the local. Send the simple information to server. Server will save it into the SGF file after the game over.

Maybe the server can save the current SGF file every few seconds. The client could fetch the last analysis report by downloading it. Here is the some SGF property.

  1. Sabaki
SBKV[45.55] # black winrate is 45.55% 
  1. Lizzie
# (version) (winrate) (root visits) (move info) ... 
LZ[0.7.4 42.3 14k
move Q4 visits 5627 winrate 5779 pv Q4 R6 Q16 D4 C17 C16 D17 F17 F18 G18 E17 F16 E16 E15 D15 B15 D14 E14 E13 F13 info 
move Q16 visits 4050 winrate 5777 pv Q16 R17 Q17 R16 Q15 S14 Q4 D4 C3 C4 D3 F3 F2 G2 E3 F4 E4 E5 D5 B5 D6 E6 E7 F7 C7 B3 E2 H3 B2 B7 B8 A2 info 
]
  1. Ogatak
OGSC[-0.9] # black score lead is -0.9
SBKV[45.55] # black winrate is 45.55% 

I will keep updating it.

@zakki
Copy link
Author

zakki commented Dec 31, 2022

Also goreviewpartner has similar extension.

@zakki
Copy link
Author

zakki commented Dec 31, 2022

Maybe the server can save the current SGF file every few seconds. The client could fetch the last analysis report by downloading it.

Opponent player may be able to exploit realtime report. Does a few moves delay prevent these attack?

@CGLemon
Copy link

CGLemon commented Dec 31, 2022

@zakki
It is a good proposal. Maybe to delay time is more easy. Use Producer-consumer model. The producer generates the last SGF file. The consumer writes the last SGF file after few delay time.

def producer(queue):
    delay=30 # delay 30 seconds

    task.sgf = current_sgf()
    task.timeup = time.time() + delay
    task.last_move = is_last_move()  # Finish the consumer loop if the
                                     # game is over.
    queue.put(task)


def consumer(queue):
    while True:
        task = queue.get()

        while time.time() < task.timeup:
            pass

        write_sgf(task.sgf)

        if task.last_move:
            break

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment