|

Подробный разбор механизма визуального мышления Gemini 3: 3 шага для правильного извлечения итогового изображения во избежание получения промежуточных мыслительных образов

Если вы используете API для генерации изображений через Gemini 3 Pro Image и выводите пользователю самое первое изображение, которое возвращает модель, результат часто выглядит странно: «кривая» композиция, нечеткие детали или вовсе обрезанное полотно. Это происходит не из-за снижения качества работы самой модели, а из-за того, что вы выбираете не то изображение. Скорее всего, первое изображение — это лишь «черновик» модели, а финальный результат находится в последнем элементе ответа.

gemini-3-image-thinking-process-guide-ru 图示

В этой статье мы подробно разберем механизм «мышления» изображений в Gemini 3, основываясь на официальной документации Google. Объясним, почему вызов модели может возвращать 2–3 изображения, как с помощью поля part.thought и сигнатуры thought_signature точно идентифицировать финальный результат, а также приведем примеры кода на Python, Node.js и cURL. Все примеры работают через сервис-прокси API APIYI (apiyi.com) — сервис-прокси полностью сохраняет исходную структуру ответа Gemini, поэтому разработчикам нужно просто следовать официальным правилам обработки данных.

Принцип работы механизма «мышления» Gemini 3

Прежде чем переходить к коду, давайте разберемся, почему один вызов может возвращать несколько изображений.

Почему «мышление» Gemini 3 нельзя отключить

В модели gemini-3-pro-image-preview (коммерческое название Nano Banana Pro) Google внедрила механизм «мышления» (Thinking), аналогичный текстовым моделям Gemini. Прежде чем выдать итоговое изображение, модель создает до 2 промежуточных изображений, чтобы протестировать композицию, верстку и рендеринг текста — прямо как дизайнер, который сначала делает наброски, а затем чистовой вариант.

Официальная документация выделяет три ключевых факта:

Факт Пояснение
Включено по умолчанию Функция Thinking принудительно включена на уровне API, параметров для отключения нет
До 2 черновиков Модель может создать до 2 пробных изображений, но не обязательно каждый раз
Последнее — финальное Именно последнее изображение в цепочке «мышления» является конечным результатом
Оплата за токены мышления Даже если вы не запрашиваете сами мысли, токены «мышления» расходуются и оплачиваются

Иными словами, получение нескольких изображений — это норма, а не баг. Суть не в том, чтобы «отключить» функцию, а в том, чтобы правильно выбрать финальный результат.

🎯 Архитектурный взгляд: Механизм мышления Gemini 3 при генерации изображений использует тот же движок, что и текстовые модели Gemini 3 Pro. Это объясняет, почему Nano Banana Pro значительно лучше справляется с рендерингом длинного текста и сохранением согласованности лиц по сравнению с Nano Banana предыдущих версий. При использовании сервиса-прокси API APIYI (apiyi.com) все процессы «мышления» идентичны прямому подключению к Google; слой прокси не удаляет никаких данных о процессе мышления.

Разбор типичных ошибок пользователей

Типичная ошибка в сообществе выглядит так:

Вызов API → Получение ответа → В ответе массив parts → Берем parts[0] с изображением → Отображаем пользователю

Этот псевдокод отлично работал в старой версии Nano Banana (Gemini 2.5 Flash Image), так как она возвращала только одно изображение. После перехода на Gemini 3 Pro Image тот же код принимает «черновик» за готовый продукт, и в итоге пользователь видит «полуфабрикат», который не соответствует промпту или имеет странную композицию.

Эта проблема коварна, потому что:

  • Проявляется не всегда: При простых промптах модель может не запускать процесс «мышления» и вернуть одно изображение.
  • Ошибок нет: Структура ответа корректна, обращение к parts[0] не вызывает исключений.
  • Есть результат: Пользователь думает, что модель «плохая», хотя на деле просто выбрано не то изображение.

Подробный разбор структуры ответов при генерации изображений в Gemini 3

Чтобы правильно обрабатывать ответы, нужно четко понимать, что именно может вернуться после вызова API.

Массив parts в полном ответе API

