본문으로 건너뛰기
페이지 목차
이 페이지에서 검색

로컬 LLM

이 페이지에 묻기

로컬 LLM · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.

생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.

LOCAL · LLM

로컬 LLM

생성 수정

로컬 모델 실행과 GPU·메모리 이해부터 서빙·RAG·도구 호출·업무형 앱 구현까지 차례로 살펴봅니다.

42개 문서 · 1일차 · 5 / 42

4차시 · Hugging Face 오픈소스 LLM 활용

지도 위치 : 1일차 · ②모델 파일 층 + ③추론 엔진(Transformers) | 이전: 3차시 개발환경 구축 | 다음: 5차시 Ollama 설치 및 LLM 실행 키워드 : Hugging Face Hub, 모델 탐색 · 다운로드, Transformers 모델 로딩, Tokenizer 및 텍스트 생성

이 차시를 다 읽으면

  1. Hugging Face Hub와 내려받은 모델 파일을 로컬 ↔ 원격 축에 꽂고, Git ↔ GitHub · Docker ↔ Docker Hub와 같은 모양의 세 번째 쌍 임을 말할 수 있다.
  2. 모델 카드에서 확인할 여섯 항목 (라이선스, Base/Instruct, 크기, 컨텍스트, 언어, 사용 예시)을 찾을 수 있다.
  3. 모델 폴더의 config.json · 토크나이저 파일 · .safetensors가 각각 무엇을 담는지 말할 수 있다.
  4. Transformers 로딩 코드에서 device_map, apply_chat_template, max_new_tokens 줄을 알아보고 무슨 일을 하는지 말할 수 있다.
  5. 채팅 템플릿 을 빼먹으면 왜 답이 이상해지는지 설명할 수 있다.

0. 이 차시의 판별 축

#축왼쪽 (0)오른쪽 (1)이 축으로 갈리는 것큰 축 (README 5장)
1어디에 있는가로컬 (내 디스크의 모델 파일)원격 (Hugging Face Hub)hf download = pull④ 로컬 ↔ 원격
2어디에 있는가 (내 컴퓨터 안)디스크 (파일)메모리 (로드된 모델)다운로드 ↔ from_pretrained① 디스크 ↔ 메모리
3구조인가 값인가config.json (설계)가중치 .safetensors (값)층 수 · 헤드 수 ↔ 80억 개의 숫자② 추상 ↔ 구상

1차시에서 "공개 가중치 모델은 모델 파일을 내려받을 수 있다 "고 했습니다(1차시 0절 축 2). 이 차시의 질문은 "그 파일을 어디서, 어떻게 받아서, 무엇으로 열어 실행하는가" 입니다. 받는 곳이 Hugging Face Hub(1절), 받은 파일의 구성이 2절, 그것을 열어 실행하는 도구가 Transformers(3절)입니다.

⚠️ 축 1과 축 2를 섞지 마세요. 다운로드(인터넷 너머 → 내 디스크) 와 로드(내 디스크 → 내 GPU 메모리) 는 다른 동작입니다. 다운로드가 끝났다고 모델이 실행 준비가 된 것이 아니고, 로드가 실패했다고 다운로드가 잘못된 것도 아닙니다.


1. Hugging Face Hub — 유통망

1.1 정의와 자리

Hugging Face Hub — [모델 저장소 플랫폼]인데, [ 가중치 파일과 모델 카드 · 데이터셋을 조직/모델명 이름으로 등록해 내려받게 한다 ]는 점에서 코드 저장소인 GitHub와 구별된다.

같은 모양의 세 쌍 — 로컬 저장 ↔ 원격 유통망

Hugging Face Hub는 처음 보는 낯선 것이 아니라, 개발 세계에 이미 있는 같은 모양 의 세 번째 사례입니다.

로컬 (내 컴퓨터)원격 (공유 저장소)무엇을 주고받나
Git — 내 컴퓨터에서 코드의 변경 이력을 관리하는 도구GitHub — 그 이력을 올려 두고 남과 공유하는 사이트코드
Docker — 프로그램과 실행 환경을 한 덩어리(이미지)로 묶어 실행하는 도구 (5차시 2.3)Docker Hub — 그 이미지를 올려 두고 내려받는 사이트실행 환경 이미지
내 디스크의 모델 폴더 + Transformers · Ollama · vLLMHugging Face Hub모델 가중치

세 쌍 모두 동작 이름이 같습니다. 원격에서 내 컴퓨터로 가져오는 것이 pull (내려받기), 내 것을 원격에 올리는 것이 push 입니다. 이 과정에서는 거의 pull만 합니다.

