1. 核心概念解析

在构建搜索引擎前,我们首先要理解几个核心术语:

  1. 召回

    • 定义:从海量商品库(如数百万SKU)中,快速、初步地筛选出可能与用户查询相关的一小部分商品(如几百到几千个)的过程。目标是宁可错杀,不可放过,保证真正相关的商品不被遗漏。

    • 商超例子:用户搜索"苹果",召回系统需要快速找出所有标题、描述、类别中包含"苹果"的商品,以及可能是"iPhone"、"iPad"等品牌为苹果的商品。

  2. 多路召回

    • 定义:因为单一召回策略有局限,所以我们同时启用多种不同的召回策略,每一路策略都有自己的专长,最后将各路的结果汇总。

    • 商超例子:搜索"低脂零食"

      • 关键词召回路:使用ES,召回标题或描述中包含"低脂"、"0脂肪"的商品。

      • 向量召回路:使用向量模型,召回语义上与"健康、减肥、健身餐"相关的商品,即使其标题中没有"低脂"二字。

      • 类目/属性召回路:根据用户历史行为或查询本身,直接筛选出"健康食品"类目下,脂肪含量属性<5g的商品。

    • 优势:极大地提高了搜索的召回率和多样性,解决了单一策略的盲区。

  3. 向量召回

    • 定义:将用户查询和所有商品信息通过深度学习模型转换为数学向量(一组数字)。通过计算查询向量与商品向量之间的距离或相似度,来找出语义上最相近的商品。

    • 商超例子:搜索"宝宝吃了不上火的奶粉"。这个查询很长,关键词匹配会失效。但向量模型能理解其核心语义是"婴幼儿奶粉" + "温和" + "易消化",从而召回那些描述中含有"亲和人体"、"益生元"、"易吸收"等词语的奶粉。

  4. 融合

    • 定义:将多路召回上来的商品列表,合并成一个统一的、最终排序的列表的过程。这是决定搜索质量的关键步骤。

    • 常用方法:

      • 加权分数融合:给每一路召回的分数赋予一个权重,计算综合分。

      • RRF:一种简单有效的融合方法,不依赖于各路分数的绝对数值,只依赖排名,能平衡不同召回源的输出。

      • 模型重排:将多路召回的结果作为候选集,用一个更复杂、更精确的模型(如交叉编码器)重新计算每个商品与查询的相关性分数,并据此排序。


2. 商超搜索引擎技术组合方案

以下提供三种从简到繁的技术组合方案,您可以根据自身技术实力和数据规模进行选择。

2.1 方案一:一体化简易方案(推荐用于快速启动和中等规模)

  • 架构图:
    用户查询 -> PostgreSQL (PgVector + 全文搜索) -> 融合与重排 -> 返回结果

  • 核心组件:

    • 数据库:PostgreSQL

    • 向量扩展:PgVector

    • 召回方式:在同一个SQL查询中,同时使用tsvector进行全文搜索(关键词召回)和vector <=>进行向量相似度搜索(向量召回)。

  • 工作流程:

    1. 商品数据(ID, 标题, 描述, 类目等)和其对应的向量一并存入PostgreSQL。

    2. 收到用户查询后,将查询文本也转换为向量。

    3. 执行类似以下的SQL进行多路召回与融合:

      sql
      SELECT 
          product_id,
          product_name,
          ( -- 关键词搜索分数
              0.3 * ts_rank_cd(text_search_vector, plainto_tsquery('用户查询'))
          ) + ( -- 向量搜索分数
              0.7 * (1 - (embedding_vector <=> '查询向量'))
          ) AS combined_score
      FROM products
      ORDER BY combined_score DESC
      LIMIT 100;
    4. 对结果进行必要的业务规则调整(如库存、销量Boost)后返回。

  • 优点:架构极简,无需维护多个系统,开发速度快,运维成本低。

  • 缺点:当商品量达到数千万甚至上亿时,PostgreSQL的向量搜索性能可能成为瓶颈。

2.2 方案二:经典组合方案(推荐用于大规模、高性能场景)

  • 架构图:
    用户查询 -> [应用层] -> 并行请求 -> [ES (关键词召回) & Milvus (向量召回)] -> 融合与重排 -> 返回结果

  • 核心组件:

    • 关键词搜索引擎:Elasticsearch

    • 向量数据库:Milvus 或 Zilliz Cloud

    • 应用层:Python/Java/Go等服务,负责协调、融合和重排。

  • 工作流程:

    1. 数据同步:商品数据同步写入ES和Milvus。商品向量通过离线或实时方式生成并存入Milvus。

    2. 并行召回:应用层收到查询后,同时向ES和Milvus发起请求。

      • 向ES请求:使用BM25算法进行关键词搜索,返回Top N商品及分数。

      • 向Milvus请求:使用查询向量进行ANN搜索,返回Top N商品及相似度分数。

    3. 融合:应用层收到两路结果后,使用RRF算法进行初步融合。RRF能很好地平衡两路来源的差异。

    4. 重排:(可选但推荐)将融合后的Top 50-100个商品ID及原始查询,发送给一个交叉编码器重排模型。该模型会进行更精细的相关性计算,输出最终排序。

    5. 返回结果:应用层将最终排序的商品列表返回给前端。

  • 优点:性能强劲,专库专用,扩展性好,能应对海量商品和超高并发。

  • 缺点:架构复杂,需要维护两个数据存储,数据一致性挑战更大。

