calute.types.messages#
Message type definitions for Calute.
This module provides a comprehensive message system for handling conversations with LLM models. It includes: - Content chunk types for text, images, and image URLs - Message types for different conversation roles (system, user, assistant, tool) - Message history management with OpenAI format conversion - Support for multimodal content including images and text
The message system follows a type-safe design using Pydantic models with discriminated unions for proper serialization and validation.
Example
>>> from calute.types.messages import UserMessage, MessagesHistory
>>> user_msg = UserMessage(content="Hello, how can I help you?")
>>> history = MessagesHistory(messages=[user_msg])
>>> openai_format = history.to_openai()
- class calute.types.messages.AssistantMessage(*, role: ~typing.Literal[<Roles.assistant: 'assistant'>] = Roles.assistant, content: str | None = None, tool_calls: list[calute.types.tool_calls.ToolCall] | None = None, prefix: bool = False)[source]#
Bases:
BaseMessageMessage generated by the AI assistant.
Represents the model’s response in a conversation. May contain text content, tool/function calls, or both. The
prefixflag indicates whether this message should be treated as a prefix-fill for the next generation (used by some model APIs).- role#
The message role, always
Roles.assistant.- Type
Literal[<Roles.assistant: ‘assistant’>]
- content#
The text content of the assistant’s response, or None if the response consists only of tool calls.
- Type
str | None
- tool_calls#
Optional list of
ToolCallobjects representing function/tool invocations requested by the model.- Type
list[calute.types.tool_calls.ToolCall] | None
- prefix#
Whether this message serves as a prefix for continued generation (default: False).
- Type
bool
Example
>>> message = AssistantMessage(content="Hello, how can I help you?") >>> message.to_openai() {'role': 'assistant', 'content': 'Hello, how can I help you?'}
- content: str | None#
- classmethod from_openai(openai_message: dict[str, str | list[dict[str, str | dict[str, Any]]]]) AssistantMessage[source]#
Create an AssistantMessage from an OpenAI-format message dictionary.
Parses both the text content and any tool calls from the OpenAI message format.
- Parameters
openai_message – A dictionary with
roleset to"assistant", optionalcontentstring, and optionaltool_callslist.- Returns
A new AssistantMessage instance with parsed content and tool calls.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- prefix: bool#
- role: assistant: 'assistant'>]#
- to_openai() dict[str, str | list[dict[str, str | dict[str, Any]]]][source]#
Convert the assistant message to OpenAI API format.
Always includes
contentso OpenAI-compatible servers that require the field for tool-call turns still accept the payload.- Returns
A dictionary with
role,content, and optionallytool_callskeys in OpenAI format.
- tool_calls: list[calute.types.tool_calls.ToolCall] | None#
- class calute.types.messages.BaseContentChunk(*, type: ~typing.Literal[<ChunkTypes.text: 'text'>, <ChunkTypes.image: 'image'>, <ChunkTypes.image_url: 'image_url'>])[source]#
Bases:
CaluteBaseAbstract base class for all content chunks in multimodal messages.
Content chunks represent individual pieces of content within a message, such as text passages, images, or image URLs. Subclasses must implement the
to_openaiandfrom_openaimethods for format conversion.- type#
The discriminator type of the chunk, one of ‘text’, ‘image’, or ‘image_url’.
- Type
Literal[<ChunkTypes.text: ‘text’>, <ChunkTypes.image: ‘image’>, <ChunkTypes.image_url: ‘image_url’>]
- classmethod from_openai(openai_chunk: dict[str, str | dict[str, str]]) BaseContentChunk[source]#
Create a content chunk from an OpenAI-format dictionary.
Must be implemented by subclasses to parse the OpenAI content chunk format into the appropriate Calute chunk type.
- Parameters
openai_chunk – A dictionary in OpenAI content chunk format containing at minimum a ‘type’ key.
- Returns
An instance of the appropriate BaseContentChunk subclass.
- Raises
NotImplementedError – Always raised in the base class; subclasses must override this method.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_openai() dict[str, str | dict[str, str]][source]#
Convert this content chunk to the OpenAI API format.
Must be implemented by subclasses to provide the appropriate dictionary representation for the OpenAI messages API.
- Returns
A dictionary in OpenAI content chunk format with a ‘type’ key and type-specific content keys.
- Raises
NotImplementedError – Always raised in the base class; subclasses must override this method.
- type: image_url: 'image_url'>]#
- class calute.types.messages.BaseMessage(*, role: ~typing.Literal[<Roles.system: 'system'>, <Roles.user: 'user'>, <Roles.assistant: 'assistant'>, <Roles.tool: 'tool'>])[source]#
Bases:
CaluteBaseAbstract base class for all chat message types.
Provides the common interface for message serialization to and from OpenAI format. Subclasses implement role-specific content handling and serialization logic.
- role#
The role of the message sender, one of
system,user,assistant, ortool.- Type
Literal[<Roles.system: ‘system’>, <Roles.user: ‘user’>, <Roles.assistant: ‘assistant’>, <Roles.tool: ‘tool’>]
- classmethod from_openai(openai_message: dict[str, str | list[dict[str, str | dict[str, Any]]]]) BaseMessage[source]#
Create a message instance from an OpenAI-format dictionary.
Must be implemented by subclasses to parse OpenAI-format message dictionaries into the appropriate Calute message type.
- Parameters
openai_message – A dictionary in OpenAI message format containing at minimum a
rolekey.- Returns
An instance of the appropriate BaseMessage subclass.
- Raises
NotImplementedError – Always raised in the base class; subclasses must override this method.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- role: tool: 'tool'>]#
- to_openai() dict[str, str | list[dict[str, str | dict[str, Any]]]][source]#
Convert this message to the OpenAI API format.
Must be implemented by subclasses to produce a dictionary compatible with the OpenAI chat completion messages format.
- Returns
A dictionary with at minimum
roleandcontentkeys, formatted for the OpenAI API.- Raises
NotImplementedError – Always raised in the base class; subclasses must override this method.
- class calute.types.messages.ChunkTypes(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#
Bases:
StrEnumEnumeration of content chunk types supported in messages.
Defines the different types of content chunks that can be included in multimodal messages sent to LLM models.
- text#
A plain text content chunk.
- image#
A binary image content chunk (PIL Image or base64-encoded).
- image_url#
An image referenced by URL or base64 data URI.
Example
>>> from calute.types.messages import ChunkTypes >>> chunk_type = ChunkTypes.text >>> chunk_type.value 'text'
- image = 'image'#
- image_url = 'image_url'#
- text = 'text'#
- class calute.types.messages.ImageChunk(*, type: ~typing.Literal[<ChunkTypes.image: 'image'>] = ChunkTypes.image, image: ~PIL.Image.Image)[source]#
Bases:
BaseContentChunkContent chunk containing a binary image.
Wraps a PIL Image or base64-encoded image data for inclusion in multimodal messages. When converted to OpenAI format, the image is serialized as a base64 data URI within an
image_urlstructure.- type#
Chunk type discriminator, always
ChunkTypes.image.- Type
Literal[<ChunkTypes.image: ‘image’>]
- image#
The image data, either a PIL Image object or a base64 string, wrapped in a SerializableImage for Pydantic compatibility.
- Type
PIL.Image.Image
Example
>>> from PIL import Image >>> image_chunk = ImageChunk(image=Image.new('RGB', (200, 200), color='blue'))
- classmethod from_openai(openai_chunk: dict[str, str | dict[str, str]]) ImageChunk[source]#
Create an ImageChunk from an OpenAI-format image_url dictionary.
Parses the base64 data URI from the OpenAI format, stripping the
data:image/...;base64,prefix if present, and creates an ImageChunk with the raw base64 image data.- Parameters
openai_chunk – A dictionary with
typeset to"image_url"and animage_urlsub-dictionary containing aurlkey.- Returns
A new ImageChunk instance with the parsed image data.
- Raises
AssertionError – If the chunk type is not
"image_url"or theimage_urldictionary is malformed.
- image: Image#
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_openai() dict[str, str | dict[str, str]][source]#
Convert the image chunk to OpenAI API format.
Serializes the image to a base64 data URI and wraps it in the OpenAI
image_urlcontent chunk format.- Returns
A dictionary with
typeset to"image_url"and animage_urlsub-dictionary containing the base64 data URI.
- type: image: 'image'>]#
- class calute.types.messages.ImageURL(*, url: str, detail: str | None = None)[source]#
Bases:
CaluteBaseRepresents an image reference by URL or base64-encoded data URI.
Used within
ImageURLChunkto specify the image source and optional detail level for vision-capable models.- url#
The URL of the image or a base64-encoded data URI string (e.g.,
"data:image/png;base64,..."or"https://...").- Type
str
- detail#
Optional detail level hint for the model (e.g.,
"low","high","auto"). Controls image processing resolution.- Type
str | None
Example
>>> image_url = ImageURL(url="https://example.com/image.png", detail="high")
- detail: str | None#
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- url: str#
- class calute.types.messages.ImageURLChunk(*, type: ~typing.Literal[<ChunkTypes.image_url: 'image_url'>] = ChunkTypes.image_url, image_url: calute.types.messages.ImageURL | str)[source]#
Bases:
BaseContentChunkContent chunk containing an image referenced by URL or data URI.
Supports both plain URL strings and structured
ImageURLobjects with optional detail level hints for vision-capable models.- type#
Chunk type discriminator, always
ChunkTypes.image_url.- Type
Literal[<ChunkTypes.image_url: ‘image_url’>]
- image_url#
The image reference, either an
ImageURLobject withurland optionaldetailfields, or a plain URL string.- Type
Example
>>> chunk = ImageURLChunk(image_url="https://example.com/photo.jpg") >>> chunk_with_detail = ImageURLChunk( ... image_url=ImageURL(url="https://example.com/photo.jpg", detail="high") ... )
- classmethod from_openai(openai_chunk: dict[str, str | dict[str, str]]) ImageURLChunk[source]#
Create an ImageURLChunk from an OpenAI-format content chunk dictionary.
- Parameters
openai_chunk – A dictionary with an
image_urlkey containing either a URL string or a dictionary withurland optionaldetailkeys.- Returns
A new ImageURLChunk instance parsed from the OpenAI format.
- get_url() str[source]#
Extract the URL string from the image_url attribute.
Handles both
ImageURLobjects and plain string URLs, providing a uniform way to access the underlying URL.- Returns
The URL string for the image, regardless of whether
image_urlis anImageURLinstance or a plain string.
- image_url: calute.types.messages.ImageURL | str#
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_openai() dict[str, str | dict[str, str]][source]#
Convert the image URL chunk to OpenAI API format.
Creates an OpenAI-compatible content chunk dictionary with the image URL and optional detail level.
- Returns
A dictionary with
typeset to"image_url"and animage_urlsub-dictionary containing the URL and optionally adetailkey.
- type: image_url: 'image_url'>]#
- class calute.types.messages.MessagesHistory(*, messages: list[typing.Annotated[calute.types.messages.SystemMessage | calute.types.messages.UserMessage | calute.types.messages.AssistantMessage | calute.types.messages.ToolMessage, FieldInfo(annotation=NoneType, required=True, discriminator='role')]])[source]#
Bases:
CaluteBaseContainer for managing a sequence of chat messages.
Provides a structured container for storing and manipulating chat conversation history. Supports conversion to/from OpenAI format and generation of instruction prompts for model input.
- messages#
List of chat messages in the conversation. Each message is discriminated by its role (system, user, assistant, or tool).
- Type
list[Annotated[calute.types.messages.SystemMessage | calute.types.messages.UserMessage | calute.types.messages.AssistantMessage | calute.types.messages.ToolMessage, FieldInfo(annotation=NoneType, required=True, discriminator=’role’)]]
Example
>>> from calute.types.messages import UserMessage, AssistantMessage, MessagesHistory >>> history = MessagesHistory(messages=[ ... UserMessage(content="Hello!"), ... AssistantMessage(content="Hi there! How can I help you?"), ... ]) >>> openai_format = history.to_openai()
- classmethod from_openai(openai_messages: list[dict[str, str | list[dict[str, str | dict[str, Any]]]]]) MessagesHistory[source]#
Create a MessagesHistory from OpenAI format messages.
Converts a list of OpenAI format message dictionaries into a MessagesHistory instance with properly typed message objects.
- Parameters
openai_messages – List of message dictionaries in OpenAI format. Each dictionary must contain a ‘role’ field to determine the message type.
- Returns
A MessagesHistory instance containing the converted messages.
Example
>>> openai_msgs = [ ... {"role": "user", "content": "Hello!"}, ... {"role": "assistant", "content": "Hi there!"}, ... ] >>> history = MessagesHistory.from_openai(openai_msgs)
- make_instruction_prompt(conversation_name_holder: str = 'Messages', mention_last_turn: bool = True) str[source]#
Format the message history into a human-readable instruction prompt.
Converts the entire message history into a single, structured string suitable for LLM input. Tool calls are rendered in canonical XML format to encourage the LLM to follow the same pattern.
- Parameters
conversation_name_holder – The section header name for the conversation history section (default: “Messages”).
mention_last_turn – Whether to append a summary of the last message at the end of the prompt (default: True).
- Returns
A formatted string containing the instruction prompt with all messages properly structured and indented.
- messages: list[typing.Annotated[calute.types.messages.SystemMessage | calute.types.messages.UserMessage | calute.types.messages.AssistantMessage | calute.types.messages.ToolMessage, FieldInfo(annotation=NoneType, required=True, discriminator='role')]]#
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_openai() list[dict[str, str | list[dict[str, str | dict[str, Any]]]]][source]#
Convert all messages to OpenAI API format.
Iterates through all messages, converts each to OpenAI format, and filters out system messages with empty content.
- Returns
A dictionary with a
messageskey containing a list of OpenAI-format message dictionaries.
- class calute.types.messages.Roles(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#
Bases:
StrEnumEnumeration of message roles in a chat conversation.
Defines the four standard roles used in chat completion APIs to distinguish between different participants in a conversation.
- system#
The system role, used for initial instructions and context.
- user#
The user role, representing the human participant.
- assistant#
The assistant role, representing the AI model’s responses.
- tool#
The tool role, used for function/tool execution results.
Example
>>> role = Roles.user >>> role.value 'user'
- assistant = 'assistant'#
- system = 'system'#
- tool = 'tool'#
- user = 'user'#
- class calute.types.messages.SystemMessage(*, role: ~typing.Literal[<Roles.system: 'system'>] = Roles.system, content: str | list[typing.Annotated[calute.types.messages.TextChunk | calute.types.messages.ImageChunk | calute.types.messages.ImageURLChunk, FieldInfo(annotation=NoneType, required=True, discriminator='type')]])[source]#
Bases:
BaseMessageSystem-level instruction message for configuring model behavior.
System messages set the context, personality, and constraints for the AI assistant. They are typically placed at the beginning of a conversation and support both plain text and multimodal content.
- role#
The message role, always
Roles.system.- Type
Literal[<Roles.system: ‘system’>]
- content#
The system instruction content, either a plain text string or a list of
ContentChunkobjects.- Type
str | list[Annotated[calute.types.messages.TextChunk | calute.types.messages.ImageChunk | calute.types.messages.ImageURLChunk, FieldInfo(annotation=NoneType, required=True, discriminator=’type’)]]
Example
>>> message = SystemMessage(content="You are a helpful assistant.") >>> message.to_openai() {'role': 'system', 'content': 'You are a helpful assistant.'}
- content: str | list[typing.Annotated[calute.types.messages.TextChunk | calute.types.messages.ImageChunk | calute.types.messages.ImageURLChunk, FieldInfo(annotation=NoneType, required=True, discriminator='type')]]#
- classmethod from_openai(openai_message: dict[str, str | list[dict[str, str | dict[str, Any]]]]) SystemMessage[source]#
Create a SystemMessage from an OpenAI-format message dictionary.
- Parameters
openai_message – A dictionary with
roleset to"system"and acontentkey containing either a string or a list of content chunk dictionaries.- Returns
A new SystemMessage instance with properly typed content.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- role: system: 'system'>]#
- class calute.types.messages.TextChunk(*, type: ~typing.Literal[<ChunkTypes.text: 'text'>] = ChunkTypes.text, text: str)[source]#
Bases:
BaseContentChunkContent chunk containing plain text.
The most common content chunk type, representing a segment of text within a multimodal message.
- type#
Chunk type discriminator, always
ChunkTypes.text.- Type
Literal[<ChunkTypes.text: ‘text’>]
- text#
The text content string.
- Type
str
Example
>>> text_chunk = TextChunk(text="Hello, how can I help you?") >>> text_chunk.to_openai() {'type': 'text', 'text': 'Hello, how can I help you?'}
- classmethod from_openai(messages: dict[str, str | dict[str, str]]) TextChunk[source]#
Create a TextChunk from an OpenAI-format content chunk dictionary.
- Parameters
messages – A dictionary with
typeset to"text"and atextkey containing the text content.- Returns
A new TextChunk instance with the parsed text.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- text: str#
- to_openai() dict[str, str | dict[str, str]][source]#
Convert the text chunk to OpenAI API format.
- Returns
A dictionary with
typeset to"text"and atextkey containing the text content.
- type: text: 'text'>]#
- class calute.types.messages.ToolMessage(*, role: ~typing.Literal[<Roles.tool: 'tool'>] = Roles.tool, content: str, tool_call_id: str | None = None)[source]#
Bases:
BaseMessageMessage containing the result of a tool/function call execution.
Tool messages are sent after a function has been executed to provide the result back to the model. Each tool message must reference the specific tool call it responds to via
tool_call_id.- content#
The string result of the tool execution.
- Type
str
- role#
The message role, always
Roles.tool.- Type
Literal[<Roles.tool: ‘tool’>]
- tool_call_id#
The unique identifier of the tool call this message responds to. Must not be None when converting to OpenAI format.
- Type
str | None
Example
>>> message = ToolMessage( ... content='{"temperature": 72, "unit": "fahrenheit"}', ... tool_call_id="call_abc123" ... )
- content: str#
- classmethod from_openai(messages: dict[str, str | list[dict[str, str | dict[str, Any]]]]) ToolMessage[source]#
Create a ToolMessage from an OpenAI-format message dictionary.
- Parameters
messages – A dictionary with
roleset to"tool", acontentstring, and atool_call_idstring.- Returns
A new ToolMessage instance with the parsed content and tool call ID.
- Raises
AssertionError – If
tool_call_idis not present in the input, as it is required for tool messages.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- role: tool: 'tool'>]#
- to_openai() dict[str, str | list[dict[str, str | dict[str, Any]]]][source]#
Convert the tool message to OpenAI API format.
- Returns
A dictionary with
role,content, andtool_call_idkeys.- Raises
AssertionError – If
tool_call_idis None, as OpenAI requires tool messages to reference a specific tool call.
- tool_call_id: str | None#
- class calute.types.messages.UserMessage(*, role: ~typing.Literal[<Roles.user: 'user'>] = Roles.user, content: str | list[typing.Annotated[calute.types.messages.TextChunk | calute.types.messages.ImageChunk | calute.types.messages.ImageURLChunk, FieldInfo(annotation=NoneType, required=True, discriminator='type')]])[source]#
Bases:
BaseMessageMessage from the user in a chat conversation.
Supports both plain text content and multimodal content consisting of a list of content chunks (text, images, image URLs).
- role#
The message role, always
Roles.user.- Type
Literal[<Roles.user: ‘user’>]
- content#
The message content, either a plain text string or a list of
ContentChunkobjects for multimodal messages.- Type
str | list[Annotated[calute.types.messages.TextChunk | calute.types.messages.ImageChunk | calute.types.messages.ImageURLChunk, FieldInfo(annotation=NoneType, required=True, discriminator=’type’)]]
Example
>>> message = UserMessage(content="Can you help me to write a poem?") >>> message.role <Roles.user: 'user'>
- content: str | list[typing.Annotated[calute.types.messages.TextChunk | calute.types.messages.ImageChunk | calute.types.messages.ImageURLChunk, FieldInfo(annotation=NoneType, required=True, discriminator='type')]]#
- classmethod from_openai(openai_message: dict[str, str | list[dict[str, str | dict[str, Any]]]]) UserMessage[source]#
Create a UserMessage from an OpenAI-format message dictionary.
Handles both plain text content strings and lists of content chunk dictionaries for multimodal messages.
- Parameters
openai_message – A dictionary with
roleset to"user"and acontentkey containing either a string or a list of content chunk dictionaries.- Returns
A new UserMessage instance with properly typed content.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'use_enum_values': True, 'validate_default': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- role: user: 'user'>]#
- to_openai() dict[str, str | list[dict[str, str | dict[str, Any]]]][source]#
Convert the user message to OpenAI API format.
Handles both plain text content (returned as a string) and multimodal content (returned as a list of content chunk dictionaries).
- Returns
A dictionary with
roleandcontentkeys in OpenAI format.