Files
luke_scribe/notebooks/luke-scribe-colab.ipynb
T
lukehemmin 0d90845ac6 docs: add Colab GPU test notebook for real-model verification
CPU-only dev env verified via mocks; the notebook runs the full real
pipeline on Colab Pro T4: clone → ffmpeg/venv install → detect (GPU
capability tier) → 127 unit/integration tests → sample TTS (KO+EN
tech terms) → real faster-whisper transcription → hotword/postprocess
→ API smoke → benchmark.
2026-08-12 16:39:25 +09:00

12 KiB

luke_scribe — Colab 실전 테스트 노트북

내부용 로컬 STT 전사 API (faster-whisper, hardware-adaptive, privacy-first)

이 노트북은 CPU-only 개발 환경에서 mock으로만 검증했던 것을, Colab Pro(GPU + 터미널)에서 실전 검증하기 위한 것입니다.

검증 대상

  • luke-scribe detect → T4 GPU 실제 감지 (능력 등급 T1~T3, 정밀도, 워커수)
  • faster-whisper 모델 다운로드 + 실제 한국어 전사 (CPU-only 환경에선 불가)
  • glossary/hotword 후처리 (KO+EN 기술용어 보존)
  • REST API 흐름 (업로드 → poll → 결과)
  • turbo vs large-v3 벤치마크

준비

  1. 런타임 → 런타임 유형 변경 → T4 GPU 선택
  2. (Colab Pro) 터미널을 사용해도 동일한 명령을 실행할 수 있습니다
  3. 저장소가 private이면 아래 셀에 Gitea 토큰 입력 (Settings → Applications → Generate New Token)

In [ ]:
# 0) 런타임 확인 — T4 GPU가 활성 상태여야 합니다
!nvidia-smi
import sys
print('Python', sys.version.split()[0])

1) 저장소 클론

feat/full-platform 브랜치를 클론합니다. 저장소가 private이면 아래 셀의 GITEA_TOKEN에 토큰을 입력하세요.

In [ ]:
# 1) 클론 (private 저장소면 GITEA_TOKEN 입력)
GITEA_TOKEN = ''  # ← 필요 시 입력: https://git.lukehemmin.com/user/settings/applications

if GITEA_TOKEN:
    REPO = f'https://{GITEA_TOKEN}@git.lukehemmin.com/lukehemmin/luke_scribe.git'
else:
    REPO = 'https://git.lukehemmin.com/lukehemmin/luke_scribe.git'

!rm -rf luke_scribe
!git clone -b feat/full-platform {REPO}
import os
os.chdir('/content/luke_scribe')
print('클론 완료 →', os.getcwd())
!git log --oneline -1

2) 시스템 의존성 + 설치

ffmpeg(오디오 정규화) 설치 후 venv에 luke-scribe를 설치합니다.

In [ ]:
# 2) 시스템 패키지 (ffmpeg — ffprobe/정규화에 필수)
!apt-get update -qq && apt-get install -y -qq ffmpeg >/dev/null
!ffmpeg -version 2>&1 | head -1
!ffprobe -version 2>&1 | head -1
In [ ]:
# 3) venv + 설치 (GPU 추론은 engine+api만으로 충분 — Colab T4에 CUDA 런타임 내장)
!python3 -m venv .venv
!source .venv/bin/activate && pip install -q --upgrade pip
!source .venv/bin/activate && pip install -q -e '.[engine,api]'
!source .venv/bin/activate && pip install -q edge-tts  # 샘플 음성 생성용

# 이후 셀에서 activate 없이 CLI 사용 가능하게 PATH 등록
import os
os.environ['PATH'] = '/content/luke_scribe/.venv/bin:' + os.environ['PATH']
print('설치 완료')
!luke-scribe --help 2>&1 | head -12

3) 하드웨어 감지 — T4 GPU 실제 확인

