게시판오목 Next.js 웹과 VLM 착수 API 연결하기예제 소스

예제 소스

오목 Next.js 웹과 VLM 착수 API 연결하기 · 파일 59개

TRAINING.md

# OMK VLM 학습 파이프라인

수집한 JSONL 로그로 Qwen3-VL 을 LoRA SFT 합니다. 추론 서버는 `--lora-dir` 한 줄 추가만으로 학습 결과를 그대로 사용합니다.

## 0. 사전 준비

```bash
cd omook
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt   # peft, datasets 포함
```

## 1. 데이터 수집 (서버 실행 시)

서버를 `--log-jsonl` 로 띄워 두기만 하면 클라이언트의 모든 수가 한 줄씩 누적됩니다.

```bash
python vlm_pva_server.py \
    --host 127.0.0.1 --port 9299 --device mps \
    --model-id /path/to/Qwen__Qwen3-VL-8B-Instruct \
    --log-jsonl logs/omook_vlm.jsonl
```

클라이언트의 모드 (Human vs AI / Human vs VLM / AI vs VLM) 는 모두 `OMKL` 메시지로 서버에 같이 기록되므로, 가장 빠른 데이터 수집은 **AI vs VLM + 자동 재시작 체크** 입니다.

## 2. 데이터셋 변환

```bash
python dataset_omook.py \
    --jsonl logs/omook_vlm.jsonl \
    --out-dir sft_data/omook_sft \
    --save-images
```

기본 필터:
- 완료된 게임만 (`BlackWin` / `WhiteWin`).
- 그중 **승리한 쪽** 의 수만 → 전문가 시연으로 가정.
- 사람 / 로컬 AI 의 수만 (학습 신호로 의미 있는 것). VLM 자기 응답은 제외.
- 보드는 OMKL 의 post-move 상태에서 둔 돌을 빼서 pre-move 로 복원.

옵션:
- `--all-actors` → VLM 의 수도 포함 (자기증류식 데이터)
- `--include-losers` → 패배한 쪽 수도 포함 (대비/오답 학습용; 보통 비추천)
- `--save-images` 를 빼면 train.jsonl 만 만들어집니다 (이미지 없으면 학습 단계에서 이미지가 없어 스킵됨 — 보통 켜두세요).

결과:
```
sft_data/omook_sft/
  train.jsonl          # {id, size, stone, actor, prompt, answer, image_path}
  img_00000000.png ... # 보드 렌더 이미지
  dataset_info.json
```

> 참고: 출력 디렉토리 이름으로 `datasets/` 는 쓰지 않습니다. omook 디렉토리 안에
> `datasets/` 가 있으면 Python 이 그것을 namespace package 로 잡아 huggingface
> `datasets` 패키지를 가리는 import 충돌이 일어납니다. 기본값을 `sft_data/` 로
> 두는 이유입니다.

## 3. LoRA 파인튜닝

```bash
python train_vlm.py \
    --dataset-jsonl sft_data/omook_sft/train.jsonl \
    --base-model /path/to/Qwen__Qwen3-VL-8B-Instruct \
    --output-dir vlm_models/lora_omook \
    --epochs 1 --batch-size 1 --grad-accum 8 --lr 2e-4
```

권장 (Apple Silicon):
- 8B 모델은 MPS 메모리 부담이 큽니다. 가능하면 **Qwen3-VL-2B** 로 시작.
- `--max-samples 500` 등으로 한번 짧게 돌려 데이터/형식 검증 후 본 학습.
- bf16 은 CUDA 만, MPS 는 fp16 로 자동 폴백.

CUDA 환경에서 더 안정적입니다 (그라디언트 체크포인팅 + LoRA r=8 기준 8B 모델도 24GB 정도면 동작).

## 4. 학습 결과로 추론

