테마 전환

LangChain + Ollama 통합 실전: 로컬 LLM 애플리케이션 개발 완벽 가이드

Easton editorial illustration: MCP integration socket hub

지난달 OpenAI 청구서를 확인했더니 $52.3이 찍혀 있었습니다. 솔직히 조금 당황했습니다. 가끔 AI를 만져 보는 개인 개발자일 뿐인데 이렇게 많은 돈을 썼다는 사실이 믿기지 않았습니다. 그러다 로컬에서 실행 중인 Ollama가 떠올랐습니다. 무료로 쓸 수 있는 Llama 3.1이 바로 거기 있었습니다.

하지만 문제가 하나 있었습니다. Ollama API를 직접 호출해 애플리케이션을 만들면 코드가 제법 길어집니다. 요청 형식, 응답 파싱, 오류 처리까지 매번 작성하려니 번거로웠습니다. 이럴 때 LangChain이 유용합니다. Chat, RAG, Agent에 모두 사용할 수 있는 잘 정리된 인터페이스를 제공하고, 코드 한 줄만 바꿔 모델을 전환할 수도 있습니다.

이 글은 Ollama 로컬 LLM 실전 가이드 시리즈의 프레임워크 통합 편입니다. langchain-ollama 패키지의 기초부터 시작해 Chat, RAG, Agent 세 가지 실전 시나리오까지 살펴봅니다. 앞선 시리즈 글에서 API 호출이나 여러 모델 배포를 알아봤다면, 이번 글을 통해 흩어진 지식을 하나의 완성된 개발 프레임워크로 연결할 수 있습니다.

langchain-ollama 패키지 입문

먼저 제가 겪었던 시행착오부터 이야기하겠습니다. 예전에는 langchain_community.llms.Ollama를 사용했습니다. 코드는 문제없이 실행됐지만 문서를 찾아볼 때마다 langchain-ollama라는 패키지가 등장해 뭔가 이상하다고 느꼈습니다. 나중에야 LangChain이 Ollama 통합 기능을 langchain-ollama라는 독립 패키지로 분리했다는 사실을 알았습니다.

공식 패키지를 권장하는 이유는 무엇일까요?

타입 힌트가 더 충실해 IDE 자동 완성이 편리합니다. 유지보수 주기도 LangChain 메인 버전과 맞춰져 있어 호환성 문제를 덜 걱정해도 됩니다. 커뮤니티 패키지는 언제든 폐기될 수 있지만 공식 패키지는 장기적으로 유지될 선택지라는 점도 중요합니다. 저도 이전에 커뮤니티 패키지가 폐기되는 문제를 겪은 적이 있습니다.

설치는 명령 한 줄이면 끝납니다.

pip install langchain-ollama

설치하고 나면 이 패키지가 서로 다른 용도를 위한 세 가지 핵심 클래스를 제공한다는 것을 알 수 있습니다.

클래스명용도대표적인 사용 사례
ChatOllama대화 모델멀티턴 채팅, 질의응답 시스템
OllamaLLM텍스트 완성일회성 생성, 텍스트 이어 쓰기
OllamaEmbeddings벡터 임베딩RAG, 의미 검색

직접 사용해 보니 90%의 상황에서는 ChatOllama만으로 충분했습니다. 대화 모델은 멀티턴 상호작용과 스트리밍 출력을 지원합니다. 글자가 하나씩 나타나는 스트리밍 방식은 답변 전체를 한 번에 반환하는 것보다 훨씬 나은 사용자 경험을 제공합니다.

얼마나 간단한지 알 수 있는 최소 예제입니다.

from langchain_ollama import ChatOllama

# 모델 초기화
llm = ChatOllama(
    model="llama3.1:8b",  # 모델 이름. 먼저 Ollama에서 받아야 합니다
    temperature=0.7       # 무작위성 설정, 범위는 0~1입니다
)

# 메시지 전송
response = llm.invoke("안녕하세요. 자기소개를 해 주세요")
print(response.content)

이 코드를 실행하기 전에 ollama pull llama3.1:8b 명령으로 모델을 받아 두었는지 확인하세요. 아직 Ollama를 설치하지 않았다면 시리즈의 첫 번째 입문 글을 참고할 수 있습니다.

