公告: GPT Image 2.6 Flare 与 Sunburst 上新限时 8 折,立即体验
HiAPI
博客

教程

如何通过 HiAPI API 使用 flux-1.1-pro:curl、Python 与可运行的请求

一份动手集成指南:真正能运行的请求、异步处理,以及带真实输出的提示词配方

2026年11月10日
Abstract tutorial cover art: terracotta stepped bands descending across a warm sand background, flat print style, no text.
本页内容

在你动手写代码之前,flux-1.1-pro 能提供什么

flux-1.1-pro 是一个文生图模型,通过 HiAPI.ai 以托管端点的方式调用。你把提示词和生成参数以 JSON 形式发送出去,返回的就是生成的图像。无需安装任何东西,无需自行托管权重,也无需管理 GPU 资源。你的集成面就是一个 HTTP 端点,加上用于认证的凭证。

对开发者而言,这意味着在你写下第一行代码之前,有三件事会塑造你的设计。

第一,请求是 JSON 进、图像出。你的提示词、宽高比以及少量控制参数都放在请求体中。响应会携带图像数据或对图像数据的引用,具体取决于任务的交付方式。把请求体当作契约,并集中放在一处,这样 curl 和 Python 两条路径永远不会彼此偏离。

第二,相对于普通 API 调用,图像生成是慢操作。几秒钟是正常的;高分辨率下的复杂提示词可能需要更久。任何生产环境的调用方都必须假定存在延迟并为其做好规划,而不是把调用当作一次数据库读取。

第三,输出质量主要由提示词决定,而不是由接线决定。集成是简单的那部分。真正的功夫在于精确描述你想要的东西,并在上线之前用真实输出验证你的配方。

记住这三件事,本指南其余部分就是机械性的流程:构造请求、确认它可运行、移植它,然后加固并调优。自始至终,一切都通过 HiAPI API 路由——一个凭证、一个基础 URL、一种需要学习的 JSON 结构。

你的第一个 curl 请求

从 curl 开始。它消除了你和端点之间的所有抽象层,因此当出现失败时,你清楚问题在于你的请求体,而不是你的框架。

一个最小调用包含三个部分:端点、认证头以及 JSON 请求体。

curl -X POST "https://api.hiapi.ai/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-1.1-pro",
    "prompt": "a ceramic coffee mug on a weathered wooden table, soft morning window light, shallow depth of field, product photography",
    "aspect_ratio": "1:1"
  }'

逐字段阅读请求体:

  • model 指定你要使用的模型。要显式写出它,这样将来默认值变更时,绝不会悄悄改变你的输出。
  • prompt 是自然语言描述。你几乎所有的质量预算都在这里。
  • aspect_ratio 控制取景。要有意选择它,而不是依赖一个你未曾验证过的默认值。

把密钥放进环境变量(HIAPI_API_KEY),而不是直接粘贴到命令里。这个习惯会直接延续到 Python,以及你之后添加的任何 CI 步骤中。

调用成功时,你会得到一个描述已完成图像的 JSON 响应。在关闭终端之前,检查它并定位图像引用或数据。调用失败时,你会得到一个错误体,包含状态码和消息;请按字面阅读该消息,因为字段格式错误是最常见的首次失败原因。

一个能省下一小时的警告:不要把带未转义引号的多行提示词粘贴进 shell。对于任何长于短句的内容,使用 heredoc 或文件。

curl -X POST "https://api.hiapi.ai/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  --data @request.json

那个 request.json 就是你应该提交到版本库的产物。它是请求体的唯一事实来源,下一节会原样复用它。

把同一个调用移植到 Python

移植的目标不是编写新逻辑,而是发送完全相同的 JSON 请求体。加载同一个 request.json,这样两条路径就无法偏离。

import json
import os

import requests

API_URL = "https://api.hiapi.ai/v1/images/generations"

with open("request.json") as f:
    payload = json.load(f)

