Here’s the honest version of this lesson, stated up front rather than buried at the
end: as of this writing, there is no confirmed, dedicated method in the WordPress PHP
AI Client SDK named something like analyze_image() or describe_image(). Image is
listed as a supported input modality for models, and with_file(), the same method
used in the previous lesson’s editing example, can attach an image file to a prompt
that a vision-capable model then reasons about through the ordinary generate_text()
call. That works today. It’s just not a purpose-built vision feature with its own name,
it’s the general-purpose file-attachment method doing a job the SDK hasn’t given a
dedicated wrapper for yet. This lesson builds on that pattern honestly, and tells you
exactly what to check before you rely on it in a shipping product.
Lesson 1 of this course, in particular its use of File objects and
with_file()-style input. Course 5’s text generation lessons for generate_text()
itself.
This lesson’s entire approach rests on with_file() plus generate_text(), not on a
named vision feature. If a dedicated method for image analysis ships in a later SDK
version, prefer it over this pattern, it will almost certainly handle model-specific
quirks (how different providers expect image data formatted, size limits, and so on)
more reliably than a hand-rolled prompt does. Check the
PHP AI Client SDK repository for newer
methods before building this into new code.
Step 1: Attaching an existing image to a prompt
with_file() accepts a File object, the same DTO you saw returned from
toImageFile() in the previous lesson, or you can construct one directly from a local
path, a URL, or base64 data:
// File: my-plugin/class-image-vision.php
use WordPress\AiClient\Files\DTO\File;
$attachment_path = get_attached_file( $attachment_id );
$mime_type = get_post_mime_type( $attachment_id );
$file = new File( $attachment_path, $mime_type );
File’s constructor is deliberately flexible, it detects whether the string you passed
is a URL, a data URI, plain base64, or a local file path, and stores it accordingly. For
an existing media library attachment, passing the local path via get_attached_file()
is the simplest option.
Step 2: Asking a model to describe it
With the file built, attach it alongside a text instruction and call generate_text()
exactly like you would for a text-only prompt:
// File: my-plugin/class-image-vision.php
$description = wp_ai_client_prompt()
->with_text( 'Describe this image in one plain sentence suitable for use as alt text. Do not start with "an image of" or "a photo of".' )
->with_file( $file )
->generate_text();
The result is a plain string, the same return type generate_text() always gives you.
Whether this actually works depends entirely on the underlying model supporting image
input, most current-generation frontier models do, but the SDK doesn’t currently expose
a way to check “does this specific call support an attached image” the way
isSupportedForImageGeneration() lets you check image generation support. Wrap the
call in a try/catch and treat a failure as “this provider or model doesn’t support
image input” until proven otherwise.
Step 3: Asking for tags in a structured shape
A free-form description is useful for alt text, a flat list of tags is more useful for categorization. Ask for both in the same call rather than making two requests, and lean on the JSON output support already covered in Course 5 to get a shape you can parse reliably instead of splitting a sentence on commas:
// File: my-plugin/class-image-vision.php
$response = wp_ai_client_prompt()
->with_text(
'Look at this image and respond with JSON only: ' .
'{"alt_text": "one plain sentence describing the image", ' .
'"tags": ["3 to 6 short lowercase keywords describing subject matter"]}'
)
->with_file( $file )
->generate_text();
$parsed = json_decode( $response, true );
if ( ! is_array( $parsed ) || empty( $parsed['alt_text'] ) ) {
// Model didn't return valid JSON, fall back to a plain description call instead.
$parsed = array( 'alt_text' => '', 'tags' => array() );
}
Course 5 covers asOutputSchema() / JSON-mode style output for text generation. Whether
that same enforcement is reliable when an image is attached via with_file() hasn’t
been confirmed one way or the other here, treat the instruction-based JSON approach
above as the safer bet for now, and always validate the parsed result before trusting
it, exactly as shown above.
Step 4: Saving the result
Once you have a parsed description and tag list, saving it uses the same core WordPress functions as any other attachment metadata:
// File: my-plugin/class-image-vision.php
function my_plugin_apply_vision_result( int $attachment_id, array $parsed ): void {
if ( ! empty( $parsed['alt_text'] ) ) {
update_post_meta( $attachment_id, '_wp_attachment_image_alt', sanitize_text_field( $parsed['alt_text'] ) );
}
if ( ! empty( $parsed['tags'] ) && is_array( $parsed['tags'] ) ) {
wp_set_object_terms( $attachment_id, array_map( 'sanitize_text_field', $parsed['tags'] ), 'post_tag', true );
}
}
wp_set_object_terms() with 'post_tag' works on attachments the same way it works on
posts, attachments are a post type, taxonomies attach to them the same way. The true
final argument appends rather than replaces, so running this again later on the same
attachment doesn’t wipe out tags a human added by hand.
Test it: describe a real uploaded image
wp-env run cli wp eval '
$attachment_id = 123; // replace with a real attachment ID from your media library
$path = get_attached_file( $attachment_id );
$mime = get_post_mime_type( $attachment_id );
$file = new WordPress\AiClient\Files\DTO\File( $path, $mime );
$response = wp_ai_client_prompt()
->with_text( "Describe this image in one plain sentence." )
->with_file( $file )
->generate_text();
echo $response . "\n";
'
You should see a plain-text sentence back describing the actual contents of that specific image, not a generic placeholder. If you get an error instead, the configured provider or model likely doesn’t support image input, that’s a real, expected outcome right now, not a bug in your code.
Because there’s no dedicated vision method, there’s also no guarantee this exact
with_file() plus generate_text() combination will remain the recommended path once
the SDK adds one. Keep vision calls isolated in one function (as shown above) rather
than scattered across your plugin, so that when a dedicated method does ship, updating
is a one-function change, not a codebase-wide search and replace.
Recap
with_file() attaches an existing image to a prompt, generate_text() then asks a
vision-capable model to describe it, this is a real, working pattern today, but it’s
built from general-purpose methods, not a dedicated vision feature. Ask for a
structured JSON response to get alt text and tags in one call, validate the parsed
result before trusting it, and save the outcome with ordinary update_post_meta() and
wp_set_object_terms() calls. Treat this lesson’s approach as the current
best-available option, and check the SDK’s repository for a purpose-built method before
building new production code around it.
Resources & further reading
- PHP AI Client SDK repository, GitHub
- Introducing the AI Client in WordPress 7.0, make.wordpress.org
- _wp_attachment_image_alt convention, wp_insert_attachment() reference, developer.wordpress.org