ChatMessage

ChatMessage

LLM과 주고받는 메시지를 표현하는 가장 중심적인 데이터 클래스가 바로 ChatMessage예요. 메시지에는 역할(role)과 메타데이터가 담기고, 본문은 텍스트·이미지·파일·툴 호출·툴 호출 결과·추론 내용 등 여러 종류의 콘텐츠를 수용할 수 있어요.

ChatMessage 인스턴스를 만들 때는 from_user, from_system, from_assistant, from_tool 이렇게 네 가지 클래스 메서드를 사용해요.

그리고 본문 콘텐츠text, texts, image, images, file, files, tool_call, tool_calls, tool_call_result, tool_call_results, reasoning, reasonings 같은 프로퍼티로 꺼내 볼 수 있어요.

이 데이터 클래스의 메서드와 파라미터 상세가 궁금하다면 API 문서를 확인해 보세요.

출처: 공식문서

콘텐츠 종류 (Types of Content)

ChatMessage는 현재 TextContent, ImageContent, FileContent, ToolCall, ToolCallResult, ReasoningContent 이렇게 여섯 종류의 콘텐츠를 지원해요.

@dataclass
class TextContent:
    """
    The textual content of a chat message.

    :param text: The text content of the message.
    """

    text: str


@dataclass
class ToolCall:
    """
    Represents a Tool call prepared by the model, usually contained in an assistant message.

    :param tool_name: The name of the Tool to call.
    :param arguments: The arguments to call the Tool with.
    :param id: The ID of the Tool call.
    :param extra: Dictionary of extra information about the Tool call. Use to store provider-specific
        information. To avoid serialization issues, values should be JSON serializable.
    """

    tool_name: str
    arguments: Dict[str, Any]
    id: Optional[str] = None  # noqa: A003
    extra: Optional[Dict[str, Any]] = None


@dataclass
class ToolCallResult:
    """
    Represents the result of a Tool invocation.

    :param result: The result of the Tool invocation.
    :param origin: The Tool call that produced this result.
    :param error: Whether the Tool invocation resulted in an error.
    """

    result: str | Sequence[TextContent | ImageContent]
    origin: ToolCall
    error: bool


@dataclass
class ImageContent:
    """
    The image content of a chat message.

    :param base64_image: A base64 string representing the image.
    :param mime_type: The MIME type of the image (e.g. "image/png", "image/jpeg").
        Providing this value is recommended, as most LLM providers require it.
        If not provided, the MIME type is guessed from the base64 string, which can be slow and not always reliable.
    :param detail: Optional detail level of the image (only supported by OpenAI). One of "auto", "high", or "low".
    :param meta: Optional metadata for the image.
    :param validation: If True (default), a validation process is performed:
        - Check whether the base64 string is valid;
        - Guess the MIME type if not provided;
        - Check if the MIME type is a valid image MIME type.
        Set to False to skip validation and speed up initialization.
    """

    base64_image: str
    mime_type: Optional[str] = None
    detail: Optional[Literal["auto", "high", "low"]] = None
    meta: Dict[str, Any] = field(default_factory=dict)
    validation: bool = True


@dataclass
class FileContent:
    """
    The file content of a chat message.

    :param base64_data: A base64 string representing the file.
    :param mime_type: The MIME type of the file (e.g. "application/pdf").
        Providing this value is recommended, as most LLM providers require it.
        If not provided, the MIME type is guessed from the base64 string, which can be slow and not always reliable.
    :param filename: Optional filename of the file. Some LLM providers use this information.
    :param extra: Dictionary of extra information about the file. Can be used to store provider-specific information.
        To avoid serialization issues, values should be JSON serializable.
    :param validation: If True (default), a validation process is performed:
        - Check whether the base64 string is valid;
        - Guess the MIME type if not provided.
        Set to False to skip validation and speed up initialization.
    """

    base64_data: str
    mime_type: str | None = None
    filename: str | None = None
    extra: dict[str, Any] = field(default_factory=dict)
    validation: bool = True


