Skip to content

Nano Banana 系列

模型简介

Google 的 Nano Banana 系列是其图像生成技术的内部代号,目前提供三代模型:

  • gemini-2.5-flash-image(Nano Banana)
  • gemini-3-pro-image-preview(Nano Banana Pro)
  • gemini-3.1-flash-image-preview(Nano Banana 2)

🆕 Nano Banana 2 (最新)

  • 模型名称: gemini-3.1-flash-image-preview
  • 版本: Preview(预览版)
  • 技术基础: 基于 Gemini 3 架构,具备更强的推理能力
  • 特点: 最新技术,图像质量和细节表现更优秀
  • 分辨率支持: 支持 512、1K、2K、4K 四种分辨率
  • 适用场景: 追求最佳效果、需要高分辨率、愿意尝试新特性的用户

端点迁移说明

注意

图片生成的预览端口将于7月17日下架,平台会对依旧使用预览端口重定向至正式端口以保证不中断您的服务,但同时我们建议您在2026年7月17日之前更新至模型端点,以免后续影响服务。

预览端点正式端点
gemini-3.1-flash-image-previewgemini-3.1-flash-image
gemini-3-pro-image-previewgemini-3-pro-image

调用方式:Google 原生格式(支持自定义纵横比)

💡 模型切换说明

在 Google 原生格式中,模型名称在 URL 路径中指定:

Nano Banana 2 (最新): /v1beta/models/gemini-3.1-flash-image-preview:generateContent

Nano Banana Pro: /v1beta/models/gemini-3-pro-image-preview:generateContent

Nano Banana: /v1beta/models/gemini-2.5-flash-image:generateContent

支持的纵横比

类型纵横比选项
横向21:9 (超宽屏) , 16:9 (宽屏) , 4:3, 3:2
正方形1:1
纵向9:16 (竖屏) , 3:4, 2:3
其他5:4, 4:5

支持的分辨率

ℹ️ 分辨率支持说明

  • Nano Banana 2 (gemini-3.1-flash-image-preview):支持 512、1K、2K、4K 四种分辨率。
  • Nano Banana Pro (gemini-3-pro-image-preview):支持 1K、2K、4K 三种分辨率。
  • Nano Banana (gemini-2.5-flash-image):固定 1K (1024px),不支持 imageSize 参数。

Nano Banana 2 分辨率选项

纵横比512 分辨率1K 分辨率2K 分辨率4K 分辨率
1:1512×5121024×10242048×20484096×4096
16:9688×3841376×7682752×15365504×3072
9:16384×688768×13761536×27523072×5504
4:3600×4481200×8962400×17924800×3584
3:4448×600896×12001792×24003584×4800
21:9792×3361584×6723168×13446336×2688
3:2624×4161248×8322496×16644992×3328
2:3416×624832×12481664×24963328×4992
5:4576×4481152×8962304×17924608×3584
4:5448×576896×11521792×23043584×4608

💡 分辨率选择建议

  • 1K: 适合网页展示、社交媒体、快速预览。
  • 2K: 适合高质量打印、专业展示。
  • 4K: 适合大型打印、专业设计、极致细节。

代码示例

完整 Curl 示例(Nano Banana 2 - 4K)

bash
#!/bin/bash

# 1. 设置 API 密钥
export API_KEY="sk-xxxx"

# 2. 发送请求
curl -s -X POST "https://api.exchangetoken.ai/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
        {
            "role": "user",
            "parts": [
                {
                    "text": "A futuristic city skyline at sunset, high detailed, 4k"
                }
            ]
        }
    ],
    "generationConfig": {
        "responseModalities": ["IMAGE"]
    }
}' \
  | jq -r '.candidates[0].content.parts[0].inlineData.data' \
  | base64 --decode > output_4k.png

echo "✅ 图片已保存: output_4k.png"

快速开始 Curl 示例(Nano Banana 1K)

作为参考,以下是 Nano Banana 的调用方式。

bash
# 使用 Nano Banana(1K)
curl -s -X POST "https://api.exchangetoken.ai/v1beta/models/gemini-2.5-flash-image:generateContent" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [{"text": "a beautiful sunset over mountains"}]
    }],
    "generationConfig": {
      "responseModalities": ["IMAGE"],
      "imageConfig": {"aspectRatio": "16:9"}
    }
  }' | jq -r '.candidates[0].content.parts[0].inlineData.data' | base64 --decode > output.png

更多场景代码示例

以下是涵盖单图编辑、多图合成、智能编辑以及 Base64 数据处理工具类的进阶示例。

