fix: 修复资产/视频/三视图三处 bug + 脚本模型切 YunQi gemini
1. 视频「全部生成」串行短路:任一段提交失败就 break 致后面段不提交 (4 个框只跑 2 个)→ 改 Promise.allSettled 并发,单段失败不拖累其余, 部分失败也刷新并如实报告。(App.tsx) 2. 基础资产/三视图 AI 出图偶发失败「生成不出来」:中转站瞬时抖动 (网络/5xx/429/空返回)一次失败即退费 → 加退避重试 3 次,永久错误 (4xx 内容违规)仍立即退费。(services.py run_base_asset_task/run_triview_task) 3. 商品三视图无法用已有素材:商品卡加「使用已有素材」,选商品已有图 / 上传本地图直接 attach 成三视图(不走平台 AI 生成、不计费)。(pipeline.tsx) 4. 脚本助手:tokenssr 欠费致 GPT-5.5/Gemini 全挂 → 文本模型切 YunQi。 实测 YunQi gpt-5.5 频道扛不住重型结构化任务(skill 全提示词仅 1/5 成功、 常吐空无 JSON),gemini-3.1-pro 5/5 稳定 → 默认改 gemini,停用 gpt-5.5。 按「一 provider 一 key」拆 yunqi_gpt / yunqi_gemini 两 provider。 (.env / settings / 迁移 0017+0018) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""脚本助手文本模型从 tokenssr 切到 YunQi(tokenssr 欠费致 GPT-5.5/Gemini 全挂)。
|
||||
|
||||
YunQi 同一地址(https://www.yunqiai.chat/v1)对 gpt / gemini 分开计费、各一把 key,故按
|
||||
「一 provider 一 key」拆成两个 provider:
|
||||
- yunqi_gpt → gpt-5.5(默认脚本模型) · key=.env YUNQI_GPT_API_KEY
|
||||
- yunqi_gemini → gemini-3.1-pro-preview · key=.env YUNQI_GEMINI_API_KEY
|
||||
凭证留空 → 运行时由 settings.PROVIDER_KEYS 从 .env 解析(密钥不进库)。
|
||||
模型名经实测确认:gpt-5.5 / gemini-3.1-pro-preview 在 YunQi 返回 200 且能流式出正文;
|
||||
其余名(gpt-5 / gemini-3-pro-preview …)YunQi 报 model_not_found。
|
||||
|
||||
同时停用旧的 tokenssr 文本模型(gpt-5.5 / gemini-3-pro-preview),让 get_default_model(text)
|
||||
选到新的 YunQi gpt-5.5。幂等:全部 update_or_create / 显式置位,可重复 apply。
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
YUNQI_BASE_URL = "https://www.yunqiai.chat/v1"
|
||||
|
||||
# (provider_name, display, model_name, model_display, is_default)
|
||||
YUNQI_TEXT = [
|
||||
("yunqi_gpt", "YunQi · GPT", "gpt-5.5", "GPT-5.5", True),
|
||||
("yunqi_gemini", "YunQi · Gemini", "gemini-3.1-pro-preview", "Gemini 3.1 Pro", False),
|
||||
]
|
||||
|
||||
|
||||
def seed(apps, schema_editor):
|
||||
ModelProvider = apps.get_model("ai", "ModelProvider")
|
||||
ModelConfig = apps.get_model("ai", "ModelConfig")
|
||||
|
||||
for prov_name, prov_display, model_name, model_display, is_default in YUNQI_TEXT:
|
||||
provider, _ = ModelProvider.objects.get_or_create(
|
||||
name=prov_name,
|
||||
defaults={
|
||||
"display_name": prov_display,
|
||||
"status": "active",
|
||||
"base_url": YUNQI_BASE_URL,
|
||||
"api_key": "", # 运行时从 .env(PROVIDER_KEYS)解析,密钥不进库
|
||||
"metadata": {"kind": "relay", "gateway": "yunqi"},
|
||||
},
|
||||
)
|
||||
# down→up 循环后 get_or_create 命中旧行(可能 disabled / 缺 base_url),显式补齐
|
||||
changed = []
|
||||
if provider.status != "active":
|
||||
provider.status = "active"; changed.append("status")
|
||||
if not provider.base_url:
|
||||
provider.base_url = YUNQI_BASE_URL; changed.append("base_url")
|
||||
if changed:
|
||||
provider.save(update_fields=changed)
|
||||
|
||||
ModelConfig.objects.update_or_create(
|
||||
provider=provider,
|
||||
name=model_name,
|
||||
capability="text",
|
||||
defaults={
|
||||
"display_name": model_display,
|
||||
"endpoint": "chat/completions",
|
||||
"unit_price": "1.0000",
|
||||
"status": "active",
|
||||
"is_default": is_default,
|
||||
"metadata": {"gateway": "yunqi", "verified": True},
|
||||
},
|
||||
)
|
||||
|
||||
# 停用旧的 tokenssr 文本模型(欠费),并清掉它们可能带的 is_default,避免与新默认打架
|
||||
ModelConfig.objects.filter(
|
||||
provider__name="tokenssr", capability="text",
|
||||
).update(status="disabled", is_default=False)
|
||||
|
||||
|
||||
def unseed(apps, schema_editor):
|
||||
ModelConfig = apps.get_model("ai", "ModelConfig")
|
||||
# 回滚:停用 YunQi 文本模型,恢复 tokenssr 文本模型为 active(gpt-5.5 复位默认)
|
||||
ModelConfig.objects.filter(provider__name__in=["yunqi_gpt", "yunqi_gemini"], capability="text").update(
|
||||
status="disabled", is_default=False,
|
||||
)
|
||||
ModelConfig.objects.filter(provider__name="tokenssr", capability="text").update(status="active")
|
||||
ModelConfig.objects.filter(provider__name="tokenssr", capability="text", name="gpt-5.5").update(is_default=True)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("ai", "0016_person_triview_16_9"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(seed, unseed),
|
||||
]
|
||||
@@ -0,0 +1,38 @@
|
||||
"""脚本默认模型从 gpt-5.5 改为 gemini-3.1-pro-preview,并停用 YunQi 的 gpt-5.5。
|
||||
|
||||
实测(完整电商脚本 skill ~28KB 重型结构化任务,各连发 5 次):
|
||||
- YunQi gpt-5.5 → 仅 1/5 成功(3 次吐空、1 次出文无合法 JSON,成功那次还要 69-95s)→ 频道扛不住,不可用
|
||||
- YunQi gemini-3.1-pro → 5/5 成功(每次 ~2300 字合法 JSON,30-48s 稳定)
|
||||
故默认切 gemini;gpt-5.5 停用(YunQi 频道修好后改回 active 即可,一行)。
|
||||
幂等:显式置位,可重复 apply。
|
||||
"""
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def apply(apps, schema_editor):
|
||||
ModelConfig = apps.get_model("ai", "ModelConfig")
|
||||
# gemini 设默认 + 确保 active
|
||||
ModelConfig.objects.filter(
|
||||
provider__name="yunqi_gemini", capability="text", name="gemini-3.1-pro-preview",
|
||||
).update(is_default=True, status="active")
|
||||
# gpt-5.5 取消默认 + 停用(频道不可用)
|
||||
ModelConfig.objects.filter(
|
||||
provider__name="yunqi_gpt", capability="text", name="gpt-5.5",
|
||||
).update(is_default=False, status="disabled")
|
||||
|
||||
|
||||
def revert(apps, schema_editor):
|
||||
ModelConfig = apps.get_model("ai", "ModelConfig")
|
||||
ModelConfig.objects.filter(provider__name="yunqi_gemini", capability="text", name="gemini-3.1-pro-preview").update(is_default=False)
|
||||
ModelConfig.objects.filter(provider__name="yunqi_gpt", capability="text", name="gpt-5.5").update(is_default=True, status="active")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("ai", "0017_switch_script_to_yunqi"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(apply, revert),
|
||||
]
|
||||
Reference in New Issue
Block a user