```bash
python vlm_pva_server.py \
    --host 127.0.0.1 --port 9299 --device mps \
    --model-id /path/to/Qwen__Qwen3-VL-8B-Instruct \
    --lora-dir vlm_models/lora_omook \
    --log-jsonl logs/omook_vlm.jsonl     # 새 로그도 같이 모으기
```

서버 로그에 `LoRA 어댑터 로드: base=..., adapter=vlm_models/lora_omook` 가 출력되면 적용 성공입니다.

## 5. 데이터셋이 늘면 반복

- 새 게임 → 새 로그 누적 → 다시 `dataset_omook.py` 로 변환 → `train_vlm.py` 로 재학습.
- 수집 ↔ 학습 ↔ 평가를 반복하면 self-play 방식의 점진적 강화가 됩니다.

## 6. (권장) 학습 모드 자동 학습 — `--auto-train`

위 2~4 단계를 매 게임마다 사람이 손으로 돌리는 대신, 서버에 `--auto-train` 을 주면
**학습 모드(클라이언트의 AI vs VLM) 게임이 흑승/백승으로 끝날 때마다** 서버가 알아서:
(무승부는 승리 측 수가 없어 학습 데이터로 잡히지 않으므로 트리거에서 제외)

1. `dataset_omook.py` 를 subprocess 로 실행 → JSONL 을 SFT 데이터셋으로 갱신,
2. `train_vlm.py` 를 subprocess 로 실행 → LoRA 어댑터를 `--lora-dir` 에 덮어쓰기,
3. 추론 파이프라인 캐시를 무효화 → 다음 요청부터 갱신된 LoRA 가 자동 적용

까지 한 번에 처리합니다. 학습은 별도 프로세스라 추론 모델과 메모리가 분리됩니다.

```bash
python vlm_pva_server.py \
    --host 127.0.0.1 --port 9299 --device mps \
    --model-id /path/to/Qwen__Qwen3-VL-8B-Instruct \
    --log-jsonl logs/omook_vlm.jsonl \
    --lora-dir vlm_models/lora_omook_auto \
    --auto-train \
    --auto-train-every 1 \
    --auto-train-min-examples 8 \
    --auto-train-max-samples 200 \
    --auto-train-epochs 1
```

옵션 요약:
- `--auto-train-every N` — N 게임마다 1번만 학습 (기본 1=매 게임)
- `--auto-train-min-examples N` — 학습 예제가 N건 미만이면 데이터만 갱신, 학습은 스킵
- `--auto-train-max-samples N` — 한 라운드 최대 표본 수 (0=전체). MPS/노트북이면 200~500 권장
- `--auto-train-epochs / --auto-train-batch-size / --auto-train-grad-accum / --auto-train-lr`
- `--auto-train-num-workers N` — `dataset_omook.py` 의 이미지 렌더링 병렬도(프로세스) 와
  `train_vlm.py` 의 DataLoader 워커 수. 기본 `cpu/2`. 데이터셋 변환은 4~8 코어로
  거의 선형 스케일됨 (예: 31s → 4s).
- `--auto-train-torch-threads N` — `torch.set_num_threads(N)`. 0 = torch 기본.
- `--auto-train-dataset-dir` — 데이터셋 출력 위치 (기본 `sft_data/omook_sft_auto`)

운용 팁:
- 클라이언트의 **자동 재시작 체크박스** 와 **AI vs VLM 모드** 를 같이 켜두면 서버가
  계속 게임이 들어오는 만큼 데이터 수집 → 학습 → 즉시 적용 → 다시 게임 으로
  self-play 루프를 자율적으로 돌립니다.
- 한 학습이 끝나기 전에 들어온 추가 게임 종료 신호는 collapse 되어 백로그가 쌓이지
  않습니다. 학습 1라운드가 게임보다 오래 걸려도 안전합니다.
- 8B 모델은 MPS 1라운드가 매우 느릴 수 있습니다. 우선 `Qwen3-VL-2B-Instruct +
  --auto-train-max-samples 100` 로 동작을 확인한 뒤 늘리세요.