assetLibrary
静态流程说明 · MOCK DATA
REGISTER → UNDERSTAND → INDEX → SEARCH

一条素材,如何变成
一条可搜索的记录。

用“图片素材 A”和“视频素材 B”两组模拟数据,沿着 ID 看清入库、内容理解、索引建立,以及混合检索返回的全过程。

本页仅展示文字、表格和 JSON。示例身份、文件编号、metadata、Gemini 输出、向量与检索结果全部为 mock;没有附带或加载任何图片、视频、音轨,也不调用模型或数据库。
01 · REGISTER登记素材

保存来源、归属和权限

02 · ACK返回短 ID

任务已可靠接收

03 · UNDERSTAND理解内容

生成描述与缺失字段

04 · INDEX建立双路索引

关键词 + 文本语义

05 · SEARCH召回与回表

去重、核权、返回

01

来源传入什么

只传来源引用与业务信息,原文件继续留在来源系统。

图片素材 A

IMAGE · 没有原标题、标签

assets.register
{
  "source_system": "sozai",
  "file_id": "N4q8R2s6.jpg",
  "title": null,
  "tags": [],
  "team_id": null
}

需要先理解内容,再生成可检索的文字。

视频素材 B

VIDEO · 已有原标题、标签

assets.register
{
  "source_system": "ignis",
  "file_id": "X7b2Lm.mp4",
  "title": "一群人在甲板排队",
  "tags": [
    "甲板",
    "排队"
  ],
  "team_id": null
}

已有文字先建立关键词索引;语义随后补齐。

Authorization 在请求头中,身份由服务端上下文取得;不让调用者任意填写 user_id。两例省略 business_type,默认 material;team_id 为 null,表示个人可见。身份校验接口仍待接入。

02

入库到可检索的 9 个步骤

登记响应与异步索引分开;这里展示先后关系,不模拟处理耗时。

  1. STEP 01

    接收登记

    来源适配器用 source_system + file_id 解析媒体类型、基础信息和可读取引用。

  2. STEP 02

    写入关系库

    保存素材、来源、映射与权限;查找或建立可信的统一用户映射。

  3. STEP 03

    可靠接收任务 → 返回

    关系记录已保存,后台任务可靠接收后,返回本库 8 位短 ID;此时索引仍可未完成。

  4. STEP 04

    已有文字先建索引

    视频 B 用原标题与标签创建 keyword_sparse + payload。图片 A 暂无 point。

  5. STEP 05

    Gemini 理解媒体

    图片生成缺失标题、标签和描述;常规视频连音轨输入,已有原标题保留。

  6. STEP 06

    分析结果写回关系库

    description、generated_tags 与必要的 generated_title 更新;写回不等于向量已就绪。

  7. STEP 07

    关键词补齐或更新

    图片 A 首次创建 point;视频 B 更新原有稀疏向量。标签是编码输入。

  8. STEP 08

    生成并补齐语义向量

    内容描述 → 文本 embedding → semantic_dense,用 update_vectors 补到已有 point。

  9. STEP 09

    进入检索流程

    图片、视频各一个 point。先带权限双路召回,再融合并回表核对后返回结果。

登记成功只返回短 ID

两次登记的响应分别为:

{
  "asset_id": "c8a2t7m4"
}
{
  "asset_id": "v6p3k9d2"
}

索引逐步就绪

一个阶段完成,不代表后续阶段已经完成。

阶段图片 A视频 B
登记完成关系记录关系记录
已有文字建索引还没有 point仅关键词向量
Gemini 写回已有描述,等待索引已有描述,等待更新
补齐向量关键词 + 语义关键词 + 语义
03

四种编号,各管一件事

以图片 A 为例。所有编号都是演示用的虚构值。

从来源编号一路找到检索记录

不同来源的相同 file_id 不冲突;以 source_system + source_id 定位。

字段 / 所在位置示例值作用
asset_sources.source_id"N4q8R2s6.jpg"源系统的 file_id,保留原值
asset_sources.id"33333333-3333-4333-8333-333333333333"我们创建的来源记录 UUID
assets.id"11111111-1111-4111-8111-111111111111"内部素材 UUID;也是 Qdrant point.id
assets.asset_id"c8a2t7m4"对外 8 位字母数字短 ID;也是 payload.asset_id
来源 + file_idasset_sources.idasset_mappings.origin_idasset_mappings.asset_idassets.id = point.id

