Chapter 15
Give the AI a File
Passing an image/document as input (e.g. auto-describe an uploaded image)
Every prompt in this book so far has been words describing something. This chapter is about handing the model an actual file instead, an image, a document, something it can look at directly rather than something you describe to it in text.
A new way to add to the prompt
with_file() chains onto the builder the same way with_text() or using_system_instruction() do:
$text = wp_ai_client_prompt( 'Describe what you see in this image.' )
->with_file( $file_path, $mime_type )
->generate_text();
It accepts a local file path, a URL, a base64 string, or a data URI, whatever form the file happens to be in. The second argument, the MIME type, is worth passing explicitly when you’re working with a local file path the way this chapter’s example does, it tells the provider exactly what kind of file it’s looking at rather than leaving it to guess from the file extension alone.
Describing an image from your Media Library
This is exactly the kind of thing with_file() is for: looking at an image that already exists on your site and generating something useful from it, an alt text suggestion, a caption, a description. Create chapter-15-give-the-ai-a-file.php inside includes:
<?php
/**
* Chapter 15: Give the AI a File
* Usage: add [ai_course_ch15] to any page or post to describe the most
* recently uploaded image, or [ai_course_ch15 id="123"] to describe a
* specific Media Library attachment.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // No direct access.
}
function ai_course_ch15_describe_image( $atts ) {
$atts = shortcode_atts( array( 'id' => 0 ), $atts );
$attachment_id = absint( $atts['id'] );
if ( ! $attachment_id ) {
$attachments = get_posts(
array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'DESC',
)
);
if ( empty( $attachments ) ) {
return 'Upload an image to your Media Library first, then reload this page.';
}
$attachment_id = $attachments[0]->ID;
}
$file_path = get_attached_file( $attachment_id );
if ( ! $file_path || ! file_exists( $file_path ) ) {
return 'Could not find an image with that attachment ID.';
}
$mime_type = get_post_mime_type( $attachment_id );
$description = wp_ai_client_prompt( 'Describe what you see in this image in one or two sentences.' )
->with_file( $file_path, $mime_type )
->generate_text();
if ( is_wp_error( $description ) ) {
return 'Could not describe the image: ' . esc_html( $description->get_error_message() );
}
return '<p><strong>Describing:</strong> ' . esc_html( basename( $file_path ) ) . '</p><p>' . wp_kses_post( $description ) . '</p>';
}
add_shortcode( 'ai_course_ch15', 'ai_course_ch15_describe_image' );
Make sure you’ve got at least one image in your Media Library, then add [ai_course_ch15] to a page and load it. You get back an actual description of your most recently uploaded image, not a generic guess, a real read of what’s actually in that specific file.
Want a specific image instead of whichever one happens to be newest? Pass its attachment ID: [ai_course_ch15 id="123"]. To find that number, open Media Library, click the image to open its details, and check the browser’s address bar, it’ll show something like item=123 or post=123, that number is the ID. shortcode_atts() handles the attribute, defaulting to 0 (meaning “use the most recent”) when you don’t specify one, the same pattern you’ve probably used in any shortcode that takes optional settings.
get_attached_file() and get_post_mime_type() are both plain WordPress functions you’ve likely used before, nothing AI-specific about them. That’s the point of this chapter, really: the only new piece is with_file() itself, everything around it is ordinary WordPress code for finding a file and reading its type.
Where this is heading
Describing an uploaded image is one step away from generating alt text for it automatically, which is close to exactly what Module 8’s first capstone project builds toward, a real, shippable alt-text generator using this same pattern plus a few things from later chapters (structured JSON output, error handling, feature detection) layered on top.
Try it yourself
Pick a specific photo of something recognizable, not a generic stock image, using [ai_course_ch15 id="..."] with its attachment ID, and see how detailed a description you get back. Then try changing the prompt to ask for something more targeted than a general description, alt text under a certain character count, for instance, and see how the response changes shape to match what you actually asked for.