Когда в Gemini 3 Pro Image срабатывает механизм «мышления» (thinking), массив response.candidates[0].content.parts может выглядеть примерно так:

gemini-3-image-thinking-process-guide-ru 图示

candidates[0].content.parts = [
  { text: "Я должен обдумать композицию...", thought: true },
  { inline_data: { mime_type: "image/png", data: "..." }, thought: true },   // черновик 1
  { inline_data: { mime_type: "image/png", data: "..." }, thought: true },   // черновик 2
  { inline_data: { mime_type: "image/png", data: "..." }, thought_signature: "..." }  // финальное изображение
]

Неправильное понимание этого массива — главная причина багов. Запомните эти 3 правила, чтобы писать надежный код.

3 официальных признака финального изображения

Google выделил три признака, по которым можно распознать итоговый результат. Используйте их в порядке приоритета:

Приоритет Признак Описание Надежность
★★★ part.thought === false (или поле отсутствует) Явно помечен как не часть процесса мышления Высочайшая
★★ Наличие поля thought_signature Есть только у финального изображения Высокая
Последний inline_data в массиве Официальная документация подтверждает: «последний — это финал» Резервный

Лучший подход — комбинировать: сначала проверяем поле thought, если его нет — ищем thought_signature, и в крайнем случае берем последний inline_data.

Различия в thinking_level у Gemini 3.1 Flash Image

Важно помнить, что поведение разных моделей может отличаться:

Модель Мышление (default) Настройка thinking_level Сценарии
gemini-3-pro-image-preview Включено всегда ❌ Нельзя менять Высокая точность, профессиональные задачи
gemini-3-flash-image minimal ✅ minimal / high Интерактивы, массовая генерация
gemini-2.5-flash-image нет Старая версия

В Gemini 3.1 Flash можно вручную повысить уровень мышления для более детальной проработки или снизить до «minimal» для скорости — в версии Pro такой гибкости нет.

🎯 Совет по выбору: Если вы делаете генерацию изображений для обычных пользователей, рекомендуем использовать gemini-3-flash-image + thinking_level=minimal (быстрее и дешевле). А если пользователь переключается в «режим высокого качества» — активируйте gemini-3-pro-image-preview (для глубокого анализа и точности). На платформе APIYI (apiyi.com) вы можете бесшовно переключаться между ними, используя один и тот же API-ключ и базовый URL.

Код для корректной обработки мышления Gemini 3

Теперь к практике. Примеры ниже основаны на прозрачном проксировании через APIYI — если вы уже писали код для Google AI Studio, просто замените base_url на адрес APIYI и вставьте свой ключ, остальное останется прежним.

Правильный вариант на Python SDK

from google import genai

client = genai.Client(
    api_key="sk-your-apiyi-key",
    http_options={"base_url": "https://vip.apiyi.com/v1beta"}
)

response = client.models.generate_content(
    model="gemini-3-pro-image-preview",
    contents="Сиба-ину в стиле киберпанк под неоновой вывеской, 4K",
    config={"response_modalities": ["IMAGE"]}
)

# ✅ Правильно: фильтруем все thought parts, сохраняем только финал
for part in response.parts:
    if getattr(part, "thought", False):
        continue  # пропускаем черновики мышления
    if hasattr(part, "as_image"):
        image = part.as_image()
        if image:
            image.save("final_output.png")
            break  # первое не «мыслительное» изображение — это финал

Антипаттерн (типичная ошибка):

# ❌ Ошибка: берем первый попавшийся part, это может быть черновик
image_part = response.parts[0]
image_bytes = image_part.inline_data.data
# На выходе может оказаться полуфабрикат

Правильный вариант на Node.js / TypeScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({
  apiKey: process.env.APIYI_KEY,
  httpOptions: { baseUrl: "https://vip.apiyi.com/v1beta" }
});

const response = await ai.models.generateContent({
  model: "gemini-3-pro-image-preview",
  contents: "Сиба-ину в стиле киберпанк под неоновой вывеской, 4K",
  config: { responseModalities: ["IMAGE"] }
});

const parts = response.candidates?.[0]?.content?.parts ?? [];

