# 香蕉 2.0

使用 `gemini-3.1-flash-image-preview` 生成或编辑图片。

## 1 快速开始 {#quickstart}

使用 **125 或 139 分组**的 API Key。示例生成一张 **4K** 图片，保存并打开；按分组价格计费。 选下面一种方式运行即可，切换示例并重新发送会产生新的调用。

### 1.1 Python 3：完整流程 {#quick-python}

适用于 Windows、macOS 和 Linux。只使用 Python 标准库，无需安装 SDK。

将下面的代码保存为 `banana-2-quickstart.py`，在终端运行 `python3 banana-2-quickstart.py`（Windows 可用 `py -3 banana-2-quickstart.py`），按提示输入 API Key。程序会打印文件路径，并尝试用浏览器打开本地结果。

``` python
import base64
import getpass
import json
from pathlib import Path
from urllib.error import HTTPError
from urllib.request import Request, urlopen
import uuid
import webbrowser

URL = 'https://yyds.seqnode.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent'
PAYLOAD = {
    "contents": [
        {
            "role": "user",
            "parts": [
                {
                    "text": "一只戴蓝色围巾的白色小狐狸，浅灰背景，柔和光线，无文字。"
                }
            ]
        }
    ],
    "generationConfig": {
        "responseModalities": [
            "IMAGE"
        ],
        "imageConfig": {
            "aspectRatio": "1:1",
            "imageSize": "4K"
        }
    }
}


def main():
    api_key = getpass.getpass("输入 API Key：").strip()
    if not api_key:
        raise ValueError("请输入有效的 API Key。")
    headers = {"x-goog-api-key": api_key}
    headers["Content-Type"] = "application/json; charset=utf-8"
    headers["User-Agent"] = "YM2API-Quickstart/1.0"
    request = Request(URL, data=json.dumps(PAYLOAD, ensure_ascii=False).encode("utf-8"), headers=headers)
    with urlopen(request, timeout=300) as response:
        result = json.load(response)
    encoded = next((part["inlineData"]["data"]
        for candidate in result.get("candidates", [])
        for part in candidate.get("content", {}).get("parts", [])
        if not part.get("thought") and part.get("inlineData", {}).get("data")), None)
    if not encoded:
        raise ValueError("响应没有最终图片。请检查响应和使用记录，再决定是否重试。")
    data = base64.b64decode(encoded, validate=True)
    if data.startswith(b"\x89PNG\r\n\x1a\n"):
        extension = ".png"
    elif data.startswith(b"\xff\xd8\xff"):
        extension = ".jpg"
    elif len(data) >= 12 and data[:4] == b"RIFF" and data[8:12] == b"WEBP":
        extension = ".webp"
    else:
        raise ValueError("返回数据不是可识别的 PNG、JPEG 或 WebP。")
    path = Path.cwd() / ("banana-2-" + uuid.uuid4().hex + extension)
    with path.open("xb") as output:
        output.write(data)
    print(f"图片已保存：{path}")
    if not webbrowser.open(path.as_uri()):
        print("请到以上路径手动打开图片。")


if __name__ == "__main__":
    try:
        main()
    except HTTPError as error:
        print(f"HTTP {error.code}：{error.read(2000).decode('utf-8', errors='replace')}")
        raise SystemExit(1)
    except Exception as error:
        print(f"运行失败：{error}")
        raise SystemExit(1)
```

[下载 Python 示例](banana-2-quickstart.py)。如未自动打开结果，按输出路径手动打开。

### 1.2 PowerShell 7：完整流程 {#quick-powershell}

适合已有 PowerShell 7 的 Windows 用户。复制整段代码到终端，只按提示输入 API Key。

