灵眸文档
开放 API

Gemini 生图 API

用灵眸 Gemini 原生 v1beta 接口完成文生图、图片编辑与图生图,支持 1K / 2K / 4K、常用画幅与 Base64 图片解析。

灵眸提供 Gemini 原生 v1beta 兼容接口,可直接调用 Gemini 图片模型完成文生图、图片编辑和图生图

接口协议

Gemini 生图使用的是 Google Gemini 原生 generateContent 协议,不是 OpenAI 的 /v1/chat/completions,也不是 OpenAI Images 的 /v1/images/generations

主端点:

POST https://api.lmuai.com/v1beta/models/{model}:generateContent

1. 接口总览

方法路径说明
GET/v1beta/models查询当前 API Key 在 Gemini 分组下可用的原生模型
GET/v1beta/models/{model}查询指定模型信息
POST/v1beta/models/{model}:generateContent文生图、图片编辑、图生图主接口
POST/v1beta/models/{model}:streamGenerateContent?alt=sse流式生成;图片场景不建议作为首选
GET/v1/modelsOpenAI 兼容模型列表,适合通用模型选择器
POST/v1/images/batches灵眸 Gemini 异步批量生图扩展接口,详见Gemini 批量生图 API

Base URL:

https://api.lmuai.com

2. 鉴权

推荐:Gemini 原生请求头

x-goog-api-key: YOUR_API_KEY

兼容:Bearer 请求头

Authorization: Bearer YOUR_API_KEY

服务端按以下优先级读取 API Key:

  1. x-goog-api-key
  2. Authorization: Bearer ...
  3. x-api-key
  4. /v1beta 路径的 ?key=... 查询参数。

不要把 Key 放进 URL

?api_key=... 已弃用并会返回 400?key=... 虽然兼容,但容易被浏览器历史、反向代理和访问日志记录,生产环境请使用请求头。

典型鉴权错误:

{
  "error": {
    "code": 401,
    "message": "Invalid API key",
    "status": "UNAUTHENTICATED"
  }
}

API Key 必须绑定到 gemini 平台分组,否则不能调用 Gemini 原生接口。


3. 模型与可用性

本次图片服务主要使用以下客户端模型 ID:

模型 ID建议用途图片编辑说明
gemini-3.1-flash-image默认推荐已通过生产环境 inlineData 图片编辑实测
gemini-3.1-flash-image-preview预览兼容使用同一 generateContent 编辑协议,正式接入前建议单独验证
gemini-3-pro-image质量优先 / 复杂编辑使用同一 generateContent 编辑协议,以当前 Key 可用性为准
gemini-3-pro-image-previewPro 预览兼容使用同一编辑协议,执行模型以服务端响应为准
gemini-3.1-flash-lite-image轻量场景仅在模型列表返回且已验证图片输出时使用

查询当前 Key 的 Gemini 模型

curl 'https://api.lmuai.com/v1beta/models' \
  -H 'x-goog-api-key: YOUR_API_KEY'

OpenAI 兼容模型列表:

curl 'https://api.lmuai.com/v1/models' \
  -H 'Authorization: Bearer YOUR_API_KEY'

模型 ID 可能经过服务端映射

客户端提交的是请求模型 ID。灵眸支持兼容模型别名,因此请求模型名称不一定等于响应中的最终模型版本。

不要仅根据模型名称猜测是否可用;请以当前 Key 调用 /v1beta/models 的实际结果为准。


4. 快速开始:文生图

curl --request POST \
  'https://api.lmuai.com/v1beta/models/gemini-3.1-flash-image:generateContent' \
  --header 'x-goog-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "一只戴着宇航员头盔的橘猫,电影感灯光,精致细节"
          }
        ]
      }
    ],
    "generationConfig": {
      "responseModalities": ["TEXT", "IMAGE"],
      "imageConfig": {
        "aspectRatio": "1:1",
        "imageSize": "1K"
      }
    }
  }'

成功后,从下面的位置读取图片:

candidates[].content.parts[].inlineData.data

5. 文生图请求结构

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "电影感雨夜城市街景,霓虹灯倒映在湿润路面,广角构图"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": {
      "aspectRatio": "16:9",
      "imageSize": "2K"
    }
  }
}

请求字段

