feat: 接入 Agnes Image 2.1 Flash 文生图/图生图 API,新增 multipart 上传端点
- utils/t2i.py 重命名为 utils/mm_api_t2i.py(内容不变) - 新增 utils/agnes_image.py: Agnes 文生图/图生图/多图合成,含 size+ratio 解析、URL/Data URI下载、指数退避重试 - main.py: 修复 utils.t2i import 路径;新增 POST /agnes/images/generations(JSON 版)和 /agnes/images/generations/upload(multipart 版) - SKILL.md: 同步新端点、可调用模型、调用示例、multipart form 字段说明 - requirements.txt: 新增 python-multipart(UploadFile 依赖) - .env.example / .env: 新增 AGNES_API_KEY / AGNES_API_BASE_URL - .gitignore: 忽略 test/ 目录 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
# Generated output
|
# Generated output
|
||||||
output/
|
output/
|
||||||
|
test/
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: ai-image
|
name: ai-image
|
||||||
description: Generate images via AI text-to-image API (GPT Image / Grok). Use when the user asks to draw, paint, generate, or create an image from a text description.
|
description: Generate images via AI text-to-image API (GPT Image / Grok / Agnes Image 2.1 Flash). Use when the user asks to draw, paint, generate, or create an image from a text description, or to colorize / edit / remix existing images.
|
||||||
---
|
---
|
||||||
|
|
||||||
# AI 绘图工具
|
# AI 绘图工具
|
||||||
@@ -15,6 +15,7 @@ description: Generate images via AI text-to-image API (GPT Image / Grok). Use wh
|
|||||||
|------|------------|------------|------|
|
|------|------------|------------|------|
|
||||||
| GPT / Grok 绘图 | `main.py` | `POST /images/generations` | `gpt-image-2-1K` / `gpt-image-2-2K` / `gpt-image-2-4K` / `grok-imagine-image-lite` |
|
| GPT / Grok 绘图 | `main.py` | `POST /images/generations` | `gpt-image-2-1K` / `gpt-image-2-2K` / `gpt-image-2-4K` / `grok-imagine-image-lite` |
|
||||||
| Agnes 绘图(文生图 / 图生图 / 多图合成) | `main.py` | `POST /agnes/images/generations` | `agnes-image-2.1-flash` |
|
| Agnes 绘图(文生图 / 图生图 / 多图合成) | `main.py` | `POST /agnes/images/generations` | `agnes-image-2.1-flash` |
|
||||||
|
| Agnes 上传版(图生图 / 多图合成,multipart) | `main.py` | `POST /agnes/images/generations/upload` | `agnes-image-2.1-flash` |
|
||||||
| 健康检查 | `main.py` | `GET /health` | — |
|
| 健康检查 | `main.py` | `GET /health` | — |
|
||||||
| 图片访问 | `main.py` | `GET /output/{profile_name}/{filename}` | — |
|
| 图片访问 | `main.py` | `GET /output/{profile_name}/{filename}` | — |
|
||||||
|
|
||||||
@@ -22,10 +23,16 @@ description: Generate images via AI text-to-image API (GPT Image / Grok). Use wh
|
|||||||
|
|
||||||
| 模型 | 输出尺寸 | 备注 |
|
| 模型 | 输出尺寸 | 备注 |
|
||||||
|------|----------|------|
|
|------|----------|------|
|
||||||
| `gpt-image-2-1K` | ~1254×1254(1:1)或 1536×1024(横版) | **推荐**,线路稳定 |
|
| `gpt-image-2-1K` | 不固定 | 线路不稳定,可能 503 |
|
||||||
| `gpt-image-2-2K` | 不固定 | 线路不稳定,可能 503 |
|
| `gpt-image-2-2K` | 不固定 | 线路不稳定,可能 503 |
|
||||||
| `gpt-image-2-4K` | 不固定 | 线路不稳定,可能 503 |
|
| `gpt-image-2-4K` | 不固定 | 线路不稳定,可能 503 |
|
||||||
|
|
||||||
|
```text
|
||||||
|
注意, gpt-image-2 画图效果好, 但是有个能出现线路拥堵情况,如果报错,请重试
|
||||||
|
可以尝试 gpt-image-2-1K, gpt-image-2-2K, gpt-image-2-4K, 三个模型都尝试一下
|
||||||
|
可以生成 1:1, 4:3, 16:9 的图片
|
||||||
|
```
|
||||||
|
|
||||||
> Grok 模型的 size 参数不可靠,API 返回尺寸不受控。
|
> Grok 模型的 size 参数不可靠,API 返回尺寸不受控。
|
||||||
|
|
||||||
## 使用方式
|
## 使用方式
|
||||||
@@ -134,6 +141,43 @@ curl -X POST http://localhost:8765/agnes/images/generations \
|
|||||||
|
|
||||||
返回的 `size` 是根据 `size` 档位 + `ratio` 解析出的实际像素尺寸,便于拼接访问地址。
|
返回的 `size` 是根据 `size` 档位 + `ratio` 解析出的实际像素尺寸,便于拼接访问地址。
|
||||||
|
|
||||||
|
### 上传版(multipart/form-data)
|
||||||
|
|
||||||
|
如果不想手动 base64,可以用 `POST /agnes/images/generations/upload`,直接传本地图片文件:
|
||||||
|
|
||||||
|
单张图:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8765/agnes/images/generations/upload \
|
||||||
|
-F "prompt=color this line art with watercolor style, soft palette, preserve composition" \
|
||||||
|
-F "profile_name=tester" \
|
||||||
|
-F "size=1K" \
|
||||||
|
-F "ratio=16:9" \
|
||||||
|
-F "images=@/path/to/your-image.png"
|
||||||
|
```
|
||||||
|
|
||||||
|
多张图(多图合成,`images` 字段可以传多次):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8765/agnes/images/generations/upload \
|
||||||
|
-F "prompt=combine the two characters into an intense fantasy battle scene" \
|
||||||
|
-F "profile_name=tester" \
|
||||||
|
-F "size=1K" \
|
||||||
|
-F "ratio=16:9" \
|
||||||
|
-F "images=@/path/to/character-1.png" \
|
||||||
|
-F "images=@/path/to/character-2.png"
|
||||||
|
```
|
||||||
|
|
||||||
|
Form 字段:
|
||||||
|
|
||||||
|
- `prompt`:必填,文本提示词
|
||||||
|
- `profile_name`:必填,调用方 agent 的标识
|
||||||
|
- `size`:可选,默认 `1K`
|
||||||
|
- `ratio`:可选,宽高比;支持 `1:1` / `3:4` / `4:3` / `16:9` / `9:16` / `2:3` / `3:2` / `21:9`;默认 `1:1`
|
||||||
|
- `images`:必填,至少上传 1 张,支持 PNG / JPEG / WebP;多张传多个 `images` 字段即可
|
||||||
|
|
||||||
|
响应格式与 JSON 版完全一致。
|
||||||
|
|
||||||
### 请求参数
|
### 请求参数
|
||||||
|
|
||||||
请求体为 JSON,发送到 `POST /agnes/images/generations`:
|
请求体为 JSON,发送到 `POST /agnes/images/generations`:
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
import base64
|
||||||
from fastapi import FastAPI
|
import re
|
||||||
|
from fastapi import FastAPI, File, Form, HTTPException, UploadFile
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from pydantic import BaseModel, Field, model_validator
|
from pydantic import BaseModel, Field, model_validator
|
||||||
|
|
||||||
@@ -97,6 +98,46 @@ def agnes_generate_images_endpoint(request: AgnesImageGenerationRequest):
|
|||||||
return AgnesImageGenerationResponse(**result)
|
return AgnesImageGenerationResponse(**result)
|
||||||
|
|
||||||
|
|
||||||
|
_ALLOWED_IMAGE_TYPES = {"image/png", "image/jpeg", "image/jpg", "image/webp"}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/agnes/images/generations/upload", response_model=AgnesImageGenerationResponse)
|
||||||
|
def agnes_generate_images_upload_endpoint(
|
||||||
|
prompt: str = Form(..., description="图片提示词"),
|
||||||
|
profile_name: str = Form(..., description="调用方标识(必填)"),
|
||||||
|
size: str = Form(default="1K", description="输出尺寸档位: 1K / 2K / 3K / 4K"),
|
||||||
|
ratio: str | None = Form(default=None, description=f"宽高比,支持 {sorted(VALID_RATIOS)}"),
|
||||||
|
images: list[UploadFile] = File(default=[], description="参考图像文件,可传多个"),
|
||||||
|
):
|
||||||
|
"""multipart/form-data 版图生图:上传本地图片文件直接测试,无需 base64。"""
|
||||||
|
if not prompt.strip():
|
||||||
|
raise HTTPException(status_code=422, detail="prompt 不能为空")
|
||||||
|
if not re.match(r"^[\w-]+$", profile_name):
|
||||||
|
raise HTTPException(status_code=422, detail="profile_name 只能包含字母数字下划线和短横线")
|
||||||
|
if not images or all(not f.filename for f in images):
|
||||||
|
raise HTTPException(status_code=422, detail="必须至少上传一张参考图 images")
|
||||||
|
|
||||||
|
data_uris: list[str] = []
|
||||||
|
for f in images:
|
||||||
|
if f.content_type and f.content_type not in _ALLOWED_IMAGE_TYPES:
|
||||||
|
raise HTTPException(status_code=400, detail=f"不支持的图片类型: {f.content_type}")
|
||||||
|
raw = f.file.read()
|
||||||
|
if not raw:
|
||||||
|
raise HTTPException(status_code=400, detail=f"上传的图片 {f.filename} 为空")
|
||||||
|
mime = f.content_type or "image/png"
|
||||||
|
b64 = base64.b64encode(raw).decode("ascii")
|
||||||
|
data_uris.append(f"data:{mime};base64,{b64}")
|
||||||
|
|
||||||
|
result = agnes_generate_images(
|
||||||
|
prompt=prompt,
|
||||||
|
size=size,
|
||||||
|
ratio=ratio,
|
||||||
|
images=data_uris,
|
||||||
|
profile_name=profile_name,
|
||||||
|
)
|
||||||
|
return AgnesImageGenerationResponse(**result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
fastapi
|
fastapi
|
||||||
openai
|
openai
|
||||||
python-dotenv
|
python-dotenv
|
||||||
|
python-multipart
|
||||||
uvicorn[standard]
|
uvicorn[standard]
|
||||||
|
|||||||
Reference in New Issue
Block a user