feat: 生图模型可选(火山/gpt-image) + 工作台图「加入资产库」收纳 + 任务中心排序修复
- AI 工作室生图支持显式选模型:resolve_image_model 解析 volcano(Seedream 图生图, 无 image_edit 时走 image_generation 带参考图)/ gpt-image(image_edit 多图编辑), 未选回落系统默认;enqueue_standalone_images 透传 image_model - 资产库收纳:Asset 加 in_library 字段(迁移 0007,既有资产 db_default=True 不动); 工作台生成图默认 in_library=False,只在工作台展示,用户「加入资产库」后才进库列表; assets 视图/序列化器/library 页/types 配套 - 任务中心修复:AITaskViewSet 默认 order_by(-created_at),前端 aiTasks 取 page_size=200。 原因:列表无排序时 MySQL 按 UUID 主键乱序返回,把一批旧失败记录顶到首页, 前端又只取首页 20 条算 全部/已完成/失败 → 误显示「全部失败」(实为 421 成功/少量失败) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
"""内衣·真人上身:换火山 Seedream 生图模型,看会不会被审核拦(对照 gpt-image-2 的 sexual 拦截)。
|
||||
跑法: .venv/bin/python tryon_volcano_test.py
|
||||
产物: /Users/maidong/Desktop/zyc/volcano_test
|
||||
"""
|
||||
import os
|
||||
import django
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "airshelf.settings.development")
|
||||
django.setup()
|
||||
|
||||
from apps.products.models import Product # noqa: E402
|
||||
from apps.assets.models import Asset # noqa: E402
|
||||
from apps.ai.models import ModelConfig # noqa: E402
|
||||
from apps.ai.services import ( # noqa: E402
|
||||
get_image_provider, build_model_tryon_prompt_refs, _product_reference_urls, _asset_preview_url,
|
||||
)
|
||||
from apps.ai.providers.volcano import VolcanoArkProvider # noqa: E402
|
||||
|
||||
PRODUCT_ID = "42078cdc-8714-4fc7-be5c-6aa42b7fc995" # 棉居莫代尔无痕内衣
|
||||
MODEL_ID = "ad362810-cf3e-49c0-9426-8142a74b75b2" # 真人模特
|
||||
OUT_DIR = "/Users/maidong/Desktop/zyc/volcano_test"
|
||||
# 试两个版本(从新到旧),哪个可用用哪个
|
||||
VOLCANO_MODELS = ["doubao-seedream-5-0-260128", "doubao-seedream-4-5-251128"]
|
||||
|
||||
|
||||
def main():
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
p = Product.objects.get(id=PRODUCT_ID)
|
||||
product_urls = _product_reference_urls(p, limit=3)
|
||||
model_url = _asset_preview_url(Asset.objects.get(id=MODEL_ID))
|
||||
images = product_urls + [model_url]
|
||||
prompt = build_model_tryon_prompt_refs(p, has_model=True, base_prompt="", index=0, n_product=len(product_urls))
|
||||
print(f"商品: {p.title} | 类目: {p.category} | 商品图数: {len(product_urls)} + 模特图")
|
||||
print(f"提示词:\n{prompt}\n")
|
||||
|
||||
for mname in VOLCANO_MODELS:
|
||||
mc = ModelConfig.objects.filter(capability="image", name=mname).first()
|
||||
if mc is None:
|
||||
print(f"⚠️ 库里没有模型配置 {mname},跳过")
|
||||
continue
|
||||
provider = get_image_provider(mc)
|
||||
print(f"\n━━━ 火山 {mc.provider.name}:{mname} ━━━")
|
||||
try:
|
||||
# Seedream 多图参考走 image 参数(可传 URL 列表);size 用 2K
|
||||
resp = provider.image_generation(model=mname, prompt=prompt, image=images, size="2K")
|
||||
media = provider.extract_first_media_url(resp)
|
||||
fileobj, ct = VolcanoArkProvider.media_to_bytes(media)
|
||||
ext = ".jpg" if "jpeg" in ct else (".webp" if "webp" in ct else ".png")
|
||||
path = os.path.join(OUT_DIR, f"volcano_{mname}{ext}")
|
||||
with open(path, "wb") as f:
|
||||
f.write(fileobj.getvalue())
|
||||
print(f"✅ 出图成功 → {path}")
|
||||
break
|
||||
except Exception as exc: # noqa: BLE001
|
||||
msg = str(exc)
|
||||
flagged = any(k in msg.lower() for k in ("moderation", "safety", "sexual", "blocked", "sensitive", "审核", "违规", "content"))
|
||||
print(f"❌ 失败{' · 命中内容审核' if flagged else ''}: {msg[:600]}")
|
||||
|
||||
print(f"\n完成。产物: {OUT_DIR}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user