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.

Some Gemini models support extended thinking — the model reasons internally, producing a chain of thought before committing to a final answer. This is particularly valuable for complex analytical, mathematical, or multi-step tasks where jumping straight to an answer leads to errors. The aisdk/google provider maps the PHP AI SDK’s Reasoning object directly to thinking_level inside generation_config.

Setting reasoning effort

Pass a Reasoning object to ->reasoning() with an effort level of "low", "medium", or "high". The SDK forwards this string verbatim as generation_config.thinking_level:
use AiSdk\Generate;
use AiSdk\Google;
use AiSdk\Reasoning;

Google::create(['apiKey' => env('GOOGLE_GENERATIVE_AI_API_KEY')]);

// Low effort — faster, fewer thinking tokens
$result = Generate::text('What is 17 × 34?')
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('low'))
    ->run();

echo $result->text;
// Medium effort — balanced depth
$result = Generate::text('Explain the trade-offs between B-trees and LSM-trees.')
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('medium'))
    ->run();
// High effort — deepest reasoning, most thinking tokens
$result = Generate::text('Prove that the square root of 2 is irrational.')
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('high'))
    ->run();
The resulting generation_config payload sent to the API will contain:
{
  "generation_config": {
    "thinking_level": "high"
  }
}

Thinking tokens

When a model engages its thinking capability, the API returns thoughtsTokenCount (or thoughts_token_count) in usage_metadata. The SDK surfaces this as $result->usage->reasoningTokens:
$result = Generate::text('Design a fault-tolerant distributed cache.')
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('high'))
    ->run();

echo "Answer: " . $result->text . "\n";
echo "Input tokens:     " . $result->usage->inputTokens . "\n";
echo "Output tokens:    " . $result->usage->outputTokens . "\n";
echo "Reasoning tokens: " . ($result->usage->reasoningTokens ?? 0) . "\n";
reasoningTokens is null when thinking was not active (e.g., the model produced no thought parts, or the effort level resulted in no visible thinking tokens). Reasoning tokens are also included in the outputTokens total.

Streaming reasoning

When streaming a request with reasoning enabled, the stream emits ReasoningDeltaPart objects for each chunk of the model’s internal thought process. These arrive before the TextDeltaPart chunks that carry the final answer.
use AiSdk\Generate;
use AiSdk\Google;
use AiSdk\Reasoning;
use AiSdk\Streaming\ReasoningDeltaPart;
use AiSdk\Streaming\TextDeltaPart;
use AiSdk\Streaming\FinishPart;

$stream = Generate::text('Solve: if 3x + 7 = 28, what is x?')
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('medium'))
    ->stream();

foreach ($stream->parts() as $part) {
    if ($part instanceof ReasoningDeltaPart) {
        // Internal thought chunk — display or log separately
        echo "[thinking] " . $part->text;
    }

    if ($part instanceof TextDeltaPart) {
        // Final answer chunk
        echo $part->text;
    }

    if ($part instanceof FinishPart) {
        echo "\n\nTokens used: " . $part->usage->outputTokens . "\n";
        echo "Reasoning tokens: " . ($part->usage->reasoningTokens ?? 0) . "\n";
    }
}
ReasoningDeltaPart is yielded from GoogleStreamParser::yieldDelta() whenever a delta part has type === 'thought'.

Reasoning in non-streaming responses

In a standard (non-streaming) ->run() call, GoogleResponseParser walks the response steps and emits a ReasoningPart for each content part where type === 'thought'. You can inspect these parts alongside the text output:
use AiSdk\Responses\Parts\ReasoningPart;
use AiSdk\Responses\Parts\TextPart;

$result = Generate::text('What are the first five prime numbers and why?')
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('low'))
    ->run();

foreach ($result->parts as $part) {
    if ($part instanceof ReasoningPart) {
        echo "Thought: " . $part->text . "\n";
    }

    if ($part instanceof TextPart) {
        echo "Answer: " . $part->text . "\n";
    }
}

Supported models

Reasoning requires a model that advertises the reasoning capability. The current model catalogue includes:
Model patternReasoning support
gemini-3*
gemini-2.5*
gemini-2.0*
gemini-1.5*
Use Google::model($id)->supports(Capability::Reasoning) at runtime to check capability before setting a reasoning level:
use AiSdk\Capability;
use AiSdk\Google;

Google::create(['apiKey' => env('GOOGLE_GENERATIVE_AI_API_KEY')]);

$model = Google::model('gemini-3.5-flash');

if ($model->supports(Capability::Reasoning)) {
    $result = Generate::text($prompt)
        ->model($model)
        ->reasoning(Reasoning::effort('high'))
        ->run();
} else {
    $result = Generate::text($prompt)->model($model)->run();
}
Reasoning pairs especially well with structured output for complex extraction tasks. Set a high effort level so the model carefully considers the data before committing to a JSON shape, then use Output::object($schema) to enforce the final output structure.
$result = Generate::text($complexDocument)
    ->model(Google::model('gemini-3.5-flash'))
    ->reasoning(Reasoning::effort('high'))
    ->output(Output::object($schema))
    ->run();

$extracted = json_decode($result->text, true);

Build docs developers (and LLMs) love