图文相似度(CLIP)
更新时间:2026-09-11
简介
CLIP 双塔图文相似度算子:图像过图像塔、文本过文本塔,两侧向量 L2 归一化后取余弦。算子只产出分数,不按 min/max 过滤,过滤交给 pipeline。
功能描述
- CLIP 封装复用内部模块
multimodal/_clip_dual_tower.py(transformersCLIPProcessor+CLIPModel),文本塔与图像塔各出一次归一化向量,相似度 = 两向量逐元素乘后求和,保留 6 位小数 - 文本塔按 CLIP 的 77 token 上限做
truncation=True, max_length=77,超长文本只有前 77 个 token 参与 - 只对「图像列非空 且 文本列非空(字符串去空白后非空)」的行做推理,其余行输出
None - 按
batch_size切微批,某个微批抛异常时只把该批的行留成None并记exception日志 - 图像统一
convert("RGB")后编码,pixel_values按dtype转精度;相似度计算在 float32 上做 - 设备为
cuda:(rank % 可见卡数)(use_gpu 且 CUDA 可用)否则 cpu;CPU 上指定float16会打 warning 并回退 float32 - 权重目录
{model_path}/{model_name}不存在时构造期抛FileNotFoundError,不联网下载 - 两列长度不一致时抛
ValueError
算子参数
输入
| 输入 | 含义 |
|---|---|
| images | 图像输入列,内容形式由 image_src_type 决定(URL/本地或 BOS 路径 / Base64 字符串 / 二进制) |
| texts | 文本列,与图像逐行配对;空串或空白串视为无效 |
输出
| 输出 | 含义 |
|---|---|
| sim | float64 —— 图文 CLIP 余弦相似度,取值 [-1, 1];任一侧为空或该微批失败时为 None |
参数
| 参数名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| image_src_type | str | "image_url" | 图像输入类型:image_url(本地/BOS 路径)、image_base64、image_binary |
| model_path | str | "/opt/aihc/model" | 权重根目录 |
| model_name | str | "openai/clip-vit-base-patch32" | 相对 model_path 的 CLIP 权重子目录 |
| dtype | str | "float32" | 权重精度:float16 / float32 / bfloat16;CPU 上 float16 回退 float32 |
| batch_size | int | 16 | 算子内部推理微批大小 |
| rank | int | 0 | 多卡场景 worker 序号,设备取 cuda:(rank % 可见卡数) |
注意事项
- CLIP 文本塔硬上限 77 token,长 caption 会被静默截断,长文本场景的分数不代表全文。
- 与
ImageTextMatchingScore(BLIP ITM 判别头)不可互换:一个是双塔归一化向量的余弦([-1,1]),一个是判别头概率([0,1]),阈值必须分别标定。 - 算子只出分,不带
min_score/max_score阈值过滤,过滤在 daft 侧用where()做。
调用示例
Python
1from __future__ import annotations
2
3import os
4
5import daft
6from daft import col
7
8from daft.aihc.common.udf import aihc_udf
9from daft.aihc.functions.multimodal.image_text_similarity import ImageTextSimilarity
10
11if __name__ == "__main__":
12 if os.getenv("DAFT_RUNNER", "native") == "ray":
13 import ray
14 ray.init(ignore_reinit_error=True)
15 daft.set_runner_ray()
16 daft.set_execution_config(actor_udf_ready_timeout=6000, min_cpu_per_task=0)
17
18image = "bos://your-bucket/sample.jpg"
19 ds = daft.from_pydict({"image": [image, image], "text": ["a photo", ""]})
20 ds = ds.with_column(
21 "sim",
22 aihc_udf(
23 ImageTextSimilarity,
24 construct_args={
25 "image_src_type": "image_url",
26 "model_path": "/path/to/models",
27 "model_name": "openai/clip-vit-base-patch32",
28 },
29 num_cpus=1,
30 num_gpus=1,
31 concurrency=1,
32 batch_size=2,
33 )(col("image"), col("text")),
34 )
35 ds.show()
评价此篇文章
