OllamaChatGenerator — Ollama 채팅 생성
OllamaChatGenerator — Ollama 채팅 생성
이 컴포넌트는 Ollama에서 실행 중인 대규모 언어 모델(LLM)을 이용해 채팅 완성(chat completion)을 만들 수 있게 해 줘요. 로컬에서 돌아가는 모델을 Haystack 파이프라인에서 호출하는 한 조각이라고 보시면 돼요.
개요 (Overview)
Ollama는 LLM을 로컬에서 실행하는 데 초점을 맞춘 프로젝트예요. 내부적으로 기본적으로 양자화된 GGUF 형식을 사용해요. 덕분에 복잡한 설치 과정을 거치지 않고도 표준 머신(GPU가 없어도)에서 LLM을 실행할 수 있어요.
OllamaChatGenerator는 Ollama에서 실행되는 모델을 지원해요. llama2, mixtral 같은 모델들이죠. 지원되는 모델의 전체 목록은 여기에서 찾을 수 있어요.
OllamaChatGenerator는 동작하려면 model 이름과 url이 필요해요. 기본값은 모델 "qwen3:0.6b", URL "http://localhost:11434"예요.
OllamaChatGenerator를 사용하는 방식은 ChatMessage 객체를 쓰는 거예요. ChatMessage는 메시지와 역할(누가 만들었는지 — user, assistant, system, tool 등), 선택적 메타데이터를 담는 데이터 클래스예요. 사용 예시는 사용법 섹션을 보면 돼요.
도구 지원 (Tool Support)
OllamaChatGenerator는 tools 파라미터를 통해 함수 호출(function calling)을 지원해요. 이 파라미터는 유연한 도구 구성을 받아들여요.
- Tool 객체 리스트: 개별 도구를 리스트로 전달
- 단일 Toolset: Toolset 하나를 통째로 전달
- Tool과 Toolset 혼합: 여러 Toolset과 단독 도구를 한 리스트에 섞어서 전달
이렇게 하면 관련된 도구들을 논리적인 그룹으로 묶으면서, 필요할 때 단독 도구도 같이 포함할 수 있어요.
from haystack.tools import Tool, Toolset
from haystack_integrations.components.generators.ollama import OllamaChatGenerator
# Create individual tools
weather_tool = Tool(
name="weather", description="Get weather info", parameters=..., function=...
)
news_tool = Tool(
name="news", description="Get latest news", parameters=..., function=...
)
# Group related tools into a toolset
math_toolset = Toolset([add_tool, subtract_tool, multiply_tool])
# Pass mixed tools and toolsets to the generator
generator = OllamaChatGenerator(
model="llama2",
tools=[math_toolset, weather_tool, news_tool], # Mix of Toolset and Tool objects
)
도구를 다루는 더 자세한 내용은 Tool과 Toolset 문서를 참고하세요.
스트리밍 (Streaming)
출력이 생성되는 그대로 스트리밍할 수 있어요. streaming_callback에 콜백을 넘기면 되고, 내장 함수 print_streaming_chunk를 쓰면 텍스트 토큰과 도구 이벤트(도구 호출과 도구 결과)를 출력해 줘요.
from haystack.components.generators.utils import print_streaming_chunk
# Configure any `Generator` or `ChatGenerator` with a streaming callback
component = SomeGeneratorOrChatGenerator(streaming_callback=print_streaming_chunk)
# If this is a `ChatGenerator`, pass a list of messages:
# from haystack.dataclasses import ChatMessage
# component.run([ChatMessage.from_user("Your question here")])
# If this is a (non-chat) `Generator`, pass a prompt:
# component.run({"prompt": "Your prompt here"})
참고 스트리밍은 단일 응답일 때만 동작해요. 공급자가 여러 후보를 지원한다면
n=1로 설정하세요.
StreamingChunk가 어떻게 동작하는지, 커스텀 콜백을 어떻게 작성하는지 더 알고 싶다면 Streaming Support 문서를 참고하세요.
기본적으로는 print_streaming_chunk를 쓰는 걸 권장해요. 커스텀 콜백은 특별한 전송 방식(예: SSE/WebSocket)이나 커스텀 UI 포맷이 필요할 때만 작성하면 돼요.
도구와 함께 스트리밍 (Streaming with Tools)
스트리밍과 도구 호출을 함께 쓸 수도 있어요. tools와 streaming_callback을 모두 넘기면, 모델이 도구를 호출하기로 결정했을 때 스트리밍된 청크가 텍스트 토큰 대신 도구 호출 델타(tool-call delta)를 담아요. 그리고 최종적으로 재구성된 ChatMessage는 replies[0]에 해석된 tool_calls 리스트를 노출해 줘요.
from haystack.dataclasses import ChatMessage
from haystack.dataclasses.streaming_chunk import StreamingChunk
from haystack.tools import create_tool_from_function
from haystack_integrations.components.generators.ollama import OllamaChatGenerator
def get_weather(city: str) -> str:
"""Get current weather for a city."""
return f"Sunny, 22°C in {city}"
def callback(chunk: StreamingChunk) -> None:
if chunk.tool_calls:
print(f"[tool delta] {chunk.tool_calls}")
elif chunk.content:
print(chunk.content, end="", flush=True)
generator = OllamaChatGenerator(
model="llama3.1:8b",
generation_kwargs={"temperature": 0.0},
tools=[create_tool_from_function(get_weather)],
streaming_callback=callback,
)
response = generator.run(
messages=[
ChatMessage.from_user(
"What's the weather in Berlin? Use the get_weather tool.",
),
],
)
# Final reconstructed message: tool_calls populated, text is None
assistant_message = response["replies"][0]
print(assistant_message.tool_calls)
# -> [ToolCall(tool_name='get_weather', arguments={'city': 'Berlin'}, ...)]
자체 콜백을 작성하는 대신 내장 print_streaming_chunk 콜백(텍스트 토큰과 도구 이벤트를 모두 처리)을 쓸 수도 있어요.
사용법 (Usage)
- 실행 중인 Ollama 인스턴스가 필요해요. 설치 방법은 Ollama GitHub 저장소에 있어요. Ollama를 빨리 실행하는 방법은 Docker를 쓰는 거예요.
docker run -d -p 11434:11434 --name ollama ollama/ollama:latest
- 원하는 LLM을 다운로드하거나 pull 해야 해요. 모델 라이브러리는 Ollama 웹사이트에서 볼 수 있어요. Docker를 쓴다면 예를 들어 Zephyr 모델을 pull 할 수 있어요.
docker exec ollama ollama pull zephyr
Ollama를 시스템에 이미 설치했다면 다음 명령을 실행하면 돼요.
ollama pull zephyr
팁 — 모델의 특정 버전 고르기
태그를 지정해서 모델의 특정(양자화된) 버전을 고를 수도 있어요. 사용 가능한 태그는 Ollama 모델 라이브러리의 모델 카드에 표시돼요. Zephyr의 예시가 이렇죠. 이 경우 이렇게 실행하면 됩니다.
# ollama pull model:tag
ollama pull zephyr:7b-alpha-q3_K_S
- 그리고
ollama-haystack패키지도 설치해야 해요.
pip install ollama-haystack
단독 사용 (On its own)
from haystack_integrations.components.generators.ollama import OllamaChatGenerator
from haystack.dataclasses import ChatMessage
generator = OllamaChatGenerator(
model="zephyr",
url="http://localhost:11434",
generation_kwargs={
"num_predict": 100,
"temperature": 0.9,
},
)
messages = [
ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"),
ChatMessage.from_user("What's Natural Language Processing?"),
]
print(generator.run(messages=messages))
# >> {
# >> "replies": [
# >> ChatMessage(
# >> _role=<ChatRole.ASSISTANT: 'assistant'>,
# >> _content=[
# >> TextContent(
# >> text=(
# >> "Natural Language Processing (NLP) is a subfield of "
# >> "Artificial Intelligence that deals with understanding, "
# >> "interpreting, and generating human language in a meaningful "
# >> "way. It enables tasks such as language translation, sentiment "
# >> "analysis, and text summarization."
# >> )
# >> )
# >> ],
# >> _name=None,
# >> _meta={
# >> "model": "zephyr",...
# >> }
# >> )
# >> ]
# >> }
멀티모달 입력으로 사용:
from haystack.dataclasses import ChatMessage, ImageContent
from haystack_integrations.components.generators.ollama import OllamaChatGenerator
llm = OllamaChatGenerator(model="llava", url="http://localhost:11434")
image = ImageContent.from_file_path("apple.jpg")
user_message = ChatMessage.from_user(
content_parts=["What does the image show? Max 5 words.", image],
)
response = llm.run([user_message])["replies"][0].text
print(response)
# Red apple on straw.
파이프라인에서 사용 (In a Pipeline)
from haystack.components.builders import ChatPromptBuilder
from haystack_integrations.components.generators.ollama import OllamaChatGenerator
from haystack.dataclasses import ChatMessage
from haystack import Pipeline
# no parameter init, we don't use any runtime template variables
prompt_builder = ChatPromptBuilder()
generator = OllamaChatGenerator(
model="zephyr",
url="http://localhost:11434",
generation_kwargs={
"temperature": 0.9,
},
)
pipe = Pipeline()
pipe.add_component("prompt_builder", prompt_builder)
pipe.add_component("llm", generator)
pipe.connect("prompt_builder.prompt", "llm.messages")
location = "Berlin"
messages = [
ChatMessage.from_system(
"Always respond in Spanish even if some input data is in other languages."
),
ChatMessage.from_user("Tell me about {{location}}"),
]
print(
pipe.run(
data={
"prompt_builder": {
"template_variables": {"location": location},
"template": messages,
}
}
)
)
# >> {
# >> "llm": {
# >> "replies": [
# >> ChatMessage(
# >> _role=<ChatRole.ASSISTANT: 'assistant'>,
# >> _content=[
# >> TextContent(
# >> text=(
# >> "Berlín es la capital y la mayor ciudad de Alemania. "
# >> "Está ubicada en el estado federado de Berlín, y tiene más..."
# >> )
# >> )
# >> ],
# >> _name=None,
# >> _meta={
# >> "model": "zephyr",...
# >> }
# >> )
# >> ]
# >> }
# >> }