LLM-translator/README.md

6 KiB
Raw Permalink Blame History

LLM Translator — 4단계 고품질 번역 파이프라인

지인 공유용 웹 기반 번역기. OpenAI 호환 LLM 서버를 통해 원문을 도착 언어로 고품질 번역합니다.

특징

  • 4단계 번역 파이프라인: 초벌번역 → 고유명사/문체 분석 → 재번역 → 마무리 다듬기
  • LLM 단계별 모델 선택: Phase 1, 3, 4에 서로 다른 모델 지정 가능
  • 고유명사 관리: 추출된 고유명사를 사용자가 검토·수정 가능
  • 세로 3열 비교 UI: Phase 1 / Phase 3 / Phase 4 결과를 한눈에 비교
  • 다크모드 지원: 시스템 설정 자동 감지 + 수동 토글 (localStorage 지속화)
  • JWT 기반 인증: config-file 기반 ID/PW 로그인
  • 다중 사용자 및 영속 세션: 사용자별 SQLite 세션 저장과 동일 세션 재개
  • 직전 버전 복원: 번역을 덮어쓰기 전 세션 snapshot 보존
  • 관리자 사용자 관리: 계정 생성, 비밀번호 초기화, 활성화 및 권한 관리
  • 단일 서버 배포: FastAPI가 API + 정적 프론트엔드 동시에 서빙

빠른 시작

# 1. 의존성 설치
pip install -r requirements.txt
cd frontend && npm install && cd ..

# 2. 프론트엔드 빌드 (프로덕션 모드)
cd frontend && npm run build && cd ..

# 3. 서버 실행
uvicorn backend.main:app --host 0.0.0.0 --port 8000

# 4. 브라우저에서 http://localhost:8000 접속

기본 로그인: admin / changeme123 (첫 시작 시 비밀번호가 bcrypt 해시로 자동 변환됨)

설정 파일

LLM 서버 (config/llms.json)

[
  {
    "alias": "Qwen3.6-35B",
    "base_url": "http://btuna.net:45455/v1",
    "api_key": "...",
    "model": "hx370/qwen3.6-35b-a3b",
    "context_size": 65536
  }
]

사용자 (config/users.json)

[{"id": "admin", "password_plain": "changeme123"}]

첫 시작 시 password_plain이 자동으로 password(bcrypt hash)로 변환되어 파일에 저장됩니다.

환경 변수 (.env.example 참조)

변수 설명 기본값
JWT_SECRET_KEY JWT 서명 키 미설정 시 키 파일 자동 생성
JWT_SECRET_FILE 서명 키 자동 생성 파일 config/.jwt-secret
JWT_EXPIRE_HOURS 토큰 만료 시간(시간) 24
LLMS_CONFIG_PATH LLM 설정 파일 경로 config/llms.json
USERS_CONFIG_PATH 사용자 설정 파일 경로 config/users.json
PORT 서버 포트 8000
DATABASE_PATH SQLite DB 경로 data/translator.db
BOOTSTRAP_ADMIN_ID 최초 관리자 ID 없음
BOOTSTRAP_ADMIN_PASSWORD 최초 관리자 비밀번호 없음
LLM_TIMEOUT_SECONDS 개별 LLM 호출 제한 시간 180
TRANSLATION_CHUNK_CHARS 장문 분할 목표 크기 1500

프로젝트 구조

├── backend/          # FastAPI 백엔드 (auth, llm_client, routes)
├── frontend/         # Vue 3 + TypeScript 프론트엔드 (Vite 빌드)
│   ├── dist/         # 빌드 출력물 (.gitignore 제외)
│   └── src/          # Vue 컴포넌트, Pinia store, API 클라이언트
├── config/           # LLM 서버 및 사용자 설정 파일
└── requirements.txt  # Python 의존성

개발 모드 (프론트엔드 HMR)

# 터미널 1: 백엔드 실행
uvicorn backend.main:app --reload

# 터미널 2: 프론트엔드 dev 서버
cd frontend && npx vite        # http://localhost:5173
# /api 요청은 자동으로 localhost:8000으로 프록시됨

API 엔드포인트

Method Path 설명 인증
POST /api/auth/login 로그인 → JWT 토큰 발급 ×
GET /api/auth/me 현재 사용자 정보 ○ (JWT)
GET /api/models 사용 가능한 LLM 모델 목록
POST /api/translate/create 새 번역 세션 생성
GET /api/sessions/{id} 세션 상태 조회
PATCH /api/sessions/{id} 세션 필드 부분 업데이트
POST /api/translate/{id}/phase1 초벌번역 + 고유명사 추출
POST /api/translate/{id}/phase2 고유명사/문체 확인
POST /api/translate/{id}/phase3 재번역 (제약조건 적용)
POST /api/translate/{id}/phase4 마무리 다듬기

빌드 & 배포

# 1. 프론트엔드 빌드
cd frontend && npm run build && cd ..

# 2. 백엔드 서빙 (dist 정적 파일 포함)
uvicorn backend.main:app --host 0.0.0.0 --port 8000

backend/main.pyfrontend/dist/ 폴더를 정적 파일로 마운트하므로, 빌드 후 백엔드 서버 하나만 실행하면 됩니다.

장문은 문장 또는 줄 경계를 우선하여 기본 1,500자 단위로 나누고 Phase 1, 3, 4에서 순차 처리합니다. 공개 LLM 서버가 혼잡하면 .env에서 LLM_TIMEOUT_SECONDS를 늘리거나 TRANSLATION_CHUNK_CHARS를 줄일 수 있습니다.

LLM 처리 중에는 현재 chunk 번호와 스트리밍으로 수신 중인 최근 내용이 화면에 임시 표시됩니다. Phase 1 JSON이 불완전하면 코드 블록·주변 문구·후행 쉼표를 먼저 보정하고, 실패 시 LLM JSON 복구를 거쳐 일반 번역 결과로 폴백합니다.

Docker 배포

docker compose up -d --build
docker compose ps

첫 실행 전에 .envBOOTSTRAP_ADMIN_ID와 충분히 강한 BOOTSTRAP_ADMIN_PASSWORD를 지정해야 합니다. Docker는 로컬 개발용 기본 계정을 가져오지 않습니다. SQLite DB와 자동 생성 JWT 키는 translator-data volume에 저장됩니다. 상세 설정, 백업 및 복원 절차는 DEPLOYMENT.md를 참고하세요.

자동 테스트

python -m unittest discover -v

LLM 서버 연결 확인

curl -s http://btuna.net:45455/v1/chat/completions \
  -H "Authorization: Bearer btuna-public-key" \
  -H "Content-Type: application/json" \
  -d '{"model":"hx370/qwen3.6-35b-a3b","messages":[{"role":"user","content":"test"}],"max_tokens":10}' | jq

라이선스

내부 사용 목적