⭐ 이 대칭에서 기억할 한 가지는 저장소와 실행 장소가 다르다 는 것입니다. GitHub에 코드가 있다고 그 코드가 GitHub에서 돌아가는 것이 아니듯, Hub에 모델이 있다고 Hub에서 실행되는 것이 아닙니다. 실행은 내려받은 뒤 내 컴퓨터의 엔진 이 합니다. 그래서 역할을 이렇게 나눕니다.

엔진 (로컬)유통망 (원격)
이 과정에서Transformers · Ollama · vLLM이 모델을 실행Hugging Face Hub가 모델을 배포
이름 붙이는 단위내 폴더 경로Qwen/Qwen3-8B (조직/모델명)
내리는 동작—hf download, from_pretrained() = pull

⚠️ 반례 — 이건 Hub의 역할이 아닙니다

대상왜 다른가
Hugging Face Spaces데모 앱을 실행 해 주는 곳. 위에서 본 대로 보관(저장소)과 실행은 다른 역할 이고, Spaces는 실행 쪽
Hugging Face의 유료 추론 API남의 서버에서 실행 = 원격 추론 . 데이터가 밖으로 나감. 이 과정의 "로컬"이 아님

1.2 ⭐ 모델 카드에서 확인할 여섯 항목

모델 페이지 첫 화면이 모델 카드(Model Card) 입니다. 문의봇에 쓸 후보를 고를 때 이 여섯 줄을 봅니다.

항목어디서 보나왜 보나
라이선스페이지 오른쪽 · LICENSE 파일상업적 사용 조건이 모델마다 다름 (1차시 2.1)
Base / Instruct모델 이름 · 카드 설명Base는 글 이어쓰기 용, Instruct(또는 Chat)는 지시 따르기 용. 문의봇은 Instruct 계열
크기이름의 8B · Files 탭의 용량VRAM 계산의 출발점 (3차시 4.1)
컨텍스트 길이카드 본문 · config.json긴 문의 메일이 들어가는가 (2차시 3절)
언어카드의 지원 언어한국어는 직접 평가 해야 함 (6차시)
사용 예시 코드카드의 Quickstart필요한 라이브러리 버전 과 권장 생성 설정

⚠️ Base와 Instruct는 이름만 다른 같은 모델이 아닙니다. Base에게 "이 문의를 분류해줘"라고 하면 지시를 따르지 않고 비슷한 글을 계속 이어 쓰기 쉽습니다. Qwen3처럼 한 모델이 두 역할을 겸하는 경우도 있으니 카드에서 확인합니다.

1.3 Gated 모델과 토큰

Gated 모델 — [공개 가중치 모델]인데, [ 페이지에서 약관에 동의하고 승인을 받아야 내려받을 수 있다 ]는 점에서 누구나 바로 받는 모델과 구별된다. Llama · Gemma 계열이 대표적입니다(정책은 바뀔 수 있으니 페이지 확인).

받으려면 액세스 토큰 이 필요합니다.

hf auth login            # 토큰 입력 (구버전 CLI: huggingface-cli login)
# 또는 환경변수로
export HF_TOKEN=hf_xxxxxxxx

⚠️ 이 토큰은 비밀값(secret) 입니다. 비밀번호처럼 "가진 사람이 곧 나"로 인정받는 문자열이라, 남에게 보이면 내 계정으로 모델을 받거나 올릴 수 있습니다. 그래서 세 가지를 지킵니다.

  • 코드에 직접 쓰지 않는다 — 코드는 공유되고 복사됩니다.
  • Git에 올리지 않는다 — 한 번 올라간 값은 이력에 남아 지우기 어렵습니다.
  • 환경변수나 .env 파일로만 다룬다 — 환경변수 는 프로그램 바깥(운영체제의 실행 환경)에 넣어 두고 프로그램이 이름으로 꺼내 쓰는 값이고, .env 는 그 값들을 이름=값 줄로 적어 둔 파일입니다. .env는 Git에서 제외하고, 어떤 이름이 필요한지만 적은 빈 견본(.env.example)을 대신 공유합니다.

그리고 2차시 1절에서 짚었듯 LLM의 토큰(글 조각)과는 같은 철자, 다른 범주 입니다.


2. 모델 폴더 안을 열어 보기

2.1 파일 구성

Qwen/Qwen3-8B를 내려받으면 대략 이런 파일들이 생깁니다. (정확한 목록은 Files 탭에서 확인)

