feat(ai): 图像主力从 tokenssr 切到 yunqi(支持 images/edits 图生图)
TOKENSSR 余额将尽,切换图像默认 provider 到 yunqi。yunqi 的图生图 端点需 Azure 风格 ?api-version=2025-04-01-preview,不带会 404。 - provider 加 api_version 字段,OpenAICompatible 生图/改图端点自动附加 ?api-version=(配了才加,tokenssr 等零影响) - build_provider 解析 api_version:DB(ModelProvider.metadata)优先 → .env 回退 - 迁移 0007:启用 yunqi:gpt-image-2 为唯一 active 图像模型,禁用其余 - 摘除死代码 YunqiProvider 导出(旧类写死"不支持图生图"会误导) 端到端验证:图生图(三视图,36s)+文生图(14s)均正常出图。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""图像主力从 tokenssr:gpt-image-2 切到 yunqi:gpt-image-2(TOKENSSR 余额将尽)。
|
||||
|
||||
yunqi 的图生图(images/edits)需 Azure 风格 ?api-version=2025-04-01-preview —— 存进
|
||||
ModelProvider.metadata.api_version,运行时由 services.build_provider 注入,provider 据此拼 URL。
|
||||
凭证仍走 .env(YUNQI_API_KEY,即能走 edits 的老 key),不进库。
|
||||
|
||||
幂等:get_or_create / update_or_create,可重复 apply。
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
YUNQI_BASE_URL = "https://www.yunqiai.chat/v1"
|
||||
API_VERSION = "2025-04-01-preview"
|
||||
|
||||
|
||||
def switch(apps, schema_editor):
|
||||
ModelProvider = apps.get_model("ai", "ModelProvider")
|
||||
ModelConfig = apps.get_model("ai", "ModelConfig")
|
||||
|
||||
yunqi, _ = ModelProvider.objects.get_or_create(
|
||||
name="yunqi",
|
||||
defaults={
|
||||
"display_name": "YunQi AI(New API 网关)",
|
||||
"status": "active",
|
||||
"base_url": YUNQI_BASE_URL,
|
||||
"api_key": "", # 留空:运行时从 .env(YUNQI_API_KEY)解析,密钥不进库
|
||||
"metadata": {"kind": "relay", "api_version": API_VERSION},
|
||||
},
|
||||
)
|
||||
meta = yunqi.metadata or {}
|
||||
meta["api_version"] = API_VERSION # edits 端点必带,否则 404
|
||||
yunqi.metadata = meta
|
||||
if not yunqi.base_url:
|
||||
yunqi.base_url = YUNQI_BASE_URL
|
||||
yunqi.status = "active" # get_default_model 要求 provider__status=active
|
||||
yunqi.save(update_fields=["metadata", "base_url", "status"])
|
||||
|
||||
ModelConfig.objects.update_or_create(
|
||||
provider=yunqi,
|
||||
name="gpt-image-2",
|
||||
capability="image",
|
||||
defaults={
|
||||
"display_name": "GPT-Image-2(参考图)",
|
||||
"endpoint": "images/generations", # 文生图端点;图生图由 provider.image_edit 走 images/edits
|
||||
"unit_price": "2.0000",
|
||||
"status": "active",
|
||||
"metadata": {"family": "gpt", "supports_reference": True, "recommended": True},
|
||||
},
|
||||
)
|
||||
|
||||
# 切到 yunqi 唯一 active 图像模型:禁用所有非 yunqi 图像模型(含 tokenssr、火山 Seedream)。
|
||||
# 否则 created_at 更早且 active 的模型会被 get_default_model(order_by created_at)顶替默认。
|
||||
ModelConfig.objects.filter(capability="image").exclude(provider__name="yunqi").update(status="disabled")
|
||||
|
||||
|
||||
def revert(apps, schema_editor):
|
||||
# 反向:停用 yunqi 图像,复活 tokenssr:gpt-image-2(回到 0006 后的状态)
|
||||
ModelConfig = apps.get_model("ai", "ModelConfig")
|
||||
ModelConfig.objects.filter(provider__name="yunqi", capability="image").update(status="disabled")
|
||||
ModelConfig.objects.filter(
|
||||
provider__name="tokenssr", capability="image", name="gpt-image-2"
|
||||
).update(status="active")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [("ai", "0006_seed_tokenssr_models")]
|
||||
operations = [migrations.RunPython(switch, revert)]
|
||||
Reference in New Issue
Block a user