1. 单图编辑示例(Python)

对单张图片进行编辑操作。

python
单图编辑示例(Python)
import requests
import json
import base64
from Base64ImageHandler import Base64ImageHandler

def get_image_base64(url):
    """
    【关键步骤】
    Gemini 原生接口不支持直接传 URL,必须下载图片并转为 Base64 编码
    """
    print(f"[LOG] 正在下载图片以适配原生接口: {url}")
    try:
        headers = {'User-Agent': 'Mozilla/5.0'}
        response = requests.get(url, headers=headers, timeout=30)
        if response.status_code == 200:
            # 获取 content-type,默认为 image/png
            mime_type = response.headers.get('Content-Type', 'image/png')
            # 转换为 base64 字符串
            b64_data = base64.b64encode(response.content).decode('utf-8')
            print(f"[LOG] 图片下载成功,格式: {mime_type}, 数据长度: {len(b64_data)}")
            return mime_type, b64_data
        else:
            print(f"[ERROR] 图片下载失败,状态码: {response.status_code}")
            return None, None
    except Exception as e:
        print(f"[ERROR] 图片下载异常: {e}")
        return None, None

def creative_merge(image_urls, merge_instruction):
    print("=" * 50)
    print("开始处理图片合并请求 (Gemini 原生协议)")
    print("=" * 50)

    # 1. 准备请求内容 parts
    parts = []

    # 添加文本指令
    parts.append({
        "text": merge_instruction + "\n\n请直接生成图片,并以 Base64 格式返回。"
    })

    # 2. 处理图片:下载并转换为 inline_data 格式
    if image_urls:
        print(f"[LOG] 图片URL数量: {len(image_urls)}")
        for i, url in enumerate(image_urls, 1):
            mime_type, image_b64 = get_image_base64(url)
            if image_b64:
                parts.append({
                    "inline_data": {
                        "mime_type": mime_type,
                        "data": image_b64
                    }
                })

    # 3. 构造 Gemini 原生 Payload (contents 结构)
    # 结构: contents -> parts -> [text, inline_data]
    data = {
        "contents": [
            {
                "role": "user",
                "parts": parts
            }
        ],
        "generationConfig": {
            "temperature": 0.5,
            "maxOutputTokens": 4096 
        }
    }

    # 4. 设置原生接口 URL
    # 注意:这里使用的是 :generateContent 接口
    api_endpoint = "https://api.exchangetoken.ai/v1beta/models/gemini-3.1-flash-image-preview:generateContent"

    headers = {
        "Authorization": f"Bearer sk-xxxxx",
        "Content-Type": "application/json"
    }

    print(f"\n[LOG] 请求URL: {api_endpoint}")
    print(f"[LOG] 发送请求中...")

    try:
        response = requests.post(api_endpoint, headers=headers, json=data)

        print(f"[LOG] HTTP状态码: {response.status_code}")
        # print(f"[LOG] 响应头: {dict(response.headers)}")

        if response.status_code != 200:
            print(f"[ERROR] API请求失败")
            print(f"[ERROR] 响应内容: {response.text}")
            return None, None

        response_json = response.json()
        print(f"\n[LOG] API调用成功,开始解析原生响应...")

        # 5. 解析 Gemini 原生响应结构
        # 成功响应通常在 candidates[0].content.parts[0].text 中
        response_str = json.dumps(response_json, ensure_ascii=False)

        # 尝试打印回复文本
        try:
            candidates = response_json.get('candidates', [])
            if candidates:
                content = candidates[0].get('content', {})
                res_parts = content.get('parts', [])
                if res_parts and 'text' in res_parts[0]:
                    print(f"[LOG] 模型回复文本片段: {res_parts[0]['text'][:200]}...")
        except Exception as e:
            print(f"[WARNING] 简单解析文本失败: {e}")

        # 使用工具类在整个响应字符串中搜索 Base64
        result = Base64ImageHandler.extract_from_response(response_str)

        if result and result[0]:
            print(f"[LOG] 成功提取图片数据,长度: {len(result[0])}")
        else:
            print(f"[WARNING] 未能提取到base64数据,请检查模型回复内容。")

        return result

    except requests.exceptions.RequestException as e:
        print(f"[ERROR] 请求异常: {e}")
        return None, None
    except Exception as e:
        print(f"[ERROR] 未知错误: {e}")
        import traceback
        traceback.print_exc()
        return None, None

