feat(core): AI 生成 Agent 化 — 多模型流式脚本 agent + 可插拔 Provider + gpt-image-2 参考图 + 模特库

- 后端·可插拔 Provider 层:通用 OpenAICompatibleProvider(tokenssr 等中转站,base_url+api_key,零改代码换站)+ ModelProvider.api_key
- 后端·脚本 agent:结构化 ScriptDraft 契约 + 加载电商 skill + 出稿/改稿一体对话 agent(3模式/多模型)+ 流式 SSE 端点(DRF SSE renderer)
- 后端·图像:gpt-image-2 参考图出图 + 故事板 @图1@图2@图3 多锚点合成(锁脸锁商品);Seedance 打开 generate_audio
- 后端·模特库:gpt-image-2 生成器(9:16氛围图→16:9白底三视图)+ seed_demo_models 管理命令
- DB·迁移:tokenssr 中转站 + 多模型 seed(豆包/GPT-5.5/Gemini + gpt-image-2);ScriptSegment 结构化字段
- 前端·脚本趴:接真 SSE(工具卡 + 思考流)+ 模型下拉 + 3模式 + 改稿;agentScriptStream
- skills/ecommerce-video-script 电商脚本技能(运行时依赖)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-17 03:12:03 +08:00
co-authored by Claude Opus 4.8
parent a0ffb6fc8e
commit 6464001f84
32 changed files with 9294 additions and 54 deletions
@@ -0,0 +1,43 @@
"""预生成电商模特库(gpt-image-2:9:16 氛围正面图 → 16:9 白底三视图)。
用法:
python manage.py seed_demo_models --count 2 [--team <team_id>] [--brief "自定义画像"]
默认给「第一个有成员的团队」生成 N 个默认人设。慢(每个模特 2 次 gpt-image-2,约 1-2 分钟)。
"""
from django.core.management.base import BaseCommand, CommandError
from apps.ai.model_library import DEFAULT_MODEL_BRIEFS, generate_model
class Command(BaseCommand):
help = "用 gpt-image-2 预生成电商模特(正面氛围图 + 白底三视图),存为 person 资产"
def add_arguments(self, parser):
parser.add_argument("--count", type=int, default=2, help="生成几个模特(默认 2)")
parser.add_argument("--team", type=str, default="", help="指定团队 id(默认第一个团队)")
parser.add_argument("--brief", type=str, default="", help="自定义单个模特画像(给了就只生成这一个)")
def handle(self, *args, **opts):
from apps.accounts.models import Team, User
team = Team.objects.filter(id=opts["team"]).first() if opts["team"] else Team.objects.order_by("created_at").first()
if team is None:
raise CommandError("找不到团队,请先建团队或用 --team 指定")
user = (
User.objects.filter(team_memberships__team=team).order_by("date_joined").first()
or getattr(team, "owner", None)
or User.objects.order_by("date_joined").first()
)
briefs = [opts["brief"]] if opts["brief"] else DEFAULT_MODEL_BRIEFS[: max(1, opts["count"])]
self.stdout.write(f"团队={team.id} 用户={getattr(user, 'username', None)} · 生成 {len(briefs)} 个模特…")
for i, brief in enumerate(briefs, 1):
self.stdout.write(f" [{i}/{len(briefs)}] {brief} … 生成中(gpt-image-2,稍候)")
try:
res = generate_model(team=team, user=user, brief=brief)
self.stdout.write(self.style.SUCCESS(
f" ✓ 正面={res['frontal'].id} 三视图={res['three_view'].id}"
))
except Exception as exc: # noqa: BLE001
self.stderr.write(self.style.ERROR(f" ✗ 失败:{exc}"))
self.stdout.write(self.style.SUCCESS("done"))