Documentation Index
Fetch the complete documentation index at: https://mintlify.com/phpaisdk/openai-compatible/llms.txt
Use this file to discover all available pages before exploring further.
ChatMessageConverter handles every content type that the portable Content class can represent and converts each one to the correct OpenAI-compatible wire shape. You build messages the same way regardless of whether the content is plain text, a remote image URL, base64-encoded audio, or a PDF file — the converter figures out the right wire format automatically.
How content types map to the wire format
The converter’sconvertContent() method dispatches on $content->type and returns the appropriate object for the OpenAI messages[].content array.
Text — Content::TYPE_TEXT
Plain text content is emitted as a {type: text, text: "..."} object. When a message contains only a single text part, the converter flattens it to a bare string instead of wrapping it in a single-element array — this keeps the payload concise and maximizes provider compatibility.
The flattening to a plain string only applies when the message has exactly one content part and that part is text. As soon as a second part (image, audio, or file) is added, all parts — including the text part — are serialized as a typed content array.
Images — Content::TYPE_IMAGE
Images can be passed as remote URLs or as raw base64 data. Both are mapped to the image_url content type; the URL versus data-URI distinction is handled inside the converter.
URL image:
Audio — Content::TYPE_AUDIO
Audio content is mapped to input_audio with the raw base64 data and a normalized format string. The MIME type is resolved to one of three format tokens:
| MIME type | Wire format value |
|---|---|
audio/mpeg or audio/mp3 | mp3 |
audio/wav or audio/x-wav | wav |
audio/ogg | ogg |
| (anything else) | wav |
Files — Content::TYPE_FILE
File content (PDFs, documents, etc.) is mapped to the file content type with a filename and a file_data field. When the content source is base64, file_data is a full data URI; when the source is a URL, the URL is passed directly.
Full multimodal example
The following example is drawn directly fromChatWireFormatTest.php and shows all four content types in a single user message:
System prompts
System messages are prepended to themessages array as a plain {role: system, content: "..."} entry. Pass the system prompt through TextModelRequest::$system — never add it manually as a Message::system() entry, as the converter handles the insertion automatically.
Content type summary
Text
Content::text('...') → {type: text, text: "..."} (or bare string when it’s the only part)Image
Content::image(url) → {type: image_url, image_url: {url: "..."}}Content::image(base64, ...) → data URI wrapped in image_urlAudio
Content::audio(base64, mimeType: ...) → {type: input_audio, input_audio: {data, format}}Format resolved from MIME type: mp3, wav, or oggFile
Content::file(base64, mimeType, filename, ...) → {type: file, file: {filename, file_data}}file_data is a full data URI when source is base64