콘텐츠로 이동

NaizVL 오프라인 키트 — 제작 가이드

외부망이 연결된 개발 서버에서 폐쇄망 운영 서버용 오프라인 설치 키트를 만드는 절차.

1. 대상 환경 (키트가 지원하는 운영 환경)

항목
OS Ubuntu 22.04 LTS (USB 설치)
GPU NVIDIA RTX A6000 × 2
CUDA 12.8 (키트 동봉 local apt repo)
Python 3.10 시스템 (venv 미사용)
모델 Qwen3-VL-8B-Instruct (~16GB)
키트 크기 ~25GB tar.gz
설치 후 디스크 ~40GB

2. 빌드 호스트 사전 준비

  1. 개발 서버에 qwen3-5-vl venv (서버 코드 + 의존성 완성)
  2. wget (대부분 기본 설치) — CUDA local repo .deb 자동 다운로드
  3. apt-rdepends — transitive 의존성 펼치기. 미설치 시 스크립트가 자동 설치 시도.
  4. (선택) GPG 서명용 키 — export GPG_KEY=<keyid>

NVIDIA 드라이버는 별도 다운로드 불필요. CUDA 12.8 local repo 가 cuda-drivers 메타를 포함.

3. 제작 명령

cd /home/naiz/NaizVL

# (선택) GPG 서명
export GPG_KEY=<your-gpg-keyid>

# 기본: SRC_ROOT/dist 에 산출물 생성
./deploy/make-offline-kit.sh v20260519-qwen3vl8b

# USB 에 직접 생성 (권장 파일시스템: exfat 또는 ext4)
./deploy/make-offline-kit.sh v20260519-qwen3vl8b \
    --output /media/naiz/KINGSTON64

# OUT_DIR 환경변수로도 지정 가능
OUT_DIR=/media/naiz/KINGSTON64 \
    ./deploy/make-offline-kit.sh v20260519-qwen3vl8b

# (선택) CUDA 버전 덮어쓰기 — 기본 12.8.0 / driver 570.86.10
# export CUDA_REPO_DEB="cuda-repo-ubuntu2204-12-8-local_12.8.0-570.86.10-1_amd64.deb"
# export CUDA_REPO_URL="https://developer.download.nvidia.com/.../$CUDA_REPO_DEB"

# (선택) 캐시된 CUDA .deb 강제 재다운로드
./deploy/make-offline-kit.sh v20260519-qwen3vl8b --no-cache-debs

USB 직접 생성 주의사항

  • 파일시스템: FAT32/vfat 은 단일 파일 4GB 제한으로 불가. exfat 또는 ext4:
    sudo mkfs.exfat /dev/sdX1   # exfat
    sudo mkfs.ext4  /dev/sdX1   # ext4 (Linux 전용)
    
  • 여유 공간: 30GB+ 권장 (tar ~25GB + 해시·서명).
  • 권한: 마운트 경로 쓰기 권한 확인 — sudo chown -R $USER /media/naiz/KINGSTON64
  • 완료 후 안전 분리: sync && sudo umount /media/naiz/KINGSTON64

첫 실행 시 $SRC_ROOT/dist/nvidia-debs/cuda-repo-*.deb (3~4GB) 다운로드. 이후 SSD 캐시 재사용으로 빠름.

4. 산출물

dist/
├── naizvl-offline-kit-v20260519-qwen3vl8b.tar.gz         (~25GB)
└── naizvl-offline-kit-v20260519-qwen3vl8b.tar.gz.sha256

tar 내부에 MANIFEST.sha256 + (GPG 서명 시) MANIFEST.sha256.asc 포함.

키트 내부 구조

