# Local LLM 모델 변경 체크리스트 LLM 또는 임베딩 모델을 교체할 때 수정해야 할 모든 위치를 정리한다. --- ## 현재 구성 (기준선) | 역할 | 현재 모델 / 설정 | |------|----------------| | **LLM 추론** | `Qwen/Qwen3-Coder-Next-FP8` (vLLM, `localhost:8000/v1`) | | **임베딩** | `nomic-embed-text` (Ollama, `localhost:11434`, 768-dim) | | **벡터 DB** | Qdrant `localhost:6333` | | **Qdrant 컬렉션 — 코드베이스** | `ws-65f457145aee80b2` (768-dim) | | **Qdrant 컬렉션 — OPC UA 문서** | `experion-opc-docs` (768-dim) | --- ## 현재 실행 중인 vLLM 기동 명령 (2026-04-28) ### 기동 방법 ```bash cd ~/ai-models/spark-vllm-docker ./run-recipe.sh qwen3-coder-next-fp8 --solo ``` - `--setup` 없이 실행: 빌드/다운로드 생략, 바로 기동 - `--solo`: 단일 노드, Ray 클러스터 없음 → `-tp 1` 자동 적용 ### 실제 컨테이너 내부 vLLM 명령 (inspect 기준) ```bash vllm serve Qwen/Qwen3-Coder-Next-FP8 \ --enable-auto-tool-choice \ --tool-call-parser qwen3_coder \ --gpu-memory-utilization 0.7 \ --host 0.0.0.0 \ --port 8000 \ --kv-cache-dtype fp8 \ --load-format fastsafetensors \ --attention-backend flashinfer \ --enable-prefix-caching \ --max-model-len 131072 \ -tp 1 ``` > 레시피 기본값(`tensor_parallel: 2`, `--distributed-executor-backend ray`)에서 `--solo` 모드로 인해 `-tp 1`로 변경되고 Ray 분산 옵션이 제거됨. ### 컨테이너 실행 환경 | 항목 | 값 | |------|----| | 이미지 | `vllm-node:latest` | | 네트워크 | `host` | | GPU | all (NVIDIA_VISIBLE_DEVICES=all) | | SHM | 64MB | | Privileged | true | | HF 캐시 마운트 | `~/.cache/huggingface:/root/.cache/huggingface` | | 모델 경로 | `~/.cache/huggingface/hub/models--Qwen--Qwen3-Coder-Next-FP8` | ### 실측 성능 (2026-04-28, `-tp 1`) | 항목 | 단순 코딩 | RAG 연동 복잡 코딩 | |------|-----------|------------------| | 출력 토큰 | 1,173 | 3,382 | | 토큰 속도 | **48.2 tok/s** | **47.8 tok/s** | | TTFT | 0.261s | 0.962s | | 총 소요 시간 | 24.6s | 71.7s | **이전 모델 대비**: GLM-4.7-Flash (~16 tok/s) 대비 **약 3배 빠름** - 속도는 출력 길이·프롬프트 길이 무관하게 ~48 tok/s로 안정적 - TTFT는 프롬프트 길이에 비례 (6,392 chars → 0.96s) - RAG 검색(Qdrant + Ollama embed) 자체 오버헤드: 0.34s ### vLLM 서버 누적 통계 (기동 후 초기 세션, 2026-04-28) 다른 작업을 병행하는 상황에서 측정된 실사용 기준값: | 항목 | 값 | |------|----| | 완료 요청 | 22건 | | 총 프롬프트 토큰 | 453,080 | | 총 생성 토큰 | 23,147 | | 평균 TTFT | 1.565s | | 평균 E2E 레이턴시 | 13.3s / 요청 | | **평균 tok/s (vLLM 내부)** | **44.4 tok/s** | | KV 캐시 사용률 | 8.1% (484 GPU blocks, 여유 충분) | | **프리픽스 캐시 히트율** | **85.7%** (388,064 / 453,080 tokens) | **핵심 포인트**: `--enable-prefix-caching` 효과로 프롬프트 토큰의 85.7%가 캐시에서 처리됨. RAG 시스템 프롬프트·반복 컨텍스트 재사용 시 TTFT 대폭 절감. 다른 작업 병행 중에도 성능 유지. ### GPU 상태 (nvidia-smi, 2026-04-28 23:32 — 작업 병행 중) ``` | GPU Name Temp Pwr:Usage GPU-Util | | 0 NVIDIA GB10 60°C 25W 96% | 프로세스: VLLM::EngineCore 85,568 MiB (vLLM 모델 로드) ollama 711 MiB (nomic-embed-text) Xorg + gnome-shell 164 MiB (디스플레이) ``` - **GPU**: NVIDIA GB10 (단일 카드, `-tp 1`) - **VRAM 사용**: 85,568 MiB (vLLM) + 711 MiB (Ollama) = **~86 GB** - **GPU 사용률**: 96% (작업 처리 중) - **소비 전력**: 25W (측정값 — 추론 중 실시간) - **온도**: 60°C (정상 범위) --- ## 변경 시나리오별 수정 위치 ### Case A — LLM 모델만 교체 (임베딩 유지) 임베딩 모델과 벡터 차원이 바뀌지 않으므로 **재인덱싱 불필요**. #### 수정 파일 1: `mcp-nl2sql-server/server.py` ```python # 20~25번 줄 VLLM_BASE_URL = "http://localhost:8000/v1" # vLLM 주소 변경 시 함께 수정 VLLM_MODEL = "glm-4.7-flash" # ← 새 모델명으로 변경 ``` `VLLM_MODEL`이 사용되는 위치 (함수명 참고): - `ask_iiot_llm()` — line ~140 - `query_with_nl()` — line ~455 #### 수정 파일 2: `mcp-server/server.py` (Roo Code용) 동일 구조. 같은 위치 수정: ```python VLLM_MODEL = "glm-4.7-flash" # ← 새 모델명으로 변경 ``` #### 수정 파일 3: `mcp-nl2sql-server/server.py` — 도구 docstring LLM 모델명이 도구 설명에 하드코딩된 곳: ```python def ask_iiot_llm(question: str, context: str = "") -> str: """GLM-4.7-Flash에게 IIoT/OPC UA 질문 ... # ← 모델명 업데이트 ``` #### 수정 파일 4: Roo Code MCP 서버 설명 ``` /home/windpacer/.vscode-server/data/User/globalStorage/ rooveterinaryinc.roo-cline/settings/mcp_settings.json ``` `"description"` 필드의 모델명 문자열 업데이트 (기능에는 영향 없음, 참고용): ```json "description": "ExperionCrawler RAG — Qdrant(코드베이스+OPC UA 문서) + GLM-4.7-Flash" ``` --- ### Case B — 임베딩 모델 교체 (LLM 유지 또는 동시 교체) > ⚠️ **임베딩 모델을 바꾸면 벡터 차원이 달라질 수 있음 → Qdrant 컬렉션 전체 재인덱싱 필수** #### 수정 파일 1: `mcp-nl2sql-server/server.py` ```python OLLAMA_URL = "http://localhost:11434" # Ollama 주소 변경 시 함께 EMBED_MODEL = "nomic-embed-text" # ← 새 임베딩 모델명으로 변경 ``` #### 수정 파일 2: `mcp-server/server.py` (Roo Code용) 동일하게 수정. #### 수정 파일 3: `mcp-nl2sql-server/index_opc_docs.py` — OPC 문서 재인덱싱 스크립트 ```python EMBED_MODEL = "nomic-embed-text" # ← 새 임베딩 모델명 VECTOR_DIM = 768 # ← 새 모델의 차원으로 변경 ``` #### 수정 파일 4: Roo Code 코드베이스 인덱스 설정 Roo Code가 코드베이스 인덱싱에 사용하는 임베딩 모델은 **VS Code 설정 UI**에서 변경: - `Settings → Roo Code → Embeddings Provider` - 또는 `settings.json`: `"roo-cline.embeddingsProvider"` 항목 Roo Code 인덱스 캐시 파일(아래)은 모델 변경 후 **삭제 후 재인덱싱**: ``` ~/.vscode-server/data/User/globalStorage/rooveterinaryinc.roo-cline/ roo-index-cache-65f457145aee80b2...json ← 삭제 roo-index-cache-*.json ← 전부 삭제 ``` #### Qdrant 재인덱싱 절차 임베딩 모델 교체 후 반드시 수행: ```bash # 1. 기존 컬렉션 삭제 curl -X DELETE http://localhost:6333/collections/experion-opc-docs # ws-65f457145aee80b2 컬렉션은 Roo Code가 자동 재생성 # 2. OPC UA 문서 재인덱싱 cd /home/windpacer/projects/Text-to-SQL-AX/mcp-nl2sql-server uv run index_opc_docs.py # 3. MCP 서버 재시작 kill $(pgrep -f "mcp-nl2sql-server.*server.py") uv run server.py & # 4. Roo Code에서 코드베이스 재인덱싱 # VS Code 명령팔레트 → "Roo Code: Index Codebase" ``` --- ## 수정 파일 전체 요약 | 파일 | LLM 교체 | 임베딩 교체 | |------|:--------:|:----------:| | `mcp-nl2sql-server/server.py` — `VLLM_MODEL` | ✅ 필수 | — | | `mcp-nl2sql-server/server.py` — `EMBED_MODEL` | — | ✅ 필수 | | `mcp-server/server.py` — `VLLM_MODEL` | ✅ 필수 | — | | `mcp-server/server.py` — `EMBED_MODEL` | — | ✅ 필수 | | `mcp-nl2sql-server/index_opc_docs.py` — `EMBED_MODEL`, `VECTOR_DIM` | — | ✅ 필수 | | `mcp_settings.json` — `description` 문자열 | 참고용 | 참고용 | | Qdrant 컬렉션 재생성 + 재인덱싱 | ❌ 불필요 | ✅ 필수 | | Roo Code 캐시 삭제 + 재인덱싱 | ❌ 불필요 | ✅ 필수 | --- ## 주의 사항 - **두 `server.py`는 별개 파일**: `mcp-nl2sql-server/server.py`(NL2SQL 전용, port 5001)와 `mcp-server/server.py`(Roo Code용 RAG)는 독립 프로세스이며 각각 수정해야 한다. - **vLLM 모델명**: vLLM이 로드한 모델명(`--served-model-name` 옵션)과 `VLLM_MODEL` 상수가 일치해야 한다. 불일치 시 `model not found` 오류 발생. - **Ollama 모델 다운로드**: `ollama pull ` 먼저 실행 후 서버 수정. - **임베딩 차원 불일치**: Qdrant 컬렉션 생성 시 지정한 `size`와 실제 임베딩 벡터 차원이 다르면 upsert 시 400 오류. `VECTOR_DIM` 수정 후 컬렉션 삭제→재생성 필수. - **`query_with_nl` 시스템 프롬프트**: 모델 교체 후 SQL 생성 품질이 달라질 수 있으므로 프롬프트 튜닝이 필요할 수 있다 (`server.py` line ~424 `system = ...` 블록).