``` powershell
$apiKey = Read-Host "输入 API Key" -MaskInput
if ([string]::IsNullOrWhiteSpace($apiKey)) { throw "请输入有效的 API Key。" }
$model = "gemini-3.1-flash-image-preview"
$payload = @{
    contents = @(@{
        role = "user"
        parts = @(@{ text = "一只戴蓝色围巾的白色小狐狸，浅灰背景，柔和光线，无文字。" })
    })
    generationConfig = @{
        responseModalities = @("IMAGE")
        imageConfig = @{ aspectRatio = "1:1"; imageSize = "4K" }
    }
}
$request = @{
    Uri = "https://yyds.seqnode.com/v1beta/models/${model}:generateContent"
    Method = "Post"
    Headers = @{ "x-goog-api-key" = $apiKey }
    ContentType = "application/json; charset=utf-8"
    Body = [Text.Encoding]::UTF8.GetBytes(($payload | ConvertTo-Json -Depth 12))
    TimeoutSec = 300
    ErrorAction = "Stop"
}
$result = Invoke-RestMethod @request
$image = $result.candidates.content.parts |
    Where-Object { $_.inlineData.data } | Select-Object -First 1
if (-not $image) {
    $detail = $result | ConvertTo-Json -Depth 12
    throw "响应中没有图片。检查以下响应中的 finishReason 或 promptFeedback：`n$detail"
}
$extension = @{ "image/png" = ".png"; "image/jpeg" = ".jpg"; "image/webp" = ".webp" }[$image.inlineData.mimeType]
if (-not $extension) { throw "未识别的图片格式：$($image.inlineData.mimeType)" }
$bytes = [Convert]::FromBase64String($image.inlineData.data)
if ($bytes.Length -eq 0) { throw "图片数据为空。请保留响应排查。" }
$file = Join-Path $PWD ("banana-2-" + [guid]::NewGuid().ToString("N") + $extension)
$stream = [IO.File]::Open($file, [IO.FileMode]::CreateNew)
try { $stream.Write($bytes, 0, $bytes.Length) } finally { $stream.Dispose() }
Write-Host "图片已保存：$file"
Invoke-Item -LiteralPath $file -ErrorAction Continue
```

[下载 PowerShell 示例](banana-2-quickstart.ps1)。

### 1.3 cURL / JSON：检查原始请求 {#quick-http}

JSON 是请求体，需要由 cURL、Postman 或 Apifox 发送。先将下面内容保存为 UTF-8 的 `banana-2-request.json`，也可[下载请求 JSON](banana-2-request.json)。

``` json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "一只戴蓝色围巾的白色小狐狸，浅灰背景，柔和光线，无文字。"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "4K"
    }
  }
}
```

在该文件所在目录，用 Bash（Linux、macOS 或 Git Bash）运行下面的命令，只输入 API Key。响应保存到 `response.json`，已有同名文件会被覆盖；终端显示 HTTP 状态码。

``` bash
read -rsp 'API Key: ' API_KEY; printf '\n'
curl --silent --show-error --fail-with-body --max-time 300 "https://yyds.seqnode.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" \
  -H "x-goog-api-key: $API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary '@banana-2-request.json' \
  --output response.json --write-out 'HTTP %{http_code}\n'
unset API_KEY
```

Postman / Apifox：新建 **POST** 请求，URL 填 `https://yyds.seqnode.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent`，Body 选择 **raw → JSON** 并粘贴上面的 JSON；请求头设置 `Content-Type: application/json` 和 `x-goog-api-key: YOUR_API_KEY`，将 `YOUR_API_KEY` 替换为自己的 Key。

HTTP 200 后，还需确认响应包含图片数据。cURL 保存的是 JSON；Python 和 PowerShell 示例会自动解码并保存图片。

## 2 接入信息 {#endpoint}

先用快速开始验证 Key 和返回图片，再选择下面的文生图或图生图场景。模型名写在请求 URL 中，不放入 JSON 的 `model` 字段。

  -----------------------------------------------------------------------------------------------------------------------------
  项目                                值
  ----------------------------------- -----------------------------------------------------------------------------------------
  方法                                `POST`

  地址                                `https://yyds.seqnode.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent`

  鉴权                                `x-goog-api-key: YOUR_API_KEY`

  请求格式                            `application/json`

  返回图片                            `candidates[].content.parts[].inlineData`
  -----------------------------------------------------------------------------------------------------------------------------

分组由 API Key 决定，请求中无需填写 `group_id`。使用上面的完整模型名；不同分组的可用模型，以该 Key 请求 `/v1/models` 的结果为准。

## 3 文生图 {#parameters}

仅使用文字生成图片。`POST /v1beta/models/gemini-3.1-flash-image-preview:generateContent`，请求体为 JSON。

  ----------------------------------------------------------------------------------------------------------------------------------
  参数                                         填写要求                   用途 / 示例
  -------------------------------------------- -------------------------- ----------------------------------------------------------
  `contents[].role`                            本页示例填写 `user`        用户输入

  `contents[].parts[].text`                    填写提示词                 说明主体、场景或编辑目标

  `generationConfig.responseModalities`        示例显式填写 `["IMAGE"]`   需要文字时使用 `["TEXT", "IMAGE"]`；仍需检查实际返回内容

  `generationConfig.imageConfig.imageSize`     可选，示例显式填写         档位名称中的 `K` 大写；支持范围按本页说明

  `generationConfig.imageConfig.aspectRatio`   可选，示例显式填写         例如 `1:1`；实际像素与比例、模型有关
  ----------------------------------------------------------------------------------------------------------------------------------

