HiAPI
博客

教程

如何通过 HiAPI API 使用 nano-banana-pro:curl 与 Python 示例

2026年10月31日
平面流体形态层叠交错的封面图,墨色底上流动着青瓷绿与石板灰的波纹,呼应教程主题。

HiAPI 上的 nano-banana-pro 能为你提供什么

nano-banana-pro 是一款可通过 HiAPI 统一 API 调用的图像生成模型。你无需直接与模型提供商集成,只需向 HiAPI 发送统一格式的请求,即可获得生成的图像——与其他平台模型一样,使用相同的身份验证、相同的端点约定和相同的响应封装。

nano-banana-pro 专为提示词驱动的图像生成而设计,并可在文本提示词之外附带参考图像。参考图像让你能够用视觉上下文(主体、风格、构图)来引导输出,而不必用文字描述一切。输出以 2K 分辨率交付,因此该模型更适合生产资产,而非快速草稿。

完成本教程后,你将得到一个完整可用的集成,它可以:

  • 通过经过验证的 curl 请求向 HiAPI 发送提示词至 nano-banana-pro;
  • 在 Python 中复现相同的调用,无需更改请求负载;
  • 在请求中附带参考图像;
  • 提交异步任务、轮询直至完成,并合理处理重试;
  • 下载完成的 2K 图像并存储到你自己的基础设施中。

每一节都建立在前一节的基础上,因此最稳妥的路径是按顺序操作:先手动确认请求,再将其移入代码。

发送第一个请求之前

首次调用前你需要准备三样东西。

一个 API 密钥

在你的 HiAPI 账户中创建一个 API 密钥,并确保它不被纳入源码管理。像对待任何其他机密一样对待它:从环境变量(HIAPI_API_KEY)或密钥管理器中加载,绝不要硬编码在你可能提交的文件中。如果密钥泄露,请在仪表板中轮换它,而不是试图从历史记录中清除。

一个 HTTP 客户端

任何能发送 HTTPS 请求的工具都可以。对于第一个请求,命令行中的 curl 是理想选择,因为你和网络之间没有框架——每个请求头和响应体的每个字节都可见。对于 Python 部分,标准库的 urllib.request 就足够了;如果你已经在使用 requests 或 httpx,映射关系是一样的。本教程将 Python 限制在标准库内,因此无需额外安装任何东西。

一个存放输出的位置

由于 nano-banana-pro 任务是异步的,从一开始就要规划好用于保存完成图像的目录或存储桶。开发时本地 output/ 文件夹即可;生产环境则应以对象存储为目标。

你无需安装供应商 SDK。HiAPI 通过普通 HTTPS 调用,因此你在 curl 中构建的请求,与你之后 Python 客户端发送的请求完全相同。

一个可用的 curl 请求,分步说明

确认密钥、端点和负载都正确的最快方式是手动发送一个请求。在输入之前先将其拆解为各个部分。

端点与方法

所有模型调用都发往同一个 HiAPI 基础 URL,模型在请求体中标识,而非在路径中标识。生成请求使用 POST。

请求头

每次调用有三个重要的请求头:

  • Authorization: Bearer $HIAPI_API_KEY——你的密钥,作为 bearer 令牌传递。
  • Content-Type: application/json——用于仅含提示词的请求。
  • Accept: application/json——以便获得结构化响应,而非 HTML 错误页面。

请求体

JSON 请求体携带模型名称和生成参数。至少需要发送模型标识符和你的提示词:

curl -sS -X POST "$HIAPI_BASE_URL" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "model": "nano-banana-pro",
    "input": {
      "prompt": "a glass terrarium on a sunlit windowsill, soft morning light, shallow depth of field"
    }
  }'

运行此命令前,请在 shell 中设置 HIAPI_BASE_URL 和 HIAPI_API_KEY。将 URL 保存在变量中意味着以后你可以将同一脚本指向暂存或沙箱 URL,而无需修改命令。

读取响应