字段类型必填说明
contentsarray对话内容数组,至少包含一条用户消息
contents[].rolestring建议用户输入使用 user
contents[].partsarray文本或输入图片片段
parts[].textstring文生图必填图片提示词
generationConfigobject生成参数
generationConfig.responseModalitiesstring[]生图必须包含 IMAGE,推荐 ['TEXT', 'IMAGE']
generationConfig.imageConfigobject图片分辨率和画幅配置

图片参数必须放在 imageConfig

请使用 generationConfig.imageConfig。不要使用 responseFormat.image;该字段可能不会报参数错误,但不会按照 Gemini 原生图片参数生效。


6. 分辨率和画幅

支持的分辨率

imageSize推荐场景特点
1K草图、快速预览、批量筛选通常速度更快、费用更低
2K常规交付、文章配图、电商素材质量、耗时和成本较均衡
4K精细大图、高质量交付通常生成和传输时间更长

imageSize 必须使用大写:

{
  "imageSize": "2K"
}

支持的画面比例

aspectRatio模型级能力,不能把 Flash 的扩展比例用于 Pro 模型。灵眸会按请求模型校验比例,避免把已知无效组合发送到上游。

通用 10 种比例:

1:1
2:3
3:2
3:4
4:3
4:5
5:4
9:16
16:9
21:9

Flash 扩展 4 种比例:

1:4
1:8
4:1
8:1

模型比例矩阵

客户端模型 ID确认支持的比例数量
gemini-3.1-flash-image通用 10 种 + Flash 扩展 4 种14
gemini-3.1-flash-image-preview通用 10 种 + Flash 扩展 4 种14
gemini-3.1-flash-lite-image通用 10 种 + Flash 扩展 4 种14
gemini-3-pro-image仅通用 10 种10
gemini-3-pro-image-preview仅通用 10 种10

Pro 模型不支持 Flash 扩展比例

gemini-3-pro-imagegemini-3-pro-image-preview 传入 1:41:84:18:1 会返回 INVALID_ARGUMENT 或中转站 400 参数错误。例如:

{
  "error": {
    "code": 400,
    "message": "generationConfig.imageConfig.aspectRatio has an unsupported value",
    "status": "INVALID_ARGUMENT"
  }
}

上述矩阵结合 Google 官方模型说明和灵眸生产接口实测得到:三个 Flash / Flash Lite 模型均通过扩展比例测试;两个 Pro 模型均明确拒绝全部四个扩展比例。未知或新模型在完成验证前,应使用通用 10 种。

不指定 aspectRatio 时,由模型根据输入内容和默认策略决定画幅。不要传任意小数或任意 WIDTHxHEIGHT;必须使用目标模型接受的比例枚举。

示例:

{
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": {
      "aspectRatio": "9:16",
      "imageSize": "4K"
    }
  }
}

分辨率档位不是固定像素宽高

1K2K4K 是模型分辨率档位。图片的实际宽高由模型根据档位和画幅计算,客户端不应固定假设一定是 1024×10242048×20484096×4096


7. 图片编辑 / 图生图

Gemini 支持图片编辑,只是没有类似 GPT 的独立 /v1/images/edits 端点。

文生图和图片编辑都调用:

POST /v1beta/models/{model}:generateContent

两者的区别是:

场景contents[].parts[] 内容
文生图只有文本提示词
图片编辑 / 图生图文本编辑指令 + inlineData 输入图片

生产环境已验证

使用 gemini-3.1-flash-image,输入 JPEG 图片并通过 inlineData 提交,已成功返回:

  • HTTP 200
  • finishReason: STOP
  • image/png 编辑结果;
  • 非空 inlineData.data
  • usageMetadata 图片模态 Token 统计。

响应可能只包含图片 part、不包含文本 part,客户端不能要求响应中必须同时存在文字。

7.1 最小图片编辑请求

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "保留人物、构图和光线,把背景修改成雨夜霓虹街道"
        },
        {
          "inlineData": {
            "mimeType": "image/png",
            "data": "INPUT_IMAGE_BASE64"
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "1K"
    }
  }
}

7.2 输入图片字段

字段类型必填说明
contents[].parts[].textstring编辑指令,应明确哪些内容需要保留、哪些内容需要修改
inlineData.mimeTypestringimage/pngimage/jpegimage/webp
inlineData.datastring纯 Base64,不要带 Data URL 前缀
imageConfig.aspectRatiostring输出画幅;需要保留输入比例时填写对应比例
imageConfig.imageSizestring输出档位:1K2K4K,以模型能力为准