Qwen3-8B/
├── config.json                          ← 구조: 층 수, 헤드 수, 최대 위치 등   (축 3 왼쪽)
├── generation_config.json               ← 권장 생성 설정 (temperature 등 기본값)
├── tokenizer.json / tokenizer_config.json / vocab.json / merges.txt
│                                        ← 토크나이저 + ⭐ 채팅 템플릿
├── model-00001-of-0000N.safetensors     ← 가중치 (여러 조각으로 나뉨)     (축 3 오른쪽)
├── model.safetensors.index.json         ← 어떤 가중치가 어느 조각에 있는지
├── LICENSE
└── README.md                            ← 모델 카드
파일정의기억 고리
config.json[모델 설정 파일]인데, [ 층 수 · 헤드 수 같은 구조만 적고 값은 없다 ]는 점에서 가중치 파일과 구별된다설계도 — 건물의 층수와 방 배치만 적혀 있고 벽돌은 없음
*.safetensors[가중치 파일 형식]인데, [ 코드 실행 없이 숫자(텐서)만 읽는다 ]는 점에서 pickle 기반 .bin과 구별된다이름 그대로 "safe + tensors" (아래 설명)
토크나이저 파일글 ↔ 토큰 번호 사전 + 채팅 템플릿2차시 2절 ① 단계

⚠️ 왜 "safe"인가 — 예전 형식인 .bin은 Python의 pickle (파이썬 객체를 통째로 파일에 저장하는 방식)로 만들어졌습니다. pickle 파일은 불러오는 순간 그 안에 심어 둔 코드가 실행될 수 있습니다. 즉 남이 올린 모델 파일을 여는 것만으로 내 컴퓨터에서 악성 코드가 돌 수 있습니다. safetensors 는 숫자 배열과 그 모양 정보만 담도록 형식을 제한해, 읽기만 하고 실행은 하지 않습니다. 인터넷에서 받은 가중치는 가능하면 .safetensors 판을 고릅니다.

⭐ 축 3이 여기서 보입니다. config.json은 몇 KB짜리 구조 이고, .safetensors는 수 GB짜리 값 입니다. 같은 config.json에 다른 가중치를 넣으면 다른 모델(파인튜닝 버전)이 됩니다. 모델은 "어떤 모양으로 계산하는가"(구조) 와 "그 계산에 어떤 숫자를 쓰는가"(학습으로 정해진 가중치) 의 두 반쪽으로 이루어지는데, 그 두 반쪽이 파일로 나뉘어 있는 것입니다.

앞으로 다시 만납니다 — 9차시에서 config.json의 num_hidden_layers, num_key_value_heads를 읽어 KV 캐시 크기를 직접 계산 합니다. 그때 이 파일을 다시 엽니다.

2.2 내려받기와 저장 위치

hf download Qwen/Qwen3-8B                              # 기본 캐시 위치로
hf download Qwen/Qwen3-8B --local-dir ./models/qwen3-8b # 지정한 폴더로

🔍 읽는 포인트 : hf download 다음이 조직/모델명 . --local-dir이 있으면 그 폴더에, 없으면 캐시 폴더 에 받습니다. 구버전에서는 huggingface-cli download였습니다 — 설치된 버전에 따라 명령 이름이 다르니 hf --help로 확인합니다.

환경변수뜻언제 쓰나
HF_HOMEHugging Face 캐시의 최상위 폴더 (기본은 홈 아래 .cache/huggingface)홈 디스크가 작을 때 큰 디스크로 옮김
HF_TOKEN액세스 토큰gated 모델
HF_HUB_OFFLINE=1인터넷에 묻지 않고 캐시에 있는 파일만 씀⭐ 폐쇄망

⭐ 폐쇄망에서 (1차시 4.2): 인터넷 되는 곳에서 hf download로 받아 폴더째 반입 → 같은 HF_HOME 구조로 두거나 --local-dir 경로를 그대로 쓰고 → HF_HUB_OFFLINE=1을 켭니다. 이걸 안 켜면 라이브러리가 Hub에 확인 요청을 보내다 시간 초과로 멈춘 것처럼 보입니다.


3. Transformers로 로드하고 생성하기

3.1 코드 — 모델 카드의 예시를 그대로

Transformers — [Python 라이브러리]인데, [ Hub의 모델을 이름 하나로 불러와 PyTorch 위에서 실행한다 ]는 점에서 서빙 엔진(Ollama · vLLM)과 구별된다. 한 번 실행해 보는 추론(Inference) 도구이지, 여러 사람에게 제공하는 서빙 도구가 아닙니다(17차시).

from transformers import AutoTokenizer, AutoModelForCausalLM

name = "Qwen/Qwen3-8B"
tokenizer = AutoTokenizer.from_pretrained(name)
model = AutoModelForCausalLM.from_pretrained(
    name,
    torch_dtype="auto",        # config에 적힌 정밀도 그대로 (예: BF16)
    device_map="auto",         # GPU에 자동 배치, 모자라면 CPU로 나눔
)

