图片素材检索设计

📅 发布于 2026-10-17 14:00:00 🔄 更新于 2026-10-17 14:00:00
⏱️ 阅读时间 21 min read 📝 字数 4941 👁️ 阅读量 Loading...

图片素材如何“既搜得准,又搜得全”:我们的混合检索设计

在游戏、营销页面和 AI 应用的生成过程中,图片素材检索看起来只是“根据一句描述找几张图”,实际上却是一个典型的多目标问题:用户既希望系统准确理解“我要什么”,又希望它严格避开“我不要什么”;既不能漏掉语义相近但用词不同的素材,也不能因为语义大致相似,就忽略角色身份、画风、用途等明确要求。

单靠关键词,往往搜不全;单靠向量,又容易搜得“差不多但不对”。因此,我们将图片素材检索设计为一套分层的混合检索系统:关键词检索与文本向量检索并行召回,通过 RRF 融合排名,再执行否定条件、业务规则和置信度复核。

一、图片素材检索为什么比普通搜索更难

普通站内搜索通常围绕标题、正文和分类展开,而图片素材的检索意图更加复合。例如:

古代年轻女性主角,黑色长发,气质清冷,正面人物立绘,不要 Q 版,也不要反派感。

这句话里至少包含四类信息:

  • 主体事实:年轻女性、黑色长发;
  • 视觉语义:古代、清冷、疏离;
  • 使用意图:主角立绘、正面构图;
  • 否定约束:不要 Q 版、不要反派气质。

这些条件的“硬度”并不相同。有些是必须满足的,有些只是排序偏好,还有些一旦命中就必须排除。更麻烦的是,素材库里的名称、标签、分类和描述不一定始终完整、统一、准确。如果把某个字段永久写成硬过滤条件,元数据中的一次错误就可能让一张本来合适的图片永远无法被召回。

所以,素材搜索不能只回答“它和查询像不像”,还必须回答:

  1. 它是否满足必须条件?
  2. 它是否命中了禁止条件?
  3. 当前证据是否足够可靠?
  4. 它是同一主体的另一个状态,还是一个全新的候选?

二、为什么不选择单一检索方式

1. 纯关键词检索:准确,但容易漏

关键词检索擅长处理明确词语和精确事实。例如用户写了“黑色长发”,素材名称或标签中也出现了“黑发”,系统可以给出清晰、可解释的命中结果。

但它对表达差异非常敏感。“清冷”“疏离”“冷淡气质”在语义上接近,字面却并不相同;“庭院夜景”和“月下院落”也可能指向同一种画面。没有同义词扩展时,纯关键词检索很容易漏掉真正合适的素材。

2. 纯向量检索:搜得全,但边界不够硬

文本向量能够理解整体语义和同义表达。即使查询与素材描述没有相同字词,也可能根据语义相似度把候选找出来。

它的问题是“相似”不等于“符合”。向量可能认为 Q 版少女和写实少女语义接近,也可能把配角、反派与主角立绘排在一起。尤其面对精确属性、否定要求和业务规则时,单一相似度分数不足以承担最终判断。

3. 先后串行召回:会被第一路检索限制

我们也排除了两种看似简单的串行方案:

  • 先关键词召回,再只对关键词结果做向量排序;
  • 先向量召回,再只对向量结果做关键词排序。

两者都有同一个问题:第二路检索只能在第一路已经找出的候选里工作。第一路漏掉的素材,后面再聪明也补不回来。

因此,两路检索必须独立、并行地召回候选。

三、总体架构:召回、融合、复核分层负责

完整链路如下:

当前素材位置的检索需求
↓
查询理解与条件拆分
↓
┌──────────────────┬──────────────────┐
│ 关键词检索 │ 文本向量检索 │
│ 独立召回候选 │ 独立召回候选 │
└──────────────────┴──────────────────┘
↓
候选合并与去重
↓
RRF 排名融合
↓
否定条件与业务规则复核
↓
置信度过滤
↓
主体组内选择具体变体
↓
返回素材候选

这里最重要的设计思想是:不要让一个分数解决所有问题。

  • 关键词检索负责精确词语和可解释命中;
  • 向量检索负责同义表达和整体语义;
  • RRF 只负责融合两路排名;
  • 规则层负责必须满足和必须排除的条件;
  • 置信度层决定结果是否值得展示或自动推荐;
  • 应用前复核负责确认素材仍然有效。

每一层只承担自己擅长的职责,整个系统才更容易调试、解释和降级。

