What is multimodal AI and how do vision models work?
Multimodal AI processes more than one type of input such as text and images together. Vision-language models like GPT-4o and Claude can read screenshots, diagrams, and photos and reason about them.
AILLMMultimodal
Overview
Early LLMs understood only text. Multimodal models accept multiple types of input: images, audio, video, and documents alongside text. Vision-language models are the most common form today - you send an image (as a URL or base64-encoded bytes) with a text prompt, and the model reasons about both together. This unlocks powerful capabilities like UI analysis, document parsing, chart reading, and visual debugging.
Key Points
- •GPT-4o, Claude 3.5, and Gemini 1.5 all accept images inline with text messages.
- •Images cost tokens too: a 1080p image costs roughly 800-1500 tokens depending on the provider.
- •Vision models can read text in images (OCR), interpret charts, describe diagrams, and compare screenshots.
- •You can pass multiple images in one request for comparison tasks.
- •Audio and video input is supported by Gemini 1.5 and GPT-4o Audio - not yet standard across all providers.
- •Models cannot access URLs directly - you must fetch the image and encode it, or use a URL that the API server can access.
Examples
Analyse an image from a URL (OpenAI)
typescriptconst response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
url: 'https://example.com/screenshot.png',
detail: 'high', // 'low' (fast, cheap) or 'high' (detailed)
},
},
{
type: 'text',
text: 'What UI issues can you see in this screenshot? List them as bullet points.',
},
],
},
],
});
console.log(response.choices[0].message.content);Send a local image as base64
typescriptimport fs from 'fs';
const imageBuffer = fs.readFileSync('chart.png');
const base64Image = imageBuffer.toString('base64');
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
url: `data:image/png;base64,${base64Image}`,
},
},
{
type: 'text',
text: 'Summarise the trend shown in this chart in one paragraph.',
},
],
},
],
});Claude vision with base64 image
typescriptconst response = await anthropicClient.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: base64Image,
},
},
{
type: 'text',
text: 'Extract all the text you can see in this image.',
},
],
},
],
});Practical use case: parse a receipt image
typescriptimport { z } from 'zod';
const ReceiptSchema = z.object({
merchant: z.string(),
date: z.string(),
total: z.number(),
items: z.array(z.object({
name: z.string(),
quantity: z.number(),
price: z.number(),
})),
currency: z.string(),
});
async function parseReceipt(imageBase64: string) {
const response = await client.chat.completions.create({
model: 'gpt-4o',
temperature: 0,
response_format: { type: 'json_object' },
messages: [{
role: 'user',
content: [
{ type: 'image_url', image_url: { url: `data:image/jpeg;base64,${imageBase64}` } },
{ type: 'text', text: 'Extract all receipt data as JSON matching this schema: merchant, date, total, items (name/quantity/price), currency.' },
],
}],
});
return ReceiptSchema.parse(JSON.parse(response.choices[0].message.content!));
}Pro Tip
Use the low detail mode for tasks that just need a quick description or classification of an image - it is 4-6x cheaper. Switch to high detail only when the task requires reading small text or analysing fine-grained details like a UI screenshot or a hand-written form.