LLM-translator/README.md

155 lines
6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 + 정적 프론트엔드 동시에 서빙
## 빠른 시작
```bash
# 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`)
```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`)
```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)
```bash
# 터미널 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` | 마무리 다듬기 | ○ |
## 빌드 & 배포
```bash
# 1. 프론트엔드 빌드
cd frontend && npm run build && cd ..
# 2. 백엔드 서빙 (dist 정적 파일 포함)
uvicorn backend.main:app --host 0.0.0.0 --port 8000
```
`backend/main.py``frontend/dist/` 폴더를 정적 파일로 마운트하므로, 빌드 후 백엔드 서버 하나만 실행하면 됩니다.
장문은 문장 또는 줄 경계를 우선하여 기본 1,500자 단위로 나누고 Phase 1, 3, 4에서 순차 처리합니다. 공개 LLM 서버가 혼잡하면 `.env`에서 `LLM_TIMEOUT_SECONDS`를 늘리거나 `TRANSLATION_CHUNK_CHARS`를 줄일 수 있습니다.
LLM 처리 중에는 현재 chunk 번호와 스트리밍으로 수신 중인 최근 내용이 화면에 임시 표시됩니다. Phase 1 JSON이 불완전하면 코드 블록·주변 문구·후행 쉼표를 먼저 보정하고, 실패 시 LLM JSON 복구를 거쳐 일반 번역 결과로 폴백합니다.
## Docker 배포
```bash
docker compose up -d --build
docker compose ps
```
첫 실행 전에 `.env``BOOTSTRAP_ADMIN_ID`와 충분히 강한 `BOOTSTRAP_ADMIN_PASSWORD`를 지정해야 합니다. Docker는 로컬 개발용 기본 계정을 가져오지 않습니다. SQLite DB와 자동 생성 JWT 키는 `translator-data` volume에 저장됩니다. 상세 설정, 백업 및 복원 절차는 `DEPLOYMENT.md`를 참고하세요.
## 자동 테스트
```bash
python -m unittest discover -v
```
## LLM 서버 연결 확인
```bash
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
```
## 라이선스
내부 사용 목적