// ✅ Идем с конца: первое изображение без флага thought — искомое
let finalImage: string | null = null;
for (let i = parts.length - 1; i >= 0; i--) {
  const p = parts[i];
  if (p.thought === true) continue;
  if (p.inlineData?.mimeType?.startsWith("image/")) {
    finalImage = p.inlineData.data;
    break;
  }
}

if (finalImage) {
  fs.writeFileSync("final.png", Buffer.from(finalImage, "base64"));
}

Версия через cURL + jq

Если вы вызываете API через shell-скрипт, используйте фильтрацию с помощью jq:

curl -sS https://vip.apiyi.com/v1beta/models/gemini-3-pro-image-preview:generateContent \
  -H "x-goog-api-key: $APIYI_KEY" \
  -H "content-type: application/json" \
  -d '{
    "contents": [{
      "parts": [{"text": "Сиба-ину в стиле киберпанк"}]
    }],
    "generationConfig": {"responseModalities": ["IMAGE"]}
  }' | jq -r '
    .candidates[0].content.parts
    | map(select(.thought != true))
    | map(select(.inlineData.mimeType | startswith("image/")))
    | last.inlineData.data
  ' | base64 -d > final.png

Это выражение jq делает три вещи: отфильтровывает thought: true, оставляет только mime-типы изображений и берет last (последнее), что идеально соответствует официальным правилам.

🎯 Чек-лист для ревью: При проверке кода всегда смотрите, есть ли фильтрация по thought. Лучше всего вынести логику в единую функцию-утилиту extractFinalImage(), чтобы вся команда использовала её для обработки ответов. При работе через APIYI вы можете протестировать этот код локально, а затем сразу пушить в продакшн.

Продвинутые аспекты генерации изображений в Gemini 3

В многоходовом редактировании необходимо передавать thought_signature

Nano Banana Pro поддерживает «последовательное редактирование» — например, когда пользователь сначала просит «замени фон на морской», а затем — «сделай выражение мордочки собаки более радостным». Однако есть важный нюанс: официальные требования обязывают передавать thought_signature из предыдущего шага в последующих итерациях диалога. В противном случае модель теряет контекст рассуждений, и качество генерации заметно падает.

Правильный подход для многоходового взаимодействия:

# Первый шаг
response1 = client.models.generate_content(
    model="gemini-3-pro-image-preview",
    contents="Сиба-ину бежит по парку"
)

# Извлекаем объект part (содержащий thought_signature) для итогового изображения
final_part = next(
    p for p in response1.parts
    if not getattr(p, "thought", False) and hasattr(p, "inline_data")
)

# Второй шаг: добавляем весь объект final_part обратно в историю
response2 = client.models.generate_content(
    model="gemini-3-pro-image-preview",
    contents=[
        {"role": "user", "parts": [{"text": "Сиба-ину бежит по парку"}]},
        {"role": "model", "parts": [final_part]},  # Здесь содержится thought_signature
        {"role": "user", "parts": [{"text": "Замени фон на морской закат"}]}
    ]
)

Просмотр процесса рассуждений (для отладки)

Если вы хотите заглянуть «под капот» и увидеть, как именно модель «думала», включите include_thoughts:

from google.genai import types

response = client.models.generate_content(
    model="gemini-3-pro-image-preview",
    contents="Сложный промпт для рекламного постера бренда...",
    config=types.GenerateContentConfig(
        response_modalities=["IMAGE"],
        thinking_config=types.ThinkingConfig(
            include_thoughts=True
        )
    )
)

# Выводим процесс размышлений
for part in response.parts:
    if getattr(part, "thought", False):
        if part.text:
            print(f"[Размышление] {part.text}")
        elif hasattr(part, "as_image"):
            img = part.as_image()
            img.save(f"draft_{id(part)}.png")  # Сохраняем черновик

Это очень полезно при отладке: если результат далек от идеала, изучение черновиков поможет понять, какую именно часть промпта модель интерпретировала неверно.

gemini-3-image-thinking-process-guide-ru 图示

Логика биллинга thinking-токенов

Разработчикам стоит обратить особое внимание на то, как тарифицируется Gemini 3 Pro Image:

