
この記事で作るもの
最初の段階の成果物は派手なモデルではなく、一枚の設計表です。囲碁AIは、手を推薦するモデル、ルールを判定するエンジン、対局を保存するサーバー、ユーザーが石を置く画面が一緒に動かなければなりません。この境界を決めずにモデルから学習すると、反則手や保存エラーをモデルの性能の問題だと誤解しやすくなります。
- 19×19の正式な碁盤を使います。
- 人が黒、AIが白を担当します。
- 人の着手には時間制限を設けません。
- モデルの答えはルールエンジンがもう一度検査します。
- 毎手の盤面と手順をサーバーに保存します。
ステップ1: モデルとルールエンジンを分けます
モデルの責任は、現在の盤面を見て次の座標の候補を出すところまでです。その点が空いているか、自殺手か、直前の盤面を繰り返すコウかは、ルールエンジンが判定します。モデルがすでに石のある点を答えたら、候補を拒否してもう一度要求します。再要求も失敗したときは、勝手な手に置き換えずにエラーを記録します。
この分離が大切なのは再現性のためです。同じ盤面で問題が起きたとき、モデルの選択が悪かったのか、ルールのコードが間違っていたのかを別々に確かめられます。ルールはテストで固定し、モデルは交換可能な部品として残しておきます。
ステップ2: 対局の状態を一つのオブジェクトとして定義します
最小限の状態には、19×19の盤面、次の手番、取った石の数、コウで禁止された座標、全手順、最後の保存日時が入ります。画面だけを見て状態を復元しようとせず、サーバーが原本を保管すべきです。ブラウザを開き直しても同じ対局を続けるには、対局コードとアクセスキーも必要です。
ステップ3: 完了条件を書き出します
最初のバージョンの完了条件は「強いAI」ではありません。人が合法的に着手でき、AIの反則の答えを拒否し、再読み込みしても手順が残り、二回続けてパスすると終局する状態であれば十分です。この基準を通過してから学習データと棋力を改善すれば、問題の原因を一度に一つずつ追えます。
次の記事では、SGF棋譜一局を学習用の入力と正解座標に分ける過程を説明します。
この段階の実際のコード
MariaGO のWeb対局は、ステップ2で述べた「対局の状態を一つのオブジェクト」を、以下の GameRow 型としてサーバーに保存します。盤面、次の手番、コウの座標、取った石、連続パスの回数、全手順が一行に入り、別の端末で続きを打つためのアクセスキーも一緒に保管します。
mariago-web/lib/gameTypes.ts
export type MoveRec = {
ply: number;
color: 1 | 2;
pass?: boolean;
r?: number;
c?: number;
};
export type GameWinner = "black" | "white" | "draw";
export type GameRow = {
code: string;
guest_id: string;
/** 비공개 키 — 다른 기기 이어두기용. 남에게 코드만 공유하면 안 됨 */
access_key: string;
board: number[];
to_play: number;
ko: { r: number; c: number } | null;
last_move: { r: number; c: number } | null;
move_no: number;
cap_b: number;
cap_w: number;
pass_streak: number;
epoch: number;
started: boolean;
status: "playing" | "ended";
end_text: string | null;
winner: GameWinner | null;
moves: MoveRec[];
created_at: string;
updated_at: string;
};使用したモデル: Qwen3-VL-8B-Instruct + LoRA アダプター(lora_mix_qwen_r5)。全ソースとモデルの説明は「8. 全ソースコードと使用したモデル」の記事で見られます。
COMMENTS · CHAPTER 01
まず囲碁AIの範囲を決める コメント 0
まだコメントはありません。気になった点や補足があれば残してください。
コメントを登録するには、Googleで始めてニックネームとメールアドレスを登録してください。
Googleで始める