黄鑫AI LAB
AI EXPERIMENT / FASHION-ITEM-MATCHERLIVE

穿搭同款搜索系统

面向内容投放的服饰同款检索系统,负责向量索引层、Kafka CDC 入库流水线、价格过滤与 AI 成本治理。基于 FastAPI、Elasticsearch nested dense_vector 和多模态模型,支撑 12 万+ 商品、21 万+ SKU 向量的图搜同款、文搜选品与内容风格匹配。

模型 / 服务
Qwen3-VL-Embedding-2B / 云端 VLM / DeepSeek
技术栈
Python · FastAPI · Elasticsearch dense_vector · Kafka · Redis · Vue 3 · Qwen3-VL-Embedding · VLM · DeepSeek
状态
LIVE

项目背景

该系统面向种草内容投放:输入博主穿搭图后拆分其中的服饰单品,再从商品池中检索同一件或高度相似的商品,供上游完成选品与内容拼接。同时提供文搜选品、内容风格匹配和投放前价格校验能力。

系统以 FastAPI 提供服务,使用 Elasticsearch 承载向量与标量属性,Kafka 驱动商品、SKU、内容和返利标记的增量同步,并通过多节点 Embedding 服务和云端 VLM 完成拆图、打标、向量化与精排。

我的职责

项目由两人共同建设。我主要负责 向量索引层、入库数据流水线、价格过滤、AI 成本治理、数据运营工具和对外接口;排序融合、穿搭联合选品和评测平台由团队协作完成,不作为我的个人主导成果。

核心工作

1. 向量检索底座迁移

初版使用 Milvus 存储向量、CLIP 负责编码,中文服饰语义效果有限,类目、价格和店铺过滤还需要回查关系库,召回与过滤口径难以保持一致。

我推动迁移到 Qwen3-VL-Embedding 与 Elasticsearch dense_vector:图文进入同一向量空间,向量和标量属性落在同一文档中,通过 kNN filter 一次完成召回与业务过滤。写入侧统一进行 L2 归一化,并使用 dot product 降低高维查询中的重复归一化开销。

2. nested 多向量索引

老索引采用“一品一向量”,套装只保留主要单品,多色 SKU 也共用一个向量,导致套装中的次要单品和颜色精确匹配无法召回。

我设计了商品父文档加 SKU/单件 nested 向量的索引结构:每个单件同时保存图片向量、属性文本向量及件级标签,召回结果天然按商品去重。针对 nested kNN 父文档得分来源不明确的问题,通过 inner_hits 选择与查询类目一致的命中单件,并将分数、图片、类目和标签统一对齐到后续精排链路;同时扩展套装召回类目,避免过滤阶段漏掉套装内的目标单品。

3. SKU 粒度向量化流水线

我参与建设从 SKU 数据到向量索引的完整编码链路:

  1. 使用 LLM 对同款同色 SKU 去重,异常时 fail-open;
  2. 按图片分组,避免同图 SKU 重复处理;
  3. 单品通过 VLM 选图、主体裁剪、件级打标和编码;
  4. 套装根据标题引导拆件,再逐件打标和编码;
  5. 使用每个 SKU 自己的图片与颜色锚点,修复类目串味、颜色误判和规格文本污染。

将属性打标与商品简称合并为一次 VLM 调用后,入库阶段相关调用次数减少约一半。

4. Kafka CDC 自动化入库

从 0 搭建商品、SKU、内容和返利商品标记四条增量消费链。为应对上游批量更新产生的消息风暴,将 poll 与业务处理分离,使用固定 worker 池和信号量限制 VLM、Embedding 并发;同一商品通过任务级去重与 pending 补偿保证“不重复烧模型,也不丢最新状态”,并关闭自动 offset 提交,改为处理进度可控的手动提交。

nested 文档只能整条覆盖写。为避免 Kafka 更新冲掉运营手动换图、置顶或软删状态,写入前回读人工态字段并合并,同时区分运营手动删除与系统自动删除,防止已下架商品被增量消息静默恢复。

5. 价格过滤体系

将平台价格区间、类目规则和运营排除名单统一收敛到单一判定函数,平台与类目范围取交集、排除名单取并集。搜索链路在 ES 召回、SKU 选择和结果装配三层执行过滤,对外批量校验接口复用同一规则,但针对“价格未知”采用不同的风险口径。

价格按 SKU 粒度判定,并明确整数价格桶和小数精确匹配语义,避免后台配置与实际生效规则不一致。

6. AI 成本计量与治理

建立按模型、阶段和来源拆分的 Token 明细、日汇总和费用估算看板,让打标、拆图、去噪、选图、精排、查询理解与 SKU 去重的调用成本可以追踪。基于计量结果将高频低难度阶段切换到轻量模型,使相关阶段成本降至约原来的 1/7;结合缓存、SKU 去重及合并调用继续降低重复消耗。

同时明确统计边界:异常调用与取消调用可能无法完整反映真实计费,避免后续使用方把成本表错误理解为模型成功率数据源。

7. 内容检索与运营工具

从 0 建设内容风格检索模块,通过 VLM 归一化性别、风格、场景、季节和色调,结合向量召回、季节兼容过滤及结果不足时的降级重搜;增加多宫格与人脸完整性检查,并在随机选取前执行价格过滤。

配套提供 SKU 换图与回滚、上下架和废弃原因、批量回刷与断点续传、数据同步接口、飞书异常告警、定时统计和运行时配置页面,使索引质量问题可以被运营直接发现和修复。

关键难点

  • 得分归属:nested kNN 返回父文档,必须从 inner_hits 对齐真正命中的单件,否则可能出现“搜裤子却拿套装上衣去精排”的全链路错位;
  • 人工状态保护:整文档覆盖写成功但悄悄恢复已删除商品,属于没有报错的静默故障,需要在写入前显式合并人工态;
  • 消息风暴:瞬时大量 CDC 同时占用 VLM 与 Embedding,会拖垮主服务,需要并发限制、任务去重、pending 补偿和可靠 offset 共同处理;
  • 配置可见性:环境变量、数据库和代码默认值存在多层优先级,必须让“被覆盖、只读或需要重启”的状态在后台可见,避免保存成功但实际不生效。

项目结果

  • 商品数据池达到 12 万+,维护 21 万+ SKU 向量和 2 万+ 内容向量;
  • 多向量索引有效覆盖 5 万+ 商品,支持套装次要单品与多色 SKU 召回,并完成单向量老链路下线;
  • 入库链路打标与简称合并后,相关 VLM 调用次数减少约一半;
  • 去噪、选图和分类等阶段切换轻量模型后,成本降至约原来的 1/7;
  • 内容投放过滤在抽样验证中通过率达到 91.5%,响应保留过滤明细便于问题定位。

以上数据为项目阶段性统计并按公开口径取整;页面不展示内部系统名称、Topic、密钥、接口地址和具体业务金额。

技术栈

Python · FastAPI · Elasticsearch · Kafka · Redis · MySQL · Vue 3 · Qwen3-VL-Embedding · VLM · DeepSeek