LangChain/01.basic

04. ChatOllama

  • -

이제 간단한 chating을 처리해보자.

 

ChatOllama

 

ChatOllama API

ChatOllama를 만드는 생성자의 파라미터에 대해 살펴보자.

https://python.langchain.com/api_reference/ollama/chat_models/langchain_ollama.chat_models.ChatOllama.html

 

ChatOllama — 🦜🔗 LangChain documentation

Install langchain-ollama and download any models you want to use from ollama. ollama pull mistral:v0.3 pip install -U langchain-ollama

python.langchain.com

 

옵션 설명 기본값 예시
model 사용할 Ollama 모델 이름 필수 입력 "llama3", "mistral"
temperature 응답의 무작위성 조절 (0.0-1.0) 0.8 0.5 (더 결정론적), 0.9 (더 창의적)
num_predict 최대 생성 토큰 수 모델 기본 값 100, 200
num_ctx 모델의 컨텍스트 윈도우 크기 모델 기본값 4096, 8192
top_k 가장 높은 확률을 가진 k개의 토큰만 고려 모델 기본값 50, 10
top_p 누적 확률 기반 토큰 선택 모델 기본값 0.9
format 출력 형식 지정 None "json"
timeout API 호출 타임아웃 없음 60 (초)
base_url Ollama 서버 기본 URL "http://localhost:11434" "http://192.168.1.100:11434"

 

사용 예

실제 구성 예를 살펴보자.

import requests
import os
from langchain_ollama import ChatOllama

chatModel = ChatOllama(
    temperature= 0.1,  # 창의성: 0.0 ~ 1.0
    model='gemma3:4b-it-qat',
    num_predict=100,
    max_new_tokens=100,
    num_ctx=1024,
    # base_url=http://localhost:11434
)

 

응답 객체(langchain_core.messages.ai.AIMessage)

ChatOllama의 invoke 함수를 통해 질문을 전달하면 AIMessage 타입의 객체가 반환된다.

AIMessage는 context, usage_metadata, response_metadata라는 속성을 갖는다. 각각 출력되는 내용을 보면 속성의 특성을 쉽게 유추할 수 있으니 바로 예를 참조하자.

question = "langchain을 만든 사람은?"

response = chatModel.invoke(question)
print(type(response))
print(f"답변 내용: {response.content}")
print(f"usage metadata {response.usage_metadata}")
print(f"response metadata: {response.response_metadata}")
<class 'langchain_core.messages.ai.AIMessage'>
답변 내용: LangChain은 **Jackson VanDerPol**와 **Andrew Ng**가 주도하여 개발되었습니다. 
LangChain은 2023년 초에 처음 공개되었으며, 이후 여러 개발자들이 참여하여 지속적으로 발전하고 있습니다. 

usage metadata {'input_tokens': 14, 'output_tokens': 90, 'total_tokens': 104}

response metadata: {'model': 'gemma3:4b-it-qat', 'created_at': '2025-06-26T09:31:07.974156Z',
                    'done': True, 'done_reason': 'stop', 'total_duration': 4655479875, 
                    'load_duration': 34697583, 'prompt_eval_count': 14, 'eval_count': 90,
                    'prompt_eval_duration': 131595250, 'eval_duration': 4488076500, 
                    'model_name': 'gemma3:4b-it-qat'}

 

다양한 호출 방식

 

invoke()와 stream()

ChatOllama와 통신하기 위해서는 invoke()와 stream()이 있다.

  • invoke(): 전체 응답을 한번에 생성하는 방식으로 백그라운드에서 응답을 취합하고 한번에 전체 결과가 필요한 경우에 사용된다.
  • stream(): 토큰 단위로 점진적으로 결과를 생성한다. 실시간 채팅을 위한 UI에 적합하며 기다리지 않기 때문에 사용자 경험이 개선된다.

이제까지 invoke를 사용해봤는데 모델이 결과를 만드는 동안 사용자는 멀뚱 멀뚱 화면을 보고 있어야 했는데 stream을 사용하면 물 흐르듯이 조금씩 응답이 출력되는 것을 확인할 수 있다.

stream()의 반환형은 generator 이다. python에서 Generator는 반복 가능한 객체로 한 번에 모든 값을 메모리에 저장하지 않고 순차적으로 값을 생성한다. stream의 generator는 token들을 담고 있다.
def print_stream_response(response):
    for token in response:
        print(token.content, end="", flush=True)

