
Not started yet
Othello has neither training code nor training data. What follows is a plan.
1. Deploy the search AI
Rebuilding the web deploys the search AI from post 2. The 13–0 sequences from post 1 will no longer work.
2. Bring the VLM back up
Either fix the loading problem or switch to Qwen3-VL-8B, which the Go server uses. If the model cannot be loaded, the server will not start, and any move switched to random will be recorded and shown on the screen.
3. Coordinate alignment
In Go, after learning that each model writes coordinates differently, we spent a long time on coordinate training. We are applying the same training to Gomoku. In the pre-training test, merely aligning the columns of the text board reduced the rate of choosing an occupied square from 40% to 21%.
Othello is 8×8 and the prompt includes the list of legal moves, so the coordinate burden is small. Still, we start with the same test.
4. The search AI as teacher
In Go, after fixing the heuristic, we trained the model with that heuristic as the teacher. In Othello, the search AI is the teacher. VLM LoRA is trained with the moves chosen by the search AI as the answers.
Since the answer for every move is decided by search, the data does not become lopsided the way it did in Gomoku's automatic training, which collected only the winning side's moves.
5. Evaluation
- As in post 1, expand all of Black's moves up to move 11 and count whether any wipe-out sequence exists.
- Play 100 games each against random, the one-move AI and the search AI.
- Record the kind of opponent in games against people. The current game records have no column for it.
Moves from games lost in evaluation go back in as teacher data.
The actual code for this step
This is the prompt currently given to the VLM. It includes the list of legal moves and asks for a one-line JSON answer.
vlm_server/server.py
SYSTEM_PROMPT = (
"당신은 8×8 오델로(Reversi)의 강한 플레이어입니다. "
"보드 이미지와 텍스트 격자를 보고 다음 단 한 수를 고르세요. "
"텍스트 격자가 이미지와 다르면 텍스트를 우선하세요. "
"좌표는 0-indexed 정수 (row, col) 이며 각각 0..7 입니다. "
"(0,0)은 좌상단 A1, 열 A–H = col 0–7, 행 1–8 = row 0–7. "
"X=흑, O=백, .=빈칸. 반드시 합법수만 고르세요. "
"합법수는 상대 돌을 하나 이상 끼워 뒤집는 빈 칸입니다. "
"응답은 설명 없이 JSON 한 줄만 출력하세요."
)
# ...
def build_prompt(
board: bytes,
ai_side: int,
legal: list[tuple[int, int]],
forbidden: Optional[list[tuple[int, int]]] = None,
) -> str:
side = "흑(X)" if ai_side == 1 else "백(O)"
n_b, n_w = rules.counts(board)
forbid_note = ""
if forbidden:
banned = ", ".join(f"({r},{c})" for r, c in forbidden[:16])
forbid_note = f"\n금지 좌표(고르지 마세요): {banned}\n"
return (
f"당신의 차례: {side}. 흑 {n_b} · 백 {n_w}.\n"
"보드 (X=흑, O=백, .=빈, 행=row 0=위, 열=col 0=왼쪽):\n"
f"{rules.board_text(board)}\n\n"
f"합법수: {rules.format_moves(legal)}\n"
f"{forbid_note}"
'다음 수를 JSON 한 줄로만 답하세요. 예: {"row": 2, "col": 3} '
'합법수가 없으면 {"pass": true} 만 출력.'
)The next post is "5. The full source code and the models used".
COMMENTS · CHAPTER 04
A plan to bring what we learned from Go and Gomoku to Othello 0 comments
No comments yet. Leave a question or anything you would like to add.
To post a comment, continue with Google and register a nickname and email address.
Continue with Google