向量数据库实战:选型、调优与落地~系列文章15:多模态向量搜索:图片、音频、视频统一检索的工程实现

多模态向量搜索:图片、音频、视频统一检索的工程实现 🖼️

🔥 本文是《向量数据库实战:选型、调优与落地》专栏第 15 篇

⏱️ 阅读时间:约 13 分钟


🎯 开篇:不只是文本

2025 年,AI 应用早已不局限于文本------

  • 淘宝"拍照搜同款":拍一张照片,找到相似商品 📸
  • 抖音内容推荐:根据视频内容推荐相似视频 🎬
  • Spotify 歌曲推荐:根据音频特征推荐相似音乐 🎵

这些背后的核心技术,就是多模态向量搜索!


🧠 多模态 Embedding 模型

核心思想

多模态模型 能把不同类型的媒体(文本、图片、音频)映射到同一个向量空间中。

复制代码
┌─────────────────────────────────────────────────────────┐
│              多模态向量空间                                │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  文本: "一只猫在草地上玩耍"                                │
│  → [0.12, -0.34, 0.56, ...]                             │
│       ↕ 距离很近!                                       │
│  图片: 🐱🌿(猫在草地上的照片)                            │
│  → [0.13, -0.33, 0.55, ...]                             │
│       ↕ 距离较远                                         │
│  图片: 🚗🏙️(城市汽车照片)                               │
│  → [0.89, 0.12, -0.45, ...]                             │
│                                                         │
│  文本和图片在同一个向量空间中!                              │
│  → 可以用文本搜图片,也可以用图片搜文本                     │
│                                                         │
└─────────────────────────────────────────────────────────┘

主流多模态模型

模型 类型 维度 支持模态 开源
CLIP 图文 512/768 文本+图片
SigLIP 图文 1024 文本+图片
ImageBind 多模态 1024 文本+图片+音频+视频+深度+热成像
Chinese-CLIP 图文(中文) 768 中文文本+图片
Jina CLIP v2 图文 768 文本+图片

💻 实战:图文混合搜索

Step 1:使用 CLIP 生成多模态向量

python 复制代码
import torch
from transformers import CLIPModel, CLIPProcessor

# 加载中文 CLIP 模型
model = CLIPModel.from_pretrained("OFA-Sys/chinese-clip-vit-large-patch14")
processor = CLIPProcessor.from_pretrained("OFA-Sys/chinese-clip-vit-large-patch14")

# 文本向量化
def encode_text(text):
    inputs = processor(text=[text], return_tensors="pt", padding=True)
    with torch.no_grad():
        text_features = model.get_text_features(**inputs)
    return text_features[0].numpy()

# 图片向量化
def encode_image(image_path):
    from PIL import Image
    image = Image.open(image_path)
    inputs = processor(images=image, return_tensors="pt")
    with torch.no_grad():
        image_features = model.get_image_features(**inputs)
    return image_features[0].numpy()

# 测试
text_vec = encode_text("一只可爱的猫咪")
image_vec = encode_image("cat_photo.jpg")

# 计算相似度
from numpy.linalg import norm
similarity = np.dot(text_vec, image_vec) / (norm(text_vec) * norm(image_vec))
print(f"文本和图片的相似度: {similarity:.4f}")

Step 2:存入向量数据库

python 复制代码
from pymilvus import Collection, FieldSchema, DataType

# 创建多模态集合
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema(name="content_type", dtype=DataType.VARCHAR, max_length=20),  # text/image/video
    FieldSchema(name="original_text", dtype=DataType.VARCHAR, max_length=65535),
    FieldSchema(name="image_url", dtype=DataType.VARCHAR, max_length=1024),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=768),  # CLIP 维度
]

schema = CollectionSchema(fields=fields)
collection = Collection("multimodal", schema)

# 插入文本数据
text_embedding = encode_text("向量数据库入门教程")
collection.insert([
    ["text"],           # content_type
    ["向量数据库入门教程"],  # original_text
    [""],               # image_url
    [text_embedding.tolist()]
])

# 插入图片数据
image_embedding = encode_image("tutorial_cover.jpg")
collection.insert([
    ["image"],
    [""],
    ["tutorial_cover.jpg"],
    [image_embedding.tolist()]
])

Step 3:跨模态搜索

python 复制代码
# 用文本搜索图片!
collection.load()

query_text = "教程封面图片"
query_embedding = encode_text(query_text)

results = collection.search(
    data=[query_embedding.tolist()],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 128}},
    limit=5,
    expr='content_type == "image"',  # 只搜图片
    output_fields=["content_type", "original_text", "image_url"]
)

