Image Editing: Edit an existing image with text instructions
curl --request POST \
--url https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contents": [
{
"parts": [
{
"text": "Combine the people from these two images into one office scene, making funny faces"
},
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_1>"
}
},
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_2>"
}
}
]
}
],
"generationConfig": {
"responseModalities": [
"IMAGE"
],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K"
}
}
}
'import requests
url = "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent"
payload = {
"contents": [{ "parts": [{ "text": "Combine the people from these two images into one office scene, making funny faces" }, { "inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_1>"
} }, { "inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_2>"
} }] }],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K"
}
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [
{
parts: [
{
text: 'Combine the people from these two images into one office scene, making funny faces'
},
{inlineData: {mimeType: 'image/png', data: '<BASE64_DATA_IMG_1>'}},
{inlineData: {mimeType: 'image/png', data: '<BASE64_DATA_IMG_2>'}}
]
}
],
generationConfig: {
responseModalities: ['IMAGE'],
imageConfig: {aspectRatio: '16:9', imageSize: '2K'}
}
})
};
fetch('https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'contents' => [
[
'parts' => [
[
'text' => 'Combine the people from these two images into one office scene, making funny faces'
],
[
'inlineData' => [
'mimeType' => 'image/png',
'data' => '<BASE64_DATA_IMG_1>'
]
],
[
'inlineData' => [
'mimeType' => 'image/png',
'data' => '<BASE64_DATA_IMG_2>'
]
]
]
]
],
'generationConfig' => [
'responseModalities' => [
'IMAGE'
],
'imageConfig' => [
'aspectRatio' => '16:9',
'imageSize' => '2K'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent"
payload := strings.NewReader("{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"Combine the people from these two images into one office scene, making funny faces\"\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_1>\"\n }\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_2>\"\n }\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"16:9\",\n \"imageSize\": \"2K\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"Combine the people from these two images into one office scene, making funny faces\"\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_1>\"\n }\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_2>\"\n }\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"16:9\",\n \"imageSize\": \"2K\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"Combine the people from these two images into one office scene, making funny faces\"\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_1>\"\n }\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_2>\"\n }\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"16:9\",\n \"imageSize\": \"2K\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"candidates": [
{
"content": {
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "<string>"
}
}
]
},
"finishReason": "STOP"
}
],
"usageMetadata": {
"promptTokenCount": 10,
"candidatesTokenCount": 258
}
}Генерация изображений Nano Banana 2.1
Справочник по API редактирования изображений
Справочник по API и интерактивная песочница для редактирования изображений с помощью Nano Banana 2.1 — передайте изображение и инструкцию, чтобы получить отредактированный результат
POST
/
v1beta
/
models
/
gemini-nano-banana-2.1:generateContent
Image Editing: Edit an existing image with text instructions
curl --request POST \
--url https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contents": [
{
"parts": [
{
"text": "Combine the people from these two images into one office scene, making funny faces"
},
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_1>"
}
},
{
"inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_2>"
}
}
]
}
],
"generationConfig": {
"responseModalities": [
"IMAGE"
],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K"
}
}
}
'import requests
url = "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent"
payload = {
"contents": [{ "parts": [{ "text": "Combine the people from these two images into one office scene, making funny faces" }, { "inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_1>"
} }, { "inlineData": {
"mimeType": "image/png",
"data": "<BASE64_DATA_IMG_2>"
} }] }],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K"
}
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [
{
parts: [
{
text: 'Combine the people from these two images into one office scene, making funny faces'
},
{inlineData: {mimeType: 'image/png', data: '<BASE64_DATA_IMG_1>'}},
{inlineData: {mimeType: 'image/png', data: '<BASE64_DATA_IMG_2>'}}
]
}
],
generationConfig: {
responseModalities: ['IMAGE'],
imageConfig: {aspectRatio: '16:9', imageSize: '2K'}
}
})
};
fetch('https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'contents' => [
[
'parts' => [
[
'text' => 'Combine the people from these two images into one office scene, making funny faces'
],
[
'inlineData' => [
'mimeType' => 'image/png',
'data' => '<BASE64_DATA_IMG_1>'
]
],
[
'inlineData' => [
'mimeType' => 'image/png',
'data' => '<BASE64_DATA_IMG_2>'
]
]
]
]
],
'generationConfig' => [
'responseModalities' => [
'IMAGE'
],
'imageConfig' => [
'aspectRatio' => '16:9',
'imageSize' => '2K'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent"
payload := strings.NewReader("{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"Combine the people from these two images into one office scene, making funny faces\"\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_1>\"\n }\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_2>\"\n }\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"16:9\",\n \"imageSize\": \"2K\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"Combine the people from these two images into one office scene, making funny faces\"\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_1>\"\n }\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_2>\"\n }\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"16:9\",\n \"imageSize\": \"2K\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"Combine the people from these two images into one office scene, making funny faces\"\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_1>\"\n }\n },\n {\n \"inlineData\": {\n \"mimeType\": \"image/png\",\n \"data\": \"<BASE64_DATA_IMG_2>\"\n }\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"16:9\",\n \"imageSize\": \"2K\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"candidates": [
{
"content": {
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "<string>"
}
}
]
},
"finishReason": "STOP"
}
],
"usageMetadata": {
"promptTokenCount": 10,
"candidatesTokenCount": 258
}
}Интерактивный Playground справа поддерживает выбор параметров из выпадающего списка. Введите свой API Key в поле Authorization (формат:
Bearer sk-xxx), чтобы отправлять тестовые запросы в один клик.Область применения: эта страница предназначена для редактирования изображений. Необходимо предоставить исходное изображение (в кодировке base64) вместе с инструкциями по редактированию. Для генерации нового изображения только по тексту используйте эндпоинт Text-to-Image.
🖥️ Ограничение Playground в браузере (важно)Этот эндпоинт возвращает в ответе изображение в кодировке base64 (
inlineData.data, обычно размером в несколько МБ). Из-за ограничений рендеринга в браузере Playground справа может отображать 请求时发生错误: unable to complete request после получения ответа — на самом деле запрос выполнен успешно; браузер просто не может отобразить такую длинную строку base64.Рекомендуемый порядок действий (подходит для начинающих):- Скопируйте приведенный ниже пример для Python / Node.js / cURL и запустите его локально. Код автоматически
base64.b64decodeответ и записывает изображение в файл. - Если вам необходимо использовать Playground в браузере, используйте эталонное изображение минимального размера (< 50 КБ) и установите
imageSizeна минимальный уровень (1K).
⚠️ Структура массива Неправильно (каждая часть содержит как
parts (важно — ознакомьтесь для редактирования нескольких изображений)Каждый part должен быть либо text, либо inlineData, но ни в коем случае не обоими сразу. Это соответствует официальному контракту gemini-nano-banana-2.1 от Google.Правильно: одна текстовая часть (инструкция) + N частей inlineData (по одной на каждое изображение):"contents": [{
"parts": [
{"text": "Combine the people from these two images into one office scene"},
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_DATA_IMG_1>"}},
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_DATA_IMG_2>"}}
]
}]
text, так и inlineData — приводит к неопределенному поведению):"contents": [{
"parts": [
{"inlineData": {...}, "text": "is this the prompt 1"},
{"inlineData": {...}, "text": "is this the prompt 2"}
]
}]
🖼️ О поле После выполнения просто вставьте значение с помощью
inlineData.dataЭтот эндпоинт использует формат JSON (а не составную загрузку файлов multipart), поэтому в Playground нельзя напрямую выбрать локальные файлы. Сначала необходимо преобразовать изображение в строку base64, а затем вставить ее в поле ввода data.Однострочная команда: преобразование + копирование в буфер обмена:# macOS
base64 -i your-image.jpg | tr -d '\n' | pbcopy
# Linux
base64 -w0 your-image.jpg | xclip -selection clipboard
# Windows PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("your-image.jpg")) | Set-Clipboard
Cmd+V / Ctrl+V в поле data в Playground. Также не забудьте установить для mimeType соответствующий image/jpeg или image/png.Рекомендация: используйте для тестирования небольшие изображения (< 200 КБ), чтобы избежать зависания браузера из-за длинных строк base64. Для регулярного тестирования редактирования изображений используйте приведенные ниже примеры кода для локального запуска.Примеры кода
Python
import requests
import base64
API_KEY = "sk-your-api-key"
# Read the image to edit
with open("input.jpg", "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
response = requests.post(
"https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent",
headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
json={
"contents": [{
"parts": [
{"text": "Please blur the background to highlight the person in the foreground"},
{"inlineData": {"mimeType": "image/jpeg", "data": image_b64}}
]
}],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"}
}
},
timeout=300
).json()
img_data = [p for p in response["candidates"][0]["content"]["parts"] if "inlineData" in p][-1]["inlineData"]["data"]
with open("edited.png", 'wb') as f:
f.write(base64.b64decode(img_data))
print("Edited image saved to edited.png")
Node.js
import fs from "fs";
const API_KEY = "sk-your-api-key";
const imageB64 = fs.readFileSync("input.jpg").toString("base64");
const response = await fetch(
"https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent",
{
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
contents: [{
parts: [
{ text: "Please blur the background to highlight the person in the foreground" },
{ inlineData: { mimeType: "image/jpeg", data: imageB64 } }
]
}],
generationConfig: {
responseModalities: ["IMAGE"],
imageConfig: { aspectRatio: "16:9", imageSize: "2K" }
}
})
}
);
const data = await response.json();
const imgBase64 = data.candidates[0].content.parts.filter((p) => p.inlineData).at(-1).inlineData.data;
fs.writeFileSync("edited.png", Buffer.from(imgBase64, "base64"));
cURL
# Note: convert image to base64 first
# IMAGE_B64=$(base64 -i input.jpg | tr -d '\n')
curl -X POST "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent" \
-H "Authorization: Bearer sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"contents": [{
"parts": [
{"text": "Please blur the background to highlight the person in the foreground"},
{"inlineData": {"mimeType": "image/jpeg", "data": "'"$IMAGE_B64"'"}}
]
}],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"}
}
}'
Редактирование нескольких изображений
При объединении или сравнении нескольких входных изображений используйте одну частьtext (инструкцию), за которой следуют несколько частей inlineData (по одной на каждое изображение).
Python (несколько изображений)
import requests
import base64
API_KEY = "sk-your-api-key"
def to_b64(path):
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode()
# Prepare multiple images (2 here as an example)
images = ["person1.png", "person2.png"]
parts = [{"text": "Combine the people from these images into one office scene, making funny faces"}]
for path in images:
parts.append({"inlineData": {"mimeType": "image/png", "data": to_b64(path)}})
response = requests.post(
"https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent",
headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
json={
"contents": [{"parts": parts}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "5:4", "imageSize": "2K"}
}
},
timeout=300
).json()
img_data = [p for p in response["candidates"][0]["content"]["parts"] if "inlineData" in p][-1]["inlineData"]["data"]
with open("merged.png", "wb") as f:
f.write(base64.b64decode(img_data))
cURL (несколько изображений, повторяет официальный формат Google)
curl -X POST "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent" \
-H "Authorization: Bearer sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"contents": [{
"parts": [
{"text": "An office group photo of these people, they are making funny faces."},
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_DATA_IMG_1>"}},
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_DATA_IMG_2>"}},
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_DATA_IMG_3>"}}
]
}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "5:4", "imageSize": "2K"}
}
}'
Краткий справочник по параметрам
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
contents[].parts | массив | Да | Состоит из 1 текстовой части + N частей inlineData. Каждая часть содержит либо text, либо inlineData — но никогда оба одновременно |
contents[].parts[].text | строка | Да | Инструкция по редактированию (указывается только в первой части) |
contents[].parts[].inlineData.mimeType | строка | Да | image/jpeg или image/png |
contents[].parts[].inlineData.data | строка | Да | Изображение в формате base64 (дублируйте по одной части inlineData на каждое изображение при редактировании нескольких изображений) |
generationConfig.responseModalities | массив | Да | Обычно ["IMAGE"] |
generationConfig.imageConfig.aspectRatio | строка | Нет | 14 соотношений сторон; если не указано, модель выбирает его на основе содержимого, поэтому передавайте явно |
generationConfig.imageConfig.imageSize | строка | Нет | 1K / 2K / 4K (512 не поддерживается), по умолчанию 1K |
generationConfig.thinkingConfig.thinkingLevel | строка | Нет | minimal / medium / high, по умолчанию medium |
generationConfig.thinkingConfig.includeThoughts | логический | Нет | Возвращать текст процесса рассуждения |
Многоэтапное диалоговое редактирование
Nano Banana 2.1 (gemini-nano-banana-2.1) поддерживает полноценное диалоговое многоэтапное редактирование: добавляйте сгенерированное на каждом шаге изображение обратно в contents как role: "model" inlineData, а затем отправляйте следующую инструкцию пользователя. Модель выполняет редактирование с учётом всей истории диалога и накапливает изменения (например, сначала перекрасьте диван, затем добавьте аксессуар — предыдущее изменение сохранится).
Это отличается от моделей обратного поиска изображений: нативный формат Gemini действительно считывает изображения из реплик истории с ролью
model. Для согласованности между шагами и поэтапного уточнения используйте приведенный ниже паттерн заполнения истории.import requests, base64
API_KEY = "sk-your-api-key"
URL = "https://api.apiyi.com/v1beta/models/gemini-nano-banana-2.1:generateContent"
H = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
CFG = {"responseModalities": ["IMAGE"], "imageConfig": {"aspectRatio": "1:1", "imageSize": "2K"}}
contents = [] # keep one running conversation history
def turn(instruction, save_to):
contents.append({"role": "user", "parts": [{"text": instruction}]})
data = requests.post(URL, headers=H,
json={"contents": contents, "generationConfig": CFG}, timeout=300).json()
part = next(p for p in data["candidates"][0]["content"]["parts"] if "inlineData" in p)
contents.append({"role": "model", "parts": [part]}) # key: backfill the output image into history
with open(save_to, "wb") as f:
f.write(base64.b64decode(part["inlineData"]["data"]))
return part
turn("Generate an orange cat sitting on a blue sofa, simple line-art style", "step1.png")
turn("Make the sofa red; keep the cat and composition unchanged", "step2.png") # edits the previous image
turn("Put a small yellow hat on the cat; keep everything else the same", "step3.png") # accumulates; red sofa kept
Начало многоэтапного редактирования с существующего изображения: поместите
inlineData (ваше собственное изображение) вместе с инструкцией в первое сообщение пользователя, чтобы отредактировать существующую фотографию, а затем на каждом шаге продолжайте передавать ответ модели обратно в contents.Два стиля многоэтапного редактирования:
- Заполнение истории (выше, рекомендуется):
contentsсохраняет чередующуюся историю диалога «пользователь/модель» — накапливает изменения от шага к шагу с лучшей согласованностью. - Повторная отправка (проще): на каждом шаге отправляется одно сообщение пользователя (
text+inlineDataпредыдущего изображения) для одноэтапного редактирования без сохранения предыдущего контекста.
Авторизации
API Key obtained from APIYI Console
Тело
application/json
Была ли эта страница полезной?