5장 — 로컬 및 오픈소스 LLM 활용: Ollama와 허깅 페이스

AI 애플리케이션은 대부분 OpenAI, 앤트로픽, 구글 같은 상용 LLM에 의존합니다. 강력한 성능과 편리한 API 덕분에 빠르게 개발할 수 있지만 보안·비용·확장성 측면에서 제약이 따릅니다. 사내 기밀 데이터나 개인정보를 외부 API로 전송해야 하는 상황은 법률·규제·보안·정책에 걸림돌이 되고, 대규모 호출이 필요한 서비스라면 API 요금이 곧 비용 압박이 됩니다.

그 대안이 오픈소스 LLM입니다. 로컬 환경이나 자체 서버에 배포할 수 있어 데이터가 외부로 유출되지 않는 온프레미스 혹은 온디바이스 환경을 구현할 수 있고, 모델 구조와 파라미터가 공개되어 커스터마이징이 가능하며, API 호출 비용이 없거나 매우 저렴합니다. 특히 상용 모델과의 성능 격차가 빠르게 줄고 있어 적절한 선택과 튜닝만으로도 실무 적용이 가능합니다.

이 장은 두 가지 방식을 다룹니다.

  특징
Ollama 로컬에서 LLM을 간편하게 실행하는 플랫폼. 복잡한 배포 과정 없이 DeepSeek, Llama, Qwen 같은 최신 모델을 바로 쓸 수 있고, GPU 없이도 작은 모델을 구동할 수 있다
허깅 페이스 전 세계 연구자와 기업이 공유하는 방대한 AI 모델 허브. Ollama에서 지원하지 않는 모델도 직접 다운로드해 로컬이나 서버에서 구동할 수 있다

Ollama로 로컬 LLM 쓰기

Ollama의 핵심 목적은 LLM 접근성을 높이고 개인정보 보호를 강화하는 것입니다. 인터넷 연결 없이 오프라인에서도 실행되고, 데이터를 전송하지 않기 때문에 데이터 보안이 중요한 기업이나 개인에게 적합합니다. 모델 배포나 성능 최적화에 신경 쓰지 않아도 되도록 회사 자체에서 모델을 관리·유지보수해 최적화된 성능을 제공하는 것도 특징입니다.

어떤 모델이 있나

2024년 9월 Weights & Biases가 공개한 ‘Horangi 한국어 LLM 리더보드’에서 상위권에 오른 DeepSeek-R1, Qwen2.5-72B-Instruct, Llama-3.1-405B-Instruct를 비롯해, 2025년 8월 OpenAI가 오픈소스로 공개한 gpt-oss도 Ollama에서 쉽게 쓸 수 있습니다.

DeepSeek에 대한 책의 언급이 인상적입니다. 약 560만 달러의 투자로 개발되었는데, GPT-4의 개발 비용인 약 5억 달러와 비교하면 1% 수준입니다. 그런데도 다양한 벤치마크에서 GPT-4에 근접하는 성능을 보여 주며 주목받고 있습니다.

설치와 모델 내려받기

Ollama는 macOS, 리눅스, 윈도우를 모두 지원합니다. 설치 후 모델을 받는 방식은 깃허브에서 저장소를 클론하는 것과 비슷합니다.

ollama pull exaone3.5:2.4b

모델 선택에 대한 조언이 실용적입니다. 로컬에서 테스트한다면 가장 작은 모델부터 시도해 보는 것을 추천합니다. 파라미터가 많을수록 성능은 좋지만 GPU가 없으면 추론에 너무 많은 시간이 걸립니다. 파라미터가 가장 많은 deepseek-r1:671b는 벤치마크 성능이 gpt-o1과 유사하다고 알려졌지만 용량이 400GB를 초과해 로컬 구동에는 부담이 있습니다.

2025년 2월 기준 Ollama에서 공식적으로 한국어를 지원하는 모델은 LG AI Research의 EXAONE 3.5가 유일합니다. 이전 모델인 EXAONE 3.0은 허깅 페이스에서만 쓸 수 있었습니다.

