# ๐Ÿฝ๏ธ Vector - ์Œ์‹์  Vector DB ๊ตฌ์ถ• ๋ฐ AI ์ถ”์ฒœ ์„œ๋น„์Šค ์นด์นด์˜ค ๋กœ์ปฌ API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์Œ์‹์  ์ •๋ณด์™€ ๋ฆฌ๋ทฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ , **Chroma DB** ๊ธฐ๋ฐ˜ Vector DB๋กœ ๊ตฌ์ถ•ํ•œ ํ›„, **Claude AI**์™€ ์—ฐ๋™ํ•˜์—ฌ ์†Œ์ƒ๊ณต์ธ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐœ์„ ์„ ์ง€์›ํ•˜๋Š” ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ## ๐ŸŽฏ ํ”„๋กœ์ ํŠธ ๊ฐœ์š” ### ํ•ต์‹ฌ ๊ธฐ๋Šฅ - **๐Ÿ” ์Šค๋งˆํŠธ ์Œ์‹์  ๊ฒ€์ƒ‰**: ์ง€์—ญ๊ณผ ๊ฐ€๊ฒŒ๋ช…์œผ๋กœ ํƒ€๊ฒŸ ์Œ์‹์  ์ž๋™ ๋ฐœ๊ฒฌ - **๐Ÿ“Š ๋™์ข…์—…์ฒด ๋ฆฌ๋ทฐ ์ˆ˜์ง‘**: ์นด์นด์˜ค๋งต ๋ฆฌ๋ทฐ ๋Œ€๋Ÿ‰ ์ˆ˜์ง‘ ๋ฐ ์ „์ฒ˜๋ฆฌ - **๐Ÿค– Vector DB ๊ตฌ์ถ•**: Sentence Transformers ๊ธฐ๋ฐ˜ ๊ณ ํ’ˆ์งˆ ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ - **๐Ÿง  AI ๋น„์ฆˆ๋‹ˆ์Šค ์ปจ์„คํŒ…**: Claude Sonnet 4 ๊ธฐ๋ฐ˜ ๋งž์ถคํ˜• ์•ก์…˜ ํ”Œ๋žœ ์ œ๊ณต - **๐Ÿ”„ ์‹ค์‹œ๊ฐ„ API ์„œ๋น„์Šค**: RESTful API ๊ธฐ๋ฐ˜ ์™„์ „ ์ž๋™ํ™” ์‹œ์Šคํ…œ - **โ˜ธ๏ธ ํด๋ผ์šฐ๋“œ ๋„ค์ดํ‹ฐ๋ธŒ**: Kubernetes ๊ธฐ๋ฐ˜ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ### ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ€์น˜ - **์†Œ์ƒ๊ณต์ธ**: ๋™์ข…์—…์ฒด ๋ถ„์„์„ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ๊ฒฝ์˜ ๊ฐœ์„  - **๊ฒฝ์Ÿ ์šฐ์œ„**: AI ๊ธฐ๋ฐ˜ ๊ฐœ์ธํ™”๋œ ๋น„์ฆˆ๋‹ˆ์Šค ์ „๋žต ์ œ๊ณต - **์šด์˜ ํšจ์œจ**: ์™„์ „ ์ž๋™ํ™”๋œ ๋ถ„์„ ๋ฐ ์ถ”์ฒœ ์‹œ์Šคํ…œ ## ๐Ÿ—๏ธ ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜ ### ๐Ÿ”ง ๋ฐฑ์—”๋“œ ์Šคํƒ - **Framework**: FastAPI 0.115.9 (๊ณ ์„ฑ๋Šฅ ๋น„๋™๊ธฐ API) - **Language**: Python 3.11 (์ตœ์‹  ํƒ€์ž… ํžŒํŒ… ์ง€์›) - **Dependency Management**: Poetry (๋ฝ ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ๋นŒ๋“œ) ### ๐Ÿค– AI/ML ์Šคํƒ - **Vector DB**: ChromaDB 1.0.12 (HNSW ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ธฐ๋ฐ˜) - **Embedding Model**: `sentence-transformers/all-MiniLM-L6-v2` (384์ฐจ์›) - **AI Engine**: Claude Sonnet 4 (`claude-sonnet-4-20250514`) - **ML Framework**: PyTorch 2.7.1+cpu, Transformers 4.52.4 ### ๐Ÿš€ ์ธํ”„๋ผ ์Šคํƒ - **Container**: Docker (Multi-stage build ์ตœ์ ํ™”) - **Orchestration**: Kubernetes (AKS ๋ฐฐํฌ) - **Registry**: Azure Container Registry (ACR) - **Storage**: Persistent Volume (Vector DB ๋ฐ์ดํ„ฐ ์˜์†ํ™”) ### ๐Ÿ”— ์™ธ๋ถ€ ์—ฐ๋™ - **Restaurant API**: ์นด์นด์˜ค ๋กœ์ปฌ API ๊ธฐ๋ฐ˜ ์Œ์‹์  ๊ฒ€์ƒ‰ ์„œ๋น„์Šค - **Review API**: ์นด์นด์˜ค๋งต ๋ฆฌ๋ทฐ ์ˆ˜์ง‘ ์„œ๋น„์Šค - **Claude API**: Anthropic Claude AI API ## ๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ``` vector/ โ”œโ”€โ”€ app/ # ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ โ”‚ โ”œโ”€โ”€ main.py # FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ โ”‚ โ”œโ”€โ”€ config/ โ”‚ โ”‚ โ””โ”€โ”€ settings.py # ํ™˜๊ฒฝ๋ณ„ ์„ค์ • ๊ด€๋ฆฌ โ”‚ โ”œโ”€โ”€ models/ # Pydantic ๋ฐ์ดํ„ฐ ๋ชจ๋ธ โ”‚ โ”‚ โ”œโ”€โ”€ vector_models.py # Vector DB ์š”์ฒญ/์‘๋‹ต ๋ชจ๋ธ โ”‚ โ”‚ โ”œโ”€โ”€ restaurant_models.py # ์Œ์‹์  ์ •๋ณด ๋ชจ๋ธ โ”‚ โ”‚ โ””โ”€โ”€ review_models.py # ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ โ”‚ โ”œโ”€โ”€ services/ # ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์„œ๋น„์Šค โ”‚ โ”‚ โ”œโ”€โ”€ vector_service.py # Vector DB ๊ด€๋ฆฌ ์„œ๋น„์Šค โ”‚ โ”‚ โ”œโ”€โ”€ claude_service.py # Claude AI ํ†ตํ•ฉ ์„œ๋น„์Šค โ”‚ โ”‚ โ”œโ”€โ”€ restaurant_service.py # ์Œ์‹์  ๊ฒ€์ƒ‰ ์„œ๋น„์Šค โ”‚ โ”‚ โ””โ”€โ”€ review_service.py # ๋ฆฌ๋ทฐ ์ˆ˜์ง‘ ์„œ๋น„์Šค โ”‚ โ””โ”€โ”€ utils/ โ”‚ โ””โ”€โ”€ category_utils.py # ์Œ์‹ ์นดํ…Œ๊ณ ๋ฆฌ ์ถ”์ถœ ์œ ํ‹ธ โ”œโ”€โ”€ deployment/ # ๋ฐฐํฌ ์ธํ”„๋ผ โ”‚ โ”œโ”€โ”€ container/ โ”‚ โ”‚ โ”œโ”€โ”€ Dockerfile # ๋ฉ”์ธ ์„œ๋น„์Šค ์ด๋ฏธ์ง€ โ”‚ โ”‚ โ””โ”€โ”€ Dockerfile-base # ๋ฒ ์ด์Šค ์˜์กด์„ฑ ์ด๋ฏธ์ง€ โ”‚ โ””โ”€โ”€ manifests/ # Kubernetes ๋ฆฌ์†Œ์Šค โ”‚ โ”œโ”€โ”€ configmap.yaml # ํ™˜๊ฒฝ ์„ค์ • โ”‚ โ”œโ”€โ”€ secret.yaml # API ํ‚ค ๋“ฑ ๋ฏผ๊ฐ ์ •๋ณด โ”‚ โ”œโ”€โ”€ deployment.yaml # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ โ”‚ โ”œโ”€โ”€ service.yaml # ๋‚ด๋ถ€ ์„œ๋น„์Šค ๋…ธ์ถœ โ”‚ โ”œโ”€โ”€ ingress.yaml # ์™ธ๋ถ€ ์ ‘๊ทผ ์„ค์ • โ”‚ โ””โ”€โ”€ pvc.yaml # Vector DB ์˜๊ตฌ ๋ณผ๋ฅจ โ”œโ”€โ”€ pyproject.toml # Poetry ์˜์กด์„ฑ ์ •์˜ โ”œโ”€โ”€ poetry.lock # ์˜์กด์„ฑ ๋ฝ ํŒŒ์ผ โ”œโ”€โ”€ setup.sh # ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์ž๋™ ์„ค์ • โ”œโ”€โ”€ build-base.sh # ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ๋นŒ๋“œ โ”œโ”€โ”€ build.sh # ๋ฉ”์ธ ์ด๋ฏธ์ง€ ๋นŒ๋“œ โ”œโ”€โ”€ create-imagepullsecret.sh # ACR ์ธ์ฆ ์„ค์ • โ””โ”€โ”€ README.md # ํ”„๋กœ์ ํŠธ ๋ฌธ์„œ ``` ## ๐Ÿ“Š API ์—”๋“œํฌ์ธํŠธ ### ๐Ÿ  ๋ฉ”์ธ ์„œ๋น„์Šค | Method | Endpoint | ์„ค๋ช… | ์š”์ฒญ ๋ชจ๋ธ | ์‘๋‹ต ๋ชจ๋ธ | |--------|----------|------|-----------|-----------| | `GET` | `/` | ์„œ๋น„์Šค ํ™ˆํŽ˜์ด์ง€ (HTML) | - | HTMLResponse | | `GET` | `/docs` | Swagger UI API ๋ฌธ์„œ | - | HTMLResponse | | `GET` | `/health` | ํ—ฌ์Šค์ฒดํฌ | - | JSONResponse | | `GET` | `/vector-status` | Vector DB ์ƒํƒœ ํ™•์ธ | - | VectorDBStatusResponse | ### ๐Ÿ” ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค API | Method | Endpoint | ์„ค๋ช… | ์š”์ฒญ ๋ชจ๋ธ | ์‘๋‹ต ๋ชจ๋ธ | |--------|----------|------|-----------|-----------| | `POST` | `/find-reviews` | ๋ฆฌ๋ทฐ ์ˆ˜์ง‘ ๋ฐ Vector DB ์ €์žฅ | VectorBuildRequest | FindReviewsResponse | | `POST` | `/action-recommendation` | AI ๊ธฐ๋ฐ˜ ๋น„์ฆˆ๋‹ˆ์Šค ์ถ”์ฒœ | ActionRecommendationRequest | ActionRecommendationSimpleResponse | ## ๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘ ### 1. ์‚ฌ์ „ ์ค€๋น„ #### ํ•„์ˆ˜ API ํ‚ค ๋ฐœ๊ธ‰ **์นด์นด์˜ค API ์„ค์ •** ```bash # 1. ์นด์นด์˜ค ๊ฐœ๋ฐœ์ž ์„ผํ„ฐ ์ ‘์† https://developers.kakao.com/console/app # 2. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋“ฑ๋ก - ์•ฑ ์ด๋ฆ„: VectorDBBuilder - ์นดํ…Œ๊ณ ๋ฆฌ: ์‹์Œ๋ฃŒ # 3. ์นด์นด์˜ค๋งต API ํ™œ์„ฑํ™” - ์ขŒ์ธก ๋ฉ”๋‰ด > ์นด์นด์˜ค๋งต > ํ™œ์„ฑํ™” ``` **Claude API ์„ค์ •** ```bash # 1. Anthropic Console ์ ‘์† https://console.anthropic.com/ # 2. API ํ‚ค ๋ฐœ๊ธ‰ - API Keys ๋ฉ”๋‰ด์—์„œ ์ƒˆ ํ‚ค ์ƒ์„ฑ - ๋ชจ๋ธ: claude-sonnet-4-20250514 ``` ### 2. ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ #### ์ž๋™ ํ™˜๊ฒฝ ์„ค์ • ```bash # ์ €์žฅ์†Œ ํด๋ก  git clone cd vector # Poetry ๋ฐ ์˜์กด์„ฑ ์ž๋™ ์„ค์น˜ chmod +x setup.sh ./setup.sh ``` #### ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • ```bash # .env ํŒŒ์ผ ์ƒ์„ฑ cat > .env << EOF # Claude API ์„ค์ • CLAUDE_API_KEY=your-claude-api-key CLAUDE_MODEL=claude-sonnet-4-20250514 # API ์„œ๋ฒ„ ์„ค์ • (๋กœ์ปฌ ๊ฐœ๋ฐœ์šฉ) RESTAURANT_API_HOST=0.0.0.0 RESTAURANT_API_PORT=18000 REVIEW_API_HOST=0.0.0.0 REVIEW_API_PORT=19000 # Vector DB ์„ค์ • VECTOR_DB_PATH=./vectordb VECTOR_DB_COLLECTION=restaurant_reviews EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2 # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ • HOST=0.0.0.0 PORT=8000 LOG_LEVEL=info EOF ``` #### ์„œ๋น„์Šค ์‹คํ–‰ ```bash # ๊ฐœ๋ฐœ ๋ชจ๋“œ (์ž๋™ ์žฌ์‹œ์ž‘) poetry run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload # ๋˜๋Š” ์ง์ ‘ ์‹คํ–‰ poetry run python app/main.py ``` ### 3. Docker ์‹คํ–‰ ```bash # ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ๋นŒ๋“œ (์˜์กด์„ฑ ์บ์‹ฑ) ./build-base.sh # ๋ฉ”์ธ ์„œ๋น„์Šค ์ด๋ฏธ์ง€ ๋นŒ๋“œ ./build.sh # ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ (ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํŒŒ์ผ ์‚ฌ์šฉ) docker run -p 8000:8000 --env-file .env vector-api:latest ``` ### 4. Kubernetes ๋ฐฐํฌ #### ACR ์ธ์ฆ ์„ค์ • ```bash # Azure Container Registry ์ธ์ฆ ./create-imagepullsecret.sh acrdigitalgarage03 rg-digitalgarage-03 ``` #### ๋ฆฌ์†Œ์Šค ๋ฐฐํฌ ```bash # 1. ์˜๊ตฌ ๋ณผ๋ฅจ ์ƒ์„ฑ (Vector DB ์ €์žฅ์šฉ) kubectl apply -f deployment/manifests/pvc.yaml # 2. ์„ค์ • ์ •๋ณด ์ƒ์„ฑ kubectl apply -f deployment/manifests/configmap.yaml kubectl apply -f deployment/manifests/secret.yaml # 3. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ kubectl apply -f deployment/manifests/deployment.yaml kubectl apply -f deployment/manifests/service.yaml kubectl apply -f deployment/manifests/ingress.yaml ``` #### ๋ฐฐํฌ ์ƒํƒœ ํ™•์ธ ```bash # Pod ์ƒํƒœ ํ™•์ธ kubectl get pods -l app=vector-api # ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ kubectl get svc vector-api-service # Ingress ํ™•์ธ kubectl get ingress vector-api-ingress # ๋กœ๊ทธ ๋ชจ๋‹ˆํ„ฐ๋ง kubectl logs -l app=vector-api -f ``` ## ๐ŸŒ ์„œ๋น„์Šค ์ ‘์† ### ๋ฐฐํฌ๋œ ์„œ๋น„์Šค URL ```bash # ํ˜„์žฌ ๋ฐฐํฌ๋œ ์„œ๋น„์Šค ์ฃผ์†Œ INGRESS_URL="http://vector-api.20.249.191.180.nip.io" ``` | ์„œ๋น„์Šค | URL | ์„ค๋ช… | |--------|-----|------| | **๐Ÿ  ํ™ˆํŽ˜์ด์ง€** | http://vector-api.20.249.191.180.nip.io | ์„œ๋น„์Šค ๋Œ€์‹œ๋ณด๋“œ | | **๐Ÿ“– API ๋ฌธ์„œ** | http://vector-api.20.249.191.180.nip.io/docs | Swagger UI | | **๐Ÿ“„ ReDoc** | http://vector-api.20.249.191.180.nip.io/redoc | API ๋ฌธ์„œ (ReDoc) | | **โค๏ธ ํ—ฌ์Šค์ฒดํฌ** | http://vector-api.20.249.191.180.nip.io/health | ์„œ๋น„์Šค ์ƒํƒœ | | **๐Ÿ—‚๏ธ Vector DB ์ƒํƒœ** | http://vector-api.20.249.191.180.nip.io/vector-status | DB ์ƒํƒœ ํ™•์ธ | ### ์ ‘์† ํ…Œ์ŠคํŠธ ```bash # ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ curl "http://vector-api.20.249.191.180.nip.io/health" # Vector DB ์ƒํƒœ ํ™•์ธ curl "http://vector-api.20.249.191.180.nip.io/vector-status" ``` ## ๐Ÿ’ก API ์‚ฌ์šฉ ์˜ˆ์ œ ### 1. ๋ฆฌ๋ทฐ ์ˆ˜์ง‘ ๋ฐ Vector DB ๊ตฌ์ถ• **์š”์ฒญ** ```bash curl -X POST "http://vector-api.20.249.191.180.nip.io/find-reviews" \ -H "Content-Type: application/json" \ -d '{ "region": "์„œ์šธํŠน๋ณ„์‹œ ๊ฐ•๋‚จ๊ตฌ ์—ญ์‚ผ๋™", "store_name": "๋ง›์žˆ๋Š” ์น˜ํ‚จ์ง‘" }' ``` **์‘๋‹ต** ```json { "success": true, "message": "์ด 127๊ฐœ ๋ฆฌ๋ทฐ, 8๊ฐœ ์—…์ฒด ๋ถ„์„๋จ", "target_store": { "id": "501745730", "place_name": "๋ง›์žˆ๋Š” ์น˜ํ‚จ์ง‘", "category_name": "์Œ์‹์  > ์น˜ํ‚จ", "address_name": "์„œ์šธํŠน๋ณ„์‹œ ๊ฐ•๋‚จ๊ตฌ ์—ญ์‚ผ๋™ 123-45", "phone": "02-123-4567", "place_url": "http://place.map.kakao.com/501745730", "x": "127.0276543", "y": "37.4979234" }, "food_category": "์น˜ํ‚จ", "total_reviews": 127, "total_stores": 8, "execution_time": 45.2, "stored_data": { "501745730": { "store_info": { "id": "501745730", "name": "๋ง›์žˆ๋Š” ์น˜ํ‚จ์ง‘", "category": "์Œ์‹์  > ์น˜ํ‚จ", "rating": "4.2", "review_count": "23", "status": "์˜์—…์ค‘", "address": "์„œ์šธํŠน๋ณ„์‹œ ๊ฐ•๋‚จ๊ตฌ ์—ญ์‚ผ๋™ 123-45", "phone": "02-123-4567", "place_url": "http://place.map.kakao.com/501745730", "x": "127.0276543", "y": "37.4979234" }, "reviews": [ { "reviewer_name": "๊น€โ—‹โ—‹", "reviewer_level": "๊ณจ๋“œ๋ฆฌ๋ทฐ์–ด", "reviewer_stats": { "reviews": 156, "average_rating": 4.3, "followers": 23 }, "rating": 5, "date": "2024-06-10", "content": "์น˜ํ‚จ์ด ์ •๋ง ๋ง›์žˆ์–ด์š”! ๋ฐ”์‚ญํ•˜๊ณ  ์–‘๋…์ด ์ž˜ ๋ฐฐ์–ด์žˆ์–ด์„œ ์ž๊พธ ์†์ด ๊ฐ‘๋‹ˆ๋‹ค. ๋ฐฐ๋‹ฌ๋„ ๋นจ๋ผ์„œ ์ข‹์•˜์–ด์š”.", "badges": ["๋ง›์ง‘", "์นœ์ ˆ", "๋น ๋ฅธ๋ฐฐ๋‹ฌ"], "likes": 12, "photo_count": 3, "has_photos": true }, { "reviewer_name": "์ดโ—‹โ—‹", "reviewer_level": "์‹ค๋ฒ„๋ฆฌ๋ทฐ์–ด", "reviewer_stats": { "reviews": 89, "average_rating": 4.1, "followers": 8 }, "rating": 4, "date": "2024-06-08", "content": "์น˜ํ‚จ์€ ๋ง›์žˆ๋Š”๋ฐ ๊ฐ€๊ฒฉ์ด ์กฐ๊ธˆ ๋น„์‹ผ ๊ฒƒ ๊ฐ™์•„์š”. ๊ทธ๋ž˜๋„ ์žฌ์ฃผ๋ฌธ ์˜ํ–ฅ ์žˆ์Šต๋‹ˆ๋‹ค.", "badges": ["๋ง›์žˆ์Œ", "๊ฐ€๊ฒฉ"], "likes": 7, "photo_count": 1, "has_photos": true }, { "reviewer_name": "๋ฐ•โ—‹โ—‹", "reviewer_level": "๋ธŒ๋ก ์ฆˆ๋ฆฌ๋ทฐ์–ด", "reviewer_stats": { "reviews": 34, "average_rating": 3.9, "followers": 2 }, "rating": 3, "date": "2024-06-05", "content": "์น˜ํ‚จ์€ ๊ดœ์ฐฎ์€๋ฐ ๋ฐฐ๋‹ฌ์ด ์ข€ ๋Šฆ์—ˆ์–ด์š”. ํฌ์žฅ๋„ ์กฐ๊ธˆ ์•„์‰ฌ์› ์Šต๋‹ˆ๋‹ค.", "badges": ["๋ฐฐ๋‹ฌ์ง€์—ฐ", "ํฌ์žฅ"], "likes": 3, "photo_count": 0, "has_photos": false } ], "review_summary": { "total_reviews": 23, "average_rating": 4.2, "rating_distribution": { "5": 8, "4": 9, "3": 4, "2": 1, "1": 1 }, "positive_keywords": [ "๋ง›์žˆ์Œ", "๋ฐ”์‚ญํ•จ", "์นœ์ ˆ", "๋น ๋ฅธ๋ฐฐ๋‹ฌ" ], "negative_keywords": [ "๊ฐ€๊ฒฉ", "๋ฐฐ๋‹ฌ์ง€์—ฐ", "ํฌ์žฅ" ], "common_keywords": [ "๋ง›์žˆ์Œ", "์น˜ํ‚จ", "๋ฐฐ๋‹ฌ", "์นœ์ ˆ", "๊ฐ€๊ฒฉ", "๋ฐ”์‚ญํ•จ" ], "sentiment_analysis": { "positive": 65.2, "neutral": 26.1, "negative": 8.7 }, "photo_reviews": 15, "recent_trend": "์ƒ์Šน", "peak_hours": ["19:00-21:00", "12:00-13:00"] }, "combined_at": "2024-06-16T10:30:15" }, "502156891": { "store_info": { "id": "502156891", "name": "ํ™ฉ๊ธˆ์น˜ํ‚จ", "category": "์Œ์‹์  > ์น˜ํ‚จ", "rating": "4.4", "review_count": "67", "status": "์˜์—…์ค‘", "address": "์„œ์šธํŠน๋ณ„์‹œ ๊ฐ•๋‚จ๊ตฌ ์—ญ์‚ผ๋™ 234-56", "phone": "02-234-5678", "place_url": "http://place.map.kakao.com/502156891", "x": "127.0298765", "y": "37.4965432" }, "reviews": [ { "reviewer_name": "์ตœโ—‹โ—‹", "reviewer_level": "ํ”Œ๋ž˜ํ‹ฐ๋„˜๋ฆฌ๋ทฐ์–ด", "reviewer_stats": { "reviews": 234, "average_rating": 4.5, "followers": 45 }, "rating": 5, "date": "2024-06-12", "content": "์—ฌ๊ธฐ ์น˜ํ‚จ์€ ์ •๋ง ์ตœ๊ณ ์˜ˆ์š”! ํŠนํžˆ ์–‘๋…์น˜ํ‚จ์ด ๋‹ฌ์ฝคํ•˜๋ฉด์„œ๋„ ๋งค์ฝคํ•ด์„œ ์ค‘๋…์„ฑ์ด ์žˆ์–ด์š”. ์‚ฌ์žฅ๋‹˜๋„ ๋„ˆ๋ฌด ์นœ์ ˆํ•˜์‹œ๊ณ  ์„œ๋น„์Šค๋„ ์ข‹์Šต๋‹ˆ๋‹ค.", "badges": ["์ตœ๊ณ ", "์–‘๋…์น˜ํ‚จ", "์นœ์ ˆ", "์„œ๋น„์Šค"], "likes": 18, "photo_count": 4, "has_photos": true }, { "reviewer_name": "์ •โ—‹โ—‹", "reviewer_level": "๊ณจ๋“œ๋ฆฌ๋ทฐ์–ด", "reviewer_stats": { "reviews": 145, "average_rating": 4.2, "followers": 19 }, "rating": 4, "date": "2024-06-09", "content": "๋ง›์€ ์ข‹์€๋ฐ ๋งค์žฅ์ด ์ข€ ์ข์•„์š”. ํฌ์žฅํ•ด์„œ ๋จน๋Š” ๊ฑธ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.", "badges": ["๋ง›์ข‹์Œ", "๋งค์žฅ์ข์Œ", "ํฌ์žฅ์ถ”์ฒœ"], "likes": 9, "photo_count": 2, "has_photos": true } ], "review_summary": { "total_reviews": 67, "average_rating": 4.4, "rating_distribution": { "5": 32, "4": 25, "3": 7, "2": 2, "1": 1 }, "positive_keywords": [ "์ตœ๊ณ ", "์–‘๋…์น˜ํ‚จ", "์นœ์ ˆ", "๋ง›์ข‹์Œ", "์„œ๋น„์Šค" ], "negative_keywords": [ "๋งค์žฅ์ข์Œ", "๋Œ€๊ธฐ์‹œ๊ฐ„" ], "common_keywords": [ "์–‘๋…์น˜ํ‚จ", "๋ง›์ข‹์Œ", "์นœ์ ˆ", "์„œ๋น„์Šค", "์ตœ๊ณ ", "ํฌ์žฅ" ], "sentiment_analysis": { "positive": 73.1, "neutral": 20.9, "negative": 6.0 }, "photo_reviews": 45, "recent_trend": "์ƒ์Šน", "peak_hours": ["18:00-20:00", "12:00-14:00"] }, "combined_at": "2024-06-16T10:31:22" }, "503789456": { "store_info": { "id": "503789456", "name": "ํฌ๋ฆฌ์Šคํ”ผ์น˜ํ‚จ", "category": "์Œ์‹์  > ์น˜ํ‚จ", "rating": "3.9", "review_count": "34", "status": "์˜์—…์ค‘", "address": "์„œ์šธํŠน๋ณ„์‹œ ๊ฐ•๋‚จ๊ตฌ ์—ญ์‚ผ๋™ 345-67", "phone": "02-345-6789", "place_url": "http://place.map.kakao.com/503789456", "x": "127.0312345", "y": "37.4951234" }, "reviews": [ { "reviewer_name": "ํ•œโ—‹โ—‹", "reviewer_level": "์‹ค๋ฒ„๋ฆฌ๋ทฐ์–ด", "reviewer_stats": { "reviews": 76, "average_rating": 3.8, "followers": 5 }, "rating": 4, "date": "2024-06-11", "content": "๋ฐ”์‚ญํ•œ ์น˜ํ‚จ์„ ์ข‹์•„ํ•œ๋‹ค๋ฉด ์ถ”์ฒœ! ๋‹ค๋งŒ ์–‘๋…์ด ์ข€ ์งœ์š”.", "badges": ["๋ฐ”์‚ญํ•จ", "์–‘๋…์ง ๋ง›"], "likes": 6, "photo_count": 1, "has_photos": true } ], "review_summary": { "total_reviews": 34, "average_rating": 3.9, "rating_distribution": { "5": 8, "4": 15, "3": 7, "2": 3, "1": 1 }, "positive_keywords": [ "๋ฐ”์‚ญํ•จ", "๋ง›์žˆ์Œ" ], "negative_keywords": [ "์–‘๋…์ง ๋ง›", "์„œ๋น„์Šค" ], "common_keywords": [ "๋ฐ”์‚ญํ•จ", "์น˜ํ‚จ", "์–‘๋…", "๋ง›์žˆ์Œ" ], "sentiment_analysis": { "positive": 58.8, "neutral": 29.4, "negative": 11.8 }, "photo_reviews": 18, "recent_trend": "๋ณดํ†ต", "peak_hours": ["19:00-21:00"] }, "combined_at": "2024-06-16T10:32:05" } } } ``` ### 2. AI ๊ธฐ๋ฐ˜ ๋น„์ฆˆ๋‹ˆ์Šค ์ถ”์ฒœ **์š”์ฒญ** ```bash curl -X POST "http://vector-api.20.249.191.180.nip.io/action-recommendation" \ -H "Content-Type: application/json" \ -d '{ "store_id": "501745730", "context": "๋งค์ถœ์ด ๊ฐ์†Œํ•˜๊ณ  ์žˆ์–ด์„œ ๋ฉ”๋‰ด ๊ฐœ์„ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค." }' ``` **์‘๋‹ต** ```json { "success": true, "recommendation": { "summary": { "current_situation": "์น˜ํ‚จ ์ „๋ฌธ์ ์œผ๋กœ ๊ฐ•๋‚จ๊ตฌ ์—ญ์‚ผ๋™์— ์œ„์น˜, ํ‰๊ท  ๋ณ„์  3.8์ ์œผ๋กœ ๋™์ข…์—…์ฒด ๋Œ€๋น„ ๊ฐœ์„  ์—ฌ์ง€ ์กด์žฌ", "key_insights": [ "๋ฐฐ๋‹ฌ ์„œ๋น„์Šค ๋งŒ์กฑ๋„๊ฐ€ ๊ฒฝ์Ÿ์—…์ฒด ๋Œ€๋น„ ๋‚ฎ์Œ", "์‹ ๋ฉ”๋‰ด ์ถœ์‹œ ์ฃผ๊ธฐ๊ฐ€ 3๊ฐœ์›” ์ด์ƒ์œผ๋กœ ๊ธด ํŽธ", "์˜จ๋ผ์ธ ๋ฆฌ๋ทฐ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ ๋ถ€์žฌ" ], "priority_areas": ["๋ฐฐ๋‹ฌ ํ’ˆ์งˆ ๊ฐœ์„ ", "๋ฉ”๋‰ด ํ˜์‹ "] }, "action_plans": { "short_term": [ { "title": "๋ฐฐ๋‹ฌ ํฌ์žฅ์žฌ ๊ฐœ์„ ", "description": "๋ณด์˜จ์„ฑ์ด ์šฐ์ˆ˜ํ•œ ์นœํ™˜๊ฒฝ ํฌ์žฅ์žฌ๋กœ ๊ต์ฒดํ•˜์—ฌ ๋ฐฐ๋‹ฌ ๋งŒ์กฑ๋„ ํ–ฅ์ƒ", "expected_impact": "๋ฐฐ๋‹ฌ ๋ฆฌ๋ทฐ ํ‰์  0.5์  ์ƒ์Šน ์˜ˆ์ƒ", "timeline": "2์ฃผ", "cost": "์›” 50๋งŒ์›" } ], "mid_term": [ { "title": "์‹œ์ฆŒ ํ•œ์ • ๋ฉ”๋‰ด ๋Ÿฐ์นญ", "description": "์—ฌ๋ฆ„ ์‹œ์ฆŒ ๋งค์šด๋ง› ์‹ ๋ฉ”๋‰ด 2์ข… ๊ฐœ๋ฐœ ๋ฐ SNS ๋งˆ์ผ€ํŒ…", "expected_impact": "์‹ ๊ทœ ๊ณ ๊ฐ ์œ ์ž… 20% ์ฆ๊ฐ€", "timeline": "6์ฃผ", "cost": "์ดˆ๊ธฐ ํˆฌ์ž 300๋งŒ์›" } ], "long_term": [ { "title": "๋ธŒ๋žœ๋“œ ๋ฆฌ๋‰ด์–ผ", "description": "๋งค์žฅ ์ธํ…Œ๋ฆฌ์–ด ๊ฐœ์„  ๋ฐ ๋ธŒ๋žœ๋“œ ์•„์ด๋ดํ‹ฐํ‹ฐ ๊ฐ•ํ™”", "expected_impact": "๋ธŒ๋žœ๋“œ ์ธ์ง€๋„ ํ–ฅ์ƒ, ๊ฐ๋‹จ๊ฐ€ 15% ์ƒ์Šน", "timeline": "4๊ฐœ์›”", "cost": "1,500๋งŒ์›" } ] }, "implementation_tips": [ "๋ฐฐ๋‹ฌ์•ฑ ๋ฆฌ๋ทฐ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ๋„์ž…", "๊ฒฝ์Ÿ์—…์ฒด ๋ฉ”๋‰ด ํŠธ๋ Œ๋“œ ์ฃผ๊ธฐ์  ๋ถ„์„", "๊ณ ๊ฐ ํ”ผ๋“œ๋ฐฑ ๊ธฐ๋ฐ˜ ๊ฐœ์„ ์‚ฌํ•ญ ์šฐ์„ ์ˆœ์œ„ ์„ค์ •" ] }, "input_data": { "request_context": { "store_id": "501745730", "owner_request": "๋งค์ถœ์ด ๊ฐ์†Œํ•˜๊ณ  ์žˆ์–ด์„œ ๋ฉ”๋‰ด ๊ฐœ์„ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.", "analysis_timestamp": "2024-06-16T10:30:00" }, "market_intelligence": { "total_competitors": 7, "industry_insights": [ "์—…๊ณ„ ์ „๋ฐ˜์ ์œผ๋กœ ๊ณ ๊ฐ ๋งŒ์กฑ๋„ ๊ฐœ์„  ํ•„์š”", "๊ณ ์„ฑ๊ณผ ์—…์ฒด 3๊ฐœ ๋ฒค์น˜๋งˆํ‚น ๊ฐ€๋Šฅ" ], "performance_benchmarks": { "average_rating": 4.1, "review_volume_trend": "์ฆ๊ฐ€" } }, "competitive_insights": [ { "rank": 1, "store_name": "โ—‹โ—‹์น˜ํ‚จ", "similarity_score": 0.892, "performance_analysis": { "performance": { "rating": "4.3", "review_count": "156" }, "feedback": { "positive_aspects": ["๋ง›", "์นœ์ ˆ", "๋น ๋ฅธ๋ฐฐ๋‹ฌ"], "negative_aspects": ["๊ฐ€๊ฒฉ"] }, "business_insights": { "key_finding": "์‹ ๋ฉ”๋‰ด ๋Ÿฐ์นญ์œผ๋กœ ๋ฆฌ๋ทฐ ๊ธ‰์ฆ" } } } ], "actionable_recommendations": { "immediate_actions": [ "๋ฐฐ๋‹ฌ ์„œ๋น„์Šค ๊ฐœ์„  (์—…๊ณ„ 5๊ฐœ ์—…์ฒด ๊ณตํ†ต ๋ฌธ์ œ)" ], "strategic_improvements": [ "๋ฉ”๋‰ด ๋‹ค์–‘์„ฑ ํ™•๋Œ€" ], "benchmarking_targets": [ "โ—‹โ—‹์น˜ํ‚จ: ์‹ ๋ฉ”๋‰ด ๋งˆ์ผ€ํŒ… ์ „๋žต" ] } } } ``` ## โš™๏ธ ํ™˜๊ฒฝ ์„ค์ • ### ํ•„์ˆ˜ ํ™˜๊ฒฝ๋ณ€์ˆ˜ | ๋ณ€์ˆ˜๋ช… | ์„ค๋ช… | ์˜ˆ์‹œ | ๊ธฐ๋ณธ๊ฐ’ | |--------|------|------|--------| | `CLAUDE_API_KEY` | Claude AI API ํ‚ค | `sk-ant-api03-...` | - | | `RESTAURANT_API_HOST` | Restaurant API ํ˜ธ์ŠคํŠธ | `localhost` | `0.0.0.0` | | `RESTAURANT_API_PORT` | Restaurant API ํฌํŠธ | `18000` | `18000` | | `REVIEW_API_HOST` | Review API ํ˜ธ์ŠคํŠธ | `localhost` | `0.0.0.0` | | `REVIEW_API_PORT` | Review API ํฌํŠธ | `19000` | `19000` | ### ์„ ํƒ์  ํ™˜๊ฒฝ๋ณ€์ˆ˜ | ๋ณ€์ˆ˜๋ช… | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ | |--------|------|--------| | `CLAUDE_MODEL` | Claude ๋ชจ๋ธ๋ช… | `claude-sonnet-4-20250514` | | `VECTOR_DB_PATH` | Vector DB ์ €์žฅ ๊ฒฝ๋กœ | `./vectordb` | | `VECTOR_DB_COLLECTION` | ์ปฌ๋ ‰์…˜๋ช… | `restaurant_reviews` | | `EMBEDDING_MODEL` | ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ | `sentence-transformers/all-MiniLM-L6-v2` | | `MAX_RESTAURANTS_PER_CATEGORY` | ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์ตœ๋Œ€ ์ˆ˜์ง‘ ์Œ์‹์  | `50` | | `MAX_REVIEWS_PER_RESTAURANT` | ์Œ์‹์ ๋ณ„ ์ตœ๋Œ€ ๋ฆฌ๋ทฐ ์ˆ˜ | `100` | | `LOG_LEVEL` | ๋กœ๊ทธ ๋ ˆ๋ฒจ | `info` | ### Kubernetes ํ™˜๊ฒฝ ์ž๋™ ๊ฐ์ง€ ์‹œ์Šคํ…œ์ด ์ž๋™์œผ๋กœ ํ™˜๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ ์ ์ ˆํ•œ ์„ค์ •์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค: - **๋กœ์ปฌ ๊ฐœ๋ฐœ**: `localhost` ๊ธฐ๋ฐ˜ API ์—ฐ๋™ - **Kubernetes**: ์„œ๋น„์Šค ๋””์Šค์ปค๋ฒ„๋ฆฌ ๊ธฐ๋ฐ˜ ์—ฐ๋™ - `restaurant-api-service:80` - `kakao-review-api-service:80` ## ๐Ÿ”ง ๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ ### ๋กœ์ปฌ ๊ฐœ๋ฐœ ```bash # ์˜์กด์„ฑ ์ถ”๊ฐ€ poetry add ์ƒˆํŒจํ‚ค์ง€๋ช… # ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹คํ–‰ (Hot Reload) poetry run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload # ์ง์ ‘ ์‹คํ–‰ poetry run python app/main.py # ์˜์กด์„ฑ ์—…๋ฐ์ดํŠธ poetry update # ๊ฐ€์ƒํ™˜๊ฒฝ ์ •๋ณด ํ™•์ธ poetry env info ``` ### ์ฝ”๋“œ ํ’ˆ์งˆ ```bash # ์ฝ”๋“œ ํฌ๋งทํŒ… poetry run black app/ # ๋ฆฐํŒ… poetry run flake8 app/ # ํƒ€์ž… ์ฒดํฌ poetry run mypy app/ ``` ### Docker ๊ฐœ๋ฐœ ```bash # ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ (์˜์กด์„ฑ ๋ณ€๊ฒฝ ์‹œ) ./build-base.sh # ์„œ๋น„์Šค ์ด๋ฏธ์ง€ ๋นŒ๋“œ ./build.sh # ๋กœ์ปฌ ์‹คํ–‰ docker run -p 8000:8000 --env-file .env vector-api:latest ``` ## ๐Ÿ› ๋ฌธ์ œ ํ•ด๊ฒฐ ### ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ **1. Vector DB ์ดˆ๊ธฐํ™” ์‹คํŒจ** ```bash # Vector DB ์ƒํƒœ ํ™•์ธ curl "http://localhost:8000/vector-status" # ๋กœ๊ทธ ํ™•์ธ kubectl logs -l app=vector-api | grep -i vector # Vector DB ๋””๋ ‰ํ† ๋ฆฌ ํ™•์ธ (Kubernetes) kubectl exec -it deployment/vector-api -- ls -la /app/vectordb/ ``` **2. Claude API ์—ฐ๊ฒฐ ์‹คํŒจ** ```bash # API ํ‚ค ์œ ํšจ์„ฑ ํ…Œ์ŠคํŠธ curl -X POST "https://api.anthropic.com/v1/messages" \ -H "x-api-key: your-claude-api-key" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 10, "messages": [{"role": "user", "content": "Hi"}] }' # ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํ™•์ธ kubectl exec -it deployment/vector-api -- env | grep CLAUDE ``` **3. ์™ธ๋ถ€ API ์—ฐ๋™ ์‹คํŒจ** ```bash # Restaurant API ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ kubectl exec -it deployment/vector-api -- curl http://restaurant-api-service/health # Review API ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ kubectl exec -it deployment/vector-api -- curl http://kakao-review-api-service/health # ์„œ๋น„์Šค ๋””์Šค์ปค๋ฒ„๋ฆฌ ํ™•์ธ kubectl get svc | grep -E "(restaurant|review)" ``` **4. ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ๋ฌธ์ œ** ```bash # ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ kubectl top pods -l app=vector-api # Pod ๋ฆฌ์†Œ์Šค ์ œํ•œ ํ™•์ธ kubectl describe pod -l app=vector-api | grep -A 5 -B 5 Resources # ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋ชจ๋‹ˆํ„ฐ๋ง kubectl exec -it deployment/vector-api -- free -h ``` **5. ์˜๊ตฌ ๋ณผ๋ฅจ ๋ฌธ์ œ** ```bash # PVC ์ƒํƒœ ํ™•์ธ kubectl get pvc vector-db-pvc kubectl describe pvc vector-db-pvc # ๋ณผ๋ฅจ ๋งˆ์šดํŠธ ํ™•์ธ kubectl exec -it deployment/vector-api -- df -h /app/vectordb ``` ### ์„ฑ๋Šฅ ์ตœ์ ํ™” **๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”** ```yaml # deployment.yaml์—์„œ ๋ฆฌ์†Œ์Šค ์กฐ์ • resources: requests: memory: "2Gi" # Vector DB + ML ๋ชจ๋ธ cpu: "1000m" # ์ž„๋ฒ ๋”ฉ ๊ณ„์‚ฐ limits: memory: "4Gi" # ๋Œ€๋Ÿ‰ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์—ฌ์œ  cpu: "2000m" # ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ``` **Vector DB ์ตœ์ ํ™”** - ์ž„๋ฒ ๋”ฉ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ๋กœ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ ํ–ฅ์ƒ - ์ค‘๋ณต ๋ฐ์ดํ„ฐ ๊ฐ์ง€๋กœ ๋ถˆํ•„์š”ํ•œ ์žฌ์ฒ˜๋ฆฌ ๋ฐฉ์ง€ - ์ ์ ˆํ•œ ์ฒญํฌ ํฌ๊ธฐ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์กฐ์ ˆ ## ๐Ÿ“ˆ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๋กœ๊น… ### ํ—ฌ์Šค์ฒดํฌ ๋ชจ๋‹ˆํ„ฐ๋ง ```bash # ์ฃผ๊ธฐ์  ํ—ฌ์Šค์ฒดํฌ watch -n 5 "curl -s http://vector-api.20.249.191.180.nip.io/health | jq" # Vector DB ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง watch -n 10 "curl -s http://vector-api.20.249.191.180.nip.io/vector-status | jq" ``` ### ๋กœ๊ทธ ๋ถ„์„ ```bash # ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ์ŠคํŠธ๋ฆผ kubectl logs -l app=vector-api -f # ์—๋Ÿฌ ๋กœ๊ทธ ํ•„ํ„ฐ๋ง kubectl logs -l app=vector-api | grep -i error # Claude API ํ˜ธ์ถœ ๋กœ๊ทธ kubectl logs -l app=vector-api | grep -i claude # Vector DB ์ž‘์—… ๋กœ๊ทธ kubectl logs -l app=vector-api | grep -i vector ``` ## ๐ŸŽฏ ์›Œํฌํ”Œ๋กœ์šฐ ๋‹ค์ด์–ด๊ทธ๋žจ ### Vector DB ๊ตฌ์ถ• ํ”„๋กœ์„ธ์Šค ```mermaid sequenceDiagram participant Client participant VectorAPI participant RestaurantAPI participant ReviewAPI participant VectorDB participant ClaudeAI Client->>VectorAPI: POST /find-reviews VectorAPI->>RestaurantAPI: ํƒ€๊ฒŸ ์Œ์‹์  ๊ฒ€์ƒ‰ RestaurantAPI-->>VectorAPI: ์Œ์‹์  ์ •๋ณด ๋ฐ˜ํ™˜ VectorAPI->>RestaurantAPI: ๋™์ข…์—…์ฒด ๊ฒ€์ƒ‰ RestaurantAPI-->>VectorAPI: ๊ฒฝ์Ÿ์—…์ฒด ๋ชฉ๋ก ๋ฐ˜ํ™˜ loop ๊ฐ ์Œ์‹์  VectorAPI->>ReviewAPI: ๋ฆฌ๋ทฐ ์ˆ˜์ง‘ ReviewAPI-->>VectorAPI: ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜ end VectorAPI->>VectorAPI: ํ…์ŠคํŠธ ์ „์ฒ˜๋ฆฌ ๋ฐ ์ž„๋ฒ ๋”ฉ VectorAPI->>VectorDB: Vector ์ €์žฅ VectorDB-->>VectorAPI: ์ €์žฅ ์™„๋ฃŒ VectorAPI-->>Client: ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ ``` ### AI ์ถ”์ฒœ ํ”„๋กœ์„ธ์Šค ```mermaid sequenceDiagram participant Client participant VectorAPI participant VectorDB participant ClaudeAI Client->>VectorAPI: POST /action-recommendation VectorAPI->>VectorDB: ์œ ์‚ฌ ์ผ€์ด์Šค ๊ฒ€์ƒ‰ VectorDB-->>VectorAPI: ๊ด€๋ จ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜ VectorAPI->>VectorAPI: ์ปจํ…์ŠคํŠธ ๊ตฌ์„ฑ VectorAPI->>ClaudeAI: ์ถ”์ฒœ ์š”์ฒญ ClaudeAI-->>VectorAPI: ์•ก์…˜ ํ”Œ๋žœ ๋ฐ˜ํ™˜ VectorAPI->>VectorAPI: JSON ํŒŒ์‹ฑ VectorAPI-->>Client: ๊ตฌ์กฐํ™”๋œ ์ถ”์ฒœ ๋ฐ˜ํ™˜ ``` ## ๐Ÿ“ˆ ํ–ฅํ›„ ๋กœ๋“œ๋งต ### Phase 1: ๊ธฐ๋Šฅ ์•ˆ์ •ํ™” โœ… - [x] Vector DB ๊ตฌ์ถ• ๋ฐ ๊ด€๋ฆฌ - [x] Claude AI ํ†ตํ•ฉ - [x] ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜ - [x] Kubernetes ๋ฐฐํฌ - [x] API ๋ฌธ์„œํ™” ### Phase 2: ๊ธฐ๋Šฅ ํ™•์žฅ ๐Ÿšง - [ ] **์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘**: ์ƒˆ๋กœ์šด ๋ฆฌ๋ทฐ ์ž๋™ ์—…๋ฐ์ดํŠธ - [ ] **๋‹ค์ค‘ Vector DB ์ง€์›**: FAISS, Pinecone ์ถ”๊ฐ€ - [ ] **๊ฐ์ • ๋ถ„์„ ๊ณ ๋„ํ™”**: ์„ธ๋ฐ€ํ•œ ๊ฐ์ • ๋ถ„๋ฅ˜ ๋ฐ ํŠธ๋ Œ๋“œ ๋ถ„์„ - [ ] **์—…์ข…๋ณ„ ํŠนํ™” ๋ชจ๋ธ**: ์Œ์‹์  ์œ ํ˜•๋ณ„ ๋งž์ถค ์ถ”์ฒœ ### Phase 3: ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๐Ÿ“‹ - [ ] **์‹ค์‹œ๊ฐ„ ๋Œ€์‹œ๋ณด๋“œ**: Grafana ๊ธฐ๋ฐ˜ ๋ชจ๋‹ˆํ„ฐ๋ง - [ ] **A/B ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ**: ์ถ”์ฒœ ํšจ๊ณผ ์ธก์ • - [ ] **๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ๋ถ„์„**: ์ด๋ฏธ์ง€ + ํ…์ŠคํŠธ ํ†ตํ•ฉ ๋ถ„์„ - [ ] **์˜ˆ์ธก ๋ถ„์„**: ๋งค์ถœ ๋ฐ ํŠธ๋ Œ๋“œ ์˜ˆ์ธก ๋ชจ๋ธ ### Phase 4: ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ๐Ÿ“Š - [ ] **API ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ**: ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ผ๊ด„ ์ฒ˜๋ฆฌ - [ ] **๊ณ ๊ธ‰ ๋ณด์•ˆ**: OAuth 2.0, API ํ‚ค ๊ด€๋ฆฌ - [ ] **๋ฉ€ํ‹ฐ ํ…Œ๋„ŒํŠธ**: ๊ณ ๊ฐ๋ณ„ ๊ฒฉ๋ฆฌ๋œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ - [ ] **๋น„์ฆˆ๋‹ˆ์Šค ์ธํ…”๋ฆฌ์ „์Šค**: ์‹œ์žฅ ๋ถ„์„ ๋ฐ ๋ณด๊ณ ์„œ ์ƒ์„ฑ ## ๐Ÿค ๊ธฐ์—ฌ ๊ฐ€์ด๋“œ ### ๊ฐœ๋ฐœ ์›Œํฌํ”Œ๋กœ์šฐ 1. **์ด์Šˆ ์ƒ์„ฑ**: ๊ธฐ๋Šฅ ์š”์ฒญ ๋˜๋Š” ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ 2. **๋ธŒ๋žœ์น˜ ์ƒ์„ฑ**: `feature/๊ธฐ๋Šฅ๋ช…` ๋˜๋Š” `fix/๋ฒ„๊ทธ๋ช…` 3. **๊ฐœ๋ฐœ ๋ฐ ํ…Œ์ŠคํŠธ**: ๋กœ์ปฌ์—์„œ ์ถฉ๋ถ„ํ•œ ํ…Œ์ŠคํŠธ 4. **Pull Request**: ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์š”์ฒญ 5. **๋ฐฐํฌ**: ๊ฒ€ํ†  ํ›„ ๋ฉ”์ธ ๋ธŒ๋žœ์น˜ ๋ณ‘ํ•ฉ ### ์ฝ”๋”ฉ ์ปจ๋ฒค์…˜ - **ํƒ€์ž… ํžŒํŒ…**: ๋ชจ๋“  ํ•จ์ˆ˜์™€ ๋ณ€์ˆ˜์— ํƒ€์ž… ๋ช…์‹œ - **Docstring**: Google ์Šคํƒ€์ผ ๋ฌธ์„œํ™” - **์—๋Ÿฌ ์ฒ˜๋ฆฌ**: ๋ชจ๋“  ์™ธ๋ถ€ API ํ˜ธ์ถœ์— ์˜ˆ์™ธ ์ฒ˜๋ฆฌ - **๋กœ๊น…**: ์ ์ ˆํ•œ ๋กœ๊ทธ ๋ ˆ๋ฒจ๊ณผ ๊ตฌ์กฐํ™”๋œ ๋ฉ”์‹œ์ง€ ## ๐Ÿ“ž ์ง€์› ๋ฐ ๋ฌธ์˜ ### ๊ธฐ์ˆ  ์ง€์› - **๐Ÿ› ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ**: GitHub Issues - **๐Ÿ’ก ๊ธฐ๋Šฅ ์ œ์•ˆ**: GitHub Discussions - **๐Ÿ“š API ๋ฌธ์˜**: Swagger UI ๋ฌธ์„œ ์ฐธ์กฐ - **๐Ÿ“ง ๊ธฐ์ˆ  ์ง€์›**: ๊ฐœ๋ฐœํŒ€ Slack ์ฑ„๋„ ### ๋ฌธ์„œ ๋ฐ ๋ฆฌ์†Œ์Šค - **๐Ÿ“– API ๋ฌธ์„œ**: http://vector-api.20.249.191.180.nip.io/docs - **๐Ÿ”ง ๋ชจ๋‹ˆํ„ฐ๋ง**: http://vector-api.20.249.191.180.nip.io/vector-status - **โค๏ธ ํ—ฌ์Šค์ฒดํฌ**: http://vector-api.20.249.191.180.nip.io/health --- ## ๐Ÿ“ ๋ผ์ด์„ ์Šค ์ด ํ”„๋กœ์ ํŠธ๋Š” ์†Œ์ƒ๊ณต์ธ์˜ ์„ฑ์žฅ๊ณผ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์˜์‚ฌ๊ฒฐ์ •์„ ์ง€์›ํ•˜๋Š” ๋ชฉ์ ์œผ๋กœ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. --- **๐Ÿ’ก ํ•ต์‹ฌ ๊ฐ€์น˜**: AI์™€ ๋ฐ์ดํ„ฐ์˜ ํž˜์œผ๋กœ ์†Œ์ƒ๊ณต์ธ์˜ ์„ฑ๊ณต์„ ๋•์Šต๋‹ˆ๋‹ค! **๐ŸŽฏ ๋ฏธ์…˜**: ๋ชจ๋“  ์†Œ์ƒ๊ณต์ธ์ด ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜์œผ๋กœ ์Šค๋งˆํŠธํ•œ ๊ฒฝ์˜ ๊ฒฐ์ •์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.