messages = [
    {"role": "system", "content": "당신은 쇼핑몰 고객센터 문의를 요약하는 도우미입니다."},
    {"role": "user", "content": "주문한 신발이 일주일째 안 와요. 주문번호 20261128-001입니다."},
]
text = tokenizer.apply_chat_template(
    messages, tokenize=False, add_generation_prompt=True,
    enable_thinking=False,     # Qwen3 전용 옵션: 생각 모드 끄기
)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=256)
print(tokenizer.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))

🔍 읽는 포인트

줄알아볼 것0절 축
from_pretrained(name)캐시에 없으면 내려받고 (pull), 있으면 디스크에서 메모리로 올림 (load)축 1 + 축 2
torch_dtype="auto"정밀도. 최신 버전은 이름이 dtype으로 바뀌는 중 — 경고가 뜨면 버전 확인2일차 정밀도
device_map="auto"GPU에 다 안 들어가면 일부를 CPU/RAM으로 조용히 나눔 → 느려짐. accelerate 필요① VRAM ↔ RAM (12차시)
apply_chat_template⭐ messages를 모델이 학습한 대화 형식의 글 로 바꿈 (3.2절)⑧ 구문
add_generation_prompt=True"이제 assistant 차례"라는 표시를 끝에 붙임
max_new_tokens=256새로 생성할 토큰의 상한. 입력은 포함 안 함2차시 3절
out[0][inputs...shape[1]:]출력에는 입력이 앞에 붙어서 나옴 → 입력 길이만큼 잘라 냄

3.2 ⭐ 채팅 템플릿 — 왜 빼먹으면 안 되는가

LLM은 결국 글 한 줄을 이어 쓰는 기계입니다(1차시 1.2). messages 배열(역할 · 내용)을 그대로 이해하지 못합니다. 그래서 모델마다 학습 때 쓴 특수 표시 로 대화를 한 줄 글로 펼쳐야 합니다.

[messages 배열]                       [apply_chat_template 결과 — 모양은 모델마다 다름]
system: 당신은 ...도우미입니다          <|im_start|>system
user:   주문한 신발이 ...       ───▶    당신은 ...도우미입니다<|im_end|>
                                       <|im_start|>user
                                       주문한 신발이 ...<|im_end|>
                                       <|im_start|>assistant          ← add_generation_prompt

채팅 템플릿 (Chat Template) — [입력 변환 규칙]인데, [ 역할별 메시지를 그 모델이 학습한 특수 토큰 형식의 글로 펼친다 ]는 점에서 모델과 무관한 일반 문자열 결합과 구별된다. 템플릿은 토크나이저 설정 파일에 들어 있습니다.

템플릿을결과
⭕ 썼다모델이 "지금 assistant로서 답할 차례"임을 앎
❌ 안 쓰고 문자열을 그냥 붙였다에러는 안 남 . 대신 질문을 되풀이하거나, user 역할까지 지어 쓰거나, 끝나지 않음
❌ 다른 모델의 템플릿을 썼다같은 증상. 형식(구문)이 틀려서 뜻(의미)이 무너짐 — ⑧ 축

⭐ 이 문제는 추론에서만 생기지 않습니다. 내 데이터로 모델을 추가 학습시키는 파인튜닝 (README 1.2)에서도 학습 데이터가 그 모델의 대화 템플릿 형식과 맞아야 합니다. 학습이든 추론이든 템플릿이 틀리면 에러 없이 결과만 이상해집니다.

앞으로 다시 만납니다 — 5차시 Ollama와 19차시 vLLM은 이 템플릿을 엔진이 알아서 적용합니다(GGUF 파일이나 토크나이저 설정에 들어 있음). 그래서 API에는 messages만 보내면 됩니다. 12차시에서 GGUF를 직접 가져올 때 템플릿이 빠지면 같은 증상이 다시 나타납니다.

3.3 ⚠️ Qwen3의 생각 모드

Qwen3 계열은 답 앞에 <think> ... </think>로 생각 과정을 먼저 출력 하는 모드가 있습니다. 끄지 않으면:

  • 문의봇 응답에 생각 과정이 그대로 섞여 나옴
  • 생각에 토큰을 써서 max_new_tokens 안에 본 답이 시작도 못 하고 잘림

