图文互检与以图搜图:多模态 Embedding 选型 + Milvus 生产实战
电商拍照购物、版权溯源、设计素材库都在做「以图搜图」,但很多人直接用 CLIP 向量化 + 向量库检索后却发现:召回不准、中文失效、索引一塌糊涂。本文从双塔对比学习原理讲起,带你用最新多模态 Embedding 模型 + Milvus 从零搭一套生产级图文互检系统,并给出 2026 年最新的模型选型实测数据。
开篇:从一个真实业务场景说起
假设你负责一个电商平台的「拍照购物」功能:用户拍一张运动鞋的照片,系统要在 1000 万级商品图库里瞬间找出同款或相似款。再比如你维护一个版权图库,需要检测某张图是否被裁剪、加滤镜后盗用。这些场景的核心都是同一个能力——跨模态检索(Cross-Modal Retrieval):让「图片找图片」「文字找图片」「图片找文字」在同一套系统里都能跑通。
很多人第一反应是:把图片丢给视觉大模型(VLM)生成一段描述,再走文本检索。这条路对单张图可行,但对千万级图库来说,每张图都过一次大模型推理的成本和延迟都不可接受。真正工业界的做法是多模态 Embedding(Multimodal Embedding):用一个双塔模型把图片和文本编码进同一个向量空间,离线批量向量化建索引,在线做 ANN(近似最近邻)检索,单次查询毫秒级返回。本文就围绕这条技术路线,从原理到生产完整讲透。
技术背景与核心概念扫盲
什么是多模态 Embedding
Embedding 是把非结构化数据(文本、图片、音视频)映射成固定维度的浮点向量。多模态 Embedding 的特殊之处在于:图片编码器和文本编码器共享同一个向量空间,语义相近的图文向量距离近。这样「一只白色的狗」这句话的向量,和一张白狗照片的向量,余弦相似度就很高——文搜图、图搜图在数学上统一成了「向量最近邻检索」。
双塔架构与对比学习
实现上述目标的标准范式是双塔架构(Two-Tower / Dual Encoder):一个图像编码器(Image Encoder)塔、一个文本编码器(Text Encoder)塔,各自独立编码,最后通过**对比学习(Contrastive Learning)**拉近正样本对、推远负样本对。
flowchart LR
subgraph 训练阶段
I[图片样本] --> IE[图像编码器 Image Encoder]
T[文本样本] --> TE[文本编码器 Text Encoder]
IE --> IF[图片向量]
TE --> TF[文本向量]
IF --> L[对比损失<br/>拉近正对 / 推远负对]
TF --> L
end
subgraph 推理阶段
Q[查询: 文本或图片] --> E[对应编码器]
E --> QV[查询向量]
QV --> VS[(向量数据库 ANN 检索)]
VS --> R[Top-K 结果]
end
这条路的代表作是 2021 年 1 月 OpenAI 发布的 CLIP(Contrastive Language-Image Pre-training),它在 4 亿图文对(WIT 数据集)上预训练,zero-shot 在 ImageNet 上达到 76.2% 精度,与当时有监督训练的 ResNet-50 打平。2023 年 Google DeepMind 发布 SigLIP(Sigmoid Loss for Language-Image Pre-training),用 sigmoid 损失替代 softmax 损失,训练更稳、对小 batch 更友好,成为新一代双塔基准。
适用边界:什么时候用它,什么时候不用
多模态 Embedding 适合「召回」:海量数据、高吞吐、低延迟、只求粗粒度相似。它不适合「细粒度理解」:比如判断「图里这个人是不是在喝咖啡」这种需要推理的问题,应该交给 VLM(如 Qwen2.5-VL)做生成式理解。生产系统中两者经常组合:Embedding 负责第一轮召回 Top-100,VLM 或重排序模型负责精排。想明白这条边界,你就不会拿着 CLIP 硬刚 VQA 了。
底层原理深度拆解
CLIP 的对比学习:softmax 归一化带来的三个隐患
CLIP 的训练目标是把 batch 内 N 个图文对变成 N×N 的相似度矩阵。矩阵对角线上是正样本对,其余 N²-N 个都是负样本对。损失函数是对称的交叉熵(InfoNCE 形式):
L = -1/|B| Σ_i log( exp(sim(I_i,T_i)) / Σ_j exp(sim(I_i,T_j)) )
公式里的分母是归一化项(normalization term),它把相似度变成概率。这个设计带来了三个工程隐患:
- batch 必须大:分母遍历了整个 batch 的负样本,负样本越丰富,学习信号越好,所以 CLIP 训练动辄上万甚至几十万的 batch size,普通团队根本跑不动;
- batch 内不能有相似样本:如果 batch 里恰好有两只柯基犬的照片,它们的相似度会污染分母,导致 loss 震荡,训练前还得做语义去重;
- loss 要算两遍:图像固定遍历文本 + 文本固定遍历图像,计算量翻倍。
SigLIP 的 sigmoid 损失:干掉归一化项
SigLIP 的思路非常直接:把多分类的 softmax 换成逐对独立的二分类 sigmoid。每个图文对独立计算损失,互不依赖:
L = -1/|B| Σ_i Σ_j log( 1 / (1 + exp( z_ij · (-t · x_i·y_j + b) )) )
其中 z_ij 表示这对样本是正样本(+1,对角线)还是负样本(-1,其余);t 是可学习温度(temperature),控制 sigmoid 的陡峭程度;b 是可学习偏置(bias),用于抵消训练初期正负样本不平衡。由于损失不再依赖 batch 内其他样本,batch 大小不再影响损失形式,小 batch 也能稳定训练。论文实测:batch size < 16k 时 sigmoid loss 显著优于 softmax;同样 4 张 TPU-v4 上,SigLIP 能塞下 4096 的 batch,而 CLIP 只能塞 2048。
工程上这意味着:如果你要自己微调一个图文检索模型,SigLIP 的训练成本门槛比 CLIP 低一个量级。这也是为什么 PaliGemma 等新一代 VLM 都换用 SigLIP 作为视觉塔。
Modality Gap:跨模态检索的最大敌人
一个反直觉的现象是:即使训练完成,图片向量簇和文本向量簇在向量空间里往往并不重合,而是各自聚成两团、中间隔着一段距离,这段距离被称为 Modality Gap。gap 越大,图文互检越难——文本查询向量离目标图片簇越远,检索精度越差。
2026 年 Zilliz 的 CCKM Benchmark 实测了各模型的 modality gap:Qwen3-VL-Embedding-2B 仅 0.25,Gemini Embedding 2 为 0.73,老牌 CLIP ViT-L-14 高达 0.83。这直接解释了为什么新版多模态模型在跨模态 R@1 上碾压 CLIP——不是特征提取变强了,而是模态对齐(alignment)做得更好。
flowchart LR
subgraph 小Modality_Gap[小 Modality Gap: 0.25]
A1[文本簇] --- B1[图片簇]
end
subgraph 大Modality_Gap[大 Modality Gap: 0.83]
A2[文本簇] -.- C2[空旷地带] -.- B2[图片簇]
end
演进路线:从 CLIP 到 2026 年的多模态 Embedding
- BLIP(2022):ViT+BERT 双塔,加入 ITC/ITM/LM 三个目标,用 CapFilt 清洗噪声图文对;
- BLIP-2(2023):引入 Q-Former 桥接冻结的视觉编码器与冻结的 LLM,只训练中间层,129M 数据即可训练;
- SigLIP2(2025):在 sigmoid 损失基础上融合自监督、解码器预训练、数据蒸馏等多项技术,支持密集定位任务;
- Qwen3-VL-Embedding(2025):把 2B 的 VLM 改造为检索模型,modality gap 做到 0.25,跨模态 R@1 登顶;
- Jina CLIP v2(2025):现代化的 CLIP 架构,原生多语言多模态;
- Gemini Embedding 2(2025):闭源 API,文本/图片/视频/音频/PDF 全模态覆盖,跨语言检索接近满分。
可以看出,2026 年的多模态 Embedding 已经分化为两条路线:开源轻量的(Qwen3-VL、SigLIP、Jina CLIP v2)和闭源全能的(Gemini Embedding 2、Voyage MM-3.5)。
手把手实战落地
下面我们搭建一个完整的图文互检系统:SigLIP 负责向量化,Milvus 负责存储与检索。环境假设为 Python 3.10+,有 GPU 更好(无 GPU 也能跑,只是慢一些)。
第一步:安装依赖
# 向量数据库客户端 + 多模态模型 + 图像处理
pip install --upgrade pymilvus transformers pillow torch
Milvus 我们直接使用 Milvus Lite(单文件嵌入式版本),无需部署服务端,最适合本地开发和原型验证;生产环境换成 Docker/K8s 部署的 Milvus 2.6,连接方式完全一致。
第二步:加载模型与图文向量化
代码示例 1:加载 SigLIP 模型(含关键参数注释)
import torch
from transformers import AutoModel, AutoProcessor
# google/siglip-so400m-patch14-384:视觉塔为 SoViT-400m,输入分辨率 384x384
# 相比 CLIP ViT-L/14(224px),SigLIP 在图文检索上零样本 ImageNet 精度更高(83.1% vs 75.5%)
model_name = "google/siglip-so400m-patch14-384"
model = AutoModel.from_pretrained(model_name, torch_dtype=torch.float16)
processor = AutoProcessor.from_pretrained(model_name)
model.eval() # 推理模式,关闭 dropout 等训练行为
# SigLIP 的视觉塔 hidden_size 为 1152,文本塔为 1152,向量维度一致
print("向量维度:", model.config.vision_config.hidden_size)
代码示例 2:图文统一向量化函数(L2 归一化是命门)
from PIL import Image
def encode_image(image_path: str) -> list[float]:
"""将图片编码为归一化的 1152 维向量"""
image = Image.open(image_path).convert("RGB") # 统一转 RGB,避免 RGBA/灰度图报错
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
feat = model.get_image_features(**inputs)
# L2 归一化:把向量长度变为 1,之后余弦相似度 = 内积,可直接用 IP 度量
feat = torch.nn.functional.normalize(feat, p=2, dim=-1)
return feat.squeeze().tolist()
def encode_text(text: str) -> list[float]:
"""将文本编码为归一化向量,与图片向量位于同一空间"""
inputs = processor(text=text, return_tensors="pt")
with torch.no_grad():
feat = model.get_text_features(**inputs)
feat = torch.nn.functional.normalize(feat, p=2, dim=-1)
return feat.squeeze().tolist()
⚠️ 归一化必须做:SigLIP/CLIP 训练时对特征做了 L2 归一化,推理时不归一化,相似度分数会失真,检索排序直接崩。
第三步:创建 Milvus 集合
代码示例 3:Milvus Lite 建集合 + HNSW 索引参数
from pymilvus import MilvusClient
# uri 指向本地文件即自动启用 Milvus Lite;生产环境改成 http://localhost:19530
client = MilvusClient(uri="multimodal_search.db")
COLLECTION = "image_gallery"
DIM = 1152 # 必须与模型输出维度一致,否则插入时报错
if client.has_collection(COLLECTION):
client.drop_collection(COLLECTION) # 演示场景先清库
client.create_collection(
collection_name=COLLECTION,
dimension=DIM,
primary_field_name="id", # 主键字段,auto_id 自动生成
vector_field_name="vector", # 向量字段名
metric_type="COSINE", # 相似度度量:归一化后用 COSINE 或 IP 均可
auto_id=True, # 主键自增
enable_dynamic_field=True, # 开启动态字段:filepath 等标量字段无需预定义
index_params={
"index_type": "HNSW", # 分层可导航小世界图索引,召回率/延迟均衡
"M": 16, # 每个节点的最大连接数,越大召回越高、内存越大
"efConstruction": 200, # 建索引时的动态列表大小,越大索引质量越高
},
)
print("集合创建完成")
第四步:批量灌库
代码示例 4:遍历图库批量向量化并写入
import os
from glob import glob
def build_index(image_dir: str, batch_size: int = 64):
"""批量将图片向量化后写入 Milvus,支持 jpg/png/webp"""
paths = []
for ext in ("*.jpg", "*.jpeg", "*.png", "*.webp"):
paths += glob(os.path.join(image_dir, "**", ext), recursive=True)
print(f"发现 {len(paths)} 张图片,开始灌库...")
for i in range(0, len(paths), batch_size):
batch = paths[i : i + batch_size]
rows = []
for p in batch:
try:
rows.append({"vector": encode_image(p), "filepath": p})
except Exception as e:
print(f"跳过损坏图片 {p}: {e}") # 单张失败不影响整体
if rows:
res = client.insert(collection_name=COLLECTION, data=rows)
print(f"灌库完成,当前集合行数: {client.get_collection_stats(COLLECTION)['row_count']}")
# build_index("./images_folder/train") # 换成你自己的图库目录
第五步:文搜图 + 图搜图
代码示例 5:文搜图——用一句话找图片
def search_by_text(query: str, top_k: int = 5) -> list[tuple[str, float]]:
"""文本查询 → 向量 → Milvus 检索 → 返回 (图片路径, 相似度)"""
q_vec = encode_text(query)
hits = client.search(
collection_name=COLLECTION,
data=[q_vec],
limit=top_k,
output_fields=["filepath"], # 需要返回的标量字段
)
return [(h["entity"]["filepath"], round(h["distance"], 4)) for h in hits[0]]
# 示例:查询 "a white dog"(英文效果最佳;中文建议用 SigLIP2 多语言版或 Chinese-CLIP)
for path, score in search_by_text("a white dog"):
print(f"{score:.4f} {path}")
代码示例 6:图搜图——上传一张图找相似图
def search_by_image(image_path: str, top_k: int = 5) -> list[tuple[str, float]]:
"""图片查询 → 向量 → Milvus 检索,实现以图搜图 / 相似图检测"""
q_vec = encode_image(image_path)
hits = client.search(
collection_name=COLLECTION,
data=[q_vec],
limit=top_k,
output_fields=["filepath"],
)
return [(h["entity"]["filepath"], round(h["distance"], 4)) for h in hits[0]]
# 示例:用图库里某张图查它的"近亲",可用于版权溯源/去重
for path, score in search_by_image("images_folder/train/n01440764/n01440764_10026.JPEG"):
print(f"{score:.4f} {path}")
到这里,一个可用的图文互检系统已经跑通了。
search_by_text和search_by_image底层是同一个 ANN 检索,区别只在于查询向量来自哪个编码塔——这就是「图文不分家」的数学基础。
第六步:封装为生产级 HTTP 服务
代码示例 7:FastAPI 封装(含批量请求与错误兜底)
from fastapi import FastAPI, UploadFile, File
from pydantic import BaseModel
app = FastAPI(title="多模态图文检索服务")
class TextQuery(BaseModel):
text: str
top_k: int = 5
@app.post("/search/text")
def text_search(q: TextQuery):
"""POST /search/text body: {"text": "a red car", "top_k": 10}"""
results = [{"filepath": p, "score": s} for p, s in search_by_text(q.text, q.top_k)]
return {"query": q.text, "results": results}
@app.post("/search/image")
def image_search(file: UploadFile = File(...)):
"""POST /search/image multipart 上传图片文件"""
tmp_path = f"/tmp/{file.filename}"
with open(tmp_path, "wb") as f:
f.write(file.file.read()) # 落盘后交给编码器
results = [{"filepath": p, "score": s} for p, s in search_by_image(tmp_path)]
return {"results": results}
启动服务:uvicorn main:app --host 0.0.0.0 --port 8000。生产环境中建议把模型加载做成全局单例(如上),避免每个请求重复加载权重;并发推理用 torch.cuda.amp 或 batching 进一步压吞吐。
关键细节与踩坑指南
这一节全部来自真实项目里踩过的坑,按频率排序。
坑 1:中文查询效果差。 原版 CLIP 的 tokenizer 是英文 BPE,对中文几乎无感知。中文字符被拆成字节级 token,语义完全丢失。解决方案有三种:① 用 Chinese-CLIP(阿里开源,中英双语图文对齐);② 用 SigLIP2 或 Qwen3-VL-Embedding 等多语言模型;③ 查询前先把中文翻译成英文(延迟高,不推荐做在线主路径)。
坑 2:忘记归一化导致相似度失真。 上面代码里 normalize 是命门。没归一化时,向量模长差异会主导内积结果,大图/长文本天然"更相似",排序彻底乱掉。
坑 3:维度不匹配报错。 Milvus 建集合时 dimension 必须精确等于模型输出维度。CLIP ViT-B/32 是 512,ViT-L/14 是 768,SigLIP SO400M 是 1152。换模型忘记重建集合,插入时直接抛异常。
坑 4:索引参数照抄默认值。 HNSW 三个参数是互相关联的:
M越大召回越高、内存和构建时间越大,一般 16~32;efConstruction控制建图质量,200~400 是常见区间;- 查询参数
ef每次搜索可单独传,越大召回越高但延迟越高,线上从 64 起步调。
# 查询时动态调整 ef,兼顾召回与延迟
client.search(
collection_name=COLLECTION,
data=[q_vec],
limit=10,
search_params={"ef": 128}, # 高召回场景调大,低延迟场景调小
)
坑 5:一次性向量化所有图片导致 OOM。 千万级图库不能一张张过(太慢)也不能全量塞显存(会爆)。正确姿势是 dataloader 分批 + FP16 推理:
def encode_batch(image_paths: list[str], batch_size: int = 32) -> list[list[float]]:
"""分批向量化,规避显存溢出;fp16 可再省一半显存"""
vecs = []
for i in range(0, len(image_paths), batch_size):
batch_imgs = [Image.open(p).convert("RGB") for p in image_paths[i:i+batch_size]]
inputs = processor(images=batch_imgs, return_tensors="pt")
with torch.no_grad():
feats = model.get_image_features(**inputs) # 注意 get_image_features 支持 batch
vecs.extend(torch.nn.functional.normalize(feats, p=2, dim=-1).tolist())
return vecs
坑 6:相似度度量的选择。 归一化后 COSINE 和 IP 数学等价,但 COSINE 语义更直观(分数范围 [-1,1])。如果未来要上量化(如 int8),IP 配合归一化向量通常更稳。别用 L2 欧氏距离,它和余弦相似度不等价,会改变排序。
坑 7:图像预处理差异。 SigLIP 的 384 分辨率比 224 分辨率召回高但推理慢;processor 内置的 resize/归一化参数必须用它自带的那套,自己用 cv2.resize 随手缩放会破坏分布。另外 convert("RGB") 必须加——灰度图、RGBA 图是生产数据里最常见的"隐形杀手"。
生产环境最佳实践
一套可直接复用的生产配置模板
# docker-compose.yml 片段:Milvus 2.6 Standalone 生产部署(最小高可用)
services:
etcd:
image: quay.io/coreos/etcd:v3.5.18
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
minio:
image: minio/minio:RELEASE.2024-01-16T16-07-38Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
milvus:
image: milvusdb/milvus:v2.6.5
command: ["milvus", "run", "standalone"]
ports:
- "19530:19530" # gRPC 客户端端口
# 生产连接配置:与 Milvus Lite 同一套 MilvusClient API,无缝切换
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus", # 生产务必改密码
)
双路召回 + 重排序,别裸奔单一向量
单一稠密向量的天花板很明显:CLIP 系模型对「颜色换一下」「构图细节不同」的商品图区分度不足。生产系统建议做混合检索(Hybrid Search):一路是 SigLIP/CLIP 稠密向量,另一路是图片关联文本的稀疏检索(BM25/Sparse),再用 RRF(Reciprocal Rank Fusion) 或重排序模型融合。Milvus 2.4+ 原生支持多向量字段,一个集合里同时存 dense 和 sparse 向量,一次查询并行召回再融合:
def reciprocal_rank_fusion(ranked_lists: list[list[str]], k: int = 60) -> list[tuple[str, float]]:
"""RRF 融合多路召回:按名次加权,不依赖分数绝对大小,抗分布漂移"""
scores: dict[str, float] = {}
for lst in ranked_lists:
for rank, doc in enumerate(lst):
scores[doc] = scores.get(doc, 0.0) + 1.0 / (k + rank + 1)
return sorted(scores.items(), key=lambda x: x[1], reverse=True)
监控与成本
- 监控三件套:查询 P99 延迟(目标 <50ms)、召回率(抽样人工标注 Top-10 命中率)、QPS 与索引内存占用。Milvus 暴露 Prometheus metrics,接入 Grafana 即可。
- 成本优化:① 向量降维——Jina v4 支持 MRL(Matryoshka Representation Learning) 截断到 256 维仍保持 95%+ 质量,存储直降 8 倍;② 量化——Milvus 支持 int8/FP16 标量量化,内存再减半;③ 冷热分层——老图放磁盘索引(DiskANN),热图放内存 HNSW。
- 数据一致性:图片库增量更新用 Milvus 的
upsert按主键覆盖,删除用delete按主键过滤,别全量重建。
横向对比与选型建议
| 模型 | 来源 | 参数 | 维度 | 模态 | 跨模态 R@1* | Modality Gap | 适合场景 |
|---|---|---|---|---|---|---|---|
| CLIP ViT-L-14 | OpenAI(2021) | 428M | 768 | 图文 | 0.768 | 0.83 | 老系统迁移/基线 |
| SigLIP SO400M | Google(2024) | 400M | 1152 | 图文 | 略优于CLIP | 较小 | 自托管、中文弱 |
| Jina CLIP v2 | Jina(2025) | ~1B | 1024 | 多语言图文 | 0.873 | 0.87 | 多语言图文互检 |
| Qwen3-VL-Embedding-2B | 阿里(2025) | 2B | 2048 | 图文/视频 | 0.945 | 0.25 | 开源首选、跨模态召回 |
| Gemini Embedding 2 | Google(2025) | 闭源 | 3072 | 文/图/视频/音频/PDF | 0.928 | 0.73 | 全模态、跨语言最强 |
| Voyage MM-3.5 | Voyage(2026) | 闭源 | 1024 | 图文/视频 | 0.900 | 0.59 | 均衡、MRL 友好 |
*跨模态 R@1 数据来自 Zilliz CCKM Benchmark(2026 年实测,200 图文对 + 600 hard negatives 干扰项)。
选型决策路径:
- 数据只有英文、预算敏感、自托管 → SigLIP 或 CLIP 系,几百 M 参数单卡可跑;
- 中文/多语言、要开源可控 → Jina CLIP v2(1B,多语言)或 Qwen3-VL-Embedding-2B(跨模态精度最高但显存要求高);
- 图片+视频+音频+PDF 全模态、不差钱 → Gemini Embedding 2,跨语言检索 0.997 近乎满分;
- 存储成本敏感 → Voyage MM-3.5 或 Jina v4(支持 MRL 截断到 256 维);
- 只是做相似图去重/版权溯源 → 不需要文本塔,CLIP 单视觉塔即可,别为用不上的能力付费。
性能实测与效果验证
CCKM Benchmark:2026 年跨模态检索实测
Zilliz 在 2026 年发布的 CCKM Benchmark 用 200 个 COCO 图文对 + 600 个 hard negatives(只差一两个细节的干扰描述)测试了 10 款模型,结果极具参考价值:
| 排名 | 模型 | 跨模态 R@1 | Modality Gap |
|---|---|---|---|
| 1 | Qwen3-VL-Embedding-2B | 0.945 | 0.25 |
| 2 | Gemini Embedding 2 | 0.928 | 0.73 |
| 3 | Voyage Multimodal 3.5 | 0.900 | 0.59 |
| 4 | Jina CLIP v2 | 0.873 | 0.87 |
| 5 | CLIP ViT-L-14(基线) | 0.768 | 0.83 |
关键结论:开源 2B 的 Qwen3-VL 反超所有闭源 API,modality gap(0.25)只有 Gemini 的三分之一、CLIP 的三成——2026 年做跨模态检索,开源已经不是妥协方案,而是首选方案。这也解释了为什么很多团队把老 CLIP 换掉后,图文召回率能提升 20 个百分点以上。
零样本 ImageNet 精度(OpenCLIP 模型库,2026 实测)
| 模型 | 训练数据 | 参数量 | Zero-shot ImageNet |
|---|---|---|---|
| ViT-L-14-quickgelu (CLIP) | WIT | 13B | 75.5% |
| ViT-SO400M-14-SigLIP-384 | WebLI | 45B | 83.1% |
| ViT-L-14 (DFN) | DFN-2B | 39B | 82.2% |
| ViT-H-14-378-quickgelu (DFN) | DFN-5B | 44B | 84.4% |
同样 224 输入,SigLIP 比 CLIP 高 6.5 个百分点;把输入分辨率提到 384 还能再涨。分辨率是免费午餐:推理资源够的话,优先选 384 及以上输入版本的模型。
总结与未来展望
多模态 Embedding 双塔架构把「以图搜图、文搜图、图搜文」统一成了向量最近邻检索:CLIP 用 softmax 对比损失奠定范式,SigLIP 用 sigmoid 损失解决训练稳定性和 batch 依赖,2025-2026 年的新一代模型(Qwen3-VL、Jina v2、Gemini Embedding 2)则通过更小的 modality gap 把跨模态召回精度推上新高。生产落地时记住四件事:归一化必须做、维度必须对齐、索引参数要按量调、双路召回 + RRF 别裸奔。未来这条路的演进方向很明确:MRL 降维与量化让存储成本持续走低、late-interaction(ColPali 式)弥补全局向量的细粒度短板、多模态 Embedding 与 VLM 生成式理解的前后端融合(召回 + 精排 + 推理)将成为标准检索流水线。