多模态检索实战:Sentence Transformers支持Embedding与Reranker

18 阅读4分钟

传统文本检索正在进化——现在你可以用文字搜索图片,用图片搜索文档,甚至构建跨模态的RAG系统。Sentence Transformers v5.4带来了多模态Embedding与Reranker能力,Java开发者该如何利用?


从单模态到多模态检索

传统Embedding模型只处理文本——把一段文字转换成向量,然后计算相似度。但现实世界的知识远不止文字:产品图片、扫描文档、视频片段、音频录音……这些内容同样需要被检索和理解。

多模态Embedding模型解决了这个问题:它将文本、图片、音频、视频等不同模态的输入映射到同一个向量空间。在这个空间里,"一只橘猫"的文字描述和一张橘猫图片的向量是接近的——即使它们来自完全不同的模态。

多模态Reranker更进一步:它不是简单计算向量距离,而是对查询和候选文档进行深度交互评分,精度更高(当然速度也慢一些)。


核心应用场景

场景描述
视觉文档检索扫描PDF、截图、照片,用文字描述搜索
跨模态搜索用图片搜索相关文字,或用文字搜索匹配图片
多模态RAG知识库包含图片+文字,LLM综合理解后回答
电商商品搜索用商品图片搜索相似商品或相关描述

技术原理

Embedding模型

输入A(文本) → [多模态模型] → 向量A (768维)
输入B(图片) → [多模态模型] → 向量B (768维)

相似度 = cosine_similarity(向量A, 向量B)

关键点:同一个模型处理不同模态,输出维度相同,语义空间对齐。

Reranker模型

查询(文本) + 候选文档(图片) → [CrossEncoder] → 相关性得分

Reranker不是单独编码再计算距离,而是把查询和文档拼接后一起编码,让模型深度理解它们的关系。


主流模型选择

Sentence Transformers v5.4支持的多模态模型:

VLM-based模型(需要GPU)

  • Qwen/Qwen3-VL-2B-Instruct — 2B参数,约8GB显存
  • Qwen/Qwen3-VL-8B-Instruct — 8B参数,约20GB显存
  • 适合高质量多模态检索

CLIP模型(CPU友好)

  • clip-ViT-B-32 — 经典CLIP,资源需求低
  • clip-ViT-L-14 — 更大更准,仍可CPU推理
  • 适合资源受限场景

Java开发者的集成路径

方案一:Python服务 + Java调用

[Java应用] --HTTP--> [FastAPI服务] --调用--> [Sentence Transformers]

FastAPI服务示例:

from fastapi import FastAPI
from sentence_transformers import SentenceTransformer

app = FastAPI()
model = SentenceTransformer("Qwen/Qwen3-VL-2B-Instruct")

@app.post("/embed")
async def embed(text: str = None, image_url: str = None):
    inputs = []
    if text:
        inputs.append(text)
    if image_url:
        inputs.append({"image": image_url})
    
    embeddings = model.encode(inputs)
    return {"embeddings": embeddings.tolist()}

Java端使用RestTemplateOkHttp调用即可。

方案二:ONNX导出 + Java推理

对于CLIP模型,可以导出为ONNX格式,用ONNX Runtime Java版直接推理:

// 加载ONNX模型
OrtEnvironment env = OrtEnvironment.getEnvironment();
OrtSession session = env.createSession("clip-vit-b-32.onnx");

// 文本编码
OrtSession.Result textResult = session.run(textInput);
float[] textEmbedding = extractEmbedding(textResult);

// 图片编码
OrtSession.Result imageResult = session.run(imageInput);
float[] imageEmbedding = extractEmbedding(imageResult);

// 计算余弦相似度
double similarity = cosineSimilarity(textEmbedding, imageEmbedding);

方案三:Spring AI集成

Spring AI的Embedding接口天然支持扩展:

public interface MultimodalEmbeddingModel extends EmbeddingModel {
    EmbeddingResponse embed(Image image);
    EmbeddingResponse embed(MultimodalContent content); // 文本+图片组合
}

可以自行封装Sentence Transformers的HTTP调用。


检索流程最佳实践

两阶段检索是业界标准做法:

  1. Embedding检索(粗筛):快速从百万文档中召回Top-100
  2. Reranker重排(精排):对Top-100精确评分,返回Top-10
[用户查询][Embedding编码][向量检索Top-100][Reranker重排][返回Top-10]

Embedding编码可以预计算存储,Reranker需要实时运行(因此只在小规模候选集上使用)。


实际案例:电商图片搜索

需求:用户上传商品图片,系统返回相似商品列表

技术方案

  1. 离线阶段:用多模态Embedding模型编码所有商品图片,存入向量数据库
  2. 在线阶段:
    • 编码用户上传图片
    • 向量检索Top-50
    • Reranker精排返回Top-10

关键代码(Python服务):

def search_similar_products(query_image, top_k=10):
    # 编码查询图片
    query_emb = model.encode([{"image": query_image}])
    
    # 向量检索(假设用Milvus)
    results = milvus_collection.search(
        query_emb, 
        anns_field="embedding",
        param={"metric_type": "COSINE", "params": {"nprobe": 16}},
        limit=50
    )
    
    # Reranker精排
    candidates = [(r.id, r.entity.get("image_url")) for r in results[0]]
    rerank_scores = reranker.rank(
        query=query_image,
        candidates=[c[1] for c in candidates]
    )
    
    # 返回Top-K
    return sorted(zip(candidates, rerank_scores), 
                  key=lambda x: x[1], reverse=True)[:top_k]

注意事项

  1. 硬件需求:VLM-based模型需要GPU,CLIP模型CPU可用但速度较慢
  2. 输入格式:支持本地路径、URL、PIL Image对象、base64编码
  3. 模态对齐:不是所有多模态模型都对齐得很好,实际效果需要评测
  4. 中文支持:Qwen系列对中文友好,CLIP主要是英文

总结

多模态检索正在成为RAG系统的标配能力。对于Java开发者:

  • 快速上手:用FastAPI封装Sentence Transformers,Java HTTP调用
  • 生产部署:考虑ONNX导出+Java推理,或Spring AI扩展
  • 最佳实践:Embedding粗筛 + Reranker精排的两阶段架构

Sentence Transformers v5.4的多模态支持降低了技术门槛,现在就是入场的好时机。


相关资源