拼消消生图管线升级:6 sheet 单形状满画布 + 洋红去背 + 自适应切图 + 提示词优化
改为 6 张 sheet,每张单形状,取消全部 FILL/留白,AI 填满画布后多画少取 新增洋红去背步骤,对接 platform-image alpha 管线 新增 find_non_transparent_bounds 四方向内容边界扫描 新增 fill_transparent_with_opaque_average 透明像素填充 自适应网格检测 (detect_cell_grid_seed) 用于组间边界对齐 重写 slice_puzzle_clear_sheet 为两阶段:group bbox → 等分 cell 提示词优化:主前缀改为裁片级描述,每 sheet 增加精确占格约束 修复 jump_hop 测试断言 (1×1×1 → 1×1×1 的立方体) 新增分析脚本 tools/analyze_puzzle_clear_output.py 和 tools/test_ve_api.py Sheet-06 为纵向 1×3 缓冲区
This commit is contained in:
171
tools/test_ve_api.py
Normal file
171
tools/test_ve_api.py
Normal file
@@ -0,0 +1,171 @@
|
||||
"""
|
||||
Vector Engine API 连通性与生图耗时测试脚本。
|
||||
|
||||
用法:
|
||||
python tools/test_ve_api.py
|
||||
python tools/test_ve_api.py --prompt "你的自定义提示词"
|
||||
python tools/test_ve_api.py --size 1024x1024 --samples 3
|
||||
|
||||
前置条件:
|
||||
环境变量 VECTOR_ENGINE_API_KEY 已设置,
|
||||
或从 ../.env.secrets.local 自动读取。
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
|
||||
API_URL = "https://api.vectorengine.cn/v1/images/generations"
|
||||
DEFAULT_PROMPT = "生成一张白色背景上的一只飞踢橘猫,绘本风格,不要文字水印"
|
||||
DEFAULT_SIZE = "1024x1536"
|
||||
DEFAULT_NEGATIVE = "文字、Logo、水印、按钮、UI、网格线、边框、编号、标签、纯色背景、白底、孤立主体"
|
||||
|
||||
|
||||
def load_env_from_file(filepath):
|
||||
"""从 .env 文件中加载环境变量(简单实现)"""
|
||||
if not os.path.exists(filepath):
|
||||
return
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
if "=" in line:
|
||||
key, _, value = line.partition("=")
|
||||
key = key.strip()
|
||||
value = value.strip().strip('"').strip("'")
|
||||
if key and value and key not in os.environ:
|
||||
os.environ[key] = value
|
||||
|
||||
|
||||
def single_request(api_key, base_url, prompt, negative, size, quality, index):
|
||||
"""单次生图请求,返回 (耗时秒, task_id, 图片字节数)"""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
body = {
|
||||
"model": "gpt-image-2",
|
||||
"prompt": prompt,
|
||||
"n": 1,
|
||||
"size": size,
|
||||
}
|
||||
if negative:
|
||||
body["negative_prompt"] = negative
|
||||
if quality:
|
||||
body["quality"] = quality
|
||||
|
||||
start = time.time()
|
||||
try:
|
||||
resp = requests.post(
|
||||
base_url.rstrip("/") + "/v1/images/generations",
|
||||
headers=headers,
|
||||
json=body,
|
||||
timeout=600,
|
||||
)
|
||||
elapsed = time.time() - start
|
||||
|
||||
if resp.status_code != 200:
|
||||
print(f" [#{index}] HTTP {resp.status_code}: {resp.text[:300]}")
|
||||
return elapsed, None, 0
|
||||
|
||||
data = resp.json()
|
||||
task_id = data.get("task_id", "")
|
||||
images = data.get("data", [])
|
||||
b64_len = len(images[0].get("b64_json", "")) if images else 0
|
||||
url = images[0].get("url", "") if images else ""
|
||||
|
||||
print(f" [#{index}] {elapsed:.1f}s task_id={task_id} b64={b64_len}chars url={'present' if url else 'none'}")
|
||||
return elapsed, task_id, b64_len
|
||||
except requests.Timeout:
|
||||
elapsed = time.time() - start
|
||||
print(f" [#{index}] TIMEOUT after {elapsed:.0f}s")
|
||||
return elapsed, None, 0
|
||||
except Exception as e:
|
||||
elapsed = time.time() - start
|
||||
print(f" [#{index}] ERROR: {e}")
|
||||
return elapsed, None, 0
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Vector Engine API 测试")
|
||||
parser.add_argument("--prompt", default=DEFAULT_PROMPT, help="生图提示词")
|
||||
parser.add_argument("--negative", default=DEFAULT_NEGATIVE, help="负面提示词")
|
||||
parser.add_argument("--size", default=DEFAULT_SIZE, help="图片尺寸 (1024x1024 / 1024x1536 / 1536x1024)")
|
||||
parser.add_argument("--samples", type=int, default=1, help="请求次数")
|
||||
parser.add_argument("--parallel", type=int, default=1, help="并行请求数 (默认1=串行)")
|
||||
parser.add_argument("--quality", default="", help="生图质量 (low/medium/high)")
|
||||
parser.add_argument("--base-url", default=API_URL, help="API 地址")
|
||||
args = parser.parse_args()
|
||||
|
||||
# 自动加载 secrets
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
repo_root = os.path.dirname(script_dir)
|
||||
for fname in [".env.secrets.local", ".env.local", ".env"]:
|
||||
load_env_from_file(os.path.join(repo_root, fname))
|
||||
|
||||
api_key = os.environ.get("VECTOR_ENGINE_API_KEY", "")
|
||||
if not api_key:
|
||||
print("错误: 未设置 VECTOR_ENGINE_API_KEY")
|
||||
print("请设置环境变量或将密钥写入 .env.secrets.local")
|
||||
sys.exit(1)
|
||||
|
||||
base_url = os.environ.get("VECTOR_ENGINE_BASE_URL", args.base_url)
|
||||
print(f"API: {base_url}")
|
||||
print(f"Size: {args.size}")
|
||||
print(f"Samples: {args.samples}")
|
||||
print(f"Parallel: {args.parallel}")
|
||||
if args.quality:
|
||||
print(f"Quality: {args.quality}")
|
||||
print(f"Prompt ({len(args.prompt)} chars):")
|
||||
print(f" {args.prompt[:120]}...")
|
||||
print(f"Negative ({len(args.negative)} chars):")
|
||||
print(f" {args.negative[:120]}...")
|
||||
print()
|
||||
|
||||
parallel = args.parallel
|
||||
total_start = time.time()
|
||||
|
||||
if parallel <= 1:
|
||||
times = []
|
||||
for i in range(1, args.samples + 1):
|
||||
elapsed, task_id, b64_len = single_request(
|
||||
api_key, base_url, args.prompt, args.negative, args.size, args.quality, i
|
||||
)
|
||||
if b64_len > 0:
|
||||
times.append(elapsed)
|
||||
else:
|
||||
times = []
|
||||
with ThreadPoolExecutor(max_workers=parallel) as pool:
|
||||
futures = {
|
||||
pool.submit(
|
||||
single_request,
|
||||
api_key, base_url, args.prompt, args.negative, args.size, args.quality, idx
|
||||
): idx
|
||||
for idx in range(1, args.samples + 1)
|
||||
}
|
||||
for future in as_completed(futures):
|
||||
elapsed, task_id, b64_len = future.result()
|
||||
if b64_len > 0:
|
||||
times.append(elapsed)
|
||||
|
||||
total_elapsed = time.time() - total_start
|
||||
|
||||
if times:
|
||||
avg = sum(times) / len(times)
|
||||
print(f"\n成功: {len(times)}/{args.samples}")
|
||||
print(f"总耗时: {total_elapsed:.1f}s")
|
||||
print(f"平均: {avg:.1f}s")
|
||||
print(f"最快: {min(times):.1f}s")
|
||||
print(f"最慢: {max(times):.1f}s")
|
||||
else:
|
||||
print(f"\n全部失败 ({args.samples} 次)" + f" | 总耗时: {total_elapsed:.1f}s")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user