Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/phpaisdk/google/llms.txt

Use this file to discover all available pages before exploring further.

The request builders are the translation layer between PHP AI SDK request objects and the raw JSON bodies sent to the Gemini API. GoogleRequestBuilder handles text generation requests, and GoogleImageRequestBuilder handles image generation requests. You do not call these classes directly in normal usage — GoogleTextModel and GoogleImageModel call them internally — but understanding their output is valuable when you need to pass providerOptions('google')['raw'] overrides or debug unexpected API errors.

GoogleRequestBuilder

Namespace: AiSdk\Google\Support\GoogleRequestBuilder Converts a TextModelRequest into a Gemini-compatible JSON body for both synchronous and streaming calls.

build() Signature

/**
 * @return array<string, mixed>
 */
public static function build(
    string $modelId,
    string $providerName,
    TextModelRequest $request,
    bool $stream,
): array
modelId
string
required
The Gemini model identifier. Placed verbatim in the model key of the output body.
providerName
string
required
The provider name string ('google'). Used to look up providerOptions('google')['raw'] from the request.
request
TextModelRequest
required
The SDK request object containing messages, system prompt, generation parameters, output format, and provider-specific options.
stream
bool
required
When true, adds "stream": true to the top-level body. GoogleTextModel passes false for generate() and true for stream().

Output Body Structure

[
    'model'             => 'gemini-2.5-pro',
    'input'             => '...',           // string or array — see below
    'generation_config' => [ /* ... */ ],
    'system_instruction'=> '...',           // only when system prompt is set
    'stream'            => true,            // only when $stream === true
]
model
string
The $modelId passed to build().
input
string|array
When the request contains exactly one user message with a single text part, this is a plain string shortcut. In all other cases it is an array of step objects — one per message — each with type and content keys.
generation_config
array
Generation parameters. See generation_config keys below.
system_instruction
string
Present only when $request->system is a non-empty string.
stream
bool
Present only when $stream is true.

input — Single-Message Shortcut vs. Step Array

When there is exactly one message, the role is user, and that message contains a single text part, build() collapses input to a plain string:
// Single user text → string shortcut
'input' => 'Explain quantum entanglement.'
For all other conversations — multiple messages, non-user roles, or multimodal content — input becomes an array of step objects:
'input' => [
    [
        'type'    => 'user_input',       // user message
        'content' => [ /* parts */ ],
    ],
    [
        'type'    => 'model_response',   // assistant message
        'content' => [ /* parts */ ],
    ],
    [
        'type'         => 'tool_result', // tool response
        'tool_call_id' => 'call_abc123',
        'content'      => [ /* parts */ ],
    ],
]
The type value is derived from the message role:
RoleStep type
useruser_input
assistantmodel_response
tooltool_result

Content Parts

Each content array contains one or more part objects. The shape depends on the content type: Text part:
['type' => 'text', 'text' => 'Hello, world!']
URL-referenced media (image, audio, document):
[
    'type'      => 'image',                     // or 'audio', 'document'
    'uri'       => 'https://example.com/img.png',
    'mime_type' => 'image/png',
]
Inline base64 media:
[
    'type'        => 'image',
    'inline_data' => [
        'mime_type' => 'image/jpeg',
        'data'      => 'base64encodedstring...',
    ],
]
Content type–to–part type mapping:
SDK Content::TYPE_*Part type
TYPE_IMAGEimage
TYPE_AUDIOaudio
TYPE_FILEdocument

generation_config Keys

max_output_tokens
int|null
Mapped from $request->maxTokens. Always present (may be null).
temperature
float|null
Mapped from $request->temperature. Always present (may be null).
top_p
float
Mapped from $request->topP. Only included when topP is non-null.
thinking_level
string
Mapped from $request->reasoning->effort. Only included when reasoning effort is set.
response_mime_type
string
Set to 'application/json' when $request->output is an Output of kind object. Only included when structured output is requested.
response_schema
array
The JSON Schema array from $request->output->schema->jsonSchema(). Only included when a schema is provided alongside response_mime_type.

Raw Passthrough (Shallow Merge)

After the body is assembled, build() applies any raw provider overrides using a shallow array_replace:
$raw = $request->providerOptionsFor($providerName)['raw'] ?? null;
if (is_array($raw)) {
    $body = array_replace($body, $raw);
}
This means top-level keys in $raw replace keys in the built body outright. If you pass 'generation_config' inside $raw, it replaces the entire generation_config array rather than merging individual keys. Use this to pass Gemini-specific parameters that have no SDK equivalent.

GoogleImageRequestBuilder

Namespace: AiSdk\Google\Support\GoogleImageRequestBuilder Converts an ImageRequest into a Gemini generateContent JSON body for image generation.

build() Signature

/**
 * @return array<string, mixed>
 */
public static function build(string $providerName, ImageRequest $request): array
providerName
string
required
The provider name string ('google'). Used to look up providerOptions('google')['raw'] from the request.
request
ImageRequest
required
The SDK image request object. Must have count === 1 and seed === null; otherwise an InvalidArgumentException is thrown immediately.

Output Body Structure

[
    'contents' => [[
        'parts' => [
            ['text' => 'A photorealistic mountain landscape'],
        ],
    ]],
    'generation_config' => [
        'response_modalities' => ['TEXT', 'IMAGE'],
        'image_config' => [           // only when aspect_ratio or size is set
            'aspect_ratio' => '16:9', // only when set
            'image_size'   => '1K',   // only when size is set
        ],
    ],
]
contents[0].parts[0].text
string
The text prompt from $request->prompt. This is the only input content sent for image generation.
generation_config.response_modalities
array
Always ['TEXT', 'IMAGE']. Required by the Gemini image generation API to signal that image output is expected.
generation_config.image_config.aspect_ratio
string
Passed through from $request->aspectRatio when set (e.g. '16:9', '1:1', '9:16').
generation_config.image_config.image_size
string
Derived from $request->size (a 'widthxheight' string) by taking the longest edge. Values larger than 1024 map to '2K'; values of 1024 or smaller map to '1K'.

Size Mapping

The image size string (e.g. '1920x1080') is converted to a Gemini size tier:
private static function imageSize(string $size): string
{
    [$width, $height] = array_map('intval', explode('x', $size, 2));
    $longest = max($width, $height);

    return $longest > 1024 ? '2K' : '1K';
}
Longest edgeGemini image_size
> 1024 px'2K'
≤ 1024 px'1K'

Raw Passthrough (Recursive Merge)

After the body is assembled, build() applies raw provider overrides using a recursive array_replace_recursive:
$raw = $request->providerOptionsFor($providerName)['raw'] ?? null;
if (is_array($raw)) {
    $body = array_replace_recursive($body, $raw);
}
The merge strategy differs between the two builders:
  • GoogleRequestBuilder (text) uses array_replace — a shallow merge. Top-level keys in $raw replace top-level keys in the body. Passing 'generation_config' replaces the entire generation config object.
  • GoogleImageRequestBuilder (image) uses array_replace_recursive — a deep merge. Nested arrays are merged key-by-key, so you can add a single field inside generation_config.image_config without replacing the whole structure.
Choose your $raw payload shape accordingly to avoid inadvertently deleting required fields.

Build docs developers (and LLMs) love