成功提交会返回一个标识任务的 JSON 对象。重要的字段是任务标识符——你将在轮询步骤中使用它。由于生成需要时间,不要期望在首次响应中就能拿到图像本身;nano-banana-pro 以异步方式运行,此调用只是交互中的提交部分。

如果命令返回错误,请在此处停下,在编写任何代码之前修复它。经过验证的 curl 请求就是你的参考实现:后续每一步都应产生相同的 HTTP 请求。

将请求移植到 Python

移植是机械性的:URL、方法、请求头和 JSON 请求体保持不变。只有客户端发生变化。

使用 urllib 的同一请求

import json
import os
import urllib.request

api_key = os.environ["HIAPI_API_KEY"]
base_url = os.environ["HIAPI_BASE_URL"]

payload = {
    "model": "nano-banana-pro",
    "input": {
        "prompt": "a glass terrarium on a sunlit windowsill, soft morning light, shallow depth of field"
    },
}

request = urllib.request.Request(
    base_url,
    data=json.dumps(payload).encode("utf-8"),
    method="POST",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
)

with urllib.request.urlopen(request, timeout=60) as response:
    body = json.loads(response.read().decode("utf-8"))

print(body)

映射规则

从 curl 转换时,有三个细节容易出错:

  1. 请求体必须是字节。 json.dumps 生成字符串;在交给请求对象之前需要编码。
  2. 请求头是字典,不是标志。 每个 -H 行变成一个键/值对。保留 Bearer 前缀及其后的空格。
  3. 方法必须显式指定。 当存在数据时,urllib.request 默认使用 POST,但设置 method="POST" 能让意图更明确,并在你以后移除请求体时防止意外。

如果你使用 requests,等效写法是 requests.post(base_url, headers=headers, json=payload, timeout=60)——json= 会为你处理序列化和内容类型。如果你使用 httpx,调用形式相同。

一个值得拥有的小辅助函数

将提交调用放入一个接收提示词并返回任务标识符的函数中。后续每一节——参考图像、轮询、下载——都建立在该函数之上,将其保存在一个地方意味着请求形式的变化只发生一次。

随提示词发送参考图像

参考图像会改变请求的形式,因此要尽早决定你的应用程序将使用哪种输入方式。

两种实用选项

基于 URL 的输入。 如果参考图像已可通过 HTTPS 访问,你可以在请求体中附带其 URL 以及提示词。这使请求保持为 application/json,这是最容易重试和记录的形式。

上传文件。 如果图像位于客户端或私有存储中,你可以将其作为文件部分在 multipart/form-data 请求中发送。在这种情况下,Content-Type: application/json 请求头会被 multipart 内容类型替换——让你的 HTTP 客户端生成它以确保边界正确——JSON 字段则成为同一请求中的表单字段。

对于大多数服务器端集成,基于 URL 的输入更简单:你的图像已经在对象存储中,请求保持为 JSON,并且你在重试时避免了两次发送大请求体。

保持提示词与参考图像同步

提示词应描述参考图像的用途,而不仅仅是其内容。“匹配参考图像的光照和色调;将主体改为陶瓷花瓶”给了模型一个明确的任务。忽略参考图像的提示词会浪费输入。

发送前验证

参考图像是请求错误最常见的来源。检查 URL 是否可公开访问(或者你系统两端是否就签名 URL 过期时间达成一致)、文件类型是否为模型接受、图像是否大到导致上传超时。先在你自己的代码中完成这些检查——客户端验证失败的调试成本远低于被拒绝的请求。

处理异步任务并轮询结果

nano-banana-pro 生成是异步的。围绕三个独立步骤构建你的客户端:提交、轮询、下载。将它们混入一个函数会使重试和超时难以推理。

步骤 1:提交

发送上述请求并存储其返回的任务标识符。将该标识符持久化到某个持久位置——数据库行或队列消息——因为你的进程可能在提交和完成之间重启。

步骤 2:轮询

使用相同的基础 URL 和相同的 Authorization 请求头,在请求中携带任务标识符来获取任务状态。按间隔轮询而非 tight loop;检查之间间隔几秒是典型的,如果连续多次检查返回待处理状态,则应当退避。