@dataclass
class ReasoningContent:
    """
    Represents the optional reasoning content prepared by the model, usually contained in an assistant message.

    :param reasoning_text: The reasoning text produced by the model.
    :param extra: Dictionary of extra information about the reasoning content. Use to store provider-specific
        information. To avoid serialization issues, values should be JSON serializable.
    """

    reasoning_text: str
    extra: Dict[str, Any] = field(default_factory=dict)

ImageContentFileContent는 편의용 클래스 메서드인 from_file_pathfrom_url도 제공해요. 더 자세한 내용은 API 문서를 참고하세요.

ChatMessage 다루기

아래 예시들은 ChatMessage를 만들고 그 프로퍼티를 확인하는 흐름을 보여줘요.

from_user + TextContent

from haystack.dataclasses import ChatMessage

user_message = ChatMessage.from_user("What is the capital of Australia?")

print(user_message)
# >> ChatMessage(
# >>    _role=<ChatRole.USER: 'user'>,
# >>    _content=[TextContent(text='What is the capital of Australia?')],
# >>    _name=None,
# >>    _meta={}
# >> )

print(user_message.text)
# >> What is the capital of Australia?

print(user_message.texts)
# >> ['What is the capital of Australia?']

from_user + TextContent와 ImageContent

from haystack.dataclasses import ChatMessage, ImageContent

lion_image_url = (
    "https://images.unsplash.com/photo-1546182990-dffeafbe841d?"
    "ixlib=rb-4.0&q=80&w=1080&fit=max"
)

image_content = ImageContent.from_url(lion_image_url, detail="low")

user_message = ChatMessage.from_user(
    content_parts=["What does the image show?", image_content]
)

print(user_message)
# >> ChatMessage(
# >>     _role=<ChatRole.USER: 'user'>,
# >>     _content=[
# >>         TextContent(text='What does the image show?'),
# >>         ImageContent(
# >>             base64_image='/9j/4...',
# >>             mime_type='image/jpeg',
# >>             detail='low',
# >>             meta={
# >>                 'content_type': 'image/jpeg',
# >>                 'url': '...'
# >>             }
# >>         )
# >>     ],
# >>     _name=None,
# >>     _meta={}
# >> )

print(user_message.text)
# >> What does the image show?

print(user_message.texts)
# >> ['What does the image show?']

print(user_message.image)
# >> ImageContent(
# >>     base64_image='/9j/4...',
# >>     mime_type='image/jpeg',
# >>     detail='low',
# >>     meta={
# >>         'content_type': 'image/jpeg',
# >>         'url': '...'
# >>     }
# >> )

from_user + TextContent와 FileContent

from haystack.dataclasses import ChatMessage, FileContent

paper_url = "https://arxiv.org/pdf/2309.08632"

file_content = FileContent.from_url(paper_url)

user_message = ChatMessage.from_user(
    content_parts=[file_content, "Summarize this paper in 100 words."]
)

print(user_message)
# >> ChatMessage(
# >>     _role=<ChatRole.USER: 'user'>,
# >>     _content=[
# >>         FileContent(
# >>             base64_data='JVBERi0...',
# >>             mime_type='application/pdf',
# >>             filename='2309.08632',
# >>             extra={}
# >>         ),
# >>         TextContent(text='Summarize this paper in 100 words.')
# >>     ],
# >>     _name=None,
# >>     _meta={}
# >> )

print(user_message.text)
# >> Summarize this paper in 100 words.

print(user_message.texts)
# >> ['Summarize this paper in 100 words.']

print(user_message.file)
# >> FileContent(
# >>     base64_data='JVBERi0...',
# >>     mime_type='application/pdf',
# >>     filename='2309.08632',
# >>     extra={}
# >> )

from_assistant + TextContent

from haystack.dataclasses import ChatMessage

assistant_message = ChatMessage.from_assistant("How can I assist you today?")

print(assistant_message)
# >> ChatMessage(
# >>    _role=<ChatRole.ASSISTANT: 'assistant'>,
# >>    _content=[TextContent(text='How can I assist you today?')],
# >>    _name=None,
# >>    _meta={}
# >> )

print(assistant_message.text)
# >> How can I assist you today?

print(assistant_message.texts)
# >> ['How can I assist you today?']