四、查询不是一段话,而是一组不同强度的条件

如果把整段对话历史直接生成一个向量,其他角色、场景、修改过程和无关信息都会污染当前素材位置。因此,我们以“素材槽位”为单位生成独立查询。

例如,女主角立绘可以整理为:

{
"slotKey": "characters.heroine.portrait",
"vectorQueryText": "古代年轻女性主角,黑色长发,气质清冷疏离,正面人物立绘",
"negativeConstraints": ["Q版", "反派气质"],
"usageIntent": "游戏女主角立绘"
}

同时,条件还可以按强度划分为四类:

强度含义示例
MUST必须满足,否则不返回必须是人物立绘
SHOULD满足则加分,不满足仍可参与更偏清冷气质
MUST_NOT命中后排除不要 Q 版
IGNORE当前字段不可靠,不参与判断尚未完成治理的旧分类

这种动态条件模型比把分类、画风或标签永久写死在代码中更稳健。字段可信时可以参与约束;字段不可信时可以降级为排序信号,甚至临时忽略。

五、两路召回分别解决什么问题

1. 关键词召回

关键词检索可以覆盖素材名称、运营确认标签、检索描述、分类等可靠文本,并对不同字段设置不同权重。例如,名称命中通常比长描述中的一次偶然命中更可信。

它的价值主要体现在:

  • 保留精确名词和明确属性;
  • 支持业务可解释性;
  • 在向量服务不可用时提供可降级的基础结果;
  • 为必须精确匹配的条件提供证据。

2. 文本向量召回

向量检索将查询和素材描述映射到同一语义空间,用相似度找出表达不同但含义接近的素材。它主要用于处理:

  • 同义词和近义表达;
  • 人物、场景、画风与氛围的整体语义;
  • 用户语言与运营描述没有共同字词的情况;
  • 元数据不够规范时的容错召回。

素材侧向量应在入库、发布或信息变化后离线生成。在线检索时,只需批量生成各素材槽位的查询向量,并从既有索引中召回候选,不能临时对整个素材库重新向量化。

素材向量与查询向量还必须使用同一个 Embedding 模型、版本和维度。索引中应记录模型标识、模型版本、向量维度、源文本哈希和生成状态,避免模型升级后出现“不同坐标系里的向量被直接比较”的问题。

六、用 RRF 融合排名,而不是生硬地混合分数

关键词得分和向量相似度通常不在同一量纲上:一个可能是字段加权后的整数,另一个可能是 0 到 1 之间的余弦相似度。直接把两者相加,容易让分数标定和权重调节变得脆弱。

因此,我们采用 RRF(Reciprocal Rank Fusion,倒数排名融合),更关注候选在每一路结果中的名次:

RRF 分数 =
关键词权重 / (k + 关键词排名)
+ 向量权重 / (k + 向量排名)

如果一张素材在关键词和向量结果中都排在前面,它会获得稳定的高分;如果它只被其中一路发现,也仍有机会进入最终候选。这正是独立并行召回的价值。

但必须强调:RRF 不是最终裁判。它不负责判断强制条件、不负责处理否定条件,也不代表结果已经达到最低相关性。关键词权重、向量权重和参数 k 也不能凭经验拍定,需要通过真实查询集和人工标注持续调节。

七、否定条件必须从正向向量中拆出来

“不要 Q 版”不能直接拼进正向查询文本。Embedding 模型会感知其中的“Q 版”概念,反而可能提高 Q 版素材被召回的概率。

所以,正向需求与否定条件必须分开处理:

  • vectorQueryText 只描述希望出现的内容;
  • negativeConstraints 独立保存,在候选召回后判断;
  • 明确命中禁止内容的候选直接排除;
  • 证据不足的候选不能被当作已经满足条件。

否定判断使用三值结果更安全:

结果含义
MATCH有可靠证据表明候选包含禁止内容
NOT_MATCH有可靠证据表明候选不包含禁止内容
UNKNOWN当前证据不足,无法确定

其中,UNKNOWN 不是“通过”。它可以根据业务风险进入降权、备用候选或禁止自动选中等不同策略。

判断证据可以来自运营确认标签、可靠结构化字段、图片分析描述、否定概念向量,未来还可以增加图片视觉模型复核。关键词命中只是证据之一,不能代替完整的否定条件判断。

八、为什么先找“素材主体”,再选“具体变体”