ChatOllama로 연결하기

LangChain에서는 ChatOllama 클래스로 Ollama를 씁니다. 상용 LLM처럼 회사 이름으로 패키지를 구성하지 않고 langchain-community 패키지에서 가져온다는 점이 다릅니다. 모델 이름만 바꾸면 다른 모델로 쉽게 전환할 수 있습니다.

from langchain_community.chat_models import ChatOllama

llm = ChatOllama(model="exaone3.5:2.4b")
ai_message = llm.invoke("RAG 파이프라인은 무엇인가요?")
ai_message

작은 모델의 엉뚱한 답변, 그리고 보정

여기서 책이 솔직한 실패를 보여 줍니다. 위 질문에 EXAONE 3.5 2.4B는 RAG를 ‘Robust Adversarial Generative’ Pipeline이라고 풀이하며, LG AI Research가 개발한 고성능 언어 모델 학습 프레임워크라는 엉뚱한 답변을 생성했습니다.

원인은 모델이 작아서입니다. 해법은 간단합니다. 프롬프트에 RAG가 무엇인지 설명하는 식으로 문맥을 추가해 조금 더 자세히 작성하는 것입니다.

llm = ChatOllama(model="exaone3.5:2.4b")
ai_message = llm.invoke("Retrieval-Augmented Generation(RAG) Pipeline은 무엇인가요?")

약어를 풀어 쓰는 것만으로 지식베이스와 생성 모델, 작동 방식까지 제대로 설명하는 답변이 나옵니다. 문맥을 조금 더 자세히 작성하면 원하는 결과를 얻어낼 수 있다는 것이 요지입니다.

한국어 성능에 대한 반전

책은 여기서 흥미로운 지적을 합니다. EXAONE 3.5와 추론 모델 exaone-deep을 제외하면 Ollama에서 공식적으로 한국어를 지원하는 모델은 없습니다. 그런데 한국어 LLM 리더보드를 보면 이렇습니다.

  • 공식적으로 한국어를 지원하는 claude-3-opus나 gpt-4o-mini보다 Qwen2.5, Llama3.1 등이 한국어 이해 능력이 더 뛰어나다.
  • MarkerAI가 공개한 수능 국어 LLM 리더보드에 따르면, 상용 LLM인 앤트로픽 Claude Haiku 4.5보다 Llama3.1-405B가 수능 국어 문제 해결에 더 좋은 성과를 보인다.

따라서 Ollama는 여전히 쓸 만한 값어치가 있습니다. 다만 꼭 한국어를 지원하는 오픈소스 LLM을 써야 한다면 허깅 페이스 쪽이 적절합니다.

허깅 페이스의 오픈소스 LLM

LangChain을 쓴다면 langchain-huggingface 패키지로 허깅 페이스 모델을 내려받고, ChatOpenAI·ChatOllama와 유사한 ChatHuggingFace 로 LangChain의 기능과 연결할 수 있습니다.

중요한 차이가 하나 있습니다. Ollama는 양자화된 모델이라 작은 모델은 GPU 없이도 어느 정도 구동되지만, 허깅 페이스의 모델은 GPU가 없으면 답변 생성에 너무 많은 시간이 걸립니다. 그래서 책은 허깅 페이스 실습을 구글 코랩에서 진행합니다.

2025년 2월 기준 저자가 업무 질의로 테스트했을 때 우리말 성능이 가장 좋았던 모델은 LG의 LGAI-EXAONE/EXAONE-3.0 이었습니다.

새 모델이 나와도 바로 갈아타지 않는 이유

이 대목이 실무적으로 값집니다.

새로운 오픈소스 LLM이 출시되더라도 기존 모델을 계속 사용하는 이유는, 해당 모델에 최적화된 프롬프트와 워크플로가 이미 존재하기 때문입니다. LLM 성능이 아무리 뛰어나도 응답 방식이 예측되지 않는 상황에서 단순히 벤치마크 성능만 보고 모델을 교체하는 것은 운영 중인 서비스에 위험이 될 수 있습니다.