if __name__ == "__main__":
    images = [
        "https://您的图片.png",
    ]

    # 提示词:针对多模态模型的 Image-to-Text-to-Image 技巧
    prompt = (
        "你是一个图像编辑助手。请给图片中的人物带上一个时尚的帽子。\n"
        "【关键】:请直接输出修改后的图片数据,不要只输出描述。\n"
        "如果可以直接生成图像,请返回图像。\n"
        "如果只能返回文本,请将结果图片编码为 Base64 字符串,并包含在 JSON 格式中返回,"
        "例如:{\"image_base64\": \"...\"}。"
    )

    result = creative_merge(images, prompt)

    print("\n" + "=" * 50)
    print("保存图片结果")
    print("=" * 50)

    if result and result[0]:
        base64_data, image_format = result
        print(f"[LOG] 准备保存图片,格式: {image_format}")
        saved_filename = Base64ImageHandler.save_to_file(base64_data)
        print(f"[SUCCESS] 图片已保存为: {saved_filename}")
    else:
        print("[ERROR] 流程结束,未保存图片。")

2. 多图合成 - 创意融合 (Python)

将多张图片作为输入,通过 Prompt 指令进行创意融合。

python
import requests
import json
import base64
from Base64ImageHandler import Base64ImageHandler
def get_image_base64(url):
    """
    【关键步骤】
    Gemini 原生接口不支持直接传 URL,必须下载图片并转为 Base64 编码
    """
    print(f"[LOG] 正在下载图片以适配原生接口: {url}")
    try:
        headers = {'User-Agent': 'Mozilla/5.0'}
        response = requests.get(url, headers=headers, timeout=30)
        if response.status_code == 200:
            # 获取 content-type,默认为 image/png
            mime_type = response.headers.get('Content-Type', 'image/png')
            # 转换为 base64 字符串
            b64_data = base64.b64encode(response.content).decode('utf-8')
            print(f"[LOG] 图片下载成功,格式: {mime_type}, 数据长度: {len(b64_data)}")
            return mime_type, b64_data
        else:
            print(f"[ERROR] 图片下载失败,状态码: {response.status_code}")
            return None, None
    except Exception as e:
        print(f"[ERROR] 图片下载异常: {e}")
        return None, None
def creative_merge(image_urls, merge_instruction):
    print("=" * 50)
    print("开始处理图片合并请求 (Gemini 原生协议)")
    print("=" * 50)
    # 1. 准备请求内容 parts
    parts = []
    # 添加文本指令
    parts.append({
        "text": merge_instruction + "\n\n请直接生成图片,并以 Base64 格式返回。"
    })
    # 2. 处理图片:下载并转换为 inline_data 格式
    if image_urls:
        print(f"[LOG] 图片URL数量: {len(image_urls)}")
        for i, url in enumerate(image_urls, 1):
            mime_type, image_b64 = get_image_base64(url)
            if image_b64:
                parts.append({
                    "inline_data": {
                        "mime_type": mime_type,
                        "data": image_b64
                    }
                })
    # 3. 构造 Gemini 原生 Payload (contents 结构)
    # 结构: contents -> parts -> [text, inline_data]
    data = {
        "contents": [
            {
                "role": "user",
                "parts": parts
            }
        ],
        "generationConfig": {
            "temperature": 0.5,
            "maxOutputTokens": 4096 
        }
    }
    # 4. 设置原生接口 URL
    # 注意:这里使用的是 :generateContent 接口
    api_endpoint = "https://api.exchangetoken.ai/v1beta/models/gemini-3.1-flash-image-preview:generateContent"
    headers = {
        "Authorization": f"Bearer sk-xxxxx",
        "Content-Type": "application/json"
    }
    print(f"\n[LOG] 请求URL: {api_endpoint}")
    print(f"[LOG] 发送请求中...")
    try:
        response = requests.post(api_endpoint, headers=headers, json=data)
        print(f"[LOG] HTTP状态码: {response.status_code}")
        # print(f"[LOG] 响应头: {dict(response.headers)}")
        if response.status_code != 200:
            print(f"[ERROR] API请求失败")
            print(f"[ERROR] 响应内容: {response.text}")
            return None, None
        response_json = response.json()
        print(f"\n[LOG] API调用成功,开始解析原生响应...")
        # 5. 解析 Gemini 原生响应结构
        # 成功响应通常在 candidates[0].content.parts[0].text 中
        response_str = json.dumps(response_json, ensure_ascii=False)
        # 尝试打印回复文本
        try:
            candidates = response_json.get('candidates', [])
            if candidates:
                content = candidates[0].get('content', {})
                res_parts = content.get('parts', [])
                if res_parts and 'text' in res_parts[0]:
                    print(f"[LOG] 模型回复文本片段: {res_parts[0]['text'][:200]}...")
        except Exception as e:
            print(f"[WARNING] 简单解析文本失败: {e}")
        # 使用工具类在整个响应字符串中搜索 Base64
        result = Base64ImageHandler.extract_from_response(response_str)
        if result and result[0]:
            print(f"[LOG] 成功提取图片数据,长度: {len(result[0])}")
        else:
            print(f"[WARNING] 未能提取到base64数据,请检查模型回复内容。")
        return result
    except requests.exceptions.RequestException as e:
        print(f"[ERROR] 请求异常: {e}")
        return None, None
    except Exception as e:
        print(f"[ERROR] 未知错误: {e}")
        import traceback
        traceback.print_exc()
        return None, None