임베딩 모델인 OllamaEmbeddings도 비슷한 방식으로 사용하며, 주로 텍스트를 벡터로 변환할 때 쓰입니다. 뒤의 RAG 부분에서 자세히 활용하겠지만 먼저 간단한 예제를 살펴보겠습니다.

from langchain_ollama import OllamaEmbeddings

embeddings = OllamaEmbeddings(model="nomic-embed-text")

# 단일 텍스트 임베딩
vector = embeddings.embed_query("테스트용 텍스트입니다")
print(f"벡터 차원: {len(vector)}")  # 보통 768 이상이 출력됩니다

# 여러 텍스트를 일괄 임베딩
vectors = embeddings.embed_documents([
    "첫 번째 텍스트",
    "두 번째 텍스트"
])

nomic-embed-text는 현재 널리 쓰이는 임베딩 모델로 의미 검색에 특화되어 있습니다. 벡터 차원이 보통 768 이상으로 높고, 검색 성능도 범용 모델보다 상당히 좋습니다.

Chat 애플리케이션 실전: 멀티턴 대화와 스트리밍 출력

API를 한 번 호출하는 것은 간단하지만 실제 채팅 환경은 훨씬 복잡합니다. 사용자는 연속해서 질문하고 모델은 이전 대화 내용을 기억해야 합니다. LangChain은 메시지 목록으로 이 문제를 처리합니다.

멀티턴 대화 구현

LangChain의 메시지 유형은 세 가지입니다.

  • SystemMessage: 모델의 역할과 행동을 설정합니다(예: ‘당신은 전문 프로그래밍 도우미입니다’).
  • HumanMessage: 사용자 입력입니다.
  • AIMessage: 모델의 답변입니다.

코드를 살펴보겠습니다.

from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

llm = ChatOllama(model="llama3.1:8b", temperature=0.7)

# 대화 기록 구성
messages = [
    SystemMessage(content="기술 개념을 잘 설명하는 개발자 도우미입니다. 간결하고 이해하기 쉽게 답변하세요."),
    HumanMessage(content="REST API란 무엇인가요?"),
    AIMessage(content="REST API는 HTTP 메서드(GET/POST/PUT/DELETE)로 리소스를 다루는 웹 서비스 인터페이스 설계 방식입니다. 쉽게 말해 URL로 데이터에 접근하는 방법입니다."),
    HumanMessage(content="그렇다면 GraphQL과는 무엇이 다른가요?")
]

# 모델이 전체 대화 기록을 바탕으로 답변을 생성합니다
response = llm.invoke(messages)
print(response.content)

이 코드에서 모델은 이전 답변을 볼 수 있기 때문에 사용자가 GraphQL과 REST의 차이를 이어서 묻고 있다는 사실을 압니다. AIMessage 기록이 없다면 모델이 GraphQL을 처음부터 설명해 대화의 흐름이 끊길 수 있습니다.

스트리밍 출력: 응답을 더 생생하게 만들기

스트리밍 출력의 장점은 사용자가 빈 화면을 바라보며 결과를 기다리지 않아도 된다는 것입니다. 누군가 타이핑하듯 글자가 차례로 나타납니다. 긴 답변일수록 이런 경험이 특히 중요합니다.

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.1:8b")

# 스트리밍 출력
print("모델 답변: ", end="", flush=True)
for chunk in llm.stream("Python으로 퀵 정렬 알고리즘을 작성하고 원리를 설명해 주세요"):
    print(chunk.content, end="", flush=True)
print()  # 마지막 줄 바꿈

stream() 메서드는 반복자를 반환하며 각 chunk에는 짧은 텍스트 조각이 들어 있습니다. flush=True를 지정하면 내용이 버퍼에 쌓이지 않고 즉시 표시됩니다.

직접 테스트해 보니 스트리밍 출력은 전체 답변을 한 번에 반환할 때보다 체감 지연이 훨씬 적었습니다. 특히 답변이 100자를 넘으면 사용자는 시스템이 멈췄다고 느끼지 않고 ‘생각 중’이라고 느끼게 됩니다.