상용 LLM은 신규 모델이 더 저렴하거나 비용 효율이 높다면 빠르게 전환하는 것이 합리적입니다. 그러나 오픈소스 모델은 동일한 인프라에서 추론 비용 차이가 크지 않기 때문에, 프롬프트 재설계와 테스트 리스크를 고려하면 굳이 빠르게 전환할 필요가 없습니다.

새 모델을 도입할 때 함께 볼 실무 요소도 정리되어 있습니다. API 호환성, 양자화 포맷 지원, 추론 지연, VRAM 요구사항 — 충분히 검증한 뒤 점진적으로 도입하는 것이 바람직합니다.

참고로 오픈소스 모델의 한국어 성능 비교 표에서는 F-score 기준 HCX SEED 14B(35.1) 가 가장 높고, EXAONE 3.5 32B(30.1), kanana 1.5 8B(29.8), gemma 3 27B(29.6)이 뒤를 잇습니다. 같은 계열이라도 파라미터가 커질수록 점수가 뚜렷하게 오릅니다.

액세스 토큰 세 가지

모델을 내려받으려면 액세스 토큰이 필요합니다. 종류가 셋입니다.

토큰 용도
Fine Grained 특정 모델·데이터셋·스페이스 등 리소스 단위로 권한을 세부 설정. 최소 권한의 원칙(PoLP) 에 기반한 보안 설정이 필요한 환경에 유용하다. 배포 자동화처럼 오류를 최소화해야 하거나 여러 사람이 협업하는 환경에 추천
Read 모델·데이터셋·스페이스를 읽기 전용으로 접근. 비공개 저장소도 이 토큰으로 다운로드할 수 있다. 모델 추론·다운로드·분석 등 조회 목적에 적합
Write 읽기와 쓰기 모두 가능. 모델 업로드, 파일 수정, 커밋 등 변경 작업 포함. 단 저장소 삭제나 권한 변경은 불가능하므로 관리자 권한은 포함되지 않는다

모델을 내려받아 활용할 것이므로 Read 토큰을 발급합니다. 구글 코랩에서는 좌측 탭의 열쇠 아이콘에서 HF_TOKEN 이라는 이름으로 등록합니다. OPENAI_API_KEY와 마찬가지로, 이 이름으로 등록해 두면 모델을 불러올 때마다 환경변수를 명시적으로 선언하지 않아도 됩니다. 여기에 등록한 환경변수는 코랩의 모든 공간에서 공유되므로 코랩을 만들 때마다 입력하는 번거로움도 줄어듭니다.

모델 불러오기

import torch
from langchain_huggingface import ChatHuggingFace, HuggingFacePipeline

# 디바이스 설정: GPU가 있으면 0, 없으면 -1(CPU)
device = 0 if torch.cuda.is_available() else -1

chat_model = HuggingFacePipeline.from_model_id(
    model_id="LGAI-EXAONE/EXAONE-3.0-7.8B-Instruct",
    task="text-generation",
    model_kwargs=dict(
        # 모델 리포지터리에 포함된 커스텀 코드의 실행을 허용한다.
        trust_remote_code=True
    ),
    pipeline_kwargs=dict(
        max_new_tokens=1024,      # 생성할 최대 토큰 수
        do_sample=False,          # 샘플링 비활성화(결정적 생성)
        repetition_penalty=1.03,  # 반복 페널티
    ),
    device=device
)

권한이 없다는 오류가 발생하면 허깅 페이스의 모델 상세 페이지에서 권한을 요청해야 합니다. EXAONE은 바로 쓸 수 있지만, 모델에 따라 최대 24시간까지 걸릴 수 있습니다.

불러온 파이프라인을 ChatHuggingFace에 전달하면 LangChain 문법을 그대로 쓸 수 있습니다.

llm = ChatHuggingFace(llm=chat_model)
llm.invoke("RAG 파이프라인은 무엇인가요?")