修改快速开始所选语言的请求体，再运行该示例。以下 JSON 可直接作为请求 Body。

`4K` 是请求档位，实际像素尺寸与图片比例、渠道有关。费用查看[模型广场](https://yyds.seqnode.com/model-plaza)，扣费查看本站使用记录。

**请求示例**

``` json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "一只白色小狐狸，蓝色围巾，柔和光线，无文字。"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "4K"
    }
  }
}
```

**响应：** 遍历 `candidates[].content.parts[]` 查找最终图片；[保存方法](#response)。

## 4 图生图：单图与多图参考 {#reference-image}

使用与文生图相同的 `POST /v1beta/models/gemini-3.1-flash-image-preview:generateContent`。在文字 part 后添加参考图；以下是完整 JSON Body，需替换图片 Base64。

  --------------------------------------------------------------------------------------------------------------
  参数                                       填写要求                说明
  ------------------------------------------ ----------------------- -------------------------------------------
  `contents[].parts[].text`                  填写编辑要求            多图时说明第一张、第二张分别用于什么

  `contents[].parts[].inlineData.mimeType`   每张图填写              `image/png`、`image/jpeg` 或 `image/webp`

  `contents[].parts[].inlineData.data`       每张图填写              完整文件的纯 Base64，不加 Data URL 前缀
  --------------------------------------------------------------------------------------------------------------

``` json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "保留主体和构图，把围巾改成红色。"
        },
        {
          "inlineData": {
            "mimeType": "image/png",
            "data": "YOUR_IMAGE_BASE64"
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "4K"
    }
  }
}
```

**响应：** 与文生图相同，[解码后保存图片](#response)。

**PowerShell 插入片段：**

在快速开始代码中，**创建 `$payload` 之后、创建 `$request` 之前**插入下面的片段。将路径替换为本地 PNG 图片路径。

``` powershell
$reference = Read-Host "输入本地 PNG 图片的完整路径"
$referenceBytes = [IO.File]::ReadAllBytes((Resolve-Path -LiteralPath $reference -ErrorAction Stop).Path)
$payload.contents[0].parts = @(
    @{ text = "保持参考图中的主体和构图，只把围巾改成红色。" }
    @{ inlineData = @{
        mimeType = "image/png"
        data = [Convert]::ToBase64String($referenceBytes)
    } }
)
```

使用 JPEG 或 WebP 时，同步将 `mimeType` 改为 `image/jpeg` 或 `image/webp`。传入纯 Base64，不加 `data:image/...;base64,` 前缀。

多图参考时，在 `parts` 中追加多个 `inlineData` 对象，每张图一个对象，并在提示词中说明各张图的用途。参考图数量与还原效果受渠道和素材影响。

## 5 读取响应、保存与查看图片 {#response}

图片通过 `inlineData.data` 返回。先读取 `mimeType`，再选择文件扩展名；快速开始代码已处理 PNG、JPEG 和 WebP。

``` json
{
  "candidates": [{
    "content": {
      "parts": [{
        "inlineData": {
          "mimeType": "image/png",
          "data": "BASE64_IMAGE_DATA"
        }
      }]
    },
    "finishReason": "STOP"
  }]
}
```

这是响应结构示例，`BASE64_IMAGE_DATA` 是占位值。

遍历返回的 `parts`，不要假设第一项就是图片；遇到文字先读取提示。保存后打开图片文件查看，`response.json` 本身不是图片。快速开始的 Python / PowerShell 示例已包含保存和打开步骤。

图片 URL 不是本页示例的返回约定；需要长期可访问的网址时，先保存文件，再上传到自己的存储。

### 5.1 流式输出、思考签名与多轮改图 {#signed-stream}

使用 139 分组的本站 API Key。Gemini 原生流式端点为 POST /v1beta/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse，响应类型为 text/event-stream；请求体使用 contents，不需要额外添加 stream=true。

下面的 cURL 适用于 Bash / macOS / Linux。YOUR_API_KEY 替换为本站 Key；-N 关闭客户端输出缓冲。Windows 可直接使用后面的 Python 示例。

```bash
curl -N "https://yyds.seqnode.com/v1beta/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  --data-binary '{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "画一只蓝色陶瓷杯，桌上放一个橙子，柔和自然光。"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "imageSize": "1K",
      "aspectRatio": "1:1"
    }
  }
}'
```

SSE 响应结构示意（占位符不是可回传的真实值）：

```text
data: {"candidates": [{"content": {"role": "model", "parts": [{"inlineData": {"mimeType": "image/jpeg", "data": "<完整图片Base64>"}, "thoughtSignature": "<原样保存的签名>"}]}, "finishReason": "STOP"}]}
```

以空行分隔 SSE 事件，解析 data: 后的 JSON。读取 candidates[0].content.parts 中的 inlineData 图片和 thoughtSignature。忽略以冒号开头的心跳注释；不要把每个网络数据块当成一条完整 JSON。

2026-10-15 直连当前上游渠道，对两个模型各完成三轮流式改图：蓝杯子 → 红杯子 → 加勺子，六次均成功并返回签名。本次每个响应只在生成完成后发送一个完整 data 事件，没有逐段图片或思考文本输出；SSE 协议不保证更早出图，其他请求的事件数量可能不同。思考签名是需要回传的上下文数据，并不等于可读的思考文本。

本站端点的补充验证本次首轮收到 HTTP 429，未完成本站多轮验证；以下代码是接入示例，上述六次成功记录来自上游直连测试。遇到 429 请检查分组、额度和并发状态，不要持续自动重发。

下一轮仍请求相同流式端点。按 user → model → user 顺序组织历史，保留上一轮全部 model parts 的原始顺序与字段，包括图片及 thoughtSignature；不要截断、解码、改写签名，也不要将带签名的 part 与其他 part 合并。以下 JSON 仅展示单图片响应的结构；实际代码应回传完整模型内容。

```json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "画一只蓝色陶瓷杯，桌上放一个橙子，柔和自然光。"
        }
      ]
    },
    {
      "role": "model",
      "parts": [
        {
          "inlineData": {
            "mimeType": "image/jpeg",
            "data": "<上一轮完整图片Base64>"
          },
          "thoughtSignature": "<上一轮原始签名>"
        }
      ]
    },
    {
      "role": "user",
      "parts": [
        {
          "text": "把上一张图的杯子改成红色，保持橙子、桌面和构图不变。"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "imageSize": "1K",
      "aspectRatio": "1:1"
    }
  }
}
```

签名可能很大，本次样本约 129 万～191 万字符；不要按普通短 token 限长。多轮历史中的图片和签名会增加请求体大小。

[下载 Python 3 流式多轮示例](banana-signed-stream.py)

```bash
python3 banana-signed-stream.py --model gemini-3.1-flash-image
```

Windows 使用 py -3 替代 python3。程序提示输入隐藏的本站 Key，也可读取 YM2API_KEY 环境变量；默认连续调用三次、每次生成一张 1K 图片，按分组价格计费。只测试首轮可加 --turns 1。程序仅依赖标准库，图片保存到新建的 banana-stream-* 目录，签名只保存在运行内存中，不打印或写入文件。

示例支持多个 SSE 事件，按顺序保留所有 parts；HTTP 错误、SSE error、非 STOP 结束、缺少最终图片或后续轮次所需签名时停止。不会自动重试，避免重复生成。

URL 返回与签名多轮的区别：POST /v1/images/generations 设置 response_format="url" 后，返回 created 和 data[].url；当前实测返回本站随机图片地址，不含 thoughtSignature。图片 URL 可作为图片编辑的参考图，但仅保留该 URL 不会保留原生签名对话历史。Chat Completions 的 Markdown 图片链接也不应当作完整 Gemini model content 回传。

```json
{
  "created": 1792070510,
  "data": [
    {
      "url": "https://yyds.seqnode.com/随机标识.jpg"
    }
  ]
}
```

[Google 官方：图片生成与思考签名](https://ai.google.dev/gemini-api/docs/generate-content/image-generation#thought-signatures)

## 6 常见错误与重试 {#troubleshooting}

  ------------------------------------------------------------------------------------------
  现象                                操作
  ----------------------------------- ------------------------------------------------------
  `401` / `403`                       检查 Key、绑定分组、余额及访问权限

  `404` / 模型不可用                  用同一把 Key 查询 `/v1/models`，核对完整模型名

  `400`                               检查 JSON、`imageSize` 大小写、参考图 MIME 与 Base64

  `429`                               按服务端提示等待，再重试

  `5xx` / 超时                        保留错误响应，先检查使用记录，再决定是否重新提交

  HTTP 成功但没有图片                 检查 `finishReason`、`promptFeedback` 和返回文字

  已保存但未打开                      到命令输出的文件路径，用本地图片查看器打开
  ------------------------------------------------------------------------------------------

## 7 相关文档 {#related}

- [香蕉 2.1](group139-banana21-api.html)
- [香蕉 2 Pro](banana-2-pro-api.html)
- [原 Flash / Pro 参数与历史验证记录](banana-stable-leo-api.html)