名称相同,但值不同:assets.asset_id 是短 ID;asset_mappings.asset_id 与 asset_access.asset_id 都是内部 UUID,关联 assets.id。

04

关系库里,具体存什么

关系库保存正式记录;Qdrant 保存用于检索的副本。关系库建议使用 PostgreSQL。

以下是内容理解完成后的完整字段快照,共 2 条素材、2 条来源、2 条映射、2 条权限及 1 条模拟统一用户。所有尺寸、时长、大小和时间也都是 mock。窄屏可横向查看表格。

1. assets · 素材表

完整内容理解后的最终记录;原始标题、标签在来源表。

字段 / 类型图片素材 A视频素材 B
id
uuid · PK
"11111111-1111-4111-8111-111111111111""22222222-2222-4222-8222-222222222222"
asset_id
varchar(8) · UNIQUE
"c8a2t7m4""v6p3k9d2"
user_id
uuid → users.user_id
"55555555-5555-4555-8555-555555555555""55555555-5555-4555-8555-555555555555"
media_type
text
"image""video"
business_type
text
"material""material"
generated_title
text?
"小猫歪头照片"null
description
text?
"一只小猫歪头看向镜头,背景为白色。""游戏场景中,多个人物在甲板上依次排队等待。"
generated_tags
text[]
["小猫", "歪头", "白色背景", "照片"]["人物", "游戏画面", "甲板", "排队"]
metadata
jsonb
{"mime_type": "image/jpeg", "width": 800, "height": 800, "size_bytes": 120000}{"mime_type": "video/mp4", "width": 1280, "height": 720, "duration_ms": 30000, "size_bytes": 8000000}
created_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
updated_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
deleted_at
timestamptz?
nullnull

2. asset_sources · 来源表

原生 file_id 写入 source_id,来源记录自己的 UUID 是 id。

字段 / 类型图片素材 A视频素材 B
id
uuid · PK
"33333333-3333-4333-8333-333333333333""44444444-4444-4444-8444-444444444444"
source_id
text · 原生 file_id
"N4q8R2s6.jpg""X7b2Lm.mp4"
original_title
text?
null"一群人在甲板排队"
original_tags
text[]
[]["甲板", "排队"]
source_system
text
"sozai""ignis"
created_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
updated_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
deleted_at
timestamptz?
nullnull

3. asset_mappings · 素材映射表

只保存对应关系。asset_id 与 origin_id 都是内部 UUID。

字段 / 类型图片素材 A视频素材 B
asset_id
uuid · PK/FK → assets.id
"11111111-1111-4111-8111-111111111111""22222222-2222-4222-8222-222222222222"
origin_id
uuid · UNIQUE → asset_sources.id
"33333333-3333-4333-8333-333333333333""44444444-4444-4444-8444-444444444444"
user_id
uuid → users.user_id
"55555555-5555-4555-8555-555555555555""55555555-5555-4555-8555-555555555555"
created_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
deleted_at
timestamptz?
nullnull

4. asset_access · 权限表

两例均为个人范围;团队范围必须同时限定 source_system。

字段 / 类型图片素材 A视频素材 B
asset_id
uuid · PK/FK → assets.id
"11111111-1111-4111-8111-111111111111""22222222-2222-4222-8222-222222222222"
user_id
uuid → users.user_id
"55555555-5555-4555-8555-555555555555""55555555-5555-4555-8555-555555555555"
space_id
text?
nullnull
updated_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
created_at
timestamptz
"2026-09-21T12:00:00Z""2026-09-21T12:00:00Z"
deleted_at
timestamptz?
nullnull

5. users · 统一用户表

演示假设两个账号经过可信映射,属于同一人;不按名称或邮箱擅自合并。

字段类型示例值
user_iduuid · PK"55555555-5555-4555-8555-555555555555"
sozai_idtext? · UNIQUE"66666666-6666-4666-8666-666666666666"
ignis_idtext? · UNIQUE"cmockignisaccount001"
updated_attimestamptz"2026-09-21T12:00:00Z"
created_attimestamptz"2026-09-21T12:00:00Z"
deleted_attimestamptz?null

assets、asset_mappings、asset_access 的 user_id 表示同一个所有者,由同一登记事务保证一致。没有新增文件表、关系血缘表或处理进度字段。space_id 的字符串 "0" 仅保留,首版不表示公共素材。

