- skill-embedding 포트 8015 -> 8515로 수정 - 로빙 컨테이너 경량화 전략 문서 업데이트 - 함수형 프로그래밍 가이드라인 개선 - 트러블슈팅 문서들 오타 및 포맷 수정
171 lines
5.5 KiB
Markdown
171 lines
5.5 KiB
Markdown
# ONNX 기반 임베딩 경량화 작업
|
|
|
|
작성일: 2025년 8월 4일
|
|
작성자: Claude (51124 서버)
|
|
|
|
## 작업 배경
|
|
|
|
rb10508_micro의 컨테이너 이미지가 6.19GB로 매우 크고, 주요 원인이 PyTorch와 sentence-transformers였음. ONNX로 변환하여 경량화 진행.
|
|
|
|
## 작업 과정
|
|
|
|
### 오후 3시 15분 - ONNX 변환 시작
|
|
|
|
1. 작업 디렉토리 생성
|
|
```bash
|
|
mkdir -p /home/admin/ivada_project/onnx_models
|
|
```
|
|
|
|
2. uv 설치 및 가상환경 생성
|
|
```bash
|
|
pip install uv
|
|
uv venv
|
|
source .venv/bin/activate
|
|
uv pip install transformers torch onnx onnxruntime
|
|
```
|
|
|
|
### 오후 3시 20분 - 변환 스크립트 작성
|
|
|
|
`convert_to_onnx.py` 작성하여 `paraphrase-multilingual-MiniLM-L12-v2` 모델을 ONNX로 변환
|
|
|
|
주요 문제:
|
|
- 첫 시도에서 입력 이름 불일치 (`input.3` 추가 입력 요구)
|
|
- 해결: torch.onnx.export에서 명시적으로 2개 입력만 전달
|
|
|
|
### 오후 3시 30분 - 경량 추론 모듈 개발
|
|
|
|
1. ONNX 임베딩 기능 설계
|
|
- PyTorch 없이 ONNX Runtime만으로 임베딩 생성
|
|
- ChromaDB 호환 인터페이스 제공
|
|
- Mean pooling 구현
|
|
|
|
2. **주의**: 이 기능은 후에 skill-embedding 서비스에 직접 구현됨
|
|
- 별도 파일(`onnx_embedder.py`, `chroma_onnx_function.py`)로 생성하지 않음
|
|
- skill-embedding 서비스의 embedder.py에 ONNXEmbedder 클래스로 구현
|
|
- http_embedding_function.py에 HTTPEmbeddingFunction 클래스로 구현
|
|
|
|
### 오후 3시 40분 - 테스트 및 검증
|
|
|
|
테스트 결과:
|
|
- 한국어-영어 번역 문장 유사도: 0.970 (매우 높음)
|
|
- ChromaDB 통합 테스트 성공
|
|
- 한국어 문서 검색 정확도 확인
|
|
|
|
## 성능 비교
|
|
|
|
### 이미지 크기
|
|
- 기존: 6.19GB (PyTorch + sentence-transformers)
|
|
- 예상: ~500MB (Python slim + ONNX Runtime)
|
|
|
|
### 모델 크기
|
|
- ONNX 모델: 449MB (변환 완료)
|
|
- 토크나이저 포함 전체: ~500MB
|
|
|
|
### 메모리 사용량
|
|
- PyTorch 오버헤드 제거로 대폭 감소 예상
|
|
|
|
## 로컬 개발자 작업 가이드
|
|
|
|
### 1. Dockerfile 수정
|
|
```dockerfile
|
|
# 기존
|
|
FROM chroma_vector:1.0
|
|
|
|
# 변경
|
|
FROM python:3.11-slim
|
|
|
|
# sentence-transformers, torch 제거
|
|
# onnxruntime만 설치
|
|
RUN pip install onnxruntime transformers
|
|
```
|
|
|
|
### 2. 코드 수정
|
|
```python
|
|
# 기존
|
|
from sentence_transformers import SentenceTransformer
|
|
embedder = SentenceTransformer(model_name)
|
|
|
|
# 변경 (skill-embedding 서비스 사용)
|
|
from http_embedding_function import HTTPEmbeddingFunction
|
|
embedding_function = HTTPEmbeddingFunction("http://localhost:8515")
|
|
```
|
|
|
|
### 3. 모델 마운트
|
|
```yaml
|
|
volumes:
|
|
- /home/admin/ivada_project/onnx_models:/models/onnx:ro
|
|
```
|
|
|
|
## 교훈
|
|
|
|
1. **ONNX 변환 시 입력 명세 주의**
|
|
- torch.onnx.export의 input_names와 실제 모델 입력이 일치해야 함
|
|
- 불필요한 입력은 명시적으로 제외
|
|
|
|
2. **ChromaDB API 변경 대응**
|
|
- 구 API: `chromadb.Client(Settings(...))`
|
|
- 신 API: `chromadb.PersistentClient(path=...)`
|
|
|
|
3. **경량화의 핵심은 의존성 제거**
|
|
- 기능 축소만으로는 한계 (코드는 줄어도 라이브러리는 그대로)
|
|
- 무거운 라이브러리를 경량 대안으로 교체해야 진정한 경량화
|
|
|
|
4. **uv 사용으로 패키지 설치 속도 향상**
|
|
- pip 대비 10배 이상 빠른 설치
|
|
- 특히 대용량 패키지(PyTorch 등) 설치 시 효과적
|
|
|
|
## 다음 단계
|
|
|
|
1. 로컬 개발자가 Dockerfile 및 requirements.txt 수정
|
|
2. 베이스 이미지를 python:3.11-slim으로 변경
|
|
3. GitHub Actions 워크플로우 업데이트
|
|
4. 배포 후 실제 메모리 사용량 측정
|
|
|
|
## 오후 7시 04분 - rb10508_micro ONNX 통합 작업
|
|
|
|
### 문제 1: ModuleNotFoundError - sentence_transformers
|
|
- **증상**: `ModuleNotFoundError: No module named 'sentence_transformers'`
|
|
- **원인**: requirements.txt에서 sentence-transformers 제거했지만 코드에서 여전히 import
|
|
- **해결**: memory.py에서 ONNX 기반 임베딩으로 변경
|
|
|
|
### 문제 2: ChromaDB embedding function 충돌
|
|
- **증상**: `ValueError: An embedding function already exists in the collection configuration`
|
|
- **원인**: rb10508_test의 기존 ChromaDB가 default embedding으로 생성되어 있음
|
|
- **해결**: rb10508_micro 전용 ChromaDB 경로 사용 (`./chroma_db_micro`)
|
|
|
|
### 최종 수정사항
|
|
1. **memory.py 수정**:
|
|
```python
|
|
# 기존
|
|
from sentence_transformers import SentenceTransformer
|
|
self.embedder = SentenceTransformer(settings.EMBEDDING_MODEL)
|
|
|
|
# 변경
|
|
import sys
|
|
sys.path.append('/models/onnx')
|
|
from chroma_onnx_function import ONNXEmbeddingFunction
|
|
self.embedding_function = ONNXEmbeddingFunction("/models/onnx/multilingual-MiniLM-L12-v2")
|
|
```
|
|
|
|
2. **ChromaDB 컬렉션 생성 시 embedding_function 전달**:
|
|
```python
|
|
self.episodic = self.client.get_or_create_collection(
|
|
name=f"{settings.ROBING_ID}_episodic",
|
|
metadata={"type": "episodic"},
|
|
embedding_function=self.embedding_function
|
|
)
|
|
```
|
|
|
|
3. **docker-compose.yml 수정**:
|
|
```yaml
|
|
volumes:
|
|
- ./chroma_db_micro:/code/chroma_db # 전용 ChromaDB
|
|
- ./logs:/code/logs:rw
|
|
- /home/admin/ivada_project/onnx_models:/models/onnx:ro
|
|
```
|
|
|
|
### 교훈
|
|
1. **코드와 의존성 동기화**: requirements.txt 수정 시 반드시 코드도 함께 수정
|
|
2. **ChromaDB 데이터 분리**: 서로 다른 embedding function 사용 시 별도 DB 필요
|
|
3. **ONNX 모델 경로**: 서브디렉토리까지 정확히 지정 (`/models/onnx/multilingual-MiniLM-L12-v2`)
|
|
4. **추측하지 말고 확인**: 서버의 ONNX 모듈 구조와 사용법 먼저 확인 |