Тип токена Цена (за 1 млн) Обязательно к генерации?
Входной промпт $2 ✅ Да
Выход (изображение/текст) $12 ✅ Да
Thinking reasoning Включается в выходные токены ✅ Обязательно, нельзя отключить

Это означает, что даже если вам нужно только итоговое изображение и вас не интересует процесс «рассуждений», токены размышлений (thinking tokens) все равно будут создаваться и оплачиваться. Вы можете сэкономить только на передаче текста размышлений обратно себе (параметр include_thoughts), но не на самом факте их генерации.

🎯 Советы по оптимизации расходов: для простых задач (генерация изображений товаров, иллюстраций) используйте gemini-3-flash-image + thinking_level=minimal — это будет стоить заметно дешевле версии Pro. Модель Pro стоит подключать только для сложных задач (поддержание согласованности лиц у персонажей, сложная рендеринг текста). Рекомендуем при вызове через APIYI (apiyi.com) отслеживать потребление, чтобы сравнить соотношение цена/качество в ваших сценариях, прежде чем переходить к продакшн-конфигурации.

Практика отладки «мышления» при генерации изображений в Gemini 3

Проблема 1: Постоянно получаю изображения низкого качества

Шаги для диагностики:

# Вывод поля thought для всех parts
for i, part in enumerate(response.parts):
    is_thought = getattr(part, "thought", False)
    has_image = hasattr(part, "inline_data")
    has_sig = hasattr(part, "thought_signature")
    print(f"Part {i}: thought={is_thought}, image={has_image}, signature={has_sig}")

Если в выводе есть несколько parts с image=True, значит, вы столкнулись с типичной ситуацией «возврата нескольких изображений». Проверьте, не берет ли ваш код первый попавшийся part по индексу.

Проблема 2: В структуре ответа отсутствует поле thought

Возможная причина: Вы используете «сырой» JSON от REST API. Имена полей записаны в camelCase (thought), но в некоторых версиях SDK они могли быть преобразованы в snake_case. Нужно поддерживать оба варианта:

def is_thought(part):
    return getattr(part, "thought", None) or \
           getattr(part, "is_thought", None) or \
           (isinstance(part, dict) and part.get("thought", False))

Проблема 3: Нужно сохранить все изображения (для отладки)

Рекомендуемый официальный способ обхода всех элементов:

for i, part in enumerate(response.parts):
    if not hasattr(part, "inline_data"):
        continue
    is_draft = getattr(part, "thought", False)
    suffix = "draft" if is_draft else "final"
    filename = f"gemini_output_{suffix}_{i}.png"
    with open(filename, "wb") as f:
        f.write(part.inline_data.data)
    print(f"Сохранено: {filename}")

Адаптация «мышления» Gemini 3 под реальные бизнес-задачи

Помимо теории и базового кода, есть нюансы, которые важно учитывать в разных сценариях.

Сценарий 1: Отображение сгенерированного изображения во фронтенде

Фронтенд должен преобразовывать base64 в формат data:image/png;base64,xxx. Важно: не фильтруйте thought на фронтенде — пусть бэкенд возвращает уже «чистый» результат. Иначе фронтенду придется вникать в структуру ответа Gemini:

// ❌ Не рекомендуется: фронтенд сам обрабатывает сырой ответ Gemini
const parts = await apiCall();
parts.forEach(p => {
  if (!p.thought) showImage(p.inlineData.data);
});

// ✅ Рекомендуется: бэкенд выполняет фильтрацию, фронтенд получает готовое изображение
// Бэкенд API возвращает: { "image": "base64-string" }
const { image } = await fetch("/api/generate").then(r => r.json());
imgEl.src = `data:image/png;base64,${image}`;

Сценарий 2: Генерация + сохранение в OSS / CDN

При пакетной генерации сохраняйте файлы в объектное хранилище с использованием хеша, чтобы избежать дубликатов:

import hashlib, base64

def save_to_oss(bucket, base64_data):
    binary = base64.b64decode(base64_data)
    fname = f"gemini3/{hashlib.md5(binary).hexdigest()}.png"
    bucket.put_object(fname, binary)
    return fname

final_b64 = extract_final_image(response)
if final_b64:
    url = save_to_oss(my_bucket, final_b64)