# 用图片搜索文本!
query_image = encode_image("some_photo.jpg")
results = collection.search(
    data=[query_image.tolist()],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 128}},
    limit=5,
    expr='content_type == "text"',  # 只搜文本
    output_fields=["content_type", "original_text"]
)

📊 多模态搜索应用场景

应用场景 查询方式 检索目标 典型案例
以图搜图 图片 → 图片 相似图片 淘宝拍照搜同款
以文搜图 文本 → 图片 匹配的图片 素材网站搜索
以图搜文 图片 → 文本 图片描述/相关文档 图片内容理解
跨模态推荐 文本 → 图文混合 图文内容 小红书推荐
视频检索 文本/图片 → 视频帧 视频关键帧 视频内容搜索

🏗️ 视频搜索架构

复制代码
┌─────────────────────────────────────────────────────────┐
│              视频向量搜索架构                               │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  输入视频                                                │
│       │                                                 │
│       ▼                                                 │
│  ┌──────────────┐                                       │
│  │  视频抽帧      │  每秒抽 1 帧 / 关键帧检测              │
│  └──────┬───────┘                                       │
│         │                                               │
│         ▼                                               │
│  ┌──────────────┐                                       │
│  │  帧向量化      │  CLIP 对每帧生成向量                   │
│  └──────┬───────┘                                       │
│         │                                               │
│         ▼                                               │
│  ┌──────────────┐                                       │
│  │  视频向量聚合   │  平均池化 / 最大池化                    │
│  │              │  将 N 帧向量 → 1 个视频向量              │
│  └──────┬───────┘                                       │
│         │                                               │
│         ▼                                               │
│  ┌──────────────┐                                       │
│  │  向量数据库    │  存储视频向量 + 元数据                  │
│  │              │  (视频URL、时间戳、标签)                 │
│  └──────────────┘                                       │
│                                                         │
│  查询: "找一段日落的海边视频"                               │
│  → 文本向量化 → 向量搜索 → 返回匹配视频                    │
│                                                         │
└─────────────────────────────────────────────────────────┘

⚠️ 多模态搜索的坑

说明 解决方案
模型选择 不同模型的向量空间不兼容 同一集合必须用同一模型
中文支持 原版 CLIP 中文效果差 用 Chinese-CLIP
图片预处理 尺寸、格式不统一 统一 resize 到模型要求
向量维度 不同模态维度可能不同 确认模型输出维度一致
存储成本 图片/视频占空间 只存向量+URL,原始文件存 OSS

🔑 本篇核心要点回顾

要点 说明
多模态模型 CLIP/Chinese-CLIP 将文本和图片映射到同一空间
跨模态搜索 可以用文本搜图片,也可以用图片搜文本
视频搜索 抽帧 → 向量化 → 聚合 → 存储
中文场景 推荐 Chinese-CLIP 或 Jina CLIP v2
存储策略 向量存数据库,原始文件存 OSS

📌 下篇预告:《Milvus 分布式部署实战:从单机到集群的完整踩坑记录 🏗️》

💬 有问题欢迎评论区讨论,觉得有用请点赞收藏 👍

作者:高炉炼铁智能化技术研究者,专注钢铁冶金与人工智能 交叉领域。

👍 如果觉得有帮助,请点赞、收藏、转发!

版权归作者所有,未经许可请勿抄袭,套用,商用(或其它具有利益性行为)

🔔 关注专栏,不错过后续精彩内容

相关推荐
骏晔科技DreamLNK12 小时前
国产蓝牙模块哪个品牌好?骏晔科技 7 款主流型号横向对比
人工智能·科技
kirs_ur12 小时前
ECC & LDPC — SSD 的数据卫士
服务器·数据库·性能优化
用户9385156350712 小时前
从零搭建 AI 日记助手:用 Milvus 向量数据库 + RAG 让机器读懂你的每一天
javascript·人工智能·全栈
是三一seven13 小时前
Sql注入基础
数据库·安全·网络安全
Sirens.13 小时前
MySQL表设计进阶-约束范式连接索引与事务
android·数据库·mysql
阿部多瑞 ABU14 小时前
新帝国殖民主义:文化-情感-金融复合体的当代运作机制
大数据·人工智能·金融
thesky12345614 小时前
27届大模型岗面试准备(三):位置编码全景——从绝对编码到 RoPE/ALiBi 的演进与手推
人工智能·ai·大模型
动恰客流统计14 小时前
ReID边缘计算视觉统计:餐饮店客流增长的数字化破局路径
java·大数据·运维·人工智能
字节跳动开源15 小时前
火山引擎开源 Agent 驱动的搜索自迭代技术
数据库·开源·agent