naizvl-offline-kit-<version>/
├── 00-system/
│   ├── nvidia-driver-*.deb
│   ├── cuda-repo-ubuntu2204-12-8-local_*.deb
│   └── dependencies/*.deb           # libgl1, ffmpeg, gcc-12, python3.10-dev 등
├── 01-python/
│   ├── requirements.lock
│   └── wheels/*.whl                 # scipy / scikit-learn / flash-attn 포함
├── 02-app/                          # 최소 운영 키트 (~45 KB)
│   ├── naizvl_server_replica.py
│   ├── config.example.yaml
│   └── systemd/naizvl.service
├── 03-models/
│   └── Qwen3-VL-8B-Instruct/        # ~16GB
├── install.sh
├── VERSION
├── BUILD_DATE
├── MANIFEST.sha256
└── MANIFEST.sha256.asc              # GPG_KEY 지정 시

5. APT 패키지 정책

make-offline-kit.shAPT_PKGS 가 명시 포함하는 핵심 패키지:

패키지 이유
python3 python3.10 python3.10-venv python3-pip 시스템 python. python3 메타는 가상 의존성 제공자.
libpython3.10 target ISO 의 stdlib upgrade 시 broken 방지.
python3.10-dev libpython3.10-dev vLLM 의 Triton JIT 가 런타임에 cuda_utils.c 를 gcc 로 빌드 → #include <Python.h> 필요. (2026-05-19 추가)
libgl1 libglib2.0-0 libsm6 libxext6 libxrender1 ffmpeg OpenCV·이미지 디코딩 런타임.
dkms dpkg-dev make build-essential nvidia 드라이버 dkms 빌드 체인.
gcc-12 g++-12 cpp-12 22.04.5 ISO default kernel (6.8.0-40-generic) 이 gcc-12 로 빌드 → kernel header Makefile 이 -ftrivial-auto-var-init=zero 사용 → gcc-11 로는 dkms compile fail. (2026-05-19 추가)
linux-headers-$(uname -r) dkms 모듈 컴파일 시 필요.

apt-rdepends 가 transitive (Depends + PreDepends) 펼침. Recommends/Suggests 는 제외 → GUI 패키지·테마 불필요한 살이 안 붙음.

6. Python wheel 정책

REQUIRED_EXTRAS — freeze 미포함 패키지 자동 보강

# make-offline-kit.sh
REQUIRED_EXTRAS=(scipy scikit-learn)
  • scipy / scikit-learn: transformers.generation.candidate_generatorsklearn.metrics 사용. 미포함 시 PYTHONNOUSERSITE=1 운영 환경에서 ModuleNotFoundError.
  • 각 항목은 빌드 환경에 없으면 pip installrequirements.lock 에 자동 추가.

LOCAL_WHEEL_CACHE — 수동 빌드 wheel 통합

PyPI 에 사전 빌드 wheel 이 없는 패키지 (flash-attn 등) 는 별도 빌드 후 wheels_cache/ 에 두면 자동으로 키트 wheels/ 에 포함.

# 기본 위치 (환경변수로 override 가능)
export LOCAL_WHEEL_CACHE=/home/naiz/qwen3-5-vl/wheels_cache
ls $LOCAL_WHEEL_CACHE/
# → flash_attn-2.8.3-cp310-cp310-linux_x86_64.whl

make-offline-kit.sh 가 이 폴더의 모든 .whl 을: 1. 키트의 01-python/wheels/ 로 복사 2. requirements.lock<pkg>==<ver> 자동 추가

flash-attn 빌드 절차 (개발 서버, 인터넷·GPU 필요)

source /home/naiz/qwen3-5-vl/.qwen3-5-vl/bin/activate

# 캐시 충돌 방지 — 이전 flash_attn 모두 정리
pip uninstall -y flash-attn flash_attn 2>/dev/null
find ~/.cache/pip -name "flash_attn*" -delete
pip cache purge
rm -f /home/naiz/qwen3-5-vl/wheels_cache/flash_attn-*.whl

# 빌드 의존성
pip install -U packaging wheel ninja setuptools

# 환경 변수 — 멀티 GPU arch 지원
export TORCH_CUDA_ARCH_LIST="8.0;8.6;8.9;9.0+PTX"   # A100·Ampere·Ada·Hopper + 미래
export MAX_JOBS=8                                    # CPU 코어 수에 맞춤
export FLASH_ATTENTION_FORCE_BUILD=TRUE
export TMPDIR=/tmp/flash_build_tmp
mkdir -p "$TMPDIR" /home/naiz/qwen3-5-vl/wheels_cache/

# 빌드 — 캐시·사전 wheel 모두 차단, 강제 컴파일 (30~50분)
pip wheel flash-attn==2.8.3 \
    --no-cache-dir --no-binary flash-attn \
    --no-build-isolation --no-deps --verbose \
    -w /home/naiz/qwen3-5-vl/wheels_cache/ 2>&1 | tee /tmp/flash_build.log

# 검증
WHEEL=$(ls /home/naiz/qwen3-5-vl/wheels_cache/flash_attn-*.whl | head -1)
pip install --force-reinstall --no-deps "$WHEEL"
python3 -c "
import flash_attn
from flash_attn.ops.triton.rotary import apply_rotary
from flash_attn import flash_attn_func
import torch
q = torch.randn(1,4,8,64, device='cuda', dtype=torch.bfloat16)
print('flash_attn', flash_attn.__version__, 'on', torch.cuda.get_device_name(0), 'OK')
"

TORCH_CUDA_ARCH_LIST 권장 조합

운영 범위 TORCH_CUDA_ARCH_LIST 예상 wheel 크기
현재 환경만 (A6000) "8.6" ~30 MB
Ampere 이후 일반 "8.0;8.6;8.9;9.0" ~80 MB
권장 (광범위 + 미래 호환) "8.0;8.6;8.9;9.0+PTX" ~112 MB
모든 데이터센터 GPU "7.5;8.0;8.6;8.9;9.0+PTX" ~130 MB

+PTX 는 마지막 SM 에 PTX (asm) 도 포함, 미래 GPU 도 JIT 컴파일로 동작.

빌드 정보 보존

cat > /home/naiz/qwen3-5-vl/wheels_cache/flash_attn-2.8.3.BUILD_INFO.md << EOF
# flash-attn 2.8.3 빌드 정보
- 빌드일: $(date -Iseconds)
- torch: $(python3 -c "import torch; print(torch.__version__)")
- CUDA toolkit (nvcc): $(nvcc --version | grep release)
- cxx11_abi: $(python3 -c "import torch; print(torch._C._GLIBCXX_USE_CXX11_ABI)")
- TORCH_CUDA_ARCH_LIST: $TORCH_CUDA_ARCH_LIST
- 호환 GPU: A100, A6000, RTX 30xx, RTX 40xx, L4/L40, H100, +미래(PTX)
EOF

torch 또는 CUDA 업그레이드 후엔 ABI 일치 보장을 위해 반드시 재빌드 필요.

7. 02-app 정책 (운영 코드 최소화)

운영에 필요한 파일만 명시 복사 — naizvl_server_replica.py · config.example.yaml · systemd/naizvl.service 3개. 평가·튜닝·데이터셋·로그·문서 제외 → 이전 5.3GB → ~45KB 축소.

향후 서버 코드가 여러 파일로 분리되면 make-offline-kit.sh 의 명시 복사 목록에 추가해야 합니다.

8. 업데이트 전략

변경 범위 방법
코드만 (naizvl_server_replica.py) 파일만 USB → rsyncsystemctl restart
모델 교체 03-models/ tar → 디렉토리 교체 → config.yaml.checkpoint 수정 → 재기동
의존성 변경 (wheel/apt) 키트 전체 재제작 권장

9. 버전 관리 규칙

파일명: naizvl-offline-kit-<YYYYMMDD>-<model>[-<hotfix>].tar.gz

예: - v20260422-qwen3vl8b — 초기 배포 - v20260519-qwen3vl8b — gcc-12 / python3.10-dev fix 포함 - v20260501-qwen3vl8b-hotfix1 — 같은 모델 + 코드 핫픽스 - v20260615-qwen3_5-9b — 모델 교체 시

키트 내부 VERSION / BUILD_DATE 로 추적.

10. venv 정책

환경 Python 배포 방식
개발 서버 (키트 제작) qwen3-5-vl venv make-offline-kit.sh 가 venv 의 pip freeze 결과로 requirements.lock 및 wheel 수집
대상 서버 (설치) 시스템 Python 3.10 venv 생성하지 않음. sudo pip3 install --no-index … 로 system-wide

근거 - 폐쇄망 전용 서버는 Python 용도가 이 애플리케이션 단독 - venv 미사용 → systemd unit 경로 단순 (/usr/bin/python3.10), 관리 포인트 감소 - Ubuntu 22.04 는 PEP 668 미적용 → pip install 에 별도 플래그 불필요

11. 관련 문서

  • INSTALL.md — 운영 서버 설치 가이드 (USB Ubuntu 설치부터)
  • README.md — 변경 이력 + 인덱스
  • ../research.md §20 (NaizVL 저장소 참고) — 서버 전체 구조 스냅샷
  • ../eval/README.md (NaizVL 저장소 참고) — 평가 도구