OpenAIChatGenerator
OpenAIChatGenerator
OpenAI의 대형 언어 모델로 채팅 완성을 처리하는 컴포넌트예요. 파이프라인에서 ChatPromptBuilder 뒤에 붙어서 만들어 둔 메시지 목록(ChatMessage)을 받아 모델의 답변(replies)을 내뱉는 가장 전형적인 위치에 놓여요. 구조화 출력(structured output)과 스트리밍도 지원하니, 대화형 애플리케이션을 만들 때 가장 먼저 만나게 되는 Generator라 보면 돼요.
출처: 공식문서
주요 정보
| 항목 | 값 |
|---|---|
| 파이프라인에서 가장 흔한 위치 | ChatPromptBuilder 뒤 |
| 필수 초기화 변수 | api_key: OpenAI API 키. OPENAI_API_KEY 환경 변수로도 설정 가능 |
| 필수 실행 변수 | messages: 대화를 나타내는 ChatMessage 객체 리스트 또는 단일 문자열 |
| 출력 변수 | replies: 입력 대화에 대한 LLM의 대체 답변 리스트 |
| API 레퍼런스 | Generators |
| GitHub 링크 | https://github.com/deepset-ai/haystack/blob/main/haystack/components/generators/chat/openai.py |
| 패키지 이름 | haystack-ai |
개요
OpenAIChatGenerator는 OpenAI의 채팅 완성 모델(gpt-4o-mini, gpt-4.1-mini, 그리고 GPT-5 계열)을 지원해요. 기본 모델은 gpt-5-mini예요.
OpenAIChatGenerator는 OpenAI 키가 필요해요. 기본적으로 OPENAI_API_KEY 환경 변수를 사용하며, 원하면 초기화 시 api_key로 직접 넘길 수도 있어요.
generator = OpenAIChatGenerator(model="gpt-4o-mini")
이 컴포넌트는 ChatMessage 객체 리스트를 받아 동작해요. ChatMessage는 메시지 내용과 역할(누가 만들었는지 — user, assistant, system, tool), 그리고 선택적 메타데이터를 담는 데이터 클래스예요. 사용 예시는 사용법 섹션에서 확인할 수 있어요. 문자열을 넘기면 user 역할을 가진 ChatMessage 하나만 담긴 리스트로 변환돼요.
openai.ChatCompletion.create 메서드에 유효한 채팅 완성 파라미터는 generation_kwargs 파라미터를 통해 초기화 시와 run() 메서드 양쪽에서 모두 넣을 수 있어요. OpenAI API가 지원하는 파라미터 상세는 OpenAI 문서를 참고하세요.
OpenAIChatGenerator는 api_base_url 초기화 파라미터로 OpenAI 모델의 커스텀 배포도 지원해요.
구조화 출력 (Structured Output)
OpenAIChatGenerator는 예측 가능한 형식의 응답을 받을 수 있는 구조화 출력을 지원해요. generation_kwargs의 response_format 파라미터에 Pydantic 모델이나 JSON 스키마를 넣어 출력 구조를 정할 수 있어요.
텍스트에서 구조화된 데이터를 뽑아내거나, 특정 형식을 맞춰야 하는 응답이 필요할 때 유용해요.
from pydantic import BaseModel
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
class NobelPrizeInfo(BaseModel):
recipient_name: str
award_year: int
category: str
achievement_description: str
nationality: str
client = OpenAIChatGenerator(
model="gpt-4o-2024-08-06",
generation_kwargs={"response_format": NobelPrizeInfo},
)
response = client.run(
messages=[
ChatMessage.from_user(
"In 2021, American scientist David Julius received the Nobel Prize in"
" Physiology or Medicine for his groundbreaking discoveries on how the human body"
" senses temperature and touch.",
),
],
)
print(response["replies"][0].text)
# {"recipient_name":"David Julius","award_year":2021,"category":"Physiology or Medicine",
# "achievement_description":"David Julius was awarded for his transformative findings
# regarding the molecular mechanisms underlying the human body's sense of temperature
# and touch. Through innovative experiments, he identified specific receptors responsible
# for detecting heat and mechanical stimuli, ranging from gentle touch to pain-inducing
# pressure.","nationality":"American"}
모델 호환성과 제한 사항
- Pydantic 모델과 JSON 스키마는
gpt-4o-2024-08-06이후의 최신 모델부터 지원돼요.- 예전 모델은
{"type": "json_object"}를 통한 기본 JSON 모드만 지원해요. 자세한 내용은 OpenAI JSON mode 문서를 참고하세요.- 스트리밍 제한: 구조화 출력과 함께 스트리밍을 쓸 때는 Pydantic 모델 대신
response_format에 JSON 스키마를 넣어야 해요.- 전체 정보는 OpenAI Structured Outputs 문서를 확인하세요.
스트리밍
생성되는 대로 출력을 스트리밍할 수 있어요. streaming_callback에 콜백을 넘기면 되고, 내장된 print_streaming_chunk를 쓰면 텍스트 토큰과 도구 이벤트(도구 호출과 도구 결과)를 출력해 줘요.
from haystack.components.generators.chat.openai import OpenAIChatGenerator
from haystack.components.generators.utils import print_streaming_chunk
# Configure any `ChatGenerator` with a streaming callback
component = OpenAIChatGenerator(streaming_callback=print_streaming_chunk)
# pass a list of messages or a single string to `run()`
from haystack.dataclasses import ChatMessage
component.run([ChatMessage.from_user("Your question here")])
스트리밍은 단일 응답에서만 동작해요. 제공자가 여러 후보를 지원한다면
n=1로 설정하세요.
StreamingChunk가 어떻게 동작하는지, 커스텀 콜백을 어떻게 쓰는지는 Streaming Support 문서를 참고하세요.
기본적으로 print_streaming_chunk를 사용하는 걸 권장해요. 특정 전송 방식(예: SSE/WebSocket)이나 커스텀 UI 포맷이 필요할 때만 직접 콜백을 작성하세요.
사용법
단독으로 쓰기
기본 사용법:
from haystack.dataclasses import ChatMessage
from haystack.components.generators.chat import OpenAIChatGenerator
client = OpenAIChatGenerator()
response = client.run(
[ChatMessage.from_user("What's Natural Language Processing? Be brief.")],
)
print(response)
# {'replies': [ChatMessage(_role=<ChatRole.ASSISTANT: 'assistant'>, _content=
# [TextContent(text='Natural Language Processing (NLP) is a field of artificial
# intelligence that focuses on the interaction between computers and humans through
# natural language. It involves enabling machines to understand, interpret, and
# generate human language in a meaningful way, facilitating tasks such as
# language translation, sentiment analysis, and text summarization.')],
# _name=None, _meta={'model': 'gpt-5-mini-2025-08-07', 'index': 0,
# 'finish_reason': 'stop', 'usage': {'completion_tokens': 59, 'prompt_tokens': 15,
# 'total_tokens': 74, 'completion_tokens_details': {'accepted_prediction_tokens':
# 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0},
# 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}})]}
스트리밍 사용:
from haystack.dataclasses import ChatMessage
from haystack.components.generators.chat import OpenAIChatGenerator
client = OpenAIChatGenerator(
streaming_callback=lambda chunk: print(chunk.content, end="", flush=True),
)
response = client.run(
[ChatMessage.from_user("What's Natural Language Processing? Be brief.")],
)
print(response)
# Natural Language Processing (NLP) is a field of artificial intelligence that
# focuses on the interaction between computers and humans through natural language.
# It involves enabling machines to understand, interpret, and generate human
# language in a way that is both meaningful and useful. NLP encompasses various
# tasks, including speech recognition, language translation, sentiment analysis,
# and text summarization.{'replies': [ChatMessage(_role=<ChatRole.ASSISTANT:
# 'assistant'>, _content=[TextContent(text='Natural Language Processing (NLP) is a
# field of artificial intelligence that focuses on the interaction between computers
# and humans through natural language. It involves enabling machines to understand,
# interpret, and generate human language in a way that is both meaningful and
# useful. NLP encompasses various tasks, including speech recognition, language
# translation, sentiment analysis, and text summarization.')], _name=None, _meta={'
# model': 'gpt-5-mini-2025-08-07', 'index': 0, 'finish_reason': 'stop',
# 'completion_start_time': '2025-05-15T13:32:16.572912', 'usage': None})]}
멀티모달 입력:
from haystack.dataclasses import ChatMessage, ImageContent
from haystack.components.generators.chat import OpenAIChatGenerator
llm = OpenAIChatGenerator(model="gpt-4o-mini")
image = ImageContent.from_file_path("apple.jpg", detail="low")
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.
파이프라인 안에서 쓰기
from haystack.components.builders import ChatPromptBuilder
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from haystack import Pipeline
from haystack.utils import Secret
# no parameter init, we don't use any runtime template variables
prompt_builder = ChatPromptBuilder()
llm = OpenAIChatGenerator(
api_key=Secret.from_env_var("OPENAI_API_KEY"),
model="gpt-4o-mini",
)
pipe = Pipeline()
pipe.add_component("prompt_builder", prompt_builder)
pipe.add_component("llm", llm)
pipe.connect("prompt_builder.prompt", "llm.messages")
location = "Berlin"
messages = [
ChatMessage.from_system(
"Always respond in German even if some input data is in other languages.",
),
ChatMessage.from_user("Tell me about {{location}}"),
]
pipe.run(
data={
"prompt_builder": {
"template_variables": {"location": location},
"template": messages,
},
},
)
# {'llm': {'replies': [ChatMessage(_role=<ChatRole.ASSISTANT: 'assistant'>,
# _content=[TextContent(text='Berlin ist die Hauptstadt Deutschlands und eine der
# bedeutendsten Städte Europas. Es ist bekannt für ihre reiche Geschichte,
# kulturelle Vielfalt und kreative Scene. \n\nDie Stadt hat eine bewegte
# Vergangenheit, die stark von der Teilung zwischen Ost- und Westberlin während
# des Kalten Krieges geprägt war. Die Berliner Mauer, die von 1961 bis 1989 die
# Stadt teilte, ist heute ein Symbol für die Wiedervereinigung und die Freiheit.
# \n\nBerlin bietet eine Fülle von Sehenswürdigkeiten, darunter das Brandenburger
# Tor, den Reichstag, die Museumsinsel und den Alexanderplatz. Die Stadt ist auch
# für ihre lebendige Kunst- und Musikszene bekannt, mit zahlreichen Galerien,
# Theatern und Clubs. ')], _name=None, _meta={'model': 'gpt-4o-mini-2024-07-18',
# 'index': 0, 'finish_reason': 'stop', 'usage': {'completion_tokens': 260,
# 'prompt_tokens': 29, 'total_tokens': 289, 'completion_tokens_details':
# {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0,
# 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0,
# 'cached_tokens': 0}}})]}}
YAML로 쓰기
위 파이프라인의 YAML 표현이에요. 프롬프트를 동적으로 구성하고 채팅 모델로 답변을 생성해 줘요.
components:
llm:
init_parameters:
api_base_url: null
api_key:
env_vars:
- OPENAI_API_KEY
strict: true
type: env_var
generation_kwargs: {}
http_client_kwargs: null
max_retries: null
model: gpt-4o-mini
organization: null
streaming_callback: null
timeout: null
tools: null
tools_strict: false
type: haystack.components.generators.chat.openai.OpenAIChatGenerator
prompt_builder:
init_parameters:
required_variables: '*'
template: null
variables: null
type: haystack.components.builders.chat_prompt_builder.ChatPromptBuilder
connection_type_validation: true
connections:
- receiver: llm.messages
sender: prompt_builder.prompt
max_runs_per_component: 100
metadata: {}