게시판SGF 기보로 학습하는 바둑 LLM 인공지능예제 소스

예제 소스

SGF 기보로 학습하는 바둑 LLM 인공지능 · 파일 169개

run_heuristic_gemma4.py

#!/usr/bin/env python3
"""휴리스틱이 둔 수로 Gemma 4를 학습한 뒤, 계가 없이 휴리스틱과 3국을 둔다."""

from __future__ import annotations

import json
import socket
import subprocess
import time
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
PY = ROOT / ".venv" / "bin" / "python"
OUT = ROOT / "logs" / "heuristic_gemma4_20261009"
MODEL = "********"
LORA = "********"
PORT = 9341


def log(msg: str) -> None:
    print(msg, flush=True)


def run(cmd: list[str], log_path: Path) -> int:
    log("[runner] " + " ".join(cmd))
    log_path.parent.mkdir(parents=True, exist_ok=True)
    with log_path.open("ab") as fh:
        rc = subprocess.call(cmd, cwd=ROOT, stdout=fh, stderr=subprocess.STDOUT)
    log(f"[runner] rc={rc} log={log_path}")
    return rc


def port_open(port: int) -> bool:
    sock = socket.socket()
    sock.settimeout(1)
    try:
        sock.connect(("127.0.0.1", port))
        return True
    except OSError:
        return False
    finally:
        sock.close()


def wait_port(port: int, timeout_s: float) -> bool:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        if port_open(port):
            return True
        time.sleep(5)
    return False


def main() -> int:
    OUT.mkdir(parents=True, exist_ok=True)
    if port_open(PORT):
        raise SystemExit(f"port {PORT} is already in use")
    rc = run(
        [
            str(PY),
            "scripts/dataset_heuristic_teacher.py",
            "--source",
            "logs/gemma4_r5_20261009/matches.sqlite:BW",
            "--source",
            "logs/heuristic_r5_eye_20261008/matches.sqlite:W",
            "--out",
            "sft_data/heuristic_gemma4",
        ],
        OUT / "dataset.log",
    )
    if rc != 0:
        return rc
    rc = run(
        [
            str(PY),
            "scripts/train_ladder_lora.py",
            "--shape",
            "onpolicy",
            "--data-name",
            "heuristic_gemma4",
            "--log-name",
            "gemma4_heuristic",
            "--model",
            MODEL,
            "--base",
            "-",
            "--out",
            LORA,
            "--shape-n",
            "2000",
            "--skip-base-eval",
        ],
        OUT / "train.log",
    )
    if rc != 0:
        return rc
    cmd = [
        str(PY),
        "-m",
        "vlm_server",
        "serve",
        "--host",
        "127.0.0.1",
        "--port",
        str(PORT),
        "--model",
        MODEL,
        "--lora-dir",
        LORA,
        "--text-only-move",
        "--board-repr",
        "aligned",
        "--no-score-guided",
        "--illegal-retry-max",
        "16",
        "--illegal-retry-budget-s",
        "240",
        "--log-jsonl",
        str(OUT / "gemma4.jsonl"),
    ]
    serve_log = open(OUT / "gemma_serve.stdout", "ab")
    log(f"[runner] start gemma4 without score guide on {PORT}")
    proc = subprocess.Popen(cmd, cwd=ROOT, stdout=serve_log, stderr=subprocess.STDOUT, start_new_session=True)
    if not wait_port(PORT, 600):
        proc.terminate()
        raise SystemExit("gemma4 did not listen")
    log(f"[runner] gemma4 listening pid={proc.pid}")
    reg_path = ROOT / "scripts" / "models.json"
    reg = json.loads(reg_path.read_text(encoding="utf-8"))
    reg["models"]["gemma4_heuristic"] = {
        "port": PORT,
        "model": MODEL,
        "lora": LORA,
        "note": "휴리스틱 착수 학습. 대국 때는 --no-score-guided.",
    }
    reg_path.write_text(json.dumps(reg, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    rc = run(
        [
            str(PY),
            "scripts/play_heuristic_vs_model.py",
            "--port",
            str(PORT),
            "--model-name",
            "gemma4_heuristic",
            "--games",
            "3",
            "--max-moves",
            "0",
            "--out-dir",
            str(OUT.relative_to(ROOT)),
        ],
        OUT / "play.log",
    )
    log(f"[runner] match rc={rc}")
    return rc


if __name__ == "__main__":
    raise SystemExit(main())