"""赛题合成核心逻辑 — 节点采样、prompt 构造、去重。 纯函数为主,异步编排仅 generate_one。 通过 DI 接收 VLMProvider / EmbeddingProvider,不 import adapters/。 """ from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True) class AnchorContext: """锚节点上下文——生成单道题所需的全部素材。 属性: node_id: 锚节点 ID。 card_text: 锚节点 card 序列化文本。 frame_paths: 帧图片路径列表。 subtitle: 对应字幕(可空)。 distractor_texts: 同视频其他节点摘要(供 VLM 生成干扰项)。 """ node_id: str card_text: str frame_paths: list[str] subtitle: str distractor_texts: list[str] @dataclass(frozen=True) class TaskTypeSpec: """题型的生成规格。 属性: level: 锚定层级("L3" / "L2" / "L1" / "L1-L2")。 needs_frames: 是否必须提供帧图。 frame_count: 帧数范围描述(如 "1", "2-3", "0-1")。 context_fields: 需要提取的 card 字段元组。 """ level: str needs_frames: bool frame_count: str context_fields: tuple[str, ...] # --------------------------------------------------------------------------- # 12 种 Video-MME 题型 → 树层级 + 生成规格映射 # --------------------------------------------------------------------------- TASK_TYPE_LEVEL_MAP: dict[str, TaskTypeSpec] = { # --- L3 单帧题型 --- "Object Recognition": TaskTypeSpec("L3", True, "1", ("frame_summary",)), "Attribute Perception": TaskTypeSpec("L3", True, "1", ("frame_summary",)), "OCR Problems": TaskTypeSpec("L3", True, "1", ("frame_summary",)), "Spatial Reasoning": TaskTypeSpec("L3", True, "1", ("frame_summary", "spatial_layout")), "Spatial Perception": TaskTypeSpec("L3", True, "1", ("frame_summary",)), # --- L2 多帧 / 事件级题型 --- "Action Recognition": TaskTypeSpec("L2", True, "2-3", ("event_description",)), "Action Reasoning": TaskTypeSpec("L2", True, "2-3", ("event_description",)), "Counting Problem": TaskTypeSpec("L2", True, "2-3", ("event_description",)), "Temporal Perception": TaskTypeSpec("L2", False, "0-1", ("event_description", "time_range")), # --- L1 / 跨层级题型 --- "Temporal Reasoning": TaskTypeSpec("L1", True, "per-L2", ("scene_summary",)), "Information Synopsis": TaskTypeSpec("L1", True, "per-L2", ("scene_summary",)), "Object Reasoning": TaskTypeSpec("L1-L2", True, "per-L2", ("event_description",)), }