stream을 사용하는 방법은 invoke와 동일하다.

question = "대한민국 제주도의 아름다운 관광지 1곳과 주소를 알려줘."       

response = chatModel.stream(question)
print(type(response))
print_stream_response(response)

 

Message 활용

OllamaLLM이 단순한 문자열 형태로 질문을 받는 반면 OllamaChat은 Message []을 처리할 수 있다.

Message는 모델과 사용자 간의 대화에서 정보를 교환하는 구조회된 통신 단위로 대화의 맥락, 역할, 내용을 포함하는 객체이다. Message를 이용하면 대화의 기본 구성 요소를 지정하고 명확한 역할 부여, 구조화된 정보 전달, 멀티모달 지원등이 가능하다.

Message는 다음과 같이 4가지로 구분할 수 있다.

메시지 타입 주요 목적 주요 속성
SystemMessage 대화 맥락 설정 content
HumanMessage 사용자 입력 content
AIMessage AI 응답 content, usage_metadata, response_metadata
ToolMessage 도구 호출 결과 content, tool_call_id

일반적으로 SystemMessage로 페르소나를 설정하고 HumanMessage에 사용자의 요청을 설정해서 모델에 전달하면 모델은 앞서 살펴봤던 AIMessage를 생성해서 응답하게 된다.

ToolMessage의 용도는 추 후 살펴보자.

from langchain_core.messages import HumanMessage, SystemMessage
question = 'MBTI ISTJ에 대해 설명해줘.'
messages = [
    SystemMessage(content='당신은 재밋게 설명하는 것을 좋아하는 전문가입니다.'),
    HumanMessage(content=question)
]

response = chatModel.stream(messages)
print_stream_response(response)

 

Multi Modal 처리

요즘의 모델들은 단순 텍스트 뿐 아니라 이미지등 멀티 모달을 지원한다. 인공지능은 사람을 모방하고 사람이 학습할 때 단순 텍스트 뿐 아니라 이미지, 동영상등을 통해 학습하기 때문에 멀티 모달 지원은 인공지능의 학습에 매우 중요한 부분이다.

개인적으로 멀티모달을 다양하게 테스트 해보지는 않았다. 현재 ChatOllama의 경우는 전달되는 데이터가 file_path 이거나 base64로 encoding된 값이어야 하는것 같다.

먼저 url 또는 path에 위치한 파일을 base64로 인코딩 시켜보자.

import base64
# 현재는 이미지를 base64로 encoding 해서 처리 해야 함
def get_image_base64(url, type):
    try:
        if type=="base64":
            return url
        elif type=="url":
            response = requests.get(url)
            if response.status_code == 200:
                return base64.b64encode(response.content).decode('utf-8')
        elif type=="file":
            with open(url, "rb") as image_file:
                return base64.b64encode(image_file.read()).decode('utf-8')
        else:
            raise ValueError("base64, url, file 중 하나를 선택하세요.")

    except Exception as e:
        print(f"이미지 처리 중 오류 발생: {e}")
        return e

LangChain에서 멀티모달을 처리하기 위해서는 HumanMessage를 사용한다. 이때 모달의 타입에 따라서 적절한 content를 구성해주면 된다. 

def test_multi_modal(url, type):
    image_b64 = get_image_base64(url, type)
    messages = [
        SystemMessage(content="당신은 이미지를 분석하고 설명하는 전문가입니다. 위트있게 설명해주세요."),
        HumanMessage(content=[
            {"type": "text", "text": "이 이미지를 분석해서 100글자 이내로 설명해줘."},
            {"type": "image_url", "image_url": {"url": image_b64}}
        ])
    ]
    print("\n이미지 분석 중...\n")
    try:
        response = chatModel.stream(messages)
        print_stream_response(response)
    except Exception as e:
        print(f"이미지 분석 중 오류 발생: {e}")

image_url = "https://images.unsplash.com/photo-1579952363873-27f3bade9f55"
test_multi_modal(image_url, "url")

image_url="/Users/itsmeyjc/0188E6EB-40A3-486F-B4A5-13BA7512DFE3.jpg"
test_multi_modal(image_url, "file")

 

'LangChain > 01.basic' 카테고리의 다른 글

03. config & simple chat  (1) 2025.06.25
02. mac에서 langchain 관련 설정  (1) 2025.06.25
01. 기본적인 Shell 명령어  (1) 2025.06.24
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.