LlamaCppChatGenerator
LlamaCppChatGenerator
Llama.cpp에서 실행되는 LLM으로 채팅 완성을 만들어주는 컴포넌트예요. 주로 ChatPromptBuilder 뒤에 두면 돼요.
본문
개요
Llama.cpp는 대규모 언어 모델의 효율적인 추론을 위한 C/C++ 라이브러리예요. 효율적인 양자화 GGUF 형식을 활용해서 메모리 요구량을 크게 줄이고 추론을 가속화해요. 덕분에 표준 머신(GPU 없이도)에서 LLM을 효율적으로 실행할 수 있어요.
Llama.cpp는 GGUF 형식의 LLM 양자화 바이너리 파일을 사용하는데, 이 파일은 Hugging Face에서 다운로드할 수 있어요. LlamaCppChatGenerator는 초기화 때 model 파라미터로 로컬에 저장된 GGUF 파일 경로를 받아서 Llama.cpp에서 실행되는 모델을 지원해요.
도구 지원
LlamaCppChatGenerator는 tools 파라미터를 통해 함수 호출을 지원해요. 유연한 도구 구성을 받아들여요.
- Tool 객체 목록: 개별 도구를 리스트로 전달.
- 단일 Toolset: 전체 Toolset을 바로 전달.
- 도구·Toolset 혼합: 여러 Toolset을 독립 도구와 한 리스트에 결합.
관련 도구를 논리적 그룹으로 묶으면서 필요할 때 독립 도구도 포함할 수 있어요.
from haystack.tools import Tool, Toolset
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
# 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 = LlamaCppChatGenerator(
model="/path/to/model.gguf",
tools=[math_toolset, weather_tool, news_tool], # Mix of Toolset and Tool objects
)
도구 작업에 대한 자세한 내용은 Tool과 Toolset 문서를 참고하세요.
설치
이 통합을 쓰려면 llama-cpp-haystack 패키지를 설치해요.
pip install llama-cpp-haystack
다른 compute 백엔드 사용
기본 설치는 Linux·Windows에서 CPU용으로 llama.cpp를 빌드하고 MacOS에서는 Metal을 사용해요. 다른 compute 백엔드를 쓰려면:
- llama.cpp 설치 페이지의 지침에 따라 선호하는 compute 백엔드용 llama-cpp-python을 설치해요.
- 위 명령으로 llama-cpp-haystack을 설치해요.
예를 들어 cuBLAS 백엔드와 함께 llama-cpp-haystack를 쓰려면 다음 명령을 실행해야 해요.
export GGML_CUDA=1
CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python
pip install llama-cpp-haystack
이 페이지의 예시들은 sentence-transformers-haystack 패키지의 Sentence Transformers 임베더를 사용해요. 예시를 실행하려면 설치하세요.
pip install sentence-transformers-haystack
사용법
- 원하는 LLM의 GGUF 버전을 다운로드해요. 인기 모델의 GGUF 버전은 Hugging Face에서 받을 수 있어요.
- GGUF 파일 경로로
LlamaCppChatGenerator를 초기화하고 필요한 모델·텍스트 생성 파라미터를 지정해요.
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
from haystack.dataclasses import ChatMessage
generator = LlamaCppChatGenerator(
model="/content/openchat-3.5-1210.Q3_K_S.gguf",
n_ctx=512,
n_batch=128,
model_kwargs={"n_gpu_layers": -1},
generation_kwargs={"max_tokens": 128, "temperature": 0.1},
)
messages = [ChatMessage.from_user("Who is the best American actor?")]
result = generator.run(messages)
추가 모델 파라미터 전달
model, n_ctx, n_batch 인자는 편의를 위해 노출됐으며 초기화 때 키워드 인자로 Generator에 직접 전달할 수 있어요. 참고로 model은 llama.cpp의 model_path 파라미터로 변환돼요.
model_kwargs 파라미터로 모델 초기화 때 추가 인자를 전달할 수 있어요. 중복되는 경우 이 파라미터들이 model, n_ctx, n_batch 초기화 파라미터를 덮어써요.
사용 가능한 모델 인자에 대한 자세한 내용은 Llama.cpp의 LLM 문서를 참고하세요.
참고: Llama.cpp는 ChatMessage 형식 적용을 위해 모델 메타데이터에서 chat_template을 자동으로 추출해요. 모델 파라미터로 커스텀 chat_handler나 chat_format을 넘겨 사용되는 chat_template을 덮어쓸 수 있어요.
예를 들어 초기화 때 모델을 GPU로 오프로드하려면:
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
from haystack.dataclasses import ChatMessage
generator = LlamaCppChatGenerator(
model="/content/openchat-3.5-1210.Q3_K_S.gguf",
n_ctx=512,
n_batch=128,
model_kwargs={"n_gpu_layers": -1},
)
messages = [ChatMessage.from_user("Who is the best American actor?")]
result = generator.run(messages, generation_kwargs={"max_tokens": 128})
generated_reply = result["replies"][0].text
print(generated_reply)
텍스트 생성 파라미터 전달
generation_kwargs 파라미터로 max_tokens, temperature, top_k, top_p 같은 추가 생성 인자를 추론 중 모델에 전달할 수 있어요.
사용 가능한 생성 인자에 대한 자세한 내용은 Llama.cpp의 Chat Completion API 문서를 참고하세요.
참고: JSON 모드, 함수 호출, 도구는 모두 generation_kwargs로 지원돼요. 사용법은 llama-cpp-python GitHub README를 참고하세요.
예를 들어 max_tokens와 temperature를 설정하려면:
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
from haystack.dataclasses import ChatMessage
generator = LlamaCppChatGenerator(
model="/content/openchat-3.5-1210.Q3_K_S.gguf",
n_ctx=512,
n_batch=128,
generation_kwargs={"max_tokens": 128, "temperature": 0.1},
)
messages = [ChatMessage.from_user("Who is the best American actor?")]
result = generator.run(messages)
멀티모달(이미지+텍스트) 입력
from haystack.dataclasses import ChatMessage, ImageContent
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
# Initialize with multimodal support
llm = LlamaCppChatGenerator(
model="llava-v1.5-7b-q4_0.gguf",
chat_handler_name="Llava15ChatHandler", # Use llava-1-5 handler
model_clip_path="mmproj-model-f16.gguf", # CLIP model
n_ctx=4096, # Larger context for image processing
)
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.
generation_kwargs는 생성기 자체의 run 메서드에 직접 전달할 수도 있어요.
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
from haystack.dataclasses import ChatMessage
generator = LlamaCppChatGenerator(
model="/content/openchat-3.5-1210.Q3_K_S.gguf",
n_ctx=512,
n_batch=128,
)
messages = [ChatMessage.from_user("Who is the best American actor?")]
result = generator.run(
messages,
generation_kwargs={"max_tokens": 128, "temperature": 0.1},
)
파이프라인 안에서
Hugging Face의 Simple Wikipedia 데이터셋을 사용하고 OpenChat-3.5 LLM으로 답을 생성하는 Retrieval Augmented Generation 파이프라인에서 LlamaCppChatGenerator를 써 볼게요.
데이터셋 로드:
# Install HuggingFace Datasets using "pip install datasets"
from datasets import load_dataset
from haystack import Document, Pipeline
from haystack.components.builders.answer_builder import AnswerBuilder
from haystack.components.builders import ChatPromptBuilder
from haystack_integrations.components.embedders.sentence_transformers import (
SentenceTransformersDocumentEmbedder,
SentenceTransformersTextEmbedder,
)
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.components.writers import DocumentWriter
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.dataclasses import ChatMessage
# Import LlamaCppChatGenerator
from haystack_integrations.components.generators.llama_cpp import LlamaCppChatGenerator
# Load first 100 rows of the Simple Wikipedia Dataset from HuggingFace
dataset = load_dataset("pszemraj/simple_wikipedia", split="validation[:100]")
docs = [
Document(
content=doc["text"],
meta={
"title": doc["title"],
"url": doc["url"],
},
)
for doc in dataset
]
SentenceTransformersDocumentEmbedder와 DocumentWriter로 문서를 InMemoryDocumentStore에 인덱싱:
doc_store = InMemoryDocumentStore(embedding_similarity_function="cosine")
# Install the Sentence Transformers embedders using "pip install sentence-transformers-haystack"
doc_embedder = SentenceTransformersDocumentEmbedder(
model="sentence-transformers/all-MiniLM-L6-v2",
)
# Indexing Pipeline
indexing_pipeline = Pipeline()
indexing_pipeline.add_component(instance=doc_embedder, name="DocEmbedder")
indexing_pipeline.add_component(
instance=DocumentWriter(document_store=doc_store),
name="DocWriter",
)
indexing_pipeline.connect("DocEmbedder", "DocWriter")
indexing_pipeline.run({"DocEmbedder": {"documents": docs}})
RAG 파이프라인을 만들고 LlamaCppChatGenerator를 추가:
system_message = ChatMessage.from_system(
"""
Answer the question using the provided context.
Context:
{% for doc in documents %}
{{ doc.content }}
{% endfor %}
""",
)
user_message = ChatMessage.from_user("Question: {{question}}")
assistent_message = ChatMessage.from_assistant("Answer: ")
chat_template = [system_message, user_message, assistent_message]
rag_pipeline = Pipeline()
text_embedder = SentenceTransformersTextEmbedder(
model="sentence-transformers/all-MiniLM-L6-v2",
)
# Load the LLM using LlamaCppChatGenerator
model_path = "openchat-3.5-1210.Q3_K_S.gguf"
generator = LlamaCppChatGenerator(model=model_path, n_ctx=4096, n_batch=128)
rag_pipeline.add_component(
instance=text_embedder,
name="text_embedder",
)
rag_pipeline.add_component(
instance=InMemoryEmbeddingRetriever(document_store=doc_store, top_k=3),
name="retriever",
)
rag_pipeline.add_component(
instance=ChatPromptBuilder(template=chat_template),
name="prompt_builder",
)
rag_pipeline.add_component(instance=generator, name="llm")
rag_pipeline.add_component(instance=AnswerBuilder(), name="answer_builder")
rag_pipeline.connect("text_embedder", "retriever")
rag_pipeline.connect("retriever", "prompt_builder.documents")
rag_pipeline.connect("prompt_builder", "llm")
rag_pipeline.connect("llm", "answer_builder")
rag_pipeline.connect("retriever", "answer_builder.documents")
파이프라인 실행:
question = "Which year did the Joker movie release?"
result = rag_pipeline.run(
{
"text_embedder": {"text": question},
"prompt_builder": {"question": question},
"llm": {"generation_kwargs": {"max_tokens": 128, "temperature": 0.1}},
"answer_builder": {"query": question},
},
)
generated_answer = result["answer_builder"]["answers"][0]
print(generated_answer.data)
# The Joker movie was released on October 4, 2019.