페이지 목차
이 페이지에서 검색
로컬 LLM
이 페이지에 묻기
로컬 LLM · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.
생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.
LOCAL · LLM
로컬 LLM
생성 수정
로컬 모델 실행과 GPU·메모리 이해부터 서빙·RAG·도구 호출·업무형 앱 구현까지 차례로 살펴봅니다.
42개 문서 · 3일차 · 19 / 42
18차시 · vLLM 환경 구축
지도 위치 : 3일차 · ③추론 엔진 층 · vLLM 설치와 첫 추론 | 이전: 17차시 LLM Serving 아키텍처 | 다음: 19차시 vLLM 서버 구축 키워드 : vLLM 설치, GPU 환경 설정, 모델 로딩 및 기본 추론
이 차시를 다 읽으면
- vLLM을 유와 종차로 정의하고, Transformers · Ollama와 무엇으로 갈리는지 말할 수 있다.
- vLLM을 반드시 전용 가상환경 에 설치해야 하는 이유를 전역 ↔ 격리 축으로 설명할 수 있다.
- 설치 전에 확인할 것(OS · GPU · 드라이버 · 디스크)을 명령과 함께 댈 수 있다.
- 오프라인 추론 코드에서
LLM·SamplingParams·llm.chat세 줄 을 알아보고 첫 실행 성공을 판정할 수 있다. - Ollama가 이미 GPU를 쓰고 있을 때의 충돌 을
nvidia-smi로 진단할 수 있다.
0. 이 차시의 판별 축
| # | 축 | 왼쪽 (0) | 오른쪽 (1) | 이 축으로 갈리는 것 | 큰 축 (README 5장) |
|---|---|---|---|---|---|
| 1 | 어디에 설치하나 | 전역 (시스템 · 기존 환경) | 전용 가상환경 | 다른 프로젝트가 깨지는가 | ⑤ 하나 ↔ 여럿의 파생 (환경 분리) |
| 2 | 모델이 어디에 있나 | 디스크 (Hugging Face 캐시) | VRAM (로드된 모델) | 첫 실행이 느린 이유 | ① 디스크 ↔ 메모리 |
| 3 | 한 번인가, 계속인가 | 오프라인 추론 (LLM 클래스) | 서버 (vllm serve, 19차시) | 같은 엔진의 두 사용법 | 한 번 계산 ↔ 여럿에게 제공 (파생 축, 17차시 축 1) |
축 1은 앞에서 배운 가상환경(3차시 3.1) 을 다시 꺼내는 자리입니다. 짧게 되짚으면, 가상환경 은 [격리 장치]인데 [ 프로젝트마다 파이썬과 패키지 묶음을 별도의 폴더에 따로 둔다 ]는 점에서 컴퓨터 전체가 패키지 한 벌을 같이 쓰는 전역 설치와 구별됩니다. 따로 두는 이유는 의존성 지옥 때문입니다. 프로젝트 A와 B가 같은 패키지의 다른 버전 을 원하면, 한 곳에 같이 깔았을 때 둘 중 하나는 깨집니다. 가상환경은 이 고장이 다른 프로젝트로 번지지 않게 막는 장애 격리 장치 이고, vLLM에서 그 역할이 가장 절실해집니다(3절).
1. vLLM은 무엇인가
1.1 정의
vLLM — [LLM 추론 엔진 겸 서빙 프레임워크]인데, [ KV 캐시를 블록 단위로 관리하고(PagedAttention) 여러 요청을 생성 스텝마다 섞어 계산해(연속 배칭) 동시 처리량을 높이는 데 특화되었다 ]는 점에서 1인 실행의 간편함에 맞춘 Ollama, 범용 모델 라이브러리인 Transformers와 구별된다.
종차에 나온 두 기술(PagedAttention, 연속 배칭)은 21차시에서 풉니다. 지금은 "여럿이 동시에 쓸 때 강한 엔진" 이라는 위치만 잡으면 됩니다.
| Transformers | Ollama | vLLM | |
|---|---|---|---|
| 범주 | 모델 라이브러리 | 로컬 실행 도구 (서버 내장) | 추론 엔진 · 서빙 프레임워크 |
| 주 모델 형식 | Hugging Face 형식 (safetensors) | GGUF (12차시) | Hugging Face 형식 + 사전 양자화(AWQ · GPTQ · FP8 등) |
| 모델 받기 | from_pretrained | ollama pull | Hugging Face에서 (자체 저장소 없음) |
| 동시 요청 | 직접 만들어야 함 | 가능하나 1인 사용에 맞춤 | 핵심 강점 |
| 플랫폼 | 어디서나 | Mac · Windows · Linux | Linux + NVIDIA GPU가 기본 |
| 이 과정에서 | 3 · 11차시 | 5~8차시 | 18~24차시 |
1.2 반례 — 이건 vLLM이 아닙니다
| 오해 | 바로잡기 |
|---|---|
| "vLLM은 모델 이름" | ❌ 엔진 입니다. 모델은 Qwen3-8B이고, vLLM은 그것을 돌리는 쪽 |
| "vLLM은 Ollama의 고급판 설치 프로그램" | ❌ pull도 Modelfile도 없습니다. 모델은 Hugging Face에서 받고 설정은 명령 옵션으로 줍니다 |
| "vLLM으로 파인튜닝한다" | ❌ 추론 전용입니다. 가중치를 바꾸지 않습니다(2차시 1절) |
| "GGUF 파일을 그대로 쓰면 된다" | ⚠️ GGUF는 vLLM의 주 형식이 아닙니다. 지원 여부와 범위는 버전에 따라 다르니 공식 문서 확인 |
2. 설치 전 확인 — 요구사항
vLLM은 Linux + NVIDIA GPU(CUDA) 가 기본 대상입니다(README 8장). 설치를 맡기기 전에 아래 표를 먼저 채웁니다.
| 항목 | 확인 명령 | 볼 것 | 안 맞으면 |
|---|---|---|---|
| OS | cat /etc/os-release | Ubuntu 등 Linux | Windows는 WSL2, Mac은 기본 대상 아님 → 공식 문서 확인 |
| GPU · 드라이버 | nvidia-smi | GPU 이름, VRAM, 오른쪽 위 CUDA Version | 드라이버 문제 → 사람 승인 후 조치 |
| 파이썬 | python3 --version | 공식 문서의 지원 버전 범위 안인가 | uv로 맞는 버전 지정 (3.2) |
| 디스크 | df -h ~ | 패키지(수 GB) + 모델(Qwen3-8B 약 16GB) + 여유 | 정리하거나 캐시 위치 변경 (5.2) |
⚠️ nvidia-smi의 CUDA Version 은 "설치된 CUDA 툴킷 버전"이 아니라 드라이버가 지원하는 최대 CUDA 버전 입니다. pip로 받는 vLLM은 필요한 CUDA 런타임을 함께 가져오는 경우가 많아 툴킷을 따로 깔 필요가 없을 수 있습니다. 정확한 조건은 설치 페이지 에서 확인합니다.
⚠️ 드라이버 · CUDA 재설치는 시스템 전체에 영향을 줍니다. README 9장의 표대로 실행 전 설명을 받고 사람이 승인 합니다.
3. ⚠️ 전용 가상환경 — 왜 반드시 따로인가
3.1 vLLM은 PyTorch 버전을 고정한다
vLLM은 특정 PyTorch 버전에 맞춰 빌드되어 설치할 때 그 버전의 torch를 함께 깝니다. 11차시에 bitsandbytes · Transformers를 깔아 둔 환경에 vLLM을 얹으면 torch가 바뀌면서 그 환경이 깨질 수 있습니다.
원래도 파이썬 · PyTorch · CUDA 세 개는 따로 고를 수 없습니다. PyTorch는 특정 CUDA 버전에 맞춰 빌드되어 배포되고, PyTorch 버전마다 지원하는 파이썬 버전 범위가 있기 때문입니다(3차시 1절의 사슬). vLLM은 여기에 한 층을 더 얹습니다. vLLM · torch · CUDA 가 한 묶음입니다.
| 환경 이름 (예) | 들어 있는 것 | 쓰는 차시 |
|---|---|---|
.venv (3차시) | transformers, bitsandbytes, 측정 스크립트 | 3, 4, 11, 14 |
.venv-vllm (이번) | vllm (+ vLLM이 고른 torch) | 18~24 |
⭐ 가상환경은 결국 폴더 하나 라서 지우고 다시 만들면 됩니다. 다른 환경에는 아무 영향이 없습니다. 설치가 꼬이면 고치려 애쓰지 말고 .venv-vllm을 지우고 새로 만드는 것이 가장 빠릅니다.
3.2 uv로 만들기
uv — [파이썬 패키지 · 환경 관리자]인데, [ 가상환경 만들기와 패키지 설치를 한 도구로, 빠르게 한다 ]는 점에서 pip · venv · conda와 구별된다.
# uv 설치 (처음 한 번)
curl -LsSf https://astral.sh/uv/install.sh | sh
# vLLM 전용 환경
mkdir -p ~/vllm-lab && cd ~/vllm-lab
uv venv --python 3.12 .venv-vllm
source .venv-vllm/bin/activate
uv pip install vllm --torch-backend=auto # ⚠️ 옵션은 공식 설치 페이지의 현재 명령을 따를 것
🔍 읽는 포인트
.venv-vllm— 환경 이름. 기존.venv와 이름부터 갈라 둡니다.source ... activate뒤에는 터미널 프롬프트 앞에(.venv-vllm)이 붙어야 합니다. 안 붙으면 엉뚱한 곳에 설치됩니다.- 마지막 줄의 옵션(
--torch-backend=auto)은 버전에 따라 다릅니다. AI가 기억으로 쓴 명령 대신 공식 문서(docs.vllm.ai의 Installation → GPU)의 명령을 씁니다.
3.3 설치 확인 한 줄
python -c "import vllm, torch; print(vllm.__version__, torch.__version__, torch.cuda.is_available())"
| 출력 | 뜻 | 다음 행동 |
|---|---|---|
버전 두 개 + True | 정상 | 4절로 |
False | GPU를 못 잡음 | 아래에서 위로 확인: nvidia-smi(드라이버) → torch가 +cpu 빌드인지(3차시 3.3) → CUDA 조합 |
ModuleNotFoundError | 다른 환경에서 실행 중 | (.venv-vllm) 표시부터 확인 |
4. 모델 로딩과 기본 추론 — 오프라인 추론
4.1 첫 코드
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen3-8B", max_model_len=8192) # ① 모델 로딩
params = SamplingParams(temperature=0.2, max_tokens=256) # ② 생성 설정
messages = [
{"role": "system", "content": "너는 쇼핑몰 고객센터 문의를 3줄로 요약하는 도우미다."},
{"role": "user", "content": "주문한 운동화가 일주일째 안 와요. 주문번호 20261128-001입니다. 빨리 확인 부탁드려요."},
]
outputs = llm.chat(messages, params) # ③ 채팅 형식 추론
print(outputs[0].outputs[0].text)
🔍 읽는 포인트
- ①
LLM(...)— 이 한 줄에서 다운로드(처음만) → VRAM 로딩 → KV 캐시 자리 확보 까지 전부 일어납니다. 가장 오래 걸리는 줄입니다.max_model_len은 2차시의 컨텍스트 길이 설정값 입니다. - ②
SamplingParams— 6 · 13차시의 추론 파라미터 입니다.max_tokens는 이번에 생성할 최대 토큰 수. - ③
llm.chat— messages를 모델에 맞는 채팅 템플릿 으로 바꿔 넣어 줍니다. 날 문자열을 넣는llm.generate도 있습니다.
4.2 Ollama에서 배운 것과의 대응
| Ollama (7 · 13차시) | vLLM | 차이 |
|---|---|---|
options.temperature | SamplingParams(temperature=...) | 같음 |
options.num_predict | SamplingParams(max_tokens=...) | 이름만 다름 |
options.num_ctx (요청마다 바꿀 수 있음) | LLM(max_model_len=...) | ⚠️ vLLM은 로딩할 때 한 번 정합니다. 바꾸려면 다시 띄워야 합니다 |
ollama run 첫 실행이 느림 | LLM(...) 줄이 느림 | 둘 다 디스크 → VRAM (0절 축 2) |
⚠️ Qwen3 계열은 출력에 <think> 생각 과정 이 붙을 수 있습니다. 끄는 방법(채팅 템플릿 옵션 enable_thinking 등)은 모델 카드와 vLLM 버전에 따라 다르니 확인 후 씁니다.
4.3 ⚠️ 이건 아직 서빙이 아닙니다
LLM 클래스는 내 스크립트 안에서 모델을 돌리는 방식입니다. 17차시 3.1의 "앱 안에 모델"과 같은 자리입니다. 스크립트가 끝나면 모델도 내려갑니다.
그래도 쓸모가 있습니다. llm.chat에 대화 여러 개를 리스트로 넘기면 엔진이 알아서 묶어 계산합니다. 밤새 문의 1,000통을 요약하는 오프라인 배치 (17차시 1.2)에는 이쪽이 단순합니다. 여러 사람에게 계속 제공하려면 19차시의 vllm serve로 갑니다.
5. 자주 만나는 걸림돌
5.1 ⚠️ Ollama가 이미 GPU를 쓰고 있을 때
Ollama는 설치하면 systemd 서비스로 상주 하고(5차시), 마지막 요청 뒤에도 모델을 기본 5분간 VRAM에 남겨 둡니다 (OLLAMA_KEEP_ALIVE). 그런데 vLLM은 뜰 때 GPU 메모리의 정해진 비율(기본 0.9)을 미리 확보 하려 합니다(19차시). 자리가 없으면 메모리 부족 에러로 로딩이 실패 합니다.
nvidia-smi # 아래 Processes 표에 ollama 가 있는가, 몇 MiB를 쓰는가
ollama ps # 메모리에 올라가 있는 모델
ollama stop qwen3:8b # 그 모델만 내리기
sudo systemctl stop ollama # 서비스째 멈추기 (실습 끝나면 start)
🔍 읽는 포인트 — nvidia-smi 아래쪽 Processes 표가 "누가 VRAM을 쥐고 있나"의 답입니다. 11차시에 쓰던 Jupyter 커널 이 모델을 쥐고 있는 경우도 같습니다(커널 재시작).
| 증상 | 의심 | 확인 |
|---|---|---|
| 로딩 중 메모리 부족 에러, 혼자일 땐 됐는데 | 다른 프로세스가 VRAM 점유 | nvidia-smi Processes |
| 아침엔 되고 오후엔 안 됨 | Ollama가 요청을 받아 모델을 다시 올림 | ollama ps |
| vLLM 띄운 뒤 Ollama가 느려짐 | Ollama 모델이 GPU에 못 올라가 CPU로 밀림 | ollama ps의 PROCESSOR 열 (5차시) |
5.2 모델은 어디에 받아지나 — Hugging Face 캐시
4차시에서 본 그대로, vLLM은 모델을 Hugging Face 캐시 (기본 ~/.cache/huggingface/hub, HF_HOME으로 변경)에 받습니다. 폴더 이름은 models--Qwen--Qwen3-8B 모양입니다.
| Ollama | vLLM | |
|---|---|---|
| 저장 위치 | OLLAMA_MODELS (기본 위치는 설치 방식에 따름) | Hugging Face 캐시 |
| 파일 형식 | GGUF | safetensors (+ config.json, 토크나이저) |
⚠️ 그래서 같은 Qwen3-8B라도 디스크에 두 벌 이 생깁니다. 형식도 다릅니다. 이 차이가 24차시 "공정한 비교"의 함정이 됩니다.
💡 폐쇄망이라면 4차시대로 인터넷 되는 곳에서 받아 반입하고 오프라인 모드(HF_HUB_OFFLINE=1)로 실행합니다. 접근 승인이 필요한 모델은 Hugging Face 로그인 토큰이 필요합니다.
5.3 첫 실행이 느린 이유
LLM(...) 한 줄 안에서 다운로드 → 디스크에서 VRAM으로 로딩 → 엔진 준비(KV 캐시 확보, 내부 최적화 단계) 가 일어납니다. 두 번째부터는 다운로드가 빠지지만 로딩과 준비는 매번 합니다. 앞에서 배운 축 ① 디스크 ↔ 메모리 의 비용입니다. 그래서 운영에서는 한 번 띄워 계속 떠 있게 합니다(19차시).
6. 실습 — 맡기고 검수하기
지시
Linux + NVIDIA GPU 서버에 vLLM 전용 가상환경을 만들고 첫 추론까지 해줘.
맥락: vLLM 공식 문서 설치 페이지(docs.vllm.ai, Installation → GPU)를 먼저 읽고 현재 명령을 따를 것.
기억하고 있는 명령을 쓰지 마.
제약:
- 시스템 파이썬과 기존 가상환경에는 아무것도 설치하지 마. 새 환경 이름은 .venv-vllm.
- 드라이버 · CUDA 재설치가 필요해 보이면 실행하지 말고 이유를 먼저 보고해.
- 시작 전에 nvidia-smi로 GPU를 쓰는 다른 프로세스(특히 ollama, jupyter)가 있는지 확인하고,
있으면 멈추기 전에 나에게 보고하고 승인을 받아.
할 일:
1. 요구사항 확인(OS, nvidia-smi, 파이썬 버전, 디스크 여유)
2. 설치 후 버전 확인 한 줄 실행
3. LLM(model="Qwen/Qwen3-8B", max_model_len=8192) + llm.chat으로 문의 요약 1건
보고 형식: [단계 | 실행한 명령 | 결과 요약 | 출력 원문] 표.
추측하지 말고 실행 출력 원문을 붙여.
받을 증거
- 설치 전후
nvidia-smi출력 원문 - 버전 확인 한 줄의 출력 (
vllm 버전, torch 버전, True) - 로딩 로그 중 모델 가중치가 차지한 메모리 줄과 KV 캐시 관련 줄 (19차시에서 읽는 법을 배웁니다)
- 요약 결과 텍스트
내가 직접 볼 것 — 첫 실행 확인 표
| 볼 것 | 정상이면 | 이걸로 아는 것 |
|---|---|---|
터미널 앞의 (.venv-vllm) | 보임 | 격리된 환경에 설치됨 |
torch.cuda.is_available() | True | GPU 인식 |
실행 전 nvidia-smi Processes | ollama · jupyter 없음 | 충돌 없음 |
| 로그의 가중치 메모리 | 8B × 2바이트 ≈ 16GB 근처 | 9차시 계산과 맞는가 |
~/.cache/huggingface/hub/models--Qwen--Qwen3-8B | 있음 | 모델이 어디에 있는가 |
| 요약 결과 | 한국어, 주문번호 보존 | 모델 · 채팅 템플릿 정상 |
부록 A. 스스로 확인하기
| # | 질문 | 답이 있는 곳 |
|---|---|---|
| 1 | vLLM을 유와 종차로 정의하면? Ollama · Transformers와 무엇으로 갈리는가? | 1.1 |
| 2 | nvidia-smi의 CUDA Version은 무엇을 뜻하는가? | 2 |
| 3 | vLLM을 기존 환경에 깔면 왜 위험한가? | 3.1 |
| 4 | 설치 확인 한 줄의 출력이 False면 어디부터 보는가? | 3.3 |
| 5 | LLM · SamplingParams · llm.chat 세 줄은 각각 무엇을 하는가? | 4.1 |
| 6 | Ollama의 num_ctx와 vLLM의 max_model_len은 무엇이 다른가? | 4.2 |
| 7 | LLM 클래스로 돌리는 것은 왜 아직 서빙이 아닌가? | 4.3 |
| 8 | Ollama가 떠 있을 때 vLLM 로딩이 실패하는 이유와 확인 방법은? | 5.1 |
부록 B. 자주 하는 실수
| 실수 | 바로잡기 |
|---|---|
11차시 환경에 pip install vllm | ❌ torch가 바뀌어 기존 환경이 깨질 수 있음. 전용 환경 |
| AI가 기억으로 쓴 설치 명령을 그대로 실행 | ⚠️ 설치 옵션은 버전마다 바뀜. 공식 설치 페이지 기준 |
| "CUDA Version 12.x니까 툴킷이 깔려 있다" | ❌ 드라이버가 지원하는 최대 버전일 뿐 |
| Ollama를 켜 둔 채 vLLM 실행 | ⚠️ VRAM 선점 충돌. nvidia-smi Processes 먼저 |
| 컨텍스트를 요청마다 바꾸려 함 | ❌ vLLM의 max_model_len은 로딩 시 고정 |
| 설치가 꼬이면 하나씩 고치려 함 | 💡 환경을 지우고 새로 만드는 게 빠름 |
부록 C. NotebookLM 복습 프롬프트
이 18차시 노트만 근거로 5문제를 내줘. 비전공자 기준으로.
"vLLM을 전용 가상환경에 설치하는 이유", "LLM·SamplingParams·llm.chat 세 줄의 역할", "Ollama와 GPU 충돌 진단"은 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.
LangTailor