RAG 애플리케이션 실전: 로컬 지식 베이스 검색

RAG(Retrieval-Augmented Generation)는 현재 가장 실용적인 LLM 애플리케이션 시나리오 중 하나입니다. 간단히 말하면 문서 저장소에서 관련 내용을 먼저 검색한 다음, 그 내용을 바탕으로 모델이 답변을 생성하게 하는 방식입니다. 이를 통해 모델은 학습 데이터에 없던 정보도 활용할 수 있습니다.

RAG 과정 분석

완전한 RAG 시스템은 다섯 단계로 구성됩니다.

  1. 문서 로드 — PDF, TXT, Markdown 등의 파일을 읽습니다.
  2. 텍스트 분할 — 긴 문서를 검색하기 쉬운 작은 조각으로 나눕니다.
  3. 벡터 생성 — 임베딩 모델로 텍스트를 숫자 벡터로 변환합니다.
  4. 인덱스 저장 — 벡터 데이터베이스에 저장합니다(여기서는 ChromaDB 사용).
  5. 검색 및 생성 — 사용자가 질문하면 관련 조각을 검색해 모델이 답변하도록 합니다.

다음은 제가 직접 실행해 정상 작동을 확인한 전체 코드입니다.

from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_chroma import Chroma
from langchain_community.document_loaders import PyPDFLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# === 1. 문서 로드 ===
# PDF, TXT, Markdown 등 여러 형식을 지원합니다
loader = TextLoader("./my_document.txt")  # 자신의 문서 경로로 바꾸세요
docs = loader.load()

# === 2. 텍스트 분할 ===
# chunk_size=1000은 자주 쓰는 설정이며 조각 하나가 약 1000자입니다
# chunk_overlap=200은 조각 사이를 겹쳐 정보가 끊기는 것을 방지합니다
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200
)
splits = text_splitter.split_documents(docs)

# === 3 & 4. 벡터 생성 및 저장 ===
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = Chroma.from_documents(
    documents=splits,
    embedding=embeddings,
    persist_directory="./chroma_db"  # 영구 저장 경로
)

