资讯动态

VLM驱动的搜索相关性度量:从文本匹配到跨模态理解

发布时间:2026/8/28 14:30:17 来源:尧图企业网站定制
搜索相关性度量是搜索引擎里最容易被低估的环节。用户输入一个查询词系统返回十条结果看起来只是一次排序但在排序背后是检索团队对“什么才算相关”的持续定义与反复校准。过去十几年这项工作的主力是文本语义模型用 query 与 document 的向量表示判断匹配度。但今天的 Web 页面里越来越多的信息密度集中在图片、视频、图表、商品图和多媒体元素上纯文本相关性模型的瓶颈已经越来越明显。视觉语言模型VLM正是在这个背景下进入搜索相关性度量的视野。它不只是在做“看图说话”而是能够在同一套模型参数里同时建模文本和视觉信息让相关性判断从“文本匹配”升级为“跨模态理解”。这篇文章想给出一个明确判断VLM 在 Web 规模搜索相关性度量中的价值不是替代 BM25 或双塔召回而是把相关性判断的边界从纯文本扩展到了视觉内容。真正的难点不在模型效果而在工程成本、评测稳定性、以及线上线下的节奏控制。文章会从问题拆解、架构设计、示例代码、评估方法到工程踩坑逐层展开适合正在做搜索、内容平台推荐或多模态检索的工程师阅读。1. 搜索相关性度量的本质问题是什么在搜索引擎和推荐系统里相关性度量负责回答一个朴素的问题给定一个查询这条结果到底相不相关这个判断结果会被用于排序、过滤、多样性控制、也包括搜索质量评测和离线评估。传统做法是把它建模成一个“文本到文本”的相似度问题。query 是一个文本序列document 的标题、正文、摘要也被切词后映射成向量然后通过 BM25、TF-IDF 或者深度语义匹配模型算出分数。这套体系在过去二十年里非常有效尤其对纯文本页面、新闻文章和问答型查询效果足够稳定。但问题在于Web 页面并不是纯文本对象。一条商品结果里主图、细节图、价格标签、评论图片可能比商品描述承载了更多决策信息一条旅游攻略里用户真正被吸引的往往是头图而不是几百字的景点介绍一个视频搜索结果没有视觉信号的情况下只能在 metadata 上猜相关性。如果相关性模型只能读文本它就不能理解“查询里提到的某个物品长什么样”也没法区分“页面里那张配图是真的相关图片还是单纯的装饰图”。这在实际项目中会带来几个很直观的麻烦纯视觉查询没法处理。用户上传一张商品图、一件衣服、一个地标想找相似内容文本侧根本拿不到 query 向量。文本泛化能力弱。query 用的是口语化描述document 的视觉主体才是真实对象两者在字面上差异巨大文本模型匹配困难。评估和标注不一致。人工标注相关性时人是能看到缩略图和排版布局的但离线评估的模型只能看文本。这会导致标注标准与模型学到的标准出现系统性偏差。从这个角度看引入 VLM 并不是“赶多模态的热度”而是要补上相关性度量中一直被忽略的视觉信息通道。2. 视觉语言模型能为核心流程带来什么简单说VLM 是一类同时接受图像和文本输入、输出文本或表征的模型。它可以在一个模型结构里完成“看图 读字 跨模态推理”的组合任务。比如输入一张图片和一句文字它可以回答图片里有没有这只猫、描述图片场景、或者判断这句话与图片内容是否相符。在相关性度量场景里我们关心的正是“相符”这件事。传统文本相关性模型判断的是 query 文本与 document 文本是否匹配VLM 判断的是 query 文本与 document 视觉内容、或者 image query 与 document 文本之间的语义一致性。用一句话概括 VLM 的相对性度量能力它把搜索相关性从“文本信号是否存在”扩展到了“视觉内容是否语义对应”。但这里有一个容易误解的地方VLM 不是简单的“OCR 文本匹配”的叠加。OCR 只能把图片里的文字抽出来仍然只是文本侧的信息VLM 则对视觉对象本身进行语义理解。例如一张没有文字的商品图OCR 毫无作用但 VLM 可以直接判断它是不是一双“防水越野跑鞋”并且与 query 做跨模态匹配。从实际应用经验来看VLM 在相关性度量中最有价值的几个场景包括场景传统文本模型表现VLM 作用图片搜索 / 以图搜图无法处理图片 query直接编码输入图片做跨模态匹配商品搜索依赖标题和属性文本噪音大理解主图商品主体过滤图文不一致视频/短视频搜索只能看标题、描述和标签通过关键帧理解画面内容新闻/图文页正文主导配图信息被浪费结合配图判断图文是否与查询一致搜索评测/标注标注员看到图片模型看不到使模型与人工标注口径对齐这些场景有一个共同点视觉内容不是可选的附属信息而是相关性判断的关键依据。越早意识到这一点越容易判断 VLM 在自己的业务里应该放在哪个环节。3. 从文本到跨模态相关性判断链路的变化把 VLM 引入相关性度量不是换一个打分模型那么简单这会改变整个相关性判断链路的结构。3.1 相关性信号源的变化传统链路中相关性信号来自文本匹配信号query 与 title、正文、anchor 的相似度语义向量信号双塔模型产出的 query 向量与 doc 向量内积统计信号点击率、停留时长、用户反馈加入 VLM 后新增了两类信号视觉语义信号从 document 的图片、视频关键帧中抽取的语义表征跨模态匹配信号query 文本与视觉内容的匹配分数或 image query 与文档文本的匹配分数新增的信号不是叠加在旧模型之上而是直接接入了相关性判断的输入端和输出端。在输入端需要解析 document 的视觉内容在输出端需要融合文本相关性与视觉相关性。3.2 在线链路的位置如果按经典的搜索架构来分VLM 可以放在不同位置粗排层用轻量级 VLM 或者视觉表征模型过滤掉明显不相关的结果。这一层要求吞吐极高通常不会跑完整的生成式 VLM而是用视觉塔表征 近似最近邻检索。精排层对 Top 几十条结果做精细判断这里可以使用 VLM 融合图文信息打分。离线评测层用 VLM 生成评测数据、构造伪标签、做相关性标注的辅助校验。从目前行业讨论和公开资料来看成本更可控的路线是先在离线评测层使用 VLM等评估标准稳定、效果验证充分之后再逐步放大到在线精排。这个节奏适合大多数搜索团队因为相关性度量本身就是一个“先有稳定尺子再优化排序”的领域。3.3 与文本模型的关系VLM 并不会淘汰文本相关性模型。实际工程中文本模型在响应速度、可解释性和低成本推理上仍然有明显优势。更合理的分工是文本模型负责基础文本语义匹配覆盖面广、速度快。VLM 负责需要视觉理解的高价值场景在文本模型分数基础上做修正而不是全量替换。线上精排时可以根据 query 类型路由比如识别出商品类、图文类、视频类查询后再决定要不要调用 VLM 打分。这意味着团队需要的不是“一个 VLM 模型”而是一套“文本模型打底 VLM 做视觉信号增强”的混合架构。4. VLM 相关性度量的核心流程拆解一个完整的 VLM 相关性度量流程通常包含查询解析、文档视觉信号抽取、相关性打分、结果后处理四个环节。下面按步骤拆开看。4.1 查询解析查询进入系统后先做类型识别。这个查询是纯文本还是包含图片如果是纯文本是否属于需要视觉信息的类目如商品、地点、人物、品牌这一步可以用一个轻量级分类器完成也可以直接由规则触发。目标是决定后续要不要走视觉通道。伪代码思路def parse_query(query: str, image_inputNone): query_type text if image_input is not None: query_type image_text elif is_visual_intent(query): query_type text_visual return { query_text: query, query_image: image_input, query_type: query_type }这里is_visual_intent可以是规则、分类模型、也可以是 prompt 分类器。对于商品搜索这类垂直场景通常直接根据业务线路由就行。4.2 文档视觉信号抽取Web 文档不是一张图片而是一个包含多张图片、文字块、版式的复杂对象。抽取信号时一般分三步从 HTML 或数据源中抽出主图、视频封面、关键帧。对图片做标准化处理去重、裁剪、压缩、过滤低质量图。送入 VLM 得到图片表征或图文匹配分数。这一步常见的坑是图片加载失败、URL 过期、以及页面里大量与主题无关的广告图。务必要在特征抽取阶段加入质量过滤而不是把脏数据直接塞给 VLM。4.3 相关性打分打分阶段是核心。一个通用做法是构造“查询 文档内容摘要 文档图片”的多模态输入让 VLM 判断匹配程度并给出评分。打分输出可以是离散标签相关 / 部分相关 / 不相关连续分数0 到 100 的整数排序序列给定多个文档让 VLM 给出相对排序从实际使用角度看连续分数更有利于排序融合但离散标签更稳定、更容易评测。工程中可以先让模型输出离散标签加理由再映射成分数。4.4 后处理与融合VLM 打分不能直接作为最终排序分。一般还会做三件事与文本相关性分数做加权融合比例通过离线评测确定。对分数做归一化和平滑避免某个 query 的分数分布偏移。增加兜底策略VLM 超时、失败时自动降级到文本模型分数。这套流程的核心设计原则是视觉信号是增量不是替代品所有新增信号都必须能在离线评测中证明它提高了相关性指标否则不要贸然上线。5. 完整示例与代码实现下面用一个最小可运行的示例来演示 VLM 相关性打分的整体思路。这里使用的属于示意代码实际选型请根据团队基础设施决定关键是理解流程。5.1 示例 1构造 VLM 相关性打分输入假设我们需要判断一个查询与一条网页文档是否相关。文档带有标题、摘要和一张主图。# 文件路径feature_builder.py import json from typing import Dict, Optional def build_judgment_payload( query: str, doc_title: str, doc_summary: str, image_url: Optional[str] None, ) - Dict: 构造 VLM 打分输入。 document_context f标题{doc_title}\\n摘要{doc_summary if doc_summary else 无} image_part {type: image_url, image_url: {url: image_url}} if image_url else None text_part { type: text, text: ( 你是搜索相关性评估系统。 f请判断查询与文档是否相关。\\n查询{query}\\n文档信息{document_context}\\n 请按以下 JSON 格式返回 {reason: 判断理由, relevance_score: 0到100之间的整数} ), } messages [ { role: user, content: [text_part] if image_part is None else [text_part, image_part], } ] return {messages: messages} if __name__ __main__: payload build_judgment_payload( query防水越野跑鞋推荐, doc_title2025 越野跑鞋选购指南, doc_summary介绍多款越野跑鞋的防水性能和抓地力表现。, image_urlhttps://example.com/shoes.png, ) print(json.dumps(payload, ensure_asciiFalse, indent2))这里的关键不是 prompt 本身而是把 query、文档文本、文档图片统一到一个多模态消息结构里。不同的 VLM 服务对消息格式有不同要求但整体思路是一致的。5.2 示例 2调用 VLM 获取相关性分数接下来需要一个客户端来调用模型。以 OpenAI 兼容接口为例示意代码如下# 文件路径vlm_judger.py import json import httpx from typing import Dict class VLMRelevanceJudger: def __init__(self, api_base: str, api_key: str, model_name: str): self.api_base api_base self.api_key api_key self.model_name model_name self.headers {Authorization: fBearer {api_key}} async def score(self, payload: Dict) - float: request_body { model: self.model_name, messages: payload[messages], temperature: 0.0, } async with httpx.AsyncClient(timeout15) as client: resp await client.post( f{self.api_base}/chat/completions, headersself.headers, jsonrequest_body, ) resp.raise_for_status() data resp.json() content data[choices][0][message][content] parsed json.loads(content) return float(parsed[relevance_score]) async def main(): judger VLMRelevanceJudger( api_basehttps://your-vlm-endpoint.example.com/v1, api_keyyour-token, model_nameyour-multimodal-model, ) payload build_judgment_payload( query防水越野跑鞋推荐, doc_title越野跑鞋选购指南, doc_summary介绍多款越野跑鞋的防水性能和抓地力表现。, image_urlhttps://example.com/shoes.png, ) score await judger.score(payload) print(f相关性分数{score}) if __name__ __main__: import asyncio asyncio.run(main())这段代码有两点值得注意temperature必须设为 0 或尽量接近 0保证相关性打分可复现。搜索相关性是需要稳定性的场景不能一次跑一个分数。超时非常关键。Web 搜索链路对延迟敏感判断逻辑不能因为单次模型调用超时拖垮整个请求。建议配合缓存和异步批处理来降低风险。5.3 示例 3离线评测指标计算相关性强不强不能只看几个 case。需要一个可量化的离线评测脚本。下面是一个极简的评测示例计算 nDCGk# 文件路径evaluate.py import math from typing import List, Tuple def dcg_at_k(relevance_scores: List[float], k: int) - float: relevance_scores relevance_scores[:k] return sum(rel / math.log2(idx 2) for idx, rel in enumerate(relevance_scores)) def ndcg_at_k( predictions: List[Tuple[str, float]], ground_truth: List[Tuple[str, float]], k: int 5, ) - float: 计算 nDCGk。 predictions: [(doc_id, 预测分数)]已按预测分数降序 ground_truth: [(doc_id, 人工标注相关性)]分数越高越相关 pred_doc_ids [doc_id for doc_id, _ in predictions[:k]] rel_scores [] gt_dict dict(ground_truth) for doc_id in pred_doc_ids: rel_scores.append(gt_dict.get(doc_id, 0.0)) dcg dcg_at_k(rel_scores, k) ideal_scores sorted([score for _, score in ground_truth], reverseTrue) idcg dcg_at_k(ideal_scores, k) if idcg 0: return 0.0 return dcg / idcg if __name__ __main__: predictions [(doc_1, 92.0), (doc_2, 85.0), (doc_3, 70.0), (doc_4, 45.0)] ground_truth [(doc_1, 3), (doc_2, 2), (doc_3, 1), (doc_4, 0)] print(fnDCG4: {ndcg_at_k(predictions, ground_truth, k4):.4f})离线评测集的建设才是真正的难点。想让 VLM 在相关性上发挥作用需要人工标注一批包含图文信息的 query-doc 对。如果团队暂时没有标注资源可以用“让 VLM 标注再做人工抽检”的方式启动但要注意伪标签存在系统偏差。5.4 示例 4批量推断与结果缓存Web 规模意味着即使只对 Top 结果做 VLM 打分也可能面临每天千万级甚至亿级的请求。直接对每次搜索请求都实时调用大模型是不现实的。一个更可行的模式是离线批量打分 增量缓存。# 文件路径batch_infer.py import asyncio from dataclasses import dataclass from typing import Dict, List dataclass class JudgmentInput: query: str doc_id: str doc_title: str doc_summary: str image_url: str class BatchJudger: def __init__(self, judger, cache: Dict[str, float]): self.judger judger self.cache cache def _key(self, query: str, doc_id: str) - str: return f{query}::{doc_id} async def batch_score(self, inputs: List[JudgmentInput]) - Dict[str, float]: results {} pending [] for item in inputs: key self._key(item.query, item.doc_id) if key in self.cache: results[item.doc_id] self.cache[key] continue payload build_judgment_payload( queryitem.query, doc_titleitem.doc_title, doc_summaryitem.doc_summary, image_urlitem.image_url, ) pending.append((item, key, payload)) # 并发控制防止一次性打爆模型服务 semaphore asyncio.Semaphore(8) async def limited_judge(item, key, payload): async with semaphore: score await self.judger.score(payload) self.cache[key] score return item.doc_id, score if pending: done await asyncio.gather( *(limited_judge(item, key, payload) for item, key, payload in pending) ) for doc_id, score in done: results[doc_id] score return results这里引入并发信号量是为了控制对模型服务的压力。实际部署时还需要考虑重试、熔断、限流和结果回写。6. 运行结果与效果验证如果上面的批量打分流程运行成功预期输出是一个 doc_id 到相关性分数的映射。例如{ doc_1: 92.0, doc_2: 85.0, doc_3: 70.0, doc_4: 45.0 }有了每一条 doc 的分数离线评估要做的事情就很清晰了把模型打分结果写入一条评测表字段包括 query、doc_id、VLM 分数、文本模型分数、人工标注分数。计算 VLM 分数与人工标注的相关性。常用指标是 Spearman 相关系数、Pearson 相关系数、nDCGk、以及人工标注一致性。与纯文本基线对比。判断 VLM 的引入是否真正提升了相关性排序质量而不是只在个别 case 上变好。如果 VLM 分数与人工标注相关性低于文本模型基线常见原因不是模型能力不够而是输入设计出了问题。可能是文档图片没有抽到主图也可能是 prompt 里的指令不够清晰让模型把重点放在了不相关的内容上。另外用“理由”字段做案例分析非常重要。VLM 打分是黑盒但输出的 reason 能帮你定位它到底在看什么。如果发现它总是围绕“图片清晰度”“图片美观度”打分而不是围绕“是否相关”打分就需要调整 prompt。7. 常见问题与排查方法在接入 VLM 做相关性度量的过程中最容易遇到的几个问题如下问题现象可能原因排查方式解决方案同一查询多次打分差异大模型采样参数未固定检查 temperature 是否设置为 0固定采样参数必要时固定随机种子对含图文档打分明显偏低文档主图抽取失败或选了广告图可视化抽查输入图片改进主图抽取逻辑增加图片质量过滤VLM 分数与人工标注相关性低prompt 没有讲清“相关”标准读取 reason 字段分析模型关注点重写 prompt给出正反例实时调用超时严重图片加载慢、模型推理慢查看调用耗时分布改为离线批量打分 缓存图片无法访问图片 URL 过期或存在防盗链检查抓取时的图片状态码存量图片做本地备份业务点击率与 VLM 打分不一致点击行为受位置、标题等因素影响做位置归一化后再对比用搜索评测集而非原始点击率作为效果指标这里想特别提醒一点VLM 打分需要和你业务里的“相关性真值”对齐。如果业务定义的相关性是“用户点击”那么即使 VLM 在语义上判断得很合理也未必会提升点击率。相关性度量是一个系统工程模型输出只是其中一环后面还有排序公式、业务策略和用户体验的持续调优。8. Web 规模部署的工程建议如果 VLM 相关性打分要通过测试进入线上或大规模离线流程以下几个工程问题必须提前规划。8.1 成本控制VLM 推理成本远高于文本模型。Web 规模下全量 query 都走 VLM 精排不太现实。更推荐的做法是分层使用第一层文本模型粗排把候选集压到几十条。第二层VLM 只对 Top 结果打分或者只对文本模型分数处于模糊区间的结果打分。第三层对特定 query 类型图片查询、商品查询触发 VLM 打分。同时可以加入分桶策略小流量上线对比效果效果确认后再逐步扩大比例。8.2 缓存与复用搜索存在明显热点效应同一 query 在短时间内会被大量重复查询。针对 query 与 doc 的匹配结果做缓存能大幅降低 VLM 调用量。需要注意的是缓存应该有失效时间因为网页内容会更新图片可能被替换。8.3 模型蒸馏替代直接推理如果线上延迟和成本仍然难以接受可以考虑用 VLM 在离线阶段生成大量“图文相关性”训练数据然后蒸馏到一个轻量级多模态模型。蒸馏后的模型用于线上VLM 用于离线迭代。这是目前很多团队更实际的落地路径。8.4 监控与降级新增 VLM 环节后必须增加线上监控调用成功率、超时率、平均耗时打分覆盖率多少比例的 query-doc 对成功拿到了 VLM 分数分数分布变化分数均值是否出现系统性偏移降级触发次数VLM 不可用时是否有回退到文本模型的逻辑核心原则是 VLM 不能成为搜索链路的单点故障。在工程上要预设降级策略任何异常都不能影响基础检索能力。8.5 标注与评测流程无论模型多强评测数据仍然是相关性度量的地基。建议建设一套与业务目标对齐的标注指南明确“相关”“部分相关”“不相关”的定义并覆盖图文场景。标注员看到的内容应该尽量与线上模型看到的一致这样才能缩小评测标准与线上信号之间的差异。9. 趋势展望与后续学习建议从搜索技术的演进看相关性度量正在从纯文本语义走向多模态语义。这不只是给搜索引擎“加一个图片输入口”而是会在查询理解、召回、排序、评测、标注等全链路产生影响。接下来值得关注的方向有三个第一轻量级多模态表征模型。VLM 的推理成本会持续下降但短期内要真正做到 Web 规模全量使用轻量级双塔多模态模型仍然是更现实的选择。第二评测自动化。如何用 VLM 辅助生成高质量的相关性评测集减少人工标注成本同时避免模型自我评价带来的偏差这是一个很有价值的研究方向。第三搜索业务与多模态检索的深度融合。当视觉信号真正进入相关性判断搜索系统会从“关键词到文本页”的匹配演进为“语义意图到多媒体内容”的匹配这对召回链路、索引结构、排序策略都会带来连锁变化。对工程师来说最快的入门路径不是直接训练一个大模型而是先在现有搜索链路里找出那些“因为看不见图片而判断错误”的典型 case然后用 VLM 对一个限定场景做相关性增强跑通评估、监控、降级整套流程。这样既能快速产生业务价值也能沉淀出团队对多模态搜索的系统理解。这篇文章没有给出唯一的正确答案原因很简单不同业务里“相关性”的定义不同适合的模型和服务也不一样。但判断链路的设计思路是通用的先定义清楚相关性再决定视觉信号在哪一层接入最后用靠谱的评测体系持续迭代。方向已经明确剩下的就是先用小成本跑通一个真实场景。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价