图片素材 A
IMAGE · 没有原标题、标签
{
"source_system": "sozai",
"file_id": "N4q8R2s6.jpg",
"title": null,
"tags": [],
"team_id": null
}需要先理解内容,再生成可检索的文字。
用“图片素材 A”和“视频素材 B”两组模拟数据,沿着 ID 看清入库、内容理解、索引建立,以及混合检索返回的全过程。
保存来源、归属和权限
任务已可靠接收
生成描述与缺失字段
关键词 + 文本语义
去重、核权、返回
只传来源引用与业务信息,原文件继续留在来源系统。
IMAGE · 没有原标题、标签
{
"source_system": "sozai",
"file_id": "N4q8R2s6.jpg",
"title": null,
"tags": [],
"team_id": null
}需要先理解内容,再生成可检索的文字。
VIDEO · 已有原标题、标签
{
"source_system": "ignis",
"file_id": "X7b2Lm.mp4",
"title": "一群人在甲板排队",
"tags": [
"甲板",
"排队"
],
"team_id": null
}已有文字先建立关键词索引;语义随后补齐。
Authorization 在请求头中,身份由服务端上下文取得;不让调用者任意填写 user_id。两例省略 business_type,默认 material;team_id 为 null,表示个人可见。身份校验接口仍待接入。
登记响应与异步索引分开;这里展示先后关系,不模拟处理耗时。
来源适配器用 source_system + file_id 解析媒体类型、基础信息和可读取引用。
保存素材、来源、映射与权限;查找或建立可信的统一用户映射。
关系记录已保存,后台任务可靠接收后,返回本库 8 位短 ID;此时索引仍可未完成。
视频 B 用原标题与标签创建 keyword_sparse + payload。图片 A 暂无 point。
图片生成缺失标题、标签和描述;常规视频连音轨输入,已有原标题保留。
description、generated_tags 与必要的 generated_title 更新;写回不等于向量已就绪。
图片 A 首次创建 point;视频 B 更新原有稀疏向量。标签是编码输入。
内容描述 → 文本 embedding → semantic_dense,用 update_vectors 补到已有 point。
图片、视频各一个 point。先带权限双路召回,再融合并回表核对后返回结果。
两次登记的响应分别为:
{
"asset_id": "c8a2t7m4"
}{
"asset_id": "v6p3k9d2"
}一个阶段完成,不代表后续阶段已经完成。
| 阶段 | 图片 A | 视频 B |
|---|---|---|
| 登记完成 | 关系记录 | 关系记录 |
| 已有文字建索引 | 还没有 point | 仅关键词向量 |
| Gemini 写回 | 已有描述,等待索引 | 已有描述,等待更新 |
| 补齐向量 | 关键词 + 语义 | 关键词 + 语义 |
以图片 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 |
名称相同,但值不同:assets.asset_id 是短 ID;asset_mappings.asset_id 与 asset_access.asset_id 都是内部 UUID,关联 assets.id。
关系库保存正式记录;Qdrant 保存用于检索的副本。关系库建议使用 PostgreSQL。
以下是内容理解完成后的完整字段快照,共 2 条素材、2 条来源、2 条映射、2 条权限及 1 条模拟统一用户。所有尺寸、时长、大小和时间也都是 mock。窄屏可横向查看表格。
assets · 素材表完整内容理解后的最终记录;原始标题、标签在来源表。
| 字段 / 类型 | 图片素材 A | 视频素材 B |
|---|---|---|
iduuid · PK | "11111111-1111-4111-8111-111111111111" | "22222222-2222-4222-8222-222222222222" |
asset_idvarchar(8) · UNIQUE | "c8a2t7m4" | "v6p3k9d2" |
user_iduuid → users.user_id | "55555555-5555-4555-8555-555555555555" | "55555555-5555-4555-8555-555555555555" |
media_typetext | "image" | "video" |
business_typetext | "material" | "material" |
generated_titletext? | "小猫歪头照片" | null |
descriptiontext? | "一只小猫歪头看向镜头,背景为白色。" | "游戏场景中,多个人物在甲板上依次排队等待。" |
generated_tagstext[] | ["小猫", "歪头", "白色背景", "照片"] | ["人物", "游戏画面", "甲板", "排队"] |
metadatajsonb | {"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_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
updated_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
deleted_attimestamptz? | null | null |
asset_sources · 来源表原生 file_id 写入 source_id,来源记录自己的 UUID 是 id。
| 字段 / 类型 | 图片素材 A | 视频素材 B |
|---|---|---|
iduuid · PK | "33333333-3333-4333-8333-333333333333" | "44444444-4444-4444-8444-444444444444" |
source_idtext · 原生 file_id | "N4q8R2s6.jpg" | "X7b2Lm.mp4" |
original_titletext? | null | "一群人在甲板排队" |
original_tagstext[] | [] | ["甲板", "排队"] |
source_systemtext | "sozai" | "ignis" |
created_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
updated_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
deleted_attimestamptz? | null | null |
asset_mappings · 素材映射表只保存对应关系。asset_id 与 origin_id 都是内部 UUID。
| 字段 / 类型 | 图片素材 A | 视频素材 B |
|---|---|---|
asset_iduuid · PK/FK → assets.id | "11111111-1111-4111-8111-111111111111" | "22222222-2222-4222-8222-222222222222" |
origin_iduuid · UNIQUE → asset_sources.id | "33333333-3333-4333-8333-333333333333" | "44444444-4444-4444-8444-444444444444" |
user_iduuid → users.user_id | "55555555-5555-4555-8555-555555555555" | "55555555-5555-4555-8555-555555555555" |
created_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
deleted_attimestamptz? | null | null |
asset_access · 权限表两例均为个人范围;团队范围必须同时限定 source_system。
| 字段 / 类型 | 图片素材 A | 视频素材 B |
|---|---|---|
asset_iduuid · PK/FK → assets.id | "11111111-1111-4111-8111-111111111111" | "22222222-2222-4222-8222-222222222222" |
user_iduuid → users.user_id | "55555555-5555-4555-8555-555555555555" | "55555555-5555-4555-8555-555555555555" |
space_idtext? | null | null |
updated_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
created_attimestamptz | "2026-09-21T12:00:00Z" | "2026-09-21T12:00:00Z" |
deleted_attimestamptz? | null | null |
users · 统一用户表演示假设两个账号经过可信映射,属于同一人;不按名称或邮箱擅自合并。
| 字段 | 类型 | 示例值 |
|---|---|---|
user_id | uuid · PK | "55555555-5555-4555-8555-555555555555" |
sozai_id | text? · UNIQUE | "66666666-6666-4666-8666-666666666666" |
ignis_id | text? · UNIQUE | "cmockignisaccount001" |
updated_at | timestamptz | "2026-09-21T12:00:00Z" |
created_at | timestamptz | "2026-09-21T12:00:00Z" |
deleted_at | timestamptz? | null |
assets、asset_mappings、asset_access 的 user_id 表示同一个所有者,由同一登记事务保证一致。没有新增文件表、关系血缘表或处理进度字段。space_id 的字符串 "0" 仅保留,首版不表示公共素材。
整张图片一条 point,整条视频也一条 point;原生 file_id 不存入 payload。
Gemini 输出示意 · 未执行模型
{
"generated_title": "小猫歪头照片",
"description": "一只小猫歪头看向镜头,背景为白色。",
"generated_tags": [
"小猫",
"歪头",
"白色背景",
"照片"
]
}Gemini 输出示意 · 未执行模型
{
"generated_title": null,
"description": "游戏场景中,多个人物在甲板上依次排队等待。",
"generated_tags": [
"人物",
"游戏画面",
"甲板",
"排队"
]
}标题 + 描述 + 原标签 + 生成标签 → 分词与权重编码
{
"indices": [
101,
104,
106
],
"values": [
1.0,
0.8,
0.6
]
}特征编号与权重均为 mock。编号不是素材 ID;查询和入库必须使用相同词项编码规则。
媒体 → Gemini 内容描述 → 文本 embedding
[
0.12,
-0.08,
0.43,
0.21
]仅用 4 维 mock 展示数组结构,柱高表示绝对值。最终维度、模型与距离函数尚未选定。
collection 准备阶段先建筛选索引,再开始正式入库。
| 字段 | 索引类型 | 用途 |
|---|---|---|
| keyword_sparse | 稀疏向量索引 | 按关键词相关性召回 |
| semantic_dense | HNSW 向量索引 | 按语义相似性召回 |
| user_id | uuid payload 索引 | 所有者范围 |
| source_system | keyword payload 索引 | 来源与团队命名空间 |
| space_id | keyword payload 索引 | 来源系统内的共享团队 |
| media_type | keyword payload 索引 | 图片、视频等类型 |
| business_type | keyword payload 索引 | 素材、创意源、成片 |
payload 仅 6 个字段:asset_id、user_id、source_system、space_id、media_type、business_type。其中 asset_id 暂不另建 payload 索引。tags 参与编码,不是第三套向量,也不复制到 payload。
point.id 与关系库 assets.id 完全相同。
{
"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"
}
}point.id 与关系库 assets.id 完全相同。
{
"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,避免整条替换时清除另一套向量。
两路召回保留各自命中信息,正式结果必须经过关系库复核。
请求示例 · assets.search
{
"query": "甲板上排队的游戏画面",
"media_type": "video",
"limit": 8
}“甲板 / 排队 / 游戏画面” → 查询稀疏向量 → 命中视频 B
v6p3k9d2完整 query → 兼容的文本 embedding → 命中视频 B
v6p3k9d2两路带相同的服务端授权条件。本例身份由模拟认证上下文取得,不由 query 参数指定。
候选内部 UUID 进入关系库核对,最终只返回可见短 ID。
一群人在甲板排队
v6p3k9d2标题优先 original_title,否则 generated_title;results 内同一素材仅出现一次。keyword 与 semantic 可以重叠。
命中数组仅列当前页结果的短 ID;不向调用者输出内部 UUID 或原生 file_id 作为素材身份。
{
"results": [
{
"asset_id": "v6p3k9d2",
"source_system": "ignis",
"media_type": "video",
"business_type": "material",
"title": "一群人在甲板排队",
"description": "游戏场景中,多个人物在甲板上依次排队等待。",
"tags": [
"甲板",
"排队",
"人物",
"游戏画面"
],
"metadata": {
"mime_type": "video/mp4",
"width": 1280,
"height": 720,
"duration_ms": 30000,
"size_bytes": 8000000
}
}
],
"keyword": [
"v6p3k9d2"
],
"semantic": [
"v6p3k9d2"
],
"next_cursor": null
}query:按次序等候轮到自己
预设结果仍是视频 B,但关键词路线未命中。此例只解释返回结构,不代表已验证真实召回质量。
{
"keyword": [],
"semantic": [
"v6p3k9d2"
],
"next_cursor": null
}上方仅摘录命中字段,完整响应仍包含 results。
浏览最近登记的可见素材
直接走关系库列表与稳定分页,不生成查询向量。
{
"keyword": [],
"semantic": [],
"next_cursor": null
}结果仍在 results;next_cursor 是否为空取决于有无下一页。
已有文字的关键词索引目标为 1 分钟内;图片/常规短视频语义索引目标为 10 分钟内;在线检索目标为秒级。这些是设计目标,本页没有性能测试或实时处理。
无标题、无标签时,先由 Gemini 补齐,不设 1 分钟硬性期限;已取消固定 5 分钟解析超时。超长视频按可配置阈值分块,保留声音,成功块复用、失败块重试,再由 LLM 合并整片描述、标题和标签。最终仍是一个素材、一个 point。
具体模型、分块时长、运行超时、重试参数和融合算法尚待评估;任务/对话提示词暂不参与搜索。