2.3 方案三:全托管云服务方案(推荐用于无运维团队、追求效率)

  • 架构图:
    用户查询 -> [云服务API (如Azure Cognitive Search / Vespa Cloud)] -> 返回结果

  • 核心组件:

    • 云搜索服务:如 Azure Cognitive Search、Google Vertex AI Search、或托管的 Vespa Cloud。

  • 工作流程:

    1. 通过服务提供的数据接口,上传商品数据和对应的向量。

    2. 在服务控制台配置搜索策略,例如:设置混合搜索(Hybrid Search),并调整关键词和向量的权重。

    3. 通过调用服务的RESTful API发起搜索请求,服务内部自动完成多路召回、融合和排序。

    4. 直接接收服务返回的最终排序结果。

  • 优点:开箱即用,免运维,内置了最佳实践,快速上线。

  • 缺点:成本较高,定制灵活性和可控性相对较低,可能存在供应商锁定风险。


3. 实施步骤与举例

我们以最经典的方案二为例,拆解一个完整的搜索流程。

场景:用户在某商超App中搜索 "小朋友喝的纯牛奶"。

  1. 查询理解与向量化:

    • 应用层对查询进行预处理(如分词),然后使用预训练的Embedding模型(如bge-base-zh)将"小朋友喝的纯牛奶"转换为一个768维的向量。

  2. 多路召回:

    • 路1:ES关键词召回

      • 查询:"小朋友" OR "儿童" OR "纯牛奶"

      • 可能召回商品:

        • "蒙牛儿童纯牛奶" (分数:0.8)

        • "伊利纯牛奶" (分数:0.5, 因为只有"纯牛奶"匹配)

        • "光明儿童高钙奶" (分数:0.4, 因为"儿童"匹配)

    • 路2:Milvus向量召回

      • 查询:输入查询向量,查找最相似的TopK个商品向量。

      • 可能召回商品:

        • "认养一头牛 全脂纯牛奶" (相似度:0.92, 语义上高度相关)

        • "特仑苏 儿童奶" (相似度:0.88)

        • "伊利 舒化奶" (相似度:0.75, 语义上属于"易吸收的奶")

  3. 融合:

    • 应用层使用RRF算法将两路结果合并。假设RRF参数k=60,我们得到初步融合列表(按RRF分数):

      • "蒙牛儿童纯牛奶" (ES路排名1, Vec路排名未进前10, RRF分高)

      • "认养一头牛 全脂纯牛奶" (Vec路排名1, ES路排名未进前10, RRF分高)

      • "特仑苏 儿童奶"

      • "伊利纯牛奶"

      • ...

  4. 智能重排:

    • 将融合后的Top 50个商品ID和原始查询"小朋友喝的纯牛奶"一同输入交叉编码器重排模型。

    • 该模型会精细地计算每个商品与查询的匹配度。结果可能是:

      • "蒙牛儿童纯牛奶" -> 重排分数 0.95 (非常相关)

      • "特仑苏 儿童奶" -> 重排分数 0.90 (相关)

      • "认养一头牛 全脂纯牛奶" -> 重排分数 0.85 (相关,但未强调"儿童")

      • "伊利 舒化奶" -> 重排分数 0.80 (相关度稍低)

      • "伊利纯牛奶" -> 重排分数 0.70 (最不相关,因为是普通成人奶)

  5. 业务规则调整:

    • 在最终输出前,可能根据库存、销量、促销活动等对分数进行微调(如给有库存的商品小幅加分)。

  6. 返回结果:

    • 最终呈现给用户的排序可能是:"蒙牛儿童纯牛奶" -> "特仑苏 儿童奶" -> "认养一头牛 全脂纯牛奶" ... 这个结果既抓住了关键词"儿童",又通过语义理解找到了"纯牛奶",并且通过重排将最符合"小朋友喝"这个意图的商品排在了最前面。

总结:一个现代化的商超搜索引擎,不再是简单的"数据库查询",而是一个由 多路召回、智能融合、模型重排 构成的复杂且精密的系统。通过这种方式,才能真正理解用户千变万化的口语化表达,从百万商品中精准找到他们想要的商品,极大提升用户体验和转化率。

 posted on 2025-11-03 11:10  xibuhaohao  阅读(0)  评论(0)    收藏  举报