response = requests.post(
    API_URL,
    headers={
        "Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=120,
)

if response.status_code != 200:
    print(response.status_code)
    print(response.text)
    response.raise_for_status()

print(response.json())

这里有三处细节很重要。

认证头与请求头是同一组头。 使用 json=payload 会让 requests 替你序列化请求体并设置内容类型;显式写出该头无伤大雅,并且能记录意图。

设置超时。 绝不要让生成请求挂在一个无界的默认值上。一个宽松的显式超时是可以的——关键在于它是显式的。

在抛出异常之前检查错误体。 如果你先运行 raise_for_status(),它会把你日志中的响应体丢弃。先打印状态码和文本,再抛出。当某个字段被拒绝时,你会需要那段文本。

如果你正在统一使用异步 HTTP 客户端,结构不变:相同 URL、相同请求头、相同请求体,只是 await client.post(...) 并使用相同的超时。请求体契约是常量;客户端是实现细节。

把请求体放在 Python 源码之外。当一个提示词配方有效时,它应该属于文件或数据库行,而不是埋在函数里的字符串字面量,这样你才能对它做 diff 并重新运行。

处理异步任务而不阻塞你的应用

把生成当作任务,而不是函数调用。无论你的交付路径看起来是同步的,还是返回一个你需要轮询的任务,实际后果都是一样的:你的应用绝不能因为等待一张图像而无界地占用请求线程。

一个可行的模式包含四个步骤。

1. 从 worker 提交,而不是从用户请求提交

在 Web 层接受用户的生成操作,持久化一条任务记录,将其入队,然后立即返回。由后台 worker 执行实际的 API 调用。用户轮询的是你的端点,而不是模型。

2. 为等待设界

为每次尝试设置一个你刻意选择的超时。如果平台返回一个你必须轮询的任务,那就以固定间隔、最大尝试次数,以及从任务开始时刻(而非尝试次数)计算的截止时间来轮询。优先使用适度的退避,而不是紧循环。

3. 只重试值得重试的失败

对传输错误、超时和服务端失败使用指数退避加抖动进行重试,并限制在少量尝试次数内。不要重试校验错误:被拒绝的字段或空提示词每次都会以同样方式失败,重试只会让用户在看到真正消息之前多等更久。

4. 在你这一侧让任务幂等

在数据库中记录精确的请求体和任务 ID。如果你的 worker 在提交之后、记录成功之前崩溃,你可以重新检查该任务,而不是盲目重新提交。当你必须重新提交时,添加一个简短的客户端去重键,这样瞬时故障就不会排队三次相同的生成。

import time

def poll_until_done(fetch_status, job_id, deadline_seconds=180):
    start = time.monotonic()
    delay = 2.0
    while True:
        status = fetch_status(job_id)
        if status["state"] in ("succeeded", "failed"):
            return status
        if time.monotonic() - start > deadline_seconds:
            raise TimeoutError(f"generation {job_id} exceeded deadline")
        time.sleep(delay)
        delay = min(delay * 1.5, 10.0)

这个辅助函数刻意保持通用:它接收一个获取状态的函数,因此同一个循环适用于你之后集成的任何任务型端点。重要的属性是截止时间、有上限的退避以及终态检查——而不是具体的传输方式。

构造能稳定渲染的提示词

长提示词并不等于更好的提示词。结构才是。一个可重复的骨架能给你一致的结果,并在出问题时提供一个一次只改一个变量的地方。

按以下顺序使用四个槽位:

  1. 主体——画面中有什么,要具体。“一个陶瓷咖啡杯”胜过“咖啡馆用的某样东西”。
  2. 风格——视觉基调:摄影、插画、水彩、3D 渲染、产品拍摄。写明媒介,并在有用时写明光线。
  3. 构图——取景与相机:宽高比、拍摄距离、角度、景深、主体在画面中的位置。
  4. 约束——你明确想要和不想要的具体内容,保持简短。
[subject] a single ceramic coffee mug, matte glaze, small handle
[style] product photography, soft diffused window light, muted palette
[composition] 1:1, eye-level, subject centered, shallow depth of field, plain background
[constraints] no text, no logos, no hands

发送时把它展平成一条提示词;方括号是给你自己看的,不是给模型的。用槽位写作的价值在于:当输出不对时,你知道该编辑哪个槽位。

几条实用规则:

  • 把主体放在最前面。 第一个从句权重最高。
  • 优先使用具体的名词和形容词,而不是抽象的情绪词。“哑光釉”会改变像素;“高级感”基本不会。
  • 把相机语言放在构图槽位,而不是主体槽位。 混在一起会产生急切而互相矛盾的指令。
  • 迭代时一次只改一个槽位,并保留产生被接受输出的精确提示词文本。

宽高比是构图决策,不是事后补丁。选择它来匹配图像将要出现的位置——网格中用方形,主视觉横幅中用更高——并让提示词其余部分适配那个画框。

有效使用负面词列表

负面词列表告诉模型要避免什么。它是一把锋利的工具,有用范围很窄:非常适合抑制反复出现的瑕疵,但作为罗列你能想到的所有不完美之处的垃圾桶则很糟糕。

负面词要简短且具体。对大多数提示词来说,五到八个短条目就足够了。写明具体的东西:

no text, no watermark, no logos, no extra fingers, no harsh shadows

这个列表有效,是因为每个条目都命名了可见且可检查的东西。对比一下像“not ugly”或“bad quality”这样的模糊否定——它们几乎不携带可操作的信号,还会稀释真正重要的条目。

负面词真正有帮助的地方:

  • 抑制你反复看到的瑕疵。 如果手或文字反复出现,直接写出它们就是最直接的修复。
  • 品牌与法律卫生。 在图像到达面向用户的界面之前排除 logo 和水印。
  • 为产品图或贴近 UI 的图像强制干净背景。

它们会与你作对的地方:

  • 与正向提示词矛盾。 负面词里的“无阴影”对抗主体里的“戏剧性侧光”,是模型会以不可预测方式解决的冲突。应修复正向提示词。
  • 否定根本不太可能出现的东西。 一长串不太可能的失败条目只会增加噪声,不会改变渲染结果。
  • 用负面词来弥补模糊的主体。 如果主体不清晰,任何负面词列表都救不了它。

一个实用细节:有些客户端接受把负面词作为单独字段,而不是附加文本。确认你的请求支持哪种方式,并把该字段保留在你保存的请求体中,这样 curl 和 Python 的行为完全一致。

带真实输出的提示词配方

下面的配方是起点,不是保证。诚实的工作流程是:通过你自己的集成运行该配方,查看输出,然后调整一个槽位。任何你没有亲自生成过的输出,都应视为未验证。

配方 1——干净的产品图

A single matte-black wireless earbud case on a light concrete surface,
studio product photography, soft key light from the left, 1:1, centered,
shallow depth of field, plain background. No text, no logos, no hands.

预期特征:清晰、居中的主体,柔和的衰减,以及不杂乱的背景。如果表面显得太繁复,收紧“plain background”并去掉任何纹理词。如果光线太平,添加一个方向性关键词——仅此而已。

配方 2——编辑人像

Portrait of a person in a wool coat, natural window light, calm expression,
3:4, chest-up framing, subject slightly off-center, muted film palette.
No text, no watermark.

预期特征:柔和的定向光,克制的色彩。如果取景比预期更宽,把“chest-up framing”提前,并移除竞争的构图词。

配方 3——等距插画

Isometric illustration of a small reading nook: armchair, floor lamp, bookshelf,
flat vector style, limited palette of warm neutrals and one accent color,
1:1, centered composition, clean white background. No text, no gradients.

预期特征:清晰的几何结构和扁平填充。如果配色跑偏,明确写出强调色,并把“clean white background”保留为最后一个从句,这样它才会胜出。

配方 4——主视觉横幅

A wide misty mountain ridge at sunrise, layered depth, minimal detail,
16:9, subject occupying the lower third, generous empty sky for overlaid text.
No text, no watermark.

预期特征:安静、低细节的图像,带有可用的负空间。“overlaid text”这个说法预留了空间;它不会渲染字母,而负面词列表把文字挡在图像本身之外。

对每个配方,记录精确的请求体、宽高比和日期。一个月后回顾时,你可以重新运行记录的请求体,并与记录的输出对比,而不是猜测结果为何改变。

错误、限制,以及首先检查什么

当生成失败或输出不对时,在改动代码之前,先按这份清单逐项排查。

先检查请求体

  • 请求体是合法 JSON 吗? 尾随逗号或未转义的引号是最常见的首次失败原因。发送前校验你保存的 request.json。
  • 字段名完全正确吗? 拼错的参数通常会被拒绝或被静默忽略。对照文档中的请求结构,而不是凭记忆。
  • 模型名正确且存在吗? 不要依赖默认值。
  • 提示词非空且在文档规定的长度内吗? 平台文档中写明了限制;请在那里阅读,而不是假设一个数字。

然后检查认证与传输

  • API 密钥存在且当前有效吗? 401 通常意味着请求头缺失、格式错误,或密钥已被轮换。
  • 端点 URL 和方法正确吗? 把 POST 发到 GET 路径上,失败的样子会像密钥问题。
  • 你的超时太紧了吗? 如果你的客户端在任务完成前就放弃,你看到的超时与模型无关。

然后检查请求结构

  • 状态码类别告诉你该往哪看。 4xx 几乎总是你的请求问题;5xx 通常是瞬时的,值得做有界重试。
  • 按字面阅读错误消息。 在抛出异常之前打印响应体。消息中提到的字段就是需要修复的字段。
  • 限流或配额响应意味着放慢速度并用退避重试,而不是重写提示词。

最后,检查提示词

如果调用成功但图像不对,你处在提示词范畴,而不是错误范畴:

  • 主体缺失或过于笼统? 把它移到第一个从句并使其具体。
  • 构图不对? 同时修正宽高比和取景词;不要用一个去补另一个。
  • 瑕疵反复出现? 添加一个简短、具体的负面词。
  • 存在矛盾? 找出与正向提示词对抗的负面词并删除它。

最重要的是保持一个习惯:为你关心的每一次生成记录精确的请求体、响应状态以及生成的图像引用。可复现性把调试从猜测变成 diff。构造你的第一个请求,确认输出,然后在上线前收紧提示词——并保留你上线时使用的请求体,这样下一次改动就有真实基准可对比。

立即开始构建持久 AI 产物

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

阅读 API 文档