Base64 不要带 Data URL 前缀

正确:

/9j/4AAQSkZJRgABAQ...

不要传:

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...

输入图片过大会增加上传和处理时间,并可能因网关请求体限制返回 413

7.3 curl 完整示例

先把本地图片转换为不换行的 Base64:

IMAGE_BASE64=$(base64 < input.jpg | tr -d '\n')

然后调用图片模型:

curl --request POST \
  'https://api.lmuai.com/v1beta/models/gemini-3.1-flash-image:generateContent' \
  --header 'x-goog-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw "{
    \"contents\": [{
      \"role\": \"user\",
      \"parts\": [
        {
          \"text\": \"保留杯子、构图、光线和背景不变,只把杯子从蓝色改成紫色,并在杯身增加三个白色星形图案,不要添加文字\"
        },
        {
          \"inlineData\": {
            \"mimeType\": \"image/jpeg\",
            \"data\": \"${IMAGE_BASE64}\"
          }
        }
      ]
    }],
    \"generationConfig\": {
      \"responseModalities\": [\"TEXT\", \"IMAGE\"],
      \"imageConfig\": {
        \"aspectRatio\": \"3:2\",
        \"imageSize\": \"1K\"
      }
    }
  }"

7.4 Python 图片编辑示例

import base64
import requests

api_key = "YOUR_API_KEY"
model = "gemini-3.1-flash-image"
input_path = "input.jpg"

with open(input_path, "rb") as f:
    image_base64 = base64.b64encode(f.read()).decode("utf-8")

payload = {
    "contents": [{
        "role": "user",
        "parts": [
            {
                "text": "保留主体和构图,把背景改成雨夜霓虹街道"
            },
            {
                "inlineData": {
                    "mimeType": "image/jpeg",
                    "data": image_base64,
                }
            },
        ],
    }],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {
            "aspectRatio": "3:2",
            "imageSize": "1K",
        },
    },
}

response = requests.post(
    f"https://api.lmuai.com/v1beta/models/{model}:generateContent",
    headers={
        "x-goog-api-key": api_key,
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=300,
)
response.raise_for_status()
result = response.json()

saved = False
for candidate in result.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        inline_data = part.get("inlineData", {})
        if inline_data.get("data"):
            mime_type = inline_data.get("mimeType", "image/png")
            extension = "jpg" if "jpeg" in mime_type else "webp" if "webp" in mime_type else "png"
            with open(f"gemini-edited.{extension}", "wb") as f:
                f.write(base64.b64decode(inline_data["data"]))
            saved = True
            break
    if saved:
        break

if not saved:
    raise RuntimeError("HTTP 请求成功,但响应中没有编辑后的图片")

7.5 编辑提示词建议

图片编辑提示词最好明确区分“保留项”和“修改项”:

保留:主体身份、姿势、镜头角度、构图和光线。
修改:把背景改成雨夜霓虹街道。
禁止:不要增加文字,不要改变人物脸部。

相比只写“把它改好看一些”,这种结构更容易获得稳定结果。

7.6 多张参考图

部分 Gemini 图片模型可以在同一个 parts[] 中接收多张 inlineData 图片,用于风格参考、人物参考或素材融合。但不同模型允许的参考图数量和总请求体大小不同,正式使用前应针对当前模型单独验证。

不要仅因为 /v1beta/models 返回了某个图片模型,就假定它支持无限数量的参考图。


8. 成功响应

典型响应:

{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          {
            "text": "已根据要求生成图片。"
          },
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": "BASE64_IMAGE_DATA"
            }
          }
        ]
      },
      "finishReason": "STOP",
      "index": 0
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 123,
    "candidatesTokenCount": 1120,
    "totalTokenCount": 1450,
    "candidatesTokensDetails": [
      {
        "modality": "IMAGE",
        "tokenCount": 1024
      }
    ]
  },
  "modelVersion": "MODEL_VERSION"
}

关键响应字段

字段说明
candidates[]候选输出列表
candidates[].content.parts[]文本或图片片段
parts[].inlineData.mimeType返回图片 MIME 类型
parts[].inlineData.data返回图片 Base64 内容
candidates[].finishReason结束原因;常见成功值为 STOP
usageMetadata输入、输出及图片模态 token 统计
modelVersion上游返回的实际模型版本信息,若有则透传