끄는 방법은 엔진마다 다릅니다 — Transformers는 위 코드의 enable_thinking=False, 프롬프트에 /no_think를 붙이는 방식, Ollama의 think 옵션(5 · 7차시) 등. 모델 카드와 엔진 버전 문서에서 확인 합니다. 이름에 "생각"이 들어 있지만 이 과정의 추론(Inference) 과는 다른 이야기입니다(2차시 1절 Reasoning).


4. 실습 — 맡기고 검수하기

지시

목표: 가상환경 llm-hf에서 Qwen/Qwen3-8B를 내려받아 Transformers로 로드하고,
      고객 문의 3건을 요약시켜줘.
맥락: Hugging Face의 Qwen/Qwen3-8B 모델 카드의 Quickstart 코드를 기준으로 해.
      기억하는 옛 API 말고 카드의 코드와 설치된 transformers 버전을 따라.
제약: - 모델은 HF_HOME=/data/hf 아래에 받아.
      - 채팅 템플릿(apply_chat_template)을 반드시 써. 생각 모드는 꺼.
      - max_new_tokens=256 고정.
보고 형식:
  표1 [파일명 | 크기] — 받은 폴더의 파일 목록
  표2 [항목 | 값] — config.json의 num_hidden_layers, num_attention_heads,
        num_key_value_heads, max_position_embeddings, torch_dtype
  표3 [문의 | 요약 결과 | 생성 토큰 수 | 걸린 시간(초)]
  그리고 로드 직후 nvidia-smi의 Memory-Usage.
추측하지 말고 실행 출력 원문을 붙여.

받을 증거

  • 파일 목록과 config.json 원문 값 (기억으로 채운 숫자는 무효)
  • 생성 결과 원문과, 템플릿을 적용한 뒤의 글(text) 한 건
  • 로드 직후 nvidia-smi 원문

내가 직접 볼 것

볼 것이걸로 아는 것
.safetensors 크기의 합8B × 2바이트 ≈ 16GB 계산과 맞는가 (3차시 4.1)
로드 직후 Memory-Usage가중치보다 조금 더 쓰는가 → 그 차이가 9차시의 "오버헤드"
템플릿 적용 후 글의 특수 표시채팅 템플릿이 실제로 적용됐는가
요약 결과에 <think>가 없는가생각 모드가 꺼졌는가
주문번호가 정확히 옮겨졌는가2차시 실습의 "숫자 쪼개짐"이 실제로 문제가 되는가

부록 A. 스스로 확인하기

#질문답이 있는 곳
1Hugging Face Hub는 Git ↔ GitHub, Docker ↔ Docker Hub와 어떻게 같은 모양이고, 엔진인가 유통망인가?1.1
2다운로드와 from_pretrained의 로드는 각각 어느 축인가?0, 3.1
3모델 카드에서 확인할 여섯 항목은?1.2
4Base 모델에 지시를 주면 어떻게 되기 쉬운가?1.2
5config.json과 .safetensors는 각각 무엇을 담는가? safetensors는 왜 "safe"인가?2.1
6폐쇄망에서 켜야 하는 환경변수와 이유는?2.2
7device_map="auto"가 조용히 하는 일은?3.1
8채팅 템플릿을 안 쓰면 어떤 증상이 나는가?3.2
9Qwen3 생각 모드를 끄지 않으면 생기는 문제 두 가지는?3.3

부록 B. 자주 하는 실수

실수바로잡기
"Hugging Face에서 돌리면 로컬이다"❌ 유료 추론 API · Spaces는 원격 실행 . 내려받아 내 GPU에서 돌려야 로컬
"다운로드했으니 이제 메모리에 있다"❌ 다운로드는 디스크까지 . 로드해야 메모리(VRAM)
"토큰을 코드에 넣어 두면 편하다"❌ 비밀값 . 환경변수 · .env로 (1.3)
".bin이든 .safetensors든 똑같다"⚠️ pickle 기반 .bin은 여는 순간 코드가 실행될 수 있음 . 받은 파일은 safetensors 판 우선
"messages를 문자열로 이어 붙여 넣으면 된다"❌ 채팅 템플릿 을 거쳐야 함. 에러 없이 품질만 무너짐
"max_new_tokens는 입력+출력 합계"❌ 새로 생성하는 토큰만. 합계 상한은 컨텍스트 길이
"huggingface-cli가 없다고 나온다 → 설치 실패"⚠️ 신버전은 hf 명령. 버전 확인
"Instruct든 Base든 같은 모델"❌ 업무용은 Instruct 계열부터

부록 C. NotebookLM 복습 프롬프트

이 4차시 노트만 근거로 6문제를 내줘. 비전공자 기준으로.
"다운로드(로컬↔원격)와 로드(디스크↔메모리)의 구별", "config.json과 safetensors", "채팅 템플릿"은 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.