Images and Documents as Input
You can attach a photo or a PDF to a message and ask about its contents. We will look at how a file is attached, what each provider can take, and why an attached image is paid for again in every further turn of the conversation.
Ask About an Image
A message does not have to be only text. When you hand it an array instead of a string, the array can hold a file alongside the text:
use AIAccess\Media;
$chat = $client->createChat('gpt-5.6-luna');
$response = $chat->sendMessage([
'What is in this picture?',
Media::fromFile('/path/to/photo.jpg'),
]);
echo $response->getText();
Media::fromFile() loads the file and works out its content type on its own, so you do not have to tell it
anything. The model then sees the image and the question at once and answers both.
This covers a surprising amount of work: reading figures off a receipt or an invoice, having a caption written for a photo so screen readers can read it out, reading an error message from a screenshot a user sent you, or checking that an uploaded photo really shows what it should.
When the File Is Not on Disk
An image often arrives from a form or from a database and is not on disk at all. That is what fromBinary() is for,
taking the data and the content type:
$media = Media::fromBinary($bytes, 'image/png');
The file name is an optional third argument. For images it does not matter, but for documents OpenAI requires it and shows it
to the model, so a name like invoice-2026-03.pdf carries information by itself. When you leave it out, the library
fills in a generic one based on the content type so the request does not fail.
Documents, PDFs Above All
Documents are attached exactly like images:
$response = $chat->sendMessage([
'Summarize the main points of this contract.',
Media::fromFile('/path/to/contract.pdf'),
]);
They differ only in which providers accept them. The model copes with a table or a form as well, which is where ordinary text extraction in PHP breaks down. So you do not have to convert the PDF to text beforehand.
What Each Provider Accepts
| Provider | Images | Documents |
|---|---|---|
| OpenAI | ✅ | ✅ |
| Claude | ✅ | ✅ |
| Gemini | ✅ | ✅ |
| Grok | ✅ | ➖ |
| DeepSeek | ➖ | ➖ |
DeepSeek has no model that can see yet; Grok accepts images but not documents.
When you send a provider content it cannot process, you do not find out from an API error. The library notices before
the request leaves and throws AIAccess\LogicException naming the content type, so you know straight away what
was wrong:
DeepSeek cannot send image/png content: it has no vision model.
There is no point catching this exception and repeating the request. It says you are sending an image to a model that cannot see, and no further attempt will fix that; the fix belongs in the code, for instance by choosing a different provider.
An Image in the History Is Paid For Again
This is the most common unpleasant surprise on the bill. An attached image becomes part of the conversation history, and because the whole history is sent again with every further question, the image is sent and paid for again too.
Measured on a simple example: the first turn with the image cost 49 input tokens, and the second turn, which was only a short follow-up question in text, cost 64. The difference is not that short question but the image sent a second time.
With large images and longer conversations this grows quickly. There are three things you can do about it:
- Ask everything about the image at once. When you know what you need from it, ask in one message rather than in five.
- Start over once the image is exhausted. Store the model's answer and clear the conversation with
clearMessages(); carry on over the text that already describes the image. - Shrink the image beforehand. The price grows with resolution, and “is there a stamp on the invoice” needs a smaller image than reading fine print.
Where to Go Next
- Image generation – the opposite direction, when an image is to be created
- Conversation – how the history works and why it grows
- Structured output – when you need data straight out of a receipt
- Providers – what each one can do and how they differ