正确判断生图成功

客户端应同时检查:

  1. HTTP 状态码为 2xx
  2. candidates 非空;
  3. 至少一个 parts[] 含有非空 inlineData.data
  4. Base64 能成功解码;
  5. 必要时检查 finishReason

HTTP 200 不等于一定生成了图片

上游可能返回 HTTP 200,但响应中没有 inlineData.data。这类请求必须按“业务生图失败”处理,不能计入成功图片数。


9. Node.js 示例

import { writeFile } from 'node:fs/promises';

const BASE_URL = process.env.GEMINI_BASE_URL || 'https://api.lmuai.com';
const API_KEY = process.env.GEMINI_API_KEY;
const MODEL = 'gemini-3.1-flash-image';

if (!API_KEY) throw new Error('缺少 GEMINI_API_KEY');

const payload = {
  contents: [
    {
      role: 'user',
      parts: [
        { text: '日落时分的海边灯塔,水彩插画,温暖色调,细腻纸张纹理' },
      ],
    },
  ],
  generationConfig: {
    responseModalities: ['TEXT', 'IMAGE'],
    imageConfig: {
      aspectRatio: '16:9',
      imageSize: '2K',
    },
  },
};

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 300_000);

try {
  const response = await fetch(
    `${BASE_URL}/v1beta/models/${encodeURIComponent(MODEL)}:generateContent`,
    {
      method: 'POST',
      headers: {
        'x-goog-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
      signal: controller.signal,
    },
  );

  const text = await response.text();
  let data;
  try {
    data = JSON.parse(text);
  } catch {
    throw new Error(`服务返回非 JSON 内容:HTTP ${response.status}`);
  }

  if (!response.ok) {
    throw new Error(
      `HTTP ${response.status}: ${data?.error?.message || JSON.stringify(data)}`,
    );
  }

  const parts = data.candidates?.flatMap((candidate) => candidate.content?.parts || []) || [];
  const imagePart = parts.find((part) => part.inlineData?.data);

  if (!imagePart) {
    const reasons = data.candidates?.map((candidate) => candidate.finishReason).filter(Boolean);
    throw new Error(`请求完成但没有图片,finishReason=${reasons?.join(',') || 'unknown'}`);
  }

  const mimeType = imagePart.inlineData.mimeType || 'image/png';
  const extension = mimeType === 'image/jpeg'
    ? 'jpg'
    : mimeType === 'image/webp'
      ? 'webp'
      : 'png';

  await writeFile(
    `gemini-output.${extension}`,
    Buffer.from(imagePart.inlineData.data, 'base64'),
  );

  console.log('图片已保存,usageMetadata:', data.usageMetadata || null);
} finally {
  clearTimeout(timer);
}

10. Python 示例

import base64
import os
from pathlib import Path
import requests

BASE_URL = os.getenv("GEMINI_BASE_URL", "https://api.lmuai.com")
API_KEY = os.environ["GEMINI_API_KEY"]
MODEL = "gemini-3.1-flash-image"

payload = {
    "contents": [
        {
            "role": "user",
            "parts": [
                {"text": "未来主义建筑群,清晨薄雾,超广角摄影,真实材质"}
            ],
        }
    ],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {
            "aspectRatio": "16:9",
            "imageSize": "2K",
        },
    },
}