CPU-only 환경에서는 T0 / cpu / int8이 나왔지만, Colab T4(16GB VRAM, sm_75)에서는 GPU가 감지되어야 합니다.

In [ ]:
# 4) detect — GPU 감지 / 능력 등급 / 정밀도 / 워커수
!luke-scribe detect

4) 단위/통합 테스트 (127개)

mock 기반 테스트가 GPU 환경에서도 전부 통과하는지 확인합니다.

In [ ]:
# 5) 테스트 스위트
!source .venv/bin/activate && python -m pytest tests/ -q 2>&1 | tail -5

5) 실전 전사 (GPU)

5-1) 샘플 오디오 생성

edge-tts(MS TTS)로 한국어 + 영문 기술용어가 섞인 샘플을 생성합니다. 이 텍스트에는 vLLM, Kubernetes, GPU 같은 용어가 포함되어 glossary/hotword 검증에 적합합니다.

In [ ]:
# 6) 샘플 오디오 생성 (한국어 + 기술용어, 무료 TTS)
!mkdir -p samples
!edge-tts --voice ko-KR-SunHiNeural --text '오늘은 vLLM 서버를 Kubernetes 클러스터에 배포하는 방법을 설명합니다. GPU 가속 추론으로 대기 시간을 줄일 수 있습니다.' --write-media samples/colab-ko-en.mp3
!ffprobe -v error -show_entries format=duration -of json samples/colab-ko-en.mp3
In [ ]:
# 7) 실전 전사 — GPU 자동 감지 + 모델 다운로드 (large-v3-turbo)
# 첫 실행 시 Hugging Face에서 모델을 다운로드합니다 (turbo ≈ 1.6GB, 1~2분)
!time luke-scribe transcribe samples/colab-ko-en.mp3 --language ko --device auto

5-2) 후처리 검증

glossary(오인식 용어 복원) + hotword(용어 사전 주입) 동작을 확인합니다. --hotword vLLM Kubernetes를 주면 initial_prompt에 용어가 주입되어 보존률이 올라갑니다.

In [ ]:
# 8) hotword 포함 전사 (용어 보존 강화)
!luke-scribe transcribe samples/colab-ko-en.mp3 --language ko --device auto --hotword vLLM --hotword Kubernetes

6) REST API 스모크

서버를 백그라운드로 띄우고 업로드 → poll → 결과(SRT) 흐름을 검증합니다.

In [ ]:
# 9) API 키 생성 (1회 출력)
!luke-scribe key --create --scopes transcribe,admin --file /content/api_keys.json
In [ ]:
# 10) 서버 기동 (in-proc 큐, 백그라운드)
import subprocess, time, os, json
env = dict(os.environ)
env['LUKESCRIBE_API_KEY_FILE'] = '/content/api_keys.json'
env['LUKESCRIBE_QUEUE_BACKEND'] = 'inproc'
proc = subprocess.Popen(
    ['luke-scribe', 'serve', '--port', '8000'],
    env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
)
# 기동 대기
import urllib.request
for _ in range(30):
    try:
        urllib.request.urlopen('http://localhost:8000/health', timeout=1)
        break
    except Exception:
        time.sleep(1)
print('서버 기동 OK')
In [ ]:
# 11) 업로드 → poll → 결과
import json, time, urllib.request, urllib.error

KEY = json.load(open('/content/api_keys.json'))['keys'][0]

# multipart 업로드 (curl 사용 — 간단)
import subprocess
r = subprocess.run(
    ['curl', '-s', '-X', 'POST', 'http://localhost:8000/v1/jobs',
     '-H', f'X-API-Key: {KEY}',
     '-F', 'file=@samples/colab-ko-en.mp3',
     '-F', 'options={"language":"ko","formats":["json","srt"]}'],
    capture_output=True, text=True,
)
job = json.loads(r.stdout)
print('생성:', job)
job_id = job['job_id']