# === 5. 검색기 구성 ===
# search_kwargs={"k": 4}는 관련성이 가장 높은 조각 4개를 검색한다는 뜻입니다
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# === 6. RAG Chain 구성 ===
template = """다음 컨텍스트를 바탕으로 질문에 답하세요. 컨텍스트에 관련 정보가 없다면 "문서에 관련 정보가 없습니다"라고 명확히 답하세요.

컨텍스트:
{context}

질문: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

llm = ChatOllama(model="llama3.1:8b")

# LangChain의 LCEL 문법으로 | 기호를 사용해 각 구성 요소를 연결합니다
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# === 7. 질의 ===
response = rag_chain.invoke("문서의 주요 내용은 무엇인가요?")
print(response)

코드가 조금 길어 보이지만 나눠서 보면 구조는 매우 명확합니다. 핵심은 rag_chain 구성입니다. LangChain의 LCEL(LangChain Expression Language) 문법을 사용해 검색기, 프롬프트 템플릿, 모델, 출력 파서를 하나로 연결합니다.

실용적인 설정 조정 팁은 다음과 같습니다.

문서의 정보 밀도가 높다면(예: 기술 문서) chunk_size를 800으로 낮출 수 있습니다. 산문형 콘텐츠라면 1000~1500으로 설정해도 괜찮습니다.

검색할 조각 수를 뜻하는 k 값은 보통 3~5면 충분합니다. 너무 많으면 관련성이 희석되고 너무 적으면 핵심 정보를 놓칠 수 있습니다.

persist_directory는 반드시 설정하세요. 설정하지 않으면 재시작할 때마다 벡터 저장소를 다시 구축해야 해서 시간과 리소스를 낭비하게 됩니다.

저도 처음 RAG를 실행했을 때 영구 저장을 설정하지 않아 코드를 수정할 때마다 임베딩을 다시 생성해야 했습니다. 너무 느려서 답답했습니다. 나중에 persist_directory를 추가하니 이미 구축한 벡터 저장소를 바로 불러올 수 있어 몇 초 만에 시작됐습니다.

Agent 애플리케이션 실전: JSON 기반 도구 호출

Agent와 일반 대화의 가장 큰 차이는 Agent가 외부 도구를 호출할 수 있다는 점입니다.

예를 들어 사용자가 ‘오늘 베이징 날씨가 어떤가요?‘라고 물으면 일반 대화 모델은 그럴듯한 답을 지어낼 수밖에 없습니다. 반면 Agent는 먼저 날씨 조회 도구를 호출하고 실제 데이터를 받은 뒤 답변합니다.

Ollama 도구 호출의 주의점

여기서는 한 가지 문제를 솔직하게 짚어야 합니다. Ollama의 도구 호출 지원은 OpenAI만큼 완성도가 높지 않습니다. OpenAI 모델은 function calling을 네이티브로 지원해 언제 도구를 호출할지, 인자를 어떻게 전달할지 정확히 판단합니다. Llama 3.1을 포함한 Ollama 모델은 아직 이 부분이 충분히 성숙하지 않았습니다.

그렇다면 어떻게 해야 할까요? LangChain 공식 문서에서는 JSON 기반 Agent 방식을 제안합니다.

모델이 구조화된 JSON을 출력하도록 하고 Agent 프레임워크가 이 JSON을 파싱해 어떤 도구를 호출할지 결정하는 방식입니다. 직접 테스트해 보니 꽤 쓸 만했습니다. OpenAI의 네이티브 도구 호출만큼 매끄럽지는 않지만 기본적인 작업은 처리할 수 있습니다.

사용자 정의 도구 예제

먼저 간단한 도구 함수를 몇 개 정의합니다.

from langchain_ollama import ChatOllama
from langchain_core.tools import tool

# 도구 정의
@tool
def get_weather(city: str) -> str:
    """지정한 도시의 날씨 정보 조회"""
    # 예제 데이터이며 실제 환경에서는 날씨 API를 연동할 수 있습니다
    weather_data = {
        "베이징": "맑음, 25°C, 대기 질 좋음",
        "상하이": "흐림, 22°C, 약한 비 가능성",
        "선전": "더움, 30°C, 자외선 강함"
    }
    return weather_data.get(city, f"{city}의 날씨 데이터를 찾을 수 없습니다")

@tool
def calculate(expression: str) -> str:
    """수학 계산 실행"""
    try:
        result = eval(expression)  # 주의: 운영 환경에서는 더 안전하게 구현해야 합니다
        return f"계산 결과: {result}"
    except:
        return "계산 오류입니다. 수식을 확인하세요"

@tool
def search_local_docs(query: str) -> str:
    """로컬 문서 저장소 검색"""
    # 앞의 RAG 부분에서 만든 검색기를 연결할 수 있습니다
    return f"'{query}' 검색 결과: 관련 기록 3개를 찾았습니다"

@tool 데코레이터는 일반 함수를 LangChain 도구로 바꿉니다. 함수의 docstring은 자동으로 도구 설명이 되며, 모델은 이 설명을 바탕으로 언제 어떤 도구를 사용할지 판단합니다.

이제 JSON Agent를 만듭니다.

from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate

llm = ChatOllama(model="llama3.1:8b")
tools = [get_weather, calculate, search_local_docs]

# 프롬프트 템플릿 생성
prompt = ChatPromptTemplate.from_messages([
    ("system", "작업을 수행하기 위해 도구를 사용할 수 있는 유용한 도우미입니다."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

# Agent 생성
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 작업 실행
response = agent_executor.invoke({
    "input": "오늘 베이징 날씨를 확인하고 23 + 45도 계산해 주세요"
})

print(response["output"])

verbose=True로 설정하면 Agent의 사고 과정이 출력되어 디버깅에 도움이 됩니다. 모델이 도구 호출을 결정하는 과정도 확인할 수 있습니다.

직접 테스트한 결과는 다음과 같습니다.

70-80%
JSON Agent 성공률
간단한 작업은 대부분 문제없이 처리하지만 복잡한 작업에서는 가끔 오류가 발생합니다
Source: 작성자 실측 데이터

여러 작업을 실행해 본 결과 JSON Agent의 성공률은 약 70~80%였습니다. 날씨 조회나 계산 같은 간단한 작업은 대부분 문제없었지만 여러 도구를 조합하는 복잡한 작업에서는 가끔 오류가 발생했습니다. 인자 형식이 잘못되거나 적절하지 않은 도구를 선택하기도 했습니다. 이는 현재 로컬 LLM Agent의 공통적인 문제이며 OpenAI만큼 안정적이지는 않습니다.

Agent의 완성도가 중요하다면 다음 방법을 고려할 수 있습니다.

  1. Qwen 2.5나 DeepSeek처럼 더 강력한 모델을 사용합니다.
  2. 작업 흐름을 단순화하고 도구 수를 줄입니다.
  3. 또는 OpenAI의 네이티브 도구 호출을 사용합니다. 비용은 더 들지만 안정성이 훨씬 좋습니다.

OpenAI vs Ollama: 코드 한 줄로 전환하기

많은 분이 묻습니다. LangChain 코드를 잘 만들어 두었다면 OpenAI와 Ollama를 모두 사용할 수 있을까요? 답은 ‘가능하다’이며 놀라울 정도로 간단합니다.

전환 방법 1: import 변경

다음과 같은 OpenAI 코드가 있다고 가정해 보겠습니다.

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", temperature=0.7)
response = llm.invoke("양자 컴퓨팅을 설명해 주세요")

Ollama로 전환하려면 import 한 줄만 바꾸면 됩니다.

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.1:8b", temperature=0.7)
response = llm.invoke("양자 컴퓨팅을 설명해 주세요")

프롬프트 템플릿, Chain 구성, 출력 파싱 등 나머지 코드는 전혀 수정하지 않아도 됩니다. LangChain의 추상화 계층이 잘 설계되어 있어 모델을 전환해도 비즈니스 로직에는 거의 영향을 주지 않습니다.

전환 방법 2: OpenAI-Compatible API

Ollama는 자신을 OpenAI처럼 사용할 수 있는 OpenAI-Compatible API도 제공합니다. 이 방법을 사용하면 import조차 바꿀 필요가 없습니다.

from langchain_openai import ChatOpenAI

# base_url과 api_key만 바꾸고 나머지는 그대로 둡니다
llm = ChatOpenAI(
    model="llama3.1:8b",
    base_url="http://localhost:11434/v1",  # Ollama의 OpenAI 호환 엔드포인트
    api_key="ollama"  # 아무 값이나 입력해도 됩니다. Ollama는 검증하지 않습니다
)

response = llm.invoke("양자 컴퓨팅을 설명해 주세요")

이 방식은 어떤 상황에 적합할까요? 프로젝트에서 이미 ChatOpenAI를 많이 사용하고 있어 코드 구조는 바꾸고 싶지 않지만 로컬 모델의 성능을 테스트하고 싶을 때 유용합니다.

비교 요약

여러 전환 방법을 알아봤지만 결국 언제 Ollama를 쓰고 언제 OpenAI를 써야 할까요? 핵심 차이를 표로 정리했습니다.

비교 항목OpenAI (GPT-4)Ollama (Llama 3.1)
비용입력 토큰 1K개당 $0.03무료(로컬 GPU 전기 요금은 발생)
개인정보 보호데이터를 클라우드에 전송하므로 규정 준수가 중요한 상황에서는 주의 필요로컬에서 처리하므로 데이터가 외부로 나가지 않음
도구 호출네이티브 지원, 안정적이고 신뢰할 수 있음JSON Agent가 필요하며 성공률은 70~80%
응답 속도빠름(클라우드 최적화, 첫 토큰까지 1~3초)로컬 GPU에 따라 다름(3~10초)
모델 성능GPT-4는 현재 가장 강력한 모델 중 하나Llama 3.1 8B는 중상급으로 쓸 만하지만 GPT-4보다는 약함

제 권장 사항은 다음과 같습니다.

  • 개인 학습, 프로토타입 개발: Ollama를 사용하세요. 비용 없이 자유롭게 실험할 수 있습니다.
  • 운영 환경, 높은 동시 요청 수: 안정성과 응답 속도가 보장되는 OpenAI를 사용하세요.
  • 개인정보가 중요한 데이터: 데이터가 로컬 밖으로 나가지 않는 Ollama를 사용하세요.
  • 복잡한 Agent 작업: 도구 호출이 더 안정적인 OpenAI를 사용하세요.

가장 이상적인 방식은 둘 다 준비하는 것입니다. 개발 단계에서는 Ollama로 비용을 줄이고 배포 후에는 OpenAI로 안정성을 확보할 수 있습니다. 전환 비용이 코드 한 줄에 불과하니 활용하지 않을 이유가 없습니다.

마무리

여기까지 읽었다면 LangChain + Ollama 통합 경로에 대한 전체 지도를 얻은 셈입니다.

langchain-ollama 패키지부터 시작해 ChatOllama, OllamaLLM, OllamaEmbeddings라는 세 가지 핵심 클래스를 알아봤습니다. 그런 다음 Chat 멀티턴 대화(스트리밍 출력으로 더 매끄러운 경험 제공), RAG 지식 베이스 검색(로컬 문서를 지능형 질의응답으로 전환), Agent 도구 호출(JSON Agent라는 현실적인 절충안)의 세 가지 시나리오를 직접 구현했습니다. 마지막으로 코드 한 줄로 OpenAI와 Ollama를 전환해 매달 $50이 들던 비용을 무료로 바꾸는 방법도 비교했습니다.

언제 Ollama를 선택해야 할까요?

한마디로 비용을 줄이고 싶거나, 개인정보를 보호해야 하거나, LLM 개발을 배우려 할 때입니다. 로컬에서 실행하면 청구서를 걱정하지 않고 자유롭게 실험할 수 있습니다.

그래도 OpenAI를 사용해야 하는 때는 언제일까요?

복잡한 Agent 작업, 동시 요청이 많은 운영 환경, 빠른 응답과 높은 안정성이 필요한 상황입니다. 현재 로컬 LLM은 아직 클라우드 모델의 경험을 완전히 대체하지 못합니다.

아직 직접 시도해 보지 않았다면 Chat부터 시작하는 것을 권합니다. 코드가 가장 단순하고 결과도 직관적입니다. Chat을 실행한 뒤에는 RAG를 시도해 로컬 문서를 연결하고 모델이 자신의 자료를 이해하는 놀라운 경험을 해 보세요. 도구 호출에는 아직 주의할 점이 많고 인내심 있는 디버깅이 필요하므로 Agent는 나중에 시도해도 좋습니다.

이 시리즈에서는 앞으로도 여러 모델 배포(LangChain에서 모델 전환하기), 성능 최적화(로컬 LLM을 더 빠르게 실행하기), 운영 배포(로컬 애플리케이션을 실제 서비스로 만들기) 등의 내용을 다룰 예정입니다. 관심 있다면 계속 지켜봐 주세요.

궁금한 점은 댓글로 이야기하거나 GitHub에서 직접 문의해 주세요. 코드 예제는 모두 직접 실행해 봤으므로 정상적으로 동작할 것입니다. 오류가 발생한다면 모델을 아직 받지 않았거나 의존성을 설치하지 않은 경우가 많으니 오류 메시지에 따라 확인하면 됩니다.

LangChain + Ollama 통합 개발

설치와 설정부터 Chat, RAG, Agent 세 가지 실전 시나리오까지 로컬 LLM 애플리케이션 개발을 한 번에 익힙니다.

⏱️ Estimated time: 60 min

  1. 1

    Step 1: langchain-ollama 패키지 설치

    설치 명령을 실행합니다.

    ```bash
    pip install langchain-ollama
    ```

    Ollama를 설치하고 모델도 받아 두었는지 확인합니다(예: `ollama pull llama3.1:8b`).
  2. 2

    Step 2: Chat 애플리케이션 만들기

    ChatOllama를 초기화하고 메시지를 보냅니다.

    ```python
    from langchain_ollama import ChatOllama

    llm = ChatOllama(model="llama3.1:8b", temperature=0.7)
    response = llm.invoke("안녕하세요")
    print(response.content)
    ```

    멀티턴 대화와 스트리밍 출력을 지원합니다.
  3. 3

    Step 3: RAG 지식 베이스 구축

    다섯 단계로 진행합니다.

    • 문서 로드(TextLoader / PyPDFLoader)
    • 텍스트 분할(RecursiveCharacterTextSplitter)
    • 벡터 생성(OllamaEmbeddings)
    • 인덱스 저장(ChromaDB)
    • 검색 및 생성(RAG Chain)

    핵심 설정은 chunk_size=1000, k=4이며 persist_directory도 반드시 지정해야 합니다.
  4. 4

    Step 4: Agent 도구 호출 구현

    도구 함수를 정의하고 JSON Agent를 만듭니다.

    ```python
    @tool
    def get_weather(city: str) -> str:
    """날씨 정보 조회"""
    ...

    agent = create_tool_calling_agent(llm, tools, prompt)
    agent_executor = AgentExecutor(agent=agent, tools=tools)
    ```

    성공률은 약 70~80%이며 복잡한 작업에는 OpenAI를 권장합니다.
  5. 5

    Step 5: OpenAI / Ollama 전환

    방법 1: import 변경

    ```python
    from langchain_ollama import ChatOllama # Ollama 사용
    from langchain_openai import ChatOpenAI # OpenAI 사용
    ```

    방법 2: OpenAI-Compatible API 사용(import 변경 없음)

    ```python
    llm = ChatOpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
    )
    ```

FAQ

langchain-ollama와 langchain_community.llms.Ollama는 무엇이 다른가요?
langchain-ollama는 공식 독립 패키지로 타입 힌트가 더 충실하고 메인 버전과 유지보수 주기가 맞춰져 있습니다. langchain_community.llms.Ollama는 커뮤니티 패키지라 언제든 폐기될 수 있습니다. 공식 패키지인 langchain-ollama 사용을 권장합니다.
ChatOllama와 OllamaLLM 중 무엇을 사용해야 하나요?
90%의 상황에서는 ChatOllama만으로 충분합니다. 멀티턴 대화, 스트리밍 출력, 메시지 기록을 지원합니다. OllamaLLM은 일회성 텍스트 생성이나 이어 쓰기에 적합합니다.
RAG 시스템에서 chunk_size와 k 값은 어떻게 설정하나요?
기술 문서의 chunk_size는 800 정도가 좋고, 산문형 콘텐츠는 1000~1500으로 설정할 수 있습니다. k 값(검색할 조각 수)은 보통 3~5가 적당합니다. 너무 많으면 관련성이 희석되고 너무 적으면 핵심 정보를 놓칠 수 있습니다. 벡터 저장소를 유지하려면 persist_directory를 반드시 설정하세요.
Ollama의 도구 호출이 OpenAI보다 불안정한 이유는 무엇인가요?
Llama 3.1을 포함한 Ollama 모델은 네이티브 function calling을 지원하지 않기 때문에 모델이 구조화된 JSON을 출력하도록 하는 JSON Agent 방식이 필요하며 성공률은 약 70~80%입니다. OpenAI의 네이티브 도구 호출은 더 안정적이므로 복잡한 Agent 작업에는 OpenAI를 권장합니다.
OpenAI와 Ollama 사이를 어떻게 전환하나요?
방법 1은 import를 바꾸는 것입니다(ChatOpenAI를 ChatOllama로 변경). 방법 2는 OpenAI-Compatible API를 사용해 base_url과 api_key만 바꾸는 것입니다. 프롬프트 템플릿, Chain, 출력 파싱 등 나머지 코드는 전혀 수정할 필요가 없습니다.
Ollama는 운영 환경에 적합한가요?
상황에 따라 다릅니다. 개인 학습, 프로토타입 개발, 개인정보를 다루는 작업에는 Ollama가 적합합니다. 동시 요청이 많은 운영 환경, 복잡한 Agent 작업, 빠른 응답이 필요한 상황에는 OpenAI를 권장합니다. 이상적인 방식은 개발 단계에서 Ollama로 비용을 줄이고 배포 후에는 OpenAI로 안정성을 확보하는 것입니다.

3분 읽기 · 게시일: 2026년 4월 7일 · 수정일: 2026년 9월 4일

댓글

GitHub로 로그인하여 댓글을 남기세요

Easton BlogEaston Blog