05

内容如何变成可搜索的索引

整张图片一条 point,整条视频也一条 point;原生 file_id 不存入 payload。

图片 A · 补标题与标签

Gemini 输出示意 · 未执行模型

{
  "generated_title": "小猫歪头照片",
  "description": "一只小猫歪头看向镜头,背景为白色。",
  "generated_tags": [
    "小猫",
    "歪头",
    "白色背景",
    "照片"
  ]
}

视频 B · 保留原标题

Gemini 输出示意 · 未执行模型

{
  "generated_title": null,
  "description": "游戏场景中,多个人物在甲板上依次排队等待。",
  "generated_tags": [
    "人物",
    "游戏画面",
    "甲板",
    "排队"
  ]
}

keyword_sparse · 关键词向量

标题 + 描述 + 原标签 + 生成标签 → 分词与权重编码

小猫 / 歪头 / 照片稀疏特征
{
  "indices": [
    101,
    104,
    106
  ],
  "values": [
    1.0,
    0.8,
    0.6
  ]
}

特征编号与权重均为 mock。编号不是素材 ID;查询和入库必须使用相同词项编码规则。

semantic_dense · 语义向量

媒体 → Gemini 内容描述 → 文本 embedding

[
  0.12,
  -0.08,
  0.43,
  0.21
]

仅用 4 维 mock 展示数组结构,柱高表示绝对值。最终维度、模型与距离函数尚未选定。

两套向量索引 + 五个标量索引

collection 准备阶段先建筛选索引,再开始正式入库。

字段索引类型用途
keyword_sparse稀疏向量索引按关键词相关性召回
semantic_denseHNSW 向量索引按语义相似性召回
user_iduuid payload 索引所有者范围
source_systemkeyword payload 索引来源与团队命名空间
space_idkeyword payload 索引来源系统内的共享团队
media_typekeyword payload 索引图片、视频等类型
business_typekeyword payload 索引素材、创意源、成片

payload 仅 6 个字段:asset_id、user_id、source_system、space_id、media_type、business_type。其中 asset_id 暂不另建 payload 索引。tags 参与编码,不是第三套向量,也不复制到 payload。

图片 A 的完整 point

point.id 与关系库 assets.id 完全相同。

展开完整 point JSON
{
  "id": "11111111-1111-4111-8111-111111111111",
  "vector": {
    "keyword_sparse": {
      "indices": [
        101,
        104,
        106
      ],
      "values": [
        1.0,
        0.8,
        0.6
      ]
    },
    "semantic_dense": [
      0.12,
      -0.08,
      0.43,
      0.21
    ]
  },
  "payload": {
    "asset_id": "c8a2t7m4",
    "user_id": "55555555-5555-4555-8555-555555555555",
    "source_system": "sozai",
    "space_id": null,
    "media_type": "image",
    "business_type": "material"
  }
}

视频 B 的完整 point

point.id 与关系库 assets.id 完全相同。

展开完整 point JSON
{
  "id": "22222222-2222-4222-8222-222222222222",
  "vector": {
    "keyword_sparse": {
      "indices": [
        201,
        202,
        208
      ],
      "values": [
        1.0,
        1.2,
        0.8
      ]
    },
    "semantic_dense": [
      -0.2,
      0.69,
      0.34,
      -0.15
    ]
  },
  "payload": {
    "asset_id": "v6p3k9d2",
    "user_id": "55555555-5555-4555-8555-555555555555",
    "source_system": "ignis",
    "space_id": null,
    "media_type": "video",
    "business_type": "material"
  }
}

索引就绪前,semantic_dense 字段省略,不写零向量。首次创建 point 后再补向量;已有 point 使用 update_vectors,避免整条替换时清除另一套向量。

处理边界与时效

已有文字的关键词索引目标为 1 分钟内;图片/常规短视频语义索引目标为 10 分钟内;在线检索目标为秒级。这些是设计目标,本页没有性能测试或实时处理。

无标题、无标签时,先由 Gemini 补齐,不设 1 分钟硬性期限;已取消固定 5 分钟解析超时。超长视频按可配置阈值分块,保留声音,成功块复用、失败块重试,再由 LLM 合并整片描述、标题和标签。最终仍是一个素材、一个 point。

具体模型、分块时长、运行超时、重试参数和融合算法尚待评估;任务/对话提示词暂不参与搜索。