Обязательно загружайте только финальное изображение, черновики «мышления» будут засорять хранилище и тратить ваш бюджет.

Сценарий 3: Правильная обработка потоковых (streaming) ответов

Gemini 3 поддерживает стриминг: черновики «мышления» приходят первыми, финальное изображение — в конце. В потоковом режиме рекомендуется использовать логику «перезаписи по мере поступления»:

stream = client.models.generate_content_stream(
    model="gemini-3-pro-image-preview",
    contents="..."
)

current_image = None
for chunk in stream:
    for part in chunk.parts:
        if getattr(part, "thought", False):
            continue  # Пропускаем черновики
        if hasattr(part, "inline_data") and part.inline_data:
            current_image = part.inline_data.data  # Перезаписываем, оставляем последнее

🎯 Оптимизация стриминга: для улучшения пользовательского опыта можно отправлять черновики «мышления» на фронтенд для отображения «превью загрузки», а затем заменять их финальным результатом. Такой «постепенный рендеринг» очень популярен в B2C-продуктах. APIYI apiyi.com полностью поддерживает протокол SSE для Gemini, поэтому фронтенд будет работать так же, как при прямом подключении.

Gemini 3: визуальное мышление и связь с бизнес-метриками

Количественные показатели роста качества

Согласно официальным данным Google и тестам сообщества, активация функции «мышления» (thinking) значительно повышает качество генерации изображений:

Показатель Gemini 2.5 Flash Image Gemini 3 Pro Image (thinking) Прирост
Точность рендеринга длинного текста ~70% ~95% +35%
Согласованность лиц (5 человек) ~60% ~90% +50%
Следование сложным композициям ~75% ~92% +22%
Уровень использования первого изображения ~80% ~95% +18%

Цена вопроса — увеличение времени отклика на 40–80% и рост стоимости токенов на 20–40%. Стоит ли оно того? Зависит от вашего бизнес-сценария:

  • Профессиональный дизайн и рекламные материалы: прирост качества значительно перевешивает затраты, настоятельно рекомендуется.
  • UGC, массовый контент: рекомендуем использовать Flash + thinking_level=minimal для баланса.
  • Интерактивные чат-боты в реальном времени: здесь приоритет — скорость, поэтому Flash остается более подходящим выбором.

🎯 Совет по A/B-тестированию: не выбирайте модель на интуитивном уровне. Мы рекомендуем создать отдельные API-ключи для каждой модели на APIYI (apiyi.com), распределить трафик между ними 50/50 и через 7 дней сравнить реальные показатели удовлетворенности пользователей (лайки, повторные генерации, конверсии) — цифры сами покажут, стоит ли модель своих денег.

FAQ: Gemini 3 и визуальное мышление

Q1: Почему после перехода на Gemini 3 в моем коде генерации «периодически появляются полуфабрикаты»?

Потому что у Gemini 3 Pro Image мышление включено по умолчанию, и в ответе может содержаться от 1 до 3 изображений. Скорее всего, ваш старый код забирает parts[0], а это может быть черновик. Решение: обновите код так, чтобы он отфильтровывал thought: true и забирал последнее изображение, не являющееся процессом мышления.

Q2: Есть ли функция мышления в интерфейсе Gemini 3 на платформе APIYI?

Абсолютно такая же. APIYI (apiyi.com) использует архитектуру прозрачной пересылки. Все поля thought, thought_signature и inline_data из нативного ответа Gemini передаются без изменений, мы ничего не вырезаем и не модифицируем. Вы можете просто перенаправить ваш код, который раньше обращался напрямую к Google AI Studio, на APIYI — структура ответа будет полностью совместима.

Q3: Можно ли каким-то параметром принудительно заставить модель выдавать только финальное изображение?

Нет. В официальной документации четко сказано: "This feature is enabled by default and cannot be disabled in the API" (функция включена по умолчанию и не может быть отключена в API). Однако вы можете установить include_thoughts: false, чтобы в ответе не было текстовых рассуждений, но черновики изображений все равно могут остаться, поэтому фильтрация на стороне кода обязательна.

Q4: Мышление увеличивает задержку, как это оптимизировать?

