传统文本检索正在进化——现在你可以用文字搜索图片,用图片搜索文档,甚至构建跨模态的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端使用RestTemplate或OkHttp调用即可。
方案二: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调用。
检索流程最佳实践
两阶段检索是业界标准做法:
- Embedding检索(粗筛):快速从百万文档中召回Top-100
- Reranker重排(精排):对Top-100精确评分,返回Top-10
[用户查询]
↓
[Embedding编码] → [向量检索Top-100]
↓
[Reranker重排] → [返回Top-10]
Embedding编码可以预计算存储,Reranker需要实时运行(因此只在小规模候选集上使用)。
实际案例:电商图片搜索
需求:用户上传商品图片,系统返回相似商品列表
技术方案:
- 离线阶段:用多模态Embedding模型编码所有商品图片,存入向量数据库
- 在线阶段:
- 编码用户上传图片
- 向量检索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]
注意事项
- 硬件需求:VLM-based模型需要GPU,CLIP模型CPU可用但速度较慢
- 输入格式:支持本地路径、URL、PIL Image对象、base64编码
- 模态对齐:不是所有多模态模型都对齐得很好,实际效果需要评测
- 中文支持:Qwen系列对中文友好,CLIP主要是英文
总结
多模态检索正在成为RAG系统的标配能力。对于Java开发者:
- 快速上手:用FastAPI封装Sentence Transformers,Java HTTP调用
- 生产部署:考虑ONNX导出+Java推理,或Spring AI扩展
- 最佳实践:Embedding粗筛 + Reranker精排的两阶段架构
Sentence Transformers v5.4的多模态支持降低了技术门槛,现在就是入场的好时机。
相关资源:
- Sentence Transformers文档:www.sbert.net/
- 多模态模型列表:huggingface.co/models?libr…
- Spring AI Embedding:docs.spring.io/spring-ai/r…