From e3a75c5df8ea6d2a0f626f1dcbfe1c800292614f Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Tue, 5 Aug 2025 00:13:08 +0900 Subject: [PATCH] Add embedding service separation architecture design MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 로빙 임베딩 서비스 분리 아키텍처 설계서 추가: - 현재 메모리 사용량 분석 (rb10508_micro: 987.9MB) - 임베딩 서비스 공유 + 기억 저장소 분리 아키텍처 - 구체적 구현 방안 (HTTP API, ChromaDB 분리) - 메모리 절약 효과 (228MB + 확장성) - 단계별 구현 계획 및 위험 완화 방안 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ...임베딩_서비스_분리_아키텍처.md | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 ideas/250804_로빙_임베딩_서비스_분리_아키텍처.md diff --git a/ideas/250804_로빙_임베딩_서비스_분리_아키텍처.md b/ideas/250804_로빙_임베딩_서비스_분리_아키텍처.md new file mode 100644 index 0000000..c3abfa6 --- /dev/null +++ b/ideas/250804_로빙_임베딩_서비스_분리_아키텍처.md @@ -0,0 +1,271 @@ +# 로빙 임베딩 서비스 분리 아키텍처 + +작성일: 2025년 8월 4일 +작성자: Claude (51124 서버) + +## 배경 + +현재 각 로빙 컨테이너마다 독립적으로 ONNX 임베딩 모델(449MB)을 로드하여 메모리 사용량이 높은 상황입니다. rb10508_micro의 경우 987.9MB를 사용하고 있으며, 장기 운영 시 메모리 부족 위험이 있습니다. + +### 현재 메모리 사용 현황 +- rb10508_micro: 987.9MB (ONNX 모델 포함) +- rb8001: 416.4MB +- rb10408_test: 54.96MB +- 각 컨테이너마다 독립적인 임베딩 모델 로드 + +## 제안 아키텍처: 임베딩 서비스 분리 + +### 핵심 아이디어 +- **임베딩 생성**: 공유 서비스 사용 +- **기억 저장소**: 각 로빙별 완전 분리 +- **프라이버시**: 로빙 간 기억 접근 불가 +- **효율성**: 메모리 절약 + 확장성 + +### 아키텍처 구조 + +``` + 임베딩 서비스 (공유) + ├── ONNX 모델 (449MB) + ├── FastAPI HTTP API + └── 포트: 8600 + ↑ + ┌──────┴──────┐ +rb8001 컨테이너 rb10508 컨테이너 +├── ChromaDB (/chroma_db) ├── ChromaDB (/chroma_db_micro) +├── HTTP 클라이언트 ├── HTTP 클라이언트 +├── 기억: rb8001 전용 ├── 기억: rb10508 전용 +└── 메모리: ~200MB └── 메모리: ~400MB +``` + +## 구현 방안 + +### 1. 임베딩 서비스 구성 + +#### Docker Compose 설정 +```yaml +services: + embedding-service: + build: ./embedding_service + container_name: embedding_service + network_mode: host + ports: + - "8600:8600" + volumes: + - /home/admin/ivada_project/onnx_models:/models/onnx:ro + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8600/health"] + interval: 30s + timeout: 10s + retries: 3 +``` + +#### 임베딩 서비스 API +```python +# embedding_service/main.py +from fastapi import FastAPI +from onnx_embedder import ONNXEmbedder + +app = FastAPI() +embedder = ONNXEmbedder("/models/onnx/multilingual-MiniLM-L12-v2") + +@app.post("/embed") +async def create_embeddings(request: EmbedRequest): + embeddings = [] + for text in request.texts: + embedding = embedder.encode(text) + embeddings.append(embedding.tolist()) + + return {"embeddings": embeddings} + +@app.get("/health") +async def health_check(): + return {"status": "healthy"} +``` + +### 2. 로빙별 ChromaDB 분리 + +#### 볼륨 마운트 구조 +``` +호스트 디렉토리: +/home/admin/ivada_project/ +├── rb8001/chroma_db/ # rb8001 전용 기억 +├── rb10508_micro/chroma_db_micro/ # rb10508 전용 기억 +├── rb10408/chroma_db/ # rb10408 전용 기억 +└── onnx_models/ # 공유 모델 (임베딩 서비스용) +``` + +#### 로빙별 컬렉션 ID 분리 +```python +# rb8001의 memory.py +class Memory: + def __init__(self): + self.client = chromadb.PersistentClient(path="/code/chroma_db") + + # rb8001 전용 컬렉션들 + self.episodic = self.client.get_or_create_collection( + name="rb8001_episodic", + embedding_function=HTTPEmbeddingFunction() + ) + self.semantic = self.client.get_or_create_collection( + name="rb8001_semantic", + embedding_function=HTTPEmbeddingFunction() + ) + +# rb10508의 memory.py +class Memory: + def __init__(self): + self.client = chromadb.PersistentClient(path="/code/chroma_db") + + # rb10508 전용 컬렉션들 + self.episodic = self.client.get_or_create_collection( + name="rb10508_episodic", + embedding_function=HTTPEmbeddingFunction() + ) +``` + +### 3. HTTP 임베딩 함수 구현 + +```python +# common/http_embedding_function.py +import requests +from chromadb.api.types import EmbeddingFunction + +class HTTPEmbeddingFunction(EmbeddingFunction): + def __init__(self, embedding_service_url="http://localhost:8600"): + self.url = f"{embedding_service_url}/embed" + + def __call__(self, texts): + response = requests.post(self.url, + json={"texts": texts}, + timeout=10) + response.raise_for_status() + return response.json()["embeddings"] +``` + +## 동작 흐름 + +### 메모리 저장 과정 + +#### 현재 방식 +```python +def store_memory(self, content): + # 로컬 ONNX 모델로 임베딩 생성 (987MB 메모리 사용) + embedding = self.embedding_function(content) + + # ChromaDB에 저장 + self.episodic.add( + documents=[content], + embeddings=[embedding], + ids=[memory_id] + ) +``` + +#### 임베딩 서비스 방식 +```python +def store_memory(self, content): + # HTTP로 임베딩 서비스 호출 + response = requests.post("http://localhost:8600/embed", + json={"texts": [content]}) + embedding = response.json()["embeddings"][0] + + # ChromaDB에 저장 (임베딩은 받은 값 사용) + self.episodic.add( + documents=[content], + embeddings=[embedding], + ids=[memory_id] + ) +``` + +### 실제 대화 시나리오 + +#### rb8001과의 대화 +``` +사용자 → rb8001: "오늘 피자 먹었어" + +1. rb8001이 임베딩 서비스 호출 + POST localhost:8600/embed {"texts": ["오늘 피자 먹었어"]} + +2. rb8001의 ChromaDB에만 저장 + rb8001_episodic.add( + documents=["오늘 피자 먹었어"], + embeddings=[[0.1, 0.2, ...]], + metadata={"user_id": "user123", "timestamp": "..."} + ) +``` + +#### rb10508과의 대화 +``` +사용자 → rb10508: "어제 뭐 먹었지?" + +1. rb10508이 임베딩 서비스 호출 (같은 서비스 사용) + POST localhost:8600/embed {"texts": ["어제 뭐 먹었지"]} + +2. rb10508의 ChromaDB에서만 검색 (rb8001 기억 접근 불가) + rb10508_episodic.query(query_embeddings=[[0.2, 0.1, ...]]) + → 결과 없음 (rb8001의 "피자" 기억은 모름) + +3. rb10508: "죄송해요, 어제 뭘 드셨는지 기억이 없네요" +``` + +## 예상 효과 + +### 메모리 절약 +- **rb8001**: 416MB → 200MB (-216MB) +- **rb10508**: 987MB → 400MB (-587MB) +- **rb10408**: 55MB → 30MB (-25MB) +- **임베딩 서비스**: +600MB (새로 생성) +- **순 절약**: 228MB + 여러 로빙 추가 시 더 큰 절약 + +### 성능 영향 +- **레이턴시 증가**: +10-50ms (HTTP 호출 오버헤드) +- **전체 응답시간**: 1-3초 → 영향 미미 +- **처리량**: 동일 (병목은 LLM API) + +### 운영상 이점 +- **확장성**: 새로운 로빙 추가 시 임베딩 서비스 공유 +- **장애 격리**: 임베딩 서비스 장애가 모든 로빙에 영향 +- **유지보수**: 임베딩 모델 업데이트 시 한 곳만 수정 + +## 구현 단계 + +### Phase 1: 임베딩 서비스 구축 +1. 임베딩 서비스 컨테이너 개발 +2. HTTP API 구현 및 테스트 +3. 성능 벤치마크 측정 + +### Phase 2: rb10508_micro 적용 +1. HTTPEmbeddingFunction 구현 +2. memory.py 코드 수정 +3. docker-compose.yml 업데이트 +4. 배포 및 테스트 + +### Phase 3: 다른 로빙들 순차 적용 +1. rb8001 적용 +2. rb10408 적용 +3. 전체 시스템 안정성 검증 + +## 고려사항 + +### 장점 +- **메모리 효율성**: 중복 모델 로딩 제거 +- **프라이버시 보장**: 로빙 간 기억 완전 분리 +- **확장성**: 새 로빙 추가 시 효율적 +- **유지보수성**: 중앙집중식 임베딩 관리 + +### 단점 +- **네트워크 의존성**: HTTP 호출 오버헤드 +- **단일 장애점**: 임베딩 서비스 장애 시 전체 영향 +- **복잡성 증가**: 서비스 간 의존성 관리 + +### 위험 완화 방안 +- **헬스체크**: 임베딩 서비스 상태 모니터링 +- **타임아웃**: HTTP 호출 시 적절한 타임아웃 설정 +- **폴백**: 임베딩 서비스 장애 시 로컬 모델 대체 고려 +- **캐싱**: 자주 사용되는 임베딩 캐싱으로 성능 향상 + +## 결론 + +임베딩 서비스 분리 아키텍처는 메모리 효율성과 확장성을 크게 향상시키면서도 각 로빙의 프라이버시를 완벽하게 보장합니다. 약간의 레이턴시 증가가 있지만, 전체적인 이점이 훨씬 큽니다. + +특히 향후 더 많은 로빙 서비스가 추가될 것을 고려하면, 이 아키텍처는 필수적인 개선사항으로 판단됩니다. \ No newline at end of file