ChatHuggingFaceChatOpenAIChatOllama와 다르게 HuggingFacePipeline으로 모델을 먼저 불러와 llm 인수로 넘겨야 하는 이유는, 허깅 페이스를 쓰는 방법이 두 가지이기 때문입니다. 로컬로 내려받는 방식 외에 Serverless API(Inference Endpoints) 로 API처럼 호출하는 방식도 있습니다.

from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint

llm = HuggingFaceEndpoint(
    endpoint_url="<endpoint_url>",
    task="text-generation",
    max_new_tokens=1024,
    do_sample=False,
)
llm_engine_hf = ChatHuggingFace(llm=llm)
llm_engine_hf.invoke("Hugging Face is")

다만 우리나라는 보안이나 법률 문제로 내부 데이터 유출이 문제가 되는 일이 많아, 책의 실습은 로컬 다운로드 방식으로 진행합니다.

양자화는 선택이 아니다

허깅 페이스에서 LLM을 쓸 때 중요한 것이 양자화(quantization) 입니다. FP32, FP16처럼 높은 정밀도로 훈련된 모델의 수치를 8비트 정수 같은 낮은 정밀도로 변환해 모델 크기를 줄이고 추론 속도를 높이는 최적화 방법입니다.

효과와 필요성이 구체적입니다.

  • 모델 크기를 최대 75%까지 줄일 수 있고, 메모리 사용량이 감소하며 추론 속도가 향상된다.
  • 저자 경험상 7B 이상의 LLM을 내려받아 구동하면 답변 생성에 약 2분 넘는 시간이 걸린다. 챗봇이 이만큼 걸리면 사용자 경험이 나빠지므로 양자화는 필수다.
from transformers import BitsAndBytesConfig
from langchain_huggingface import ChatHuggingFace, HuggingFacePipeline
import torch

# 4비트 양자화 설정
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype="float16",
    bnb_4bit_use_double_quant=True,
)
옵션 의미
load_in_4bit=True 4비트 양자화를 활성화한다
bnb_4bit_quant_type="nf4" 노멀 플로트 4비트 양자화 방식을 사용한다
bnb_4bit_compute_dtype="float16" 연산 시 float16 타입을 사용해 메모리를 절약한다
bnb_4bit_use_double_quant=True 이중 양자화로 메모리를 추가 절약한다

설정한 옵션은 model_kwargs={"quantization_config": quantization_config}로 모델을 로드할 때 함께 전달합니다. 7.8B 파라미터의 큰 모델도 4비트 양자화를 적용해 효율적으로 로드할 수 있습니다.

결과는 명확합니다. 답변의 품질에는 크게 차이가 없지만 생성 시간이 최대 3배까지 차이 날 수 있고, 이 차이는 모델이 클수록 더 크게 벌어집니다. 온디바이스 AI가 주목받으면서 모델 경량화와 양자화가 더 부각되는 이유입니다.

정리

  • 오픈소스 LLM은 보안(데이터 미유출)·비용·커스터마이징 때문에 고른다. Ollama는 로컬 실행, 허깅 페이스는 모델 허브다.
  • 작은 모델이 엉뚱한 답을 내면 모델을 바꾸기 전에 프롬프트에 문맥을 더해 본다. 약어를 풀어 쓰는 것만으로도 달라진다.
  • 공식 한국어 지원 여부와 실제 한국어 실력은 다르다. 리더보드에서는 Qwen2.5·Llama3.1이 상용 모델을 앞서기도 한다.
  • 벤치마크만 보고 모델을 갈아타지 않는다. 프롬프트와 워크플로가 기존 모델에 최적화되어 있기 때문이며, 오픈소스는 추론 비용 차이도 작다.
  • 허깅 페이스 토큰은 목적에 맞게 고른다. 다운로드 용도라면 Read, 협업·자동화라면 Fine Grained.
  • 7B 이상이면 양자화는 필수다. 품질은 그대로인데 생성 시간이 최대 3배 갈린다.