from_assistant + ToolCall

from haystack.dataclasses import ChatMessage, ToolCall

tool_call = ToolCall(tool_name="weather_tool", arguments={"location": "Rome"})

assistant_message_w_tool_call = ChatMessage.from_assistant(tool_calls=[tool_call])

print(assistant_message_w_tool_call)
# >> ChatMessage(
# >>    _role=<ChatRole.ASSISTANT: 'assistant'>,
# >>    _content=[ToolCall(tool_name='weather_tool', arguments={'location': 'Rome'}, id=None)],
# >>    _name=None,
# >>    _meta={}
# >> )

print(assistant_message_w_tool_call.text)
# >> None

print(assistant_message_w_tool_call.texts)
# >> []

print(assistant_message_w_tool_call.tool_call)
# >> ToolCall(tool_name='weather_tool', arguments={'location': 'Rome'}, id=None)

print(assistant_message_w_tool_call.tool_calls)
# >> [ToolCall(tool_name='weather_tool', arguments={'location': 'Rome'}, id=None)]

print(assistant_message_w_tool_call.tool_call_result)
# >> None

print(assistant_message_w_tool_call.tool_call_results)
# >> []

from_tool

from haystack.dataclasses import ChatMessage

tool_message = ChatMessage.from_tool(
    tool_result="temperature: 25°C", origin=tool_call, error=False
)

print(tool_message)
# >> ChatMessage(
# >>    _role=<ChatRole.TOOL: 'tool'>,
# >>    _content=[ToolCallResult(
# >> 						   result='temperature: 25°C',
# >>                origin=ToolCall(tool_name='weather_tool', arguments={'location': 'Rome'}, id=None),
# >>                error=False
# >>                )],
# >>    _name=None,
# >>    _meta={}
# >> )

print(tool_message.text)
# >> None

print(tool_message.texts)
# >> []

print(tool_message.tool_call)
# >> None

print(tool_message.tool_calls)
# >> []

print(tool_message.tool_call_result)
# >> ToolCallResult(
# >>     result='temperature: 25°C',
# >>     origin=ToolCall(tool_name='weather_tool', arguments={'location': 'Rome'}, id=None),
# >>     error=False
# >> )

print(tool_message.tool_call_results)
# >> [
# >>     ToolCallResult(
# >>         result='temperature: 25°C',
# >>         origin=ToolCall(tool_name='weather_tool', arguments={'location': 'Rome'}, id=None),
# >>         error=False
# >>     )
# >> ]

레거시 ChatMessage에서 마이그레이션하기 (v2.9 이전)

Haystack 2.9에서 ChatMessage 데이터 클래스가 더 유연해졌고 텍스트·툴 호출·툴 호출 결과 등 여러 콘텐츠 타입을 지원하게 되면서 바뀐 부분이 있어요. 몇 가지 breaking change(호환되지 않는 변경)가 포함돼 있으니, 이 가이드를 따라 부드럽게 옮겨 오시길 권해요.

ChatMessage 만들기

이제 role, content, metaChatMessage를 직접 초기화할 수 없어요.

  • 대신 from_assistant, from_user, from_system, from_tool 클래스 메서드를 사용하세요.
  • content 파라미터는 text로 바꿔서 쓰세요.
from haystack.dataclasses import ChatMessage

# LEGACY - DOES NOT WORK IN 2.9.0
message = ChatMessage(role=ChatRole.USER, content="Hello!")

# Use the class method instead
message = ChatMessage.from_user("Hello!")

ChatMessage 속성 접근하기

  • 레거시 content 속성은 이제 내부 속성(_content)이 됐어요.
  • ChatMessage 속성은 아래 프로퍼티로 확인하세요:
    • role
    • meta
    • name
    • texttexts
    • imageimages
    • tool_calltool_calls
    • tool_call_resulttool_call_results
    • reasoningreasonings
from haystack.dataclasses import ChatMessage

message = ChatMessage.from_user("Hello!")

# LEGACY - DOES NOT WORK IN 2.9.0
print(message.content)

# Use the appropriate property instead
print(message.text)

더 알아보기 (Learn more)