879 字
4 分钟
qdrant-compare-text
2025-04-09
无标签

Qdrant 是一种向量数据库,通过向量相似度搜索来实现文本相似度比较。 现代神经网络将对象转换为向量,使得现实世界中相似的对象(如意思相近的文本)在向量空间中也相互接近。

实现步骤#

1. 文本向量化(嵌入)#

首先需要将文本转换为向量表示。有以下几种方案:

  1. 使用预训练模型

    let model = FastEmbed::new();
    let vector1 = model.embed(&text1);
    let vector2 = model.embed(&text2);
  2. 与Qdrant客户端集成: Qdrant的Python客户端可以使用FastEmbed创建嵌入并上传到Qdrant,简化API并使其更直观。

2. 选择适当的距离度量#

Qdrant支持多种距离度量方式,为文本相似度比较提供了灵活性:

  1. 余弦相似度 (Cosine Similarity): 测量两个向量的相似程度,反映向量是否指向相同方向。通常用于比较文本表示,范围从-1到1,其中1表示最相似,-1表示完全不相似。

  2. 点积 (Dot Product): 另一种测量向量相似度的方法,与余弦相似度不同,它也考虑向量的长度。当向量表示基于词频构建时,这可能很重要。

  3. 欧几里得距离 (Euclidean Distance): 适用于某些应用场景,尤其是当向量在欧几里得空间中有意义时。

3. 优化性能和速度#

为了平衡性能和速度,Qdrant提供了多种优化策略:

  1. 余弦相似度的优化: Qdrant通过两步计算余弦相似度来提高搜索速度:第一步是在将向量添加到集合时对其进行标准化(仅执行一次),第二步是比较向量,这等同于点积运算,由于SIMD(单指令多数据)技术,这是一个非常快的操作。

  2. 量化技术: 标量量化是最通用的方法,提供良好的精度、速度和压缩之间的平衡。如果不适用二进制量化,建议作为默认的量化方法。

  3. 存储配置优化: 可以选择几种不同的策略组合:

    • 低内存+高速度:使用向量量化
    • 高精度+低内存:在磁盘上存储向量和HNSW索引
    • 高精度+高速度:将数据保存在RAM中,使用带重新评分的量化
  4. HNSW算法参数调整: 可以调整HNSW算法的ef参数或exact选项,在速度和精度之间取得平衡:

    • hnsw_ef:指定HNSW算法的ef参数
    • exact:不使用近似搜索(ANN)的选项,设置为true时,搜索可能运行较长时间,因为它执行全扫描以检索准确结果

示例#

// 1. 初始化客户端
let client = QdrantClient::new("http://localhost:6333");

// 2. 创建临时集合(使用余弦相似度)
let collection_name = "text_comparison";
client.create_collection(
    collection_name,
    VectorParams {
        size: 384, // 取决于你的嵌入模型的输出维度
        distance: Distance::Cosine,
    },
).await?;

// 3. 使用嵌入模型将文本转换为向量
let text1 = "第一段文本内容...";
let text2 = "第二段文本内容...";

// 假设有一个嵌入函数
let vector1 = get_embedding(text1);
let vector2 = get_embedding(text2);

// 4. 上传向量到Qdrant
client.upsert_points(
    collection_name,
    vec![
        PointStruct {
            id: 1,
            vector: vector1,
            payload: json!({"text": text1}),
        },
        PointStruct {
            id: 2,
            vector: vector2,
            payload: json!({"text": text2}),
        },
    ],
).await?;

// 5. 计算相似度(使用搜索API)
let search_result = client.search(
    collection_name,
    vector1,
    SearchParams {
        limit: 2,
        with_payload: true,
        ..Default::default()
    },
).await?;

// 解析结果,获取相似度分数
let similarity = search_result.iter()
    .find(|point| point.id == 2)
    .map(|point| point.score)
    .unwrap_or(0.0);

println!("两段文本的相似度: {}", similarity);
qdrant-compare-text
https://blog.lpkt.cn/posts/qdrant-compare-text/
作者
lollipopkit
发布于
2025-04-09
许可协议
CC BY-NC-SA 4.0