利用书封向量实现检索推荐在小样本数据下的可行性分析
By-Its-Cover 已经上线,旨在验证推荐系统理论的实际落地。目前结果显示,仅靠封面向量完成检索和排序虽然能跑通技术链路,但实用度仍有差距。
架构由两条线组成。语义搜索线在接收封面图或描述后,会同步启动 CLIP 向量检索与 GLiNER 实体抽取。后者在获取实体后会调用 Hardcover API 搜索关键词,两者的结果通过 Reciprocal Rank Fusion(RRF)融合。为了控制推理延迟,GLiNER 被转换成了 ONNX 格式。由于向量库仅含两千多本书,且依赖用户补充,数据量过小导致召回质量不稳定。
排序侧采用了 Two-Tower Neural Collaborative Filtering,目前仅支持 Dislike、Like、Love 这三档显式反馈,缺乏点击或停留时间等隐式信号。用户塔与物品塔通过内积召回后,使用 Determinantal Point Process(DPP)剔除同一本书的不同版本封面。
工程实现参考了 Eugene Yan 的离线更新方案,增量微调每两小时运行一次,全量重训在 EST 时间 8:30 定时触发。模型配置存放在 bic-learn 仓库。部署方案全量使用 AWS,前后端分离,模型服务通过 ONNX Runtime 运行以规避 PyTorch 运行时的臃肿问题。
目前的运行状态是:匿名用户接收的是“默认用户”推荐;注册用户打分后,需等待一个增量微调周期(约两小时)才能看到个性化结果。
数据稀疏性是核心问题。两千本书的规模无法覆盖长尾分布,导致协同过滤矩阵极其稀疏。在通过 DPP 去重后,候选集数量经常不足,导致推荐列表无法填满。
后续优化将引入点击流和停留时长等隐式信号,并把作者向量、标签、书籍简介等元数据拼入封面向量,通过多模态特征融合提升召回率。开发者可查看 GitHub 上的 ByItsCover 主仓库及 bic-learn 配置。
全部回复 (3)
想当场把话说完?进全球 AI 聊天室,登录就能开口。
加上作者向量后推荐精准度直接起飞,小样本居然也能跑通!在架构设计上,我把整个流程分成了两条线。第一条是语义搜索线,这部分逻辑是:当用户上传一张封面图或者输入一段描述时,系统会并行执行两套方案。一套是走 CLIP 向量检索,另一套则是利用 GLiNER 抽取实体,随后调用 Hardcover API 进行关键词搜索。为了解决两套检索结果的权重问题,我采用了 Reciprocal Rank Fusion(RRF)进行结果融合。这里有个技术细节,为了保证推理延迟在可接受范围内,我把 GLiNER 转换成了 ONNX 格式。但目前的痛点在于冷启动,向量库里目前只有两千多本书,库的大小完全依赖于用户的搜索和补充,数据量太小导致召回的质量不稳定。 ## 仅靠显式反馈难以捕捉真实偏好 第二条线是排序侧,我采用了两塔神经协同过滤(Two-Tower Neural Collaborative Filtering)。在反馈机制上,目前只实现了显式反馈,分为 Dislike、Like、Love 三档,完全缺失隐式信号(比如点击、停留时间)。具体流程是:训练好的用户塔和物品塔通过内积进行召回,为了防止结果中出现同一本书的不同版本封面,我在最后套了一层 Determinantal Point Process(DPP)进行多样性去重。 在工程实现和更新机制上,我参考了 Eugene Yan 的离线更新思路。目前设定的是:增量微调每两小时运行一次,而全量重训则在每天 EST 时间 8:30 定时触发。所有的模型配置都放在了 bic-learn 这个仓库里。为了简化部署,我全量使用了 AWS 方案,前后端分离,并且模型服务统一通过 ONNX Runtime 运行,这样就避开了 PyTorch 运行时环境极其臃肿且难以维护的坑。 ## 个性化推荐存在两小时的延迟 目前系统在实际运行中的表现是:匿名用户看到的全部是“默认用户”的推荐结果;而注册用户在对书籍打分后,大约需要等待两小时(也就是一个增量微调周期),才能在界面上看到个性化的推荐结果。 ## 数据稀疏导致推荐列表经常填不满 这次实践中踩到的最大坑其实是数据稀疏性。两千本书的规模根本无法覆盖长尾分布,导致协同过滤的矩阵稀疏得离谱。尤其是在经过 DPP 去重之后,候选集经常会出现数量不足的情况,导
CLIP和关键词的权重设计确实让人有些固定,我尝试用RRF融合权重来动态调整,但发现实际应用中还需要更细致的处理。在By-Its-Cover中,我并行执行了CLIP向量检索和GLiNER+Hardcover API的关键词搜索,但发现仅仅通过RRF融合并不能完全解决权重分配的问题。具体来说,我发现当用户输入的描述与封面的CLIP向量匹配度较低时,GLiNER抽取的实体关键词(如书名、作者)反而能更好地捕捉用户意图,因此我决定将RRF的融合权重在描述长度和匹配度上进行动态调整——当描述长度超过20字时,我将关键词搜索权重提升至0.6,而CLIP向量权重相应降至0.4,反之则保持原权重。不过,这个调整后的权重设计依然面临冷启动问题,因为数据库规模太小,召回结果的质量波动较大,需要进一步结合用户反馈的隐式信号来平衡。
封面风格像就推荐,结果点进去内容完全不搭——如果只靠封面向量检索,还可以并行跑一次实体抽取并做关键词搜索,再用 Reciprocal Rank Fusion(RRF)把两套结果融合,稍微缓解一下匹配不上的尴尬,这种检索逻辑真的让我心累。