if __name__ == "__main__":
    images = [
        "https://图片一.png",
        "https://图片二.png"
    ]
    # 示例提示词:针对多模态模型的 Image-to-Text-to-Image 技巧
    prompt = (
        "你是一个图像编辑助手。请给图一中的人物带上一个时尚的帽子。并把图二中的金项链穿戴到图一的人物身上\n"
        "【关键】:请直接输出修改后的图片数据,不要只输出描述。\n"
        "如果可以直接生成图像,请返回图像。\n"
        "如果只能返回文本,请将结果图片编码为 Base64 字符串,并包含在 JSON 格式中返回,"
        "例如:{\"image_base64\": \"...\"}。"
    )
    result = creative_merge(images, prompt)
    print("\n" + "=" * 50)
    print("保存图片结果")
    print("=" * 50)
    if result and result[0]:
        base64_data, image_format = result
        print(f"[LOG] 准备保存图片,格式: {image_format}")
        saved_filename = Base64ImageHandler.save_to_file(base64_data)
        print(f"[SUCCESS] 图片已保存为: {saved_filename}")
    else:
        print("[ERROR] 流程结束,未保存图片。")

3. 智能多图处理策略 (Python)

根据输入图片的数量自动调整融合策略,实现单图编辑或多图创意处理。

python
def smart_multi_image_edit(images, instruction):
    """智能多图编辑,自动处理不同数量的图片"""
    
    if len(images) == 1:
        # 单图编辑
        prompt = f"Edit this image: {instruction}"
    elif len(images) == 2:
        # 双图合成
        prompt = f"Combine these two images creatively: {instruction}"
    else:
        # 多图处理
        prompt = f"Process these {len(images)} images together: {instruction}"
    
    # 构建content
    content = [{"type": "text", "text": prompt}]
    for img in images:
        content.append({
            "type": "image_url",
            "image_url": {"url": img}
        })
    
    # 发送请求...
    return send_edit_request(content)

4. Base64 数据处理工具类 (Python)

用于处理 API 返回的 Base64 数据,支持提取、保存和转换为 PIL Image 对象。

python
import base64
import io
import re
from datetime import datetime
from PIL import Image

class Base64ImageHandler:
    """Base64图片处理工具类"""
    
    @staticmethod
    def extract_from_response(response_content):
        """从API响应中提取base64数据"""
        patterns = [
            r'data:image/([^;]+);base64,([A-Za-z0-9+/=]+)',
            r'([A-Za-z0-9+/=]{100,})'
        ]
        
        for pattern in patterns:
            match = re.search(pattern, response_content)
            if match:
                if len(match.groups()) == 2:
                    return match.group(2), match.group(1)  # data, format
                else:
                    return match.group(1), 'png'  # default to png
        
        return None, None
    
    @staticmethod
    def save_to_file(base64_data, filename=None):
        """保存base64数据为文件"""
        if not filename:
            filename = f"image_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
        
        image_data = base64.b64decode(base64_data)
        with open(filename, 'wb') as f:
            f.write(image_data)
        
        return filename
    
    @staticmethod
    def to_pil_image(base64_data):
        """转换为PIL Image对象"""
        image_data = base64.b64decode(base64_data)
        return Image.open(io.BytesIO(image_data))
    
    @staticmethod
    def from_pil_image(pil_image, format='PNG'):
        """从PIL Image转换为base64"""
        buffer = io.BytesIO()
        pil_image.save(buffer, format=format)
        img_str = base64.b64encode(buffer.getvalue()).decode()
        return f"data:image/{format.lower()};base64,{img_str}"