"""取数 / 多模态读取的数据结构(pydantic)。 只保留基建用到的类型:帖子(Post)、视觉卡片(Card)、多模态提取产物(ExtractedContent)。 """ from __future__ import annotations from typing import Literal, Optional from pydantic import BaseModel, Field CardKind = Literal["image", "frame", "segment"] class Card(BaseModel): """一张"卡片":图文帖的一张图、视频抽出的一帧,或原生视频提炼出的一个时间段。 下游溯源只认 index(1-based)。""" index: int kind: CardKind = "image" url: Optional[str] = None # 段卡可无图;图片/帧有 url timestamp: Optional[float] = None # 仅 frame:该帧在视频中的秒数 start: Optional[float] = None # 仅 segment:起始秒 end: Optional[float] = None # 仅 segment:结束秒 class Post(BaseModel): """fetch_post_detail 的产物:一条帖子的原始内容(文本 + 图片 + 视频)。""" id: str # xhs_,复用为 ingest source.id platform: str = "xiaohongshu" url: str content_id: str title: str = "" content_type: str = "" # video / 图文 body_text: str = "" topic_list: list[str] = Field(default_factory=list) image_urls: list[str] = Field(default_factory=list) video_urls: list[str] = Field(default_factory=list) cards: list[Card] = Field(default_factory=list) # 统一视觉卡片(图/帧) author_id: Optional[str] = None author_name: Optional[str] = None raw: dict = Field(default_factory=dict) # 原始响应 class CardExtract(BaseModel): """某张卡片上提取到的知识要点(按卡片归因)。""" index: int content: str = "" class ExtractedContent(BaseModel): """extract_content 的产物:多模态汇总后的真实内容。不直接用 body_text。""" text: str = "" # 汇总后的正文/讲解 cards: list[CardExtract] = Field(default_factory=list) # 按卡片归因的提取 from_image: str = "" # 兼容保留:图片里提取到的知识要点 from_video: str = "" # 兼容保留:视频里提取到的知识要点 is_empty: bool = False # 多模态提取后仍无有效内容