Есть три пути:

  1. Для простых сценариев используйте gemini-3-flash-image + thinking_level=minimal.
  2. Если задача несложная, пишите промпт точнее, чтобы модель не «уходила в глубокие раздумья».
  3. Используйте стриминг (потоковую передачу), чтобы пользователь видел промежуточные черновики, а финальное изображение доходило в конце.

Q5: Как проверить, действительно ли в ответе сработало мышление?

Проверьте поле response.usage_metadata.thoughts_token_count. Если значение больше 0, значит, мышление было активировано. Это число также поможет вам оценить реальные затраты на логический вывод.

Q6: Можно ли создать или изменить thought_signature самостоятельно?

Нет. thought_signature — это криптографический ключ, выдаваемый сервером Google для проверки целостности контекста в многоходовых диалогах. Самодельные подписи будут отклонены сервером. При многоходовом редактировании просто отправляйте обратно всю часть (part), содержащую signature.

Q7: Как быть с неопределенностью, которую создает мышление при массовой генерации 100 изображений?

Рекомендуем обрабатывать ответ для каждого запроса отдельно и логировать thoughts_token_count. В личном кабинете APIYI (apiyi.com) можно просматривать потребление токенов по каждому вызову и выявлять запросы с аномально высоким потреблением ресурсов на «мышление». Для массовых сценариев также можно рассмотреть Batch API (Gemini 3 Pro Image его поддерживает) — это снизит стоимость вдвое, а ответы можно обрабатывать асинхронно.

Итоги и чек-лист по работе с Gemini 3 Image Thinking

Вспоминая всё вышесказанное: Gemini 3 Image Thinking не только повышает качество, но и полностью меняет структуру ответов модели. Если коротко:

Ключевой принцип: никогда не берите parts[0] напрямую, всегда фильтруйте thought: true и всегда берите последний inline_data в качестве итогового изображения.

gemini-3-image-thinking-process-guide-ru 图示

Чек-лист по миграции

Если ваш проект переходит с Gemini 2.5 на Gemini 3, сверьтесь со списком:

  1. Замена ID модели: gemini-2.5-flash-imagegemini-3-pro-image-preview или gemini-3-flash-image.
  2. Переработка парсинга ответа: Замените все parts[0] на логику «фильтрация thought + выбор последнего элемента».
  3. Обработка сигнатур: В многоходовых диалогах обязательно сохраняйте часть с thought_signature.
  4. Проверка затрат: Помните, что токены «мышления» (thinking tokens) засчитываются как выходные, поэтому расходы могут вырасти на 20–40%.
  5. Регрессионное тестирование: Подготовьте 20+ примеров промптов, сравните результаты Gemini 2.5 и Gemini 3, чтобы избежать неожиданных сбоев.

Шаблон для быстрой интеграции

Используйте этот код как «золотой стандарт» для вашей команды, через него должны проходить все запросы:

def extract_final_image(response):
    """Безопасное извлечение итогового изображения из ответа Gemini 3 Image"""
    parts = response.candidates[0].content.parts if response.candidates else []

    # Ищем с конца, чтобы найти первое изображение, не являющееся 'thought'
    for part in reversed(parts):
        if getattr(part, "thought", False):
            continue
        if hasattr(part, "inline_data") and part.inline_data:
            mime = part.inline_data.mime_type or ""
            if mime.startswith("image/"):
                return part.inline_data.data  # base64 байты

    return None  # Изображение не найдено, требуется повторный запрос

🎯 Совет напоследок: Механизм мышления Gemini 3 — палка о двух концах. Если использовать его правильно, вы получите качество генерации топового уровня, если нет — «лотерею» с полуготовым результатом. Мы рекомендуем после подключения через APIYI (apiyi.com) прогнать регрессионный тест на 10–20 реальных промптах, чтобы убедиться, что ваш код правильно извлекает финальное изображение при любых сценариях работы «мышления», и только потом деплоить в продакшн. Платформа поддерживает всю линейку моделей Gemini 3, а ответы API полностью идентичны официальным от Google.


Автор: Техническая команда APIYI | Больше туториалов по генерации изображений: help.apiyi.com

Похожие записи