response = requests.post(
    f"{BASE_URL}/v1beta/models/{MODEL}:generateContent",
    headers={
        "x-goog-api-key": API_KEY,
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=300,
)

data = response.json()
if not response.ok:
    message = data.get("error", {}).get("message", data)
    raise RuntimeError(f"HTTP {response.status_code}: {message}")

image_part = None
for candidate in data.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        if part.get("inlineData", {}).get("data"):
            image_part = part
            break
    if image_part:
        break

if not image_part:
    reasons = [candidate.get("finishReason") for candidate in data.get("candidates", [])]
    raise RuntimeError(f"请求完成但没有返回图片,finishReason={reasons}")

inline_data = image_part["inlineData"]
mime_type = inline_data.get("mimeType", "image/png")
extension = {
    "image/jpeg": "jpg",
    "image/webp": "webp",
}.get(mime_type, "png")

Path(f"gemini-output.{extension}").write_bytes(
    base64.b64decode(inline_data["data"])
)

print("图片已保存")
print("usageMetadata:", data.get("usageMetadata"))

11. 常见错误

Gemini 原生端点通常返回 Google 风格错误:

{
  "error": {
    "code": 429,
    "message": "upstream rate limit exceeded",
    "status": "RESOURCE_EXHAUSTED"
  }
}
HTTP 状态常见原因建议
400请求结构、模型路径或分组平台错误修正请求,不要直接重试
401API Key 缺失、无效或禁用检查 Key 和请求头
402 / 403余额、订阅、计费资格或权限不足检查账户和分组权限
413图生图请求体过大压缩输入图片
429用户并发限制或上游限流指数退避,降低并发和 RPM
500内部或容量错误记录错误码和请求 ID,有限重试
502上游认证、权限或服务暂时失败退避重试,必要时联系管理员
503无可用 Gemini 账号或上游过载延迟重试并降低流量
504网关或上游超时作为独立请求重新发起

如果错误信息提示所有 Token 均处于禁用、冷却、锁定或过期状态,属于服务容量问题,不是提示词格式错误。请停止密集重试,并将错误码和请求 ID 提供给管理员。


12. 超时、重试和并发

客户端超时建议

分辨率建议总超时
1K不低于 120 秒
2K不低于 180 秒
4K建议 300 秒

这只是接入建议,不代表固定 SLA。若请求还经过自有 Nginx、CDN 或 API 网关,需要同步调整这些组件的读取超时。

重试建议

建议重试:

  • 429
  • 502503504
  • 网络中断、连接重置和读取超时;
  • HTTP 200 但没有图片时,可有限重试一次并保存原始响应。

通常不要重试:

  • 400
  • 401
  • 明确的余额或权限错误;
  • 请求参数或内容策略错误。

推荐最多重试 2~3 次,并使用指数退避:

第 1 次:1~2 秒随机抖动
第 2 次:3~5 秒随机抖动
第 3 次:8~12 秒随机抖动

多张实时图片

实时接口当前按“一次请求一张主要图片”使用。需要多张时应拆成多个独立请求,并同时限制:

  • 最大在途并发;
  • 每分钟请求数(RPM);
  • 单用户任务数;
  • 超时与最大重试次数。

如果需要提交几十到数百条提示词并异步等待结果,请使用Gemini 批量生图 API


13. 用量与计费

响应中的 usageMetadata 可用于分析输入、输出和图片模态 token,但不一定等于最终扣费金额。

实际扣费可能受以下因素影响:

  • 请求模型 ID 与实际映射模型;
  • 1K2K4K 图片档位;
  • 分组图片单价;
  • 用户分组倍率和上游账户倍率;
  • 部署环境中的计费规则。

最终金额请以灵眸控制台的用量明细和账户余额变化为准。

进行质量或并发测试时,建议记录:

  1. 测试前余额;
  2. 测试后余额;
  3. 成功请求数;
  4. 实际返回图片数;
  5. 模型、分辨率和画幅;
  6. 余额差额;
  7. 单张成功图片平均成本。

用量记录可能异步落账,测试结束后可等待一段时间再核对最终金额。


14. 安全建议

  • API Key 只保存在服务端环境变量或密钥管理系统;
  • 不要在浏览器前端、移动端安装包或公开代码仓库中写入 Key;
  • 日志不要打印完整 API Key 和完整图片 Base64;
  • 校验输入图片 MIME 类型、文件大小和 Base64 合法性;
  • 保存响应时根据 inlineData.mimeType 选择扩展名;
  • 为每个业务请求记录自己的 trace ID、请求时间、模型、分辨率和 HTTP 状态;
  • 超时后不要在极短时间内重复创建大量相同请求。

15. 接入验收清单

  • 能使用 /v1beta/models 获取当前 Key 的 Gemini 模型列表;
  • 能使用 x-goog-api-key 或 Bearer 请求头鉴权;
  • 能完成一张 1K / 1:1 文生图;
  • 能完成 2K4K 文生图;
  • 能完成至少一次图片编辑 / 图生图;
  • 能识别 inlineData.mimeTypeinlineData.data
  • 能把 HTTP 200 但没有图片的情况标记为失败;
  • 已设置图片请求超时;
  • 已对 429 和 5xx 实现有限次数指数退避;
  • 已确认价格、余额、并发和 RPM;
  • 日志不会泄露 API Key 或完整 Base64。

下一步

最后更新:

On this page