优化故事版生成
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
链路:ffmpeg 抽帧(均匀采样) → 帧内联进多模态 messages → 走现有文本模型路由 → 纯文本分镜稿。
|
||||
|
||||
两个「本来以为要新建、其实已经有」的前提:
|
||||
1. **读图能力**:默认脚本模型(YunQi gemini-3.1-pro)本身是多模态的,OpenAI 兼容的
|
||||
``content: [{type:"text"},{type:"image_url"}]`` 直接透传即可,不需要新 provider、新模型、新 key。
|
||||
1. **读图能力**:拆视频是多模态(帧图 + 文本)。默认语言模型现在可能是纯文本豆包,
|
||||
**不能再用 get_default_model(TEXT)**。固定钉 Gemini 3.1 Pro 官转
|
||||
(``gemini-3.1-pro-preview``,展示名带「官转」优先)。
|
||||
2. **ffmpeg**:第 5 阶段导出早就依赖它,已装进后端镜像(见 Dockerfile)。
|
||||
|
||||
**没有音轨**:帧里读不到口播,只能读画面上的字幕。这是刻意取舍——接语音转写要另开火山 ASR 服务、
|
||||
@@ -198,6 +199,59 @@ def validate_digest_text(text: str) -> str:
|
||||
return cleaned
|
||||
|
||||
|
||||
# 拆视频必须会看图。默认文本模型现在常是纯文本豆包,传帧图会直接失败。
|
||||
# 钉 Gemini 3.1 Pro;展示名带「官转」的优先(中转站官方 Gemini 通道)。
|
||||
DIGEST_VISION_MODEL_NAME = "gemini-3.1-pro-preview"
|
||||
|
||||
|
||||
def resolve_digest_model_config():
|
||||
"""视频提炼用的多模态文本模型:Gemini 3.1 Pro 官转。找不到不回落默认语言模型。"""
|
||||
from apps.ai.models import ModelConfig
|
||||
|
||||
qs = (
|
||||
ModelConfig.objects.select_related("provider")
|
||||
.filter(
|
||||
capability=ModelConfig.Capability.TEXT,
|
||||
status=ModelConfig.Status.ACTIVE,
|
||||
provider__status="active",
|
||||
)
|
||||
)
|
||||
|
||||
def _blob(model) -> str:
|
||||
return " ".join(
|
||||
filter(
|
||||
None,
|
||||
[
|
||||
model.name,
|
||||
model.display_name,
|
||||
getattr(model.provider, "name", ""),
|
||||
getattr(model.provider, "display_name", ""),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
ranked = []
|
||||
for model in qs:
|
||||
blob = _blob(model)
|
||||
name_hit = "gemini-3.1" in model.name.lower() or "gemini-3.1" in (model.display_name or "").lower()
|
||||
label_hit = "gemini 3.1" in (model.display_name or "").lower()
|
||||
if not (name_hit or label_hit or model.name == DIGEST_VISION_MODEL_NAME):
|
||||
continue
|
||||
# 官转 > 精确模型名 > 其它 Gemini 3.1
|
||||
score = 0
|
||||
if "官转" in blob:
|
||||
score += 100
|
||||
if model.name == DIGEST_VISION_MODEL_NAME:
|
||||
score += 20
|
||||
if getattr(model.provider, "name", "") == "yunqi_gemini":
|
||||
score += 5
|
||||
ranked.append((score, model.created_at, model))
|
||||
if not ranked:
|
||||
return None
|
||||
ranked.sort(key=lambda item: (-item[0], item[1]))
|
||||
return ranked[0][2]
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 入口:一次真实的计费调用
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -206,15 +260,15 @@ def digest_project_video(*, project, user, upload) -> dict:
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.ai.models import AITask, ModelConfig
|
||||
from apps.ai.services import create_ai_task, execute_routed_text_request, get_default_model
|
||||
from apps.ai.models import AITask
|
||||
from apps.ai.services import create_ai_task, execute_routed_text_request
|
||||
from apps.billing.services.ledger import charge_reserved_credit
|
||||
|
||||
frames, duration = frames_from_upload(upload)
|
||||
|
||||
model_config = get_default_model(ModelConfig.Capability.TEXT)
|
||||
model_config = resolve_digest_model_config()
|
||||
if model_config is None:
|
||||
raise VideoDigestError("暂时没有可用的模型,请联系管理员")
|
||||
raise VideoDigestError("视频提炼需要 Gemini 3.1 Pro(会看图),当前没有启用,请联系管理员")
|
||||
|
||||
product = getattr(project, "product", None)
|
||||
messages = build_digest_messages(
|
||||
|
||||
Reference in New Issue
Block a user