图片素材常常不是彼此完全独立的。一名角色可能有普通、微笑、愤怒、受伤等多个变体;同一场景也可能有白天、夜晚、雨天等状态。

如果把全部图片平铺排序,同一主体的多个变体很容易占满候选名额。用户看到的可能是同一个角色的五种表情,而不是五个不同角色。这既降低了选择效率,也无法稳定表达“更换主体”和“切换状态”是两个不同动作。

因此,我们采用两阶段检索:

  1. 主体组检索:先按类型、分类、画风、名称、描述和标签排列不同素材主体;
  2. 组内变体选择:命中主体后,再根据状态要求选择具体图片;没有明确状态要求时使用运营设置的默认变体。

这样,同一主体的多个变体只占一个主体候选位置,既提高了候选多样性,也与前端“主卡推荐一个主体、抽屉内切换主体或变体”的交互保持一致。

九、检索成功不等于可以直接应用

素材从“被搜索到”到“写入项目”之间还要经过一道应用前复核。原因很现实:用户浏览和确认方案期间,素材可能被下架,图片可能失效,所属主体可能发生变化,组合资格也可能被撤销。

应用前至少需要重新确认:

  • 候选素材仍然存在;
  • 仍属于原素材主体;
  • 仍处于已发布、分析成功和可组合状态;
  • 已确定的强制约束仍然满足;
  • 当前内容包和素材槽位没有发生冲突性变化。

如果某个候选失效,只应阻止对应槽位应用,并把失败原因明确返回给用户。系统不能静默换成另一张图,也不应让一个槽位失效导致整套方案全部作废。

同样需要区分两个常被混淆的状态:

  • 素材槽位缺口:检索正常完成,但素材库中没有合适候选;
  • 素材检索技术失败:请求参数、服务或项目配置异常,检索并未有效完成。

前者可以引导用户调整条件,或由用户明确触发 AI 生图;后者应停止流程、暴露错误并修复重试,不能偷偷用生图掩盖系统故障。

十、在线性能与故障降级

混合检索并不意味着把所有重计算都放到在线请求中。合理的性能边界是:

离线阶段

  • 生成并维护素材标准检索文本;
  • 生成素材文本向量;
  • 建立关键词索引和向量索引;
  • 在素材发布、内容变化或模型升级后增量重建;
  • 保存向量版本与源文本哈希,支持审计和重算。

在线阶段

  • 按素材槽位拆分查询;
  • 批量生成查询向量;
  • 并行执行关键词和向量召回;
  • 合并去重并进行 RRF 排名;
  • 对少量候选执行规则与置信度复核;
  • 按主体折叠并选择变体。

由于两路召回可以并行执行,整体耗时主要由较慢的一路决定,而不是简单相加。系统还应具备清晰的降级策略:向量服务异常时可以退回关键词结果;后续如果增加精排模型,精排超时也应退回普通混合排序,而不是让整个检索不可用。

十一、我们如何评估“搜得更好”

检索效果不能只靠几次人工体验判断。需要建立包含真实素材槽位、正向需求、否定条件和人工相关性标注的测试集,至少关注以下指标:

  • Recall@K:合适素材是否进入前 K 个候选;
  • Precision@K:前 K 个候选中有多少真正符合要求;
  • MRR / NDCG:最佳候选是否排得足够靠前;
  • 否定条件误入率:禁止内容进入结果的比例;
  • 主体多样性:前 K 个结果是否被同一主体的变体占满;
  • 槽位缺口率:必需素材位置最终没有候选的比例;
  • 检索耗时:P50、P95 和超时率;
  • 用户更换率:首选推荐被用户更换的比例。

尤其要保留“为什么命中”和“为什么被排除”的诊断信息。没有可解释的日志,就很难判断问题出在查询拆分、素材描述、关键词召回、向量召回、融合参数,还是业务复核。

文本向量解决的是“描述方式不同”,图片向量进一步解决的是“文字写错了,但图片本身其实符合”。两者不是互相替代,而是逐步提高检索上限。

我们的核心结论可以概括为一句话:

关键词检索与文本向量检索并行召回,通过 RRF 融合,再执行否定条件、业务规则和置信度复核;结果先落到素材主体,再在主体内选择具体变体。

混合检索的真正价值,不只是让结果“看起来更智能”,而是让系统在召回率、准确率、可解释性、性能和工程可控性之间取得一个可以持续演进的平衡。

图片素材检索设计

作者:felinus

本文链接: https://felinus-blog.vercel.app/posts/f444294740/

本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。