# 완료까지 poll (워커 없이 in-proc이라 즉시 완료되지는 않음 → 여기선 생성까지만 확인)
print('job_id =', job_id)

참고 — 서버에서 실제 전사까지 실행하려면

in-proc 브로커는 큐만 받고 워커가 별도로 소비해야 합니다. 워커 스레드를 띄우거나 간단하게는 배치 파이프라인을 직접 호출하는 CLI가 더 간단합니다. API 전체 흐름(워커 포함)은 다음 셀에서 python으로 브로커 + 워커를 함께 돌려 확인합니다.

In [ ]:
# 12) 브로커 + 워커 포함 전체 흐름 (in-proc)
# 서버의 in-proc 브로커에 enqueue된 job을 같은 프로세스의 워커가 소비하는 구조는
# 프로세스 분리 필요 → 여기서는 클라이언트에서 직접 Worker.drain() 호출로 검증
from luke_scribe.config import Settings
from luke_scribe.jobqueue.broker import InProcBroker
from luke_scribe.jobqueue.worker import Worker
from luke_scribe.jobqueue.jobs import Job
from luke_scribe.results.store import ResultStore

settings = Settings(_env_file=None, queue_backend='inproc',
                    results_dir='/content/results', model_cache_dir=None)
broker = InProcBroker(settings)
store = ResultStore(settings.results_dir)

job = Job(type='file', lane='batch', source_path='samples/colab-ko-en.mp3',
         options={'model': 'large-v3-turbo', 'language': 'ko', 'device': 'auto'})
broker.enqueue(job)
worker = Worker(settings=settings, broker=broker, store=store)
worker.drain()

result = store.read_result(job.id)
print('status:', result.status)
print('text:', result.text[:120])
print('device:', result.execution.device, '| ct:', result.execution.compute_type, '| rtf:', result.timings.rtf)

7) 벤치마크 (turbo vs large-v3)

manifest에 모델 비교 항목이 있으면 실행합니다. 두 모델을 모두 다운로드하므로 시간이 걸립니다 (turbo ~1.6GB + large-v3 ~3GB).

In [ ]:
# 13) 벤치마크 — 샘플 manifest 사용 (선택, 시간 소요)
# 간단 manifest 생성
import yaml
manifest = {
    'name': 'colab-quick',
    'language': 'ko',
    'targets': {'entity_preservation': 0.95, 'cer': 0.15},
    'cases': [
        {'name': 'ko-en-tech', 'audio': 'samples/colab-ko-en.mp3',
         'expected_entities': ['vLLM', 'Kubernetes', 'GPU']},
    ],
}
yaml.safe_dump(manifest, open('/content/manifest.yaml', 'w'))

# 실행 (기본: turbo만 → 빠름)
!luke-scribe bench /content/manifest.yaml --models large-v3-turbo --device auto --repeats 2 --output /content/bench-report.json 2>&1 | tail -20

8) 문제 해결

CUDA 라이브러리 오류 (faster-whisper/CTranslate2)

Colab T4에는 CUDA 런타임이 있지만, CTranslate2가 pip wheel의 CUDA 라이브러리를 찾지 못하면 아래를 실행하세요:

import os
os.environ['LD_LIBRARY_PATH'] = (
    '/usr/local/cuda/lib64:' + os.environ.get('LD_LIBRARY_PATH', '')
)

모델 다운로드 실패

  • Hugging Face 연결 필요. 재시도: LUKESCRIBE_MODEL_DOWNLOAD_RETRIES=3
  • 특정 모델만: --model large-v3-turbo (기본) / --model large-v3

OOM (16GB VRAM)

  • EngineOwner가 자동으로 정밀도를 강등합니다 (float16 → int8_float16 → int8 → CPU)
  • 수동 지정: --compute-type int8_float16

저장소가 private인데 클론 안 됨

1번 셀의 GITEA_TOKEN에 토큰을 입력하고 런타임 → Restart session 후 다시 실행하세요.