import time

TERMINAL = {"succeeded", "failed"}

def wait_for_job(job_id, timeout=300, interval=3):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        status = get_job_status(job_id)  # same headers as submit
        if status in TERMINAL:
            return status
        time.sleep(interval)
    raise TimeoutError(f"job {job_id} did not finish in time")

步骤 3:尊重状态

将状态字段视为枚举。任务要么仍在运行,要么成功完成,要么失败。显式处理所有三种情况:成功时进入下载;失败时读取错误信息并判断是输入还是提示词的问题;超时时停止轮询并暴露任务标识符以便后续调查。

重试属于两个层级

网络级重试应应用于提交调用和每个轮询请求,并设置有限的尝试次数。任务级重试则不同:如果任务因糟糕的提示词或参考图像而失败,重新提交相同的负载将以同样的方式失败。只有在更改输入后才重试任务本身。

一种常见的生产模式是由一个 worker 负责轮询循环,这样 Web 请求永远不会因生成而阻塞。从你的 API 处理程序提交,将任务标识符交给 worker,并在 worker 完成时通知客户端。

下载并存储 2K 输出

任务的最终响应指向生成的图像而非内嵌它,这意味着下载是你需要负责的步骤。

获取图像

当任务报告成功时,响应包含输出的位置。用普通的 GET 请求检索它,然后将字节写入文件或流式传输到存储。开发时,使用由任务标识符构建的可预测名称保存到本地目录,以便将文件与任务记录关联。

import pathlib
import urllib.request

def save_image(url, job_id, out_dir="output"):
    pathlib.Path(out_dir).mkdir(exist_ok=True)
    target = pathlib.Path(out_dir) / f"nano-banana-pro-{job_id}.png"
    with urllib.request.urlopen(url, timeout=60) as response:
        target.write_bytes(response.read())
    return target

正确存储

在生产环境中,将响应直接流式传输到对象存储而非写入本地磁盘,这样无论哪个 worker 处理任务,行为都保持一致。在数据库中记录对象键和任务标识符,并检查内容类型和文件扩展名是否与模型生成的一致。如果图像将在网页上提供,请在同一管道中生成缩略图,以便公共页面永远不加载完整的 2K 分辨率文件。

规划保留策略

生成的输出是你的数据。决定保留多长时间、是否需要版本控制,以及最终位置是否是你的应用在丢失后能重新生成的。如果答案是否定的,请同时存储请求负载和图像,这样未来的 bug 或模型变更永远不会让你无法复现结果。

常见故障点及调试方法

大多数首次集成因少数几个原因失败。在假设模型有问题之前,请逐项检查此清单。

  • 授权错误。 缺少 Bearer 前缀、密钥因从环境文件复制而带有尾随换行符,或者你使用的密钥来自与所设基础 URL 不同的环境。
  • 内容类型不匹配。 使用 multipart 请求头发送 JSON 字段,或使用 application/json 发送文件,是参考图像请求被拒绝的最常见原因。对于 multipart 请求体,让客户端设置请求头。
  • 错误的方法或请求体形式。 使用 GET 而非 POST,或使用顶层 prompt 而非嵌套的 input 对象,会产生看起来完全不相关的验证错误。将你的请求与经过验证的 curl 调用逐字节比较——curl -v 显示实际发送的请求头。
  • 轮询过快或根本不轮询。 频繁请求状态端点会导致速率限制;从不轮询则什么也得不到。使用带退避的固定间隔和硬超时。
  • 输出 URL 过期。 如果在任务完成和下载之间等待太久,签名的输出 URL 可能会过期。成功之后立即下载,或准备一条获取新位置的重新获取路径。
  • 代码中的静默失败。 出错时始终记录 HTTP 状态码和响应体。HTTP 客户端抛出的一般异常消息会隐藏响应中有用的部分。

当有不清楚的地方时,回退到第一节中经过验证的 curl 请求。如果该请求有效而你的 Python 调用无效,两者之间的差异就是 bug。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档