YM2API开发者文档
跳到正文
文档 / 香蕉 2.0下载 Markdown ↓

香蕉 2.0

使用 gemini-3.1-flash-image-preview 生成或编辑图片。

1 快速开始

使用 125 或 139 分组的 API Key。两组模型和价格相同。不写 response_format 时,原生接口 #125 返回 Base64(inlineData),#139 返回图片链接(fileData);其他接口见 #125 / #139 返回格式对比。示例生成一张 4K 图片,保存并打开;按分组价格计费。 选下面一种方式运行即可,切换示例并重新发送会产生新的调用。

1.1 Python 3:完整流程

适用于 Windows、macOS 和 Linux。只使用 Python 标准库,无需安装 SDK。

将下面的代码保存为 banana-2-quickstart.py,在终端运行 python3 banana-2-quickstart.py(Windows 可用 py -3 banana-2-quickstart.py),按提示输入 API Key。程序会打印文件路径,并尝试用浏览器打开本地结果。

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)
    parts = [part
        for candidate in result.get("candidates", [])
        for part in candidate.get("content", {}).get("parts", [])
        if not part.get("thought")]
    encoded = next((p["inlineData"]["data"] for p in parts if p.get("inlineData", {}).get("data")), None)
    link = next((p["fileData"]["fileUri"] for p in parts if p.get("fileData", {}).get("fileUri")), None)
    if encoded:
        data = base64.b64decode(encoded, validate=True)
    elif link:
        # 139 分组默认返回图片链接,1 小时内有效
        with urlopen(Request(link, headers={"User-Agent": "YM2API-Quickstart/1.0"}), timeout=120) as image:
            data = image.read()
    else:
        raise ValueError("响应没有最终图片。请检查响应和使用记录,再决定是否重试。")
    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 示例。如未自动打开结果,按输出路径手动打开。

1.2 PowerShell 7:完整流程

适合已有 PowerShell 7 的 Windows 用户。复制整段代码到终端,只按提示输入 API Key。

$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 -or $_.fileData.fileUri) -and -not $_.thought } | Select-Object -First 1
if (-not $image) {
    $detail = $result | ConvertTo-Json -Depth 12
    throw "响应中没有图片。检查以下响应中的 finishReason 或 promptFeedback:`n$detail"
}
$media = if ($image.inlineData) { $image.inlineData } else { $image.fileData }
$extension = @{ "image/png" = ".png"; "image/jpeg" = ".jpg"; "image/webp" = ".webp" }[$media.mimeType]
if (-not $extension) { throw "未识别的图片格式:$($media.mimeType)" }
if ($image.inlineData) {
    $bytes = [Convert]::FromBase64String($image.inlineData.data)
} else {
    # 139 分组默认返回图片链接,1 小时内有效
    $bytes = (Invoke-WebRequest -Uri $image.fileData.fileUri -TimeoutSec 120 -ErrorAction Stop).Content
}
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 示例。

1.3 cURL / JSON:检查原始请求

JSON 是请求体,需要由 cURL、Postman 或 Apifox 发送。先将下面内容保存为 UTF-8 的 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 状态码。

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 接入信息

先用快速开始验证 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
返回图片 139 分组默认 candidates[].content.parts[].fileData(图片链接);125 分组或加 "response_format": "b64_json" 时为 inlineData(Base64)

分组由 API Key 决定,请求中无需填写 group_id。使用上面的完整模型名;不同分组的可用模型,以该 Key 请求 /v1/models 的结果为准。

3 文生图

仅使用文字生成图片。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 是请求档位,实际像素尺寸与图片比例、渠道有关。费用查看模型广场,扣费查看本站使用记录。

请求示例

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "一只白色小狐狸,蓝色围巾,柔和光线,无文字。"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "4K"
    }
  }
}

响应: 遍历 candidates[].content.parts[] 查找最终图片;保存方法。

4 图生图:单图与多图参考

使用与文生图相同的 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 前缀
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "保留主体和构图,把围巾改成红色。"
        },
        {
          "inlineData": {
            "mimeType": "image/png",
            "data": "YOUR_IMAGE_BASE64"
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "4K"
    }
  }
}

响应: 与文生图相同,解码后保存图片。

PowerShell 插入片段:

在快速开始代码中,创建 $payload 之后、创建 $request 之前插入下面的片段。将路径替换为本地 PNG 图片路径。

$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 读取响应、保存与查看图片

125 分组未指定格式时,图片通过 inlineData.data 以 Base64 返回;请求体顶层加 "response_format": "url" 可改为本站图片链接。139 分组未指定格式时默认返回本站图片链接:图片项为 fileData,fileUri 1 小时内有效,并附一个 ![image](链接) 文本项;请求体顶层加 "response_format": "b64_json" 可改回 Base64。先读取 mimeType,再选择文件扩展名;快速开始代码已处理两种返回,以及 PNG、JPEG 和 WebP。

{
  "candidates": [{
    "content": {
      "parts": [{
        "inlineData": {
          "mimeType": "image/png",
          "data": "BASE64_IMAGE_DATA"
        }
      }]
    },
    "finishReason": "STOP"
  }]
}

这是响应结构示例,BASE64_IMAGE_DATA 是占位值。

遍历返回的 parts,不要假设第一项就是图片;遇到文字先读取提示。保存后打开图片文件查看,response.json 本身不是图片。快速开始的 Python / PowerShell 示例已包含保存和打开步骤。

139 分组返回的图片链接 1 小时后失效;需要长期可访问的网址时,先下载保存,再上传到自己的存储。

图片链接说明(139 分组)

5.1 流式输出、思考签名与多轮改图

图片流式目前暂停

streamGenerateContent 和 "stream": true 的请求会立即返回 HTTP 400,不生成、不计费。本节的流式内容是 2026-10-15 的实测记录,恢复前请改用非流式 generateContent。

139 分组默认返回图片链接。签名多轮需要回传上一轮完整的 inlineData 图片,请在每轮请求体顶层加 "response_format": "b64_json"。

使用 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 示例。

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 响应结构示意(占位符不是可回传的真实值):

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 仅展示单图片响应的结构;实际代码应回传完整模型内容。

{
  "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 流式多轮示例

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 回传。

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

Google 官方:图片生成与思考签名

6 常见错误与重试

现象 操作
401 / 403 检查 Key、绑定分组、余额及访问权限
404 / 模型不可用 用同一把 Key 查询 /v1/models,核对完整模型名
400 检查 JSON、imageSize 大小写、参考图 MIME 与 Base64
429 按服务端提示等待,再重试
5xx / 超时 保留错误响应,先检查使用记录,再决定是否重新提交
HTTP 成功但没有图片 检查 finishReason、promptFeedback 和返回文字
已保存但未打开 到命令输出的文件路径,用本地图片查看器打开