> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# LangChain-Milvus混合向量搜索
- URL: https://www.hubwiz.com/blog/langchain-milvus-hybrid-search/
- Published: 2024-11-21T23:21:50.000Z
- Updated: 2024-11-21T23:21:50.000Z
- Description: 在这篇博文中，我们将简要介绍密集嵌入和稀疏嵌入之间的区别，以及如何使用混合搜索来利用这两者。
- Author: admin
- Tags: LIBRARY, LANGCHAIN, MILVUS, LANGCHAIN-MILVUS, VECTOR DATABASE, TF-IDF, BM25, ELASTICSEARCH, SPLADE, #Import 2026-10-14 14:41

最近，IBM Research 需要在[ Milvus](https://milvus.io/?ref=hubwiz.com) 向量存储中使用混合搜索。由于我们已经在使用 [LangChain](https://www.langchain.com/?ref=hubwiz.com) 框架，因此我们决定撸起袖子，贡献出在[ langchain-milvus ](https://github.com/langchain-ai/langchain-milvus?ref=hubwiz.com)中启用它所需的一切。其中包括通过 langchain 接口支持稀疏嵌入 (PR) 和多向量搜索 (PR)。

在这篇博文中，我们将简要介绍密集嵌入和稀疏嵌入之间的区别，以及如何使用混合搜索来利用这两者。我们还将提供代码演示，演示如何在 langchain-milvus 中使用这些新功能。

要使用本博文中的代码，你应该安装一些软件包：

```
pip install langchain_milvus==0.1.6
pip install langchain-huggingface==0.1.0
pip install "pymilvus[model]==2.4.8"
```

并导入以下内容：

```
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_milvus.utils.sparse import BM25SparseEmbedding
from langchain_milvus.vectorstores import Milvus
```

你还可以在此[要点](https://gist.github.com/omriel1/3b8ea57cc14b896237c47d5417eaec8f?ref=hubwiz.com)中查看和克隆整个代码。

开始吧。

## 1、密集嵌入

使用向量存储的最常见方式是使用密集嵌入。在这里，我们使用预先训练的模型将数据（通常是文本，但也可以是其他媒体，如图像等）嵌入到高维向量中，并将其存储在向量数据库中。这些向量有几百个（甚至几千个）维度，每个条目都是浮点数。通常，向量中的所有条目都由非零值占据，因此有“密集”一词。给定一个查询，我们使用相同的模型将其嵌入，向量存储根据向量相似性检索类似的相关数据。使用 langchain-milvus，只需几行代码。让我们看看它是如何完成的。

首先，我们使用 HuggingFace 中的模型定义向量存储：

```
dense_embedding = HuggingFaceEmbeddings(model_name=
    "sentence-transformers/all-MiniLM-L6-v2")
vector_store = Milvus(
    embedding_function=dense_embedding,
    connection_args={"uri": "./milvus_dense.db"}, # Using milvus-lite for simplicity
    auto_id=True,
)
```

其次，我们将数据插入向量存储：

```
document = [
    "Today was very warm during the day but cold at night",
    "In Israel, Hot is a TV provider that broadcasts 7 days a week",
]
vector_store.add_texts(documents)
```

在后台，每个文档都使用我们提供的模型嵌入到向量中，并与原始文本一起存储。

最后，我们可以搜索查询并打印得到的结果：

```
query = "What is the weather? is it hot?"
dense_output = vector_store.similarity_search(query=query, k=1)
print(f"Dense embeddings results:\n{dense_output[0].page_content}\n")

# output: Dense embeddings results: 
#         Today was very warm during the day but cold at night
```

在这里，查询被嵌入，向量存储执行（通常是近似的）相似性搜索并返回找到的最接近的内容。

密集嵌入模型经过训练，可以捕获数据的语义含义并将其表示在多维空间中。其优势很明显——它支持语义搜索，这意味着结果基于查询的含义。但有时这还不够。如果您寻找特定的关键字，甚至是没有更广泛含义的单词（如名称），语义搜索就会误导您，这种方法就会失败。

## 2、稀疏嵌入

在 LLM 出现之前，学习模型还没有那么流行，搜索引擎使用传统方法（如 [TF-IDF](https://en.wikipedia.org/wiki/Tf%E2%80%93idf?ref=hubwiz.com) 或其现代增强方法 [BM25](https://en.wikipedia.org/wiki/Okapi%5FBM25?ref=hubwiz.com)（因其在 [Elastic ](https://www.elastic.co/blog/practical-bm25-part-1-how-shards-affect-relevance-scoring-in-elasticsearch?ref=hubwiz.com)中的使用而闻名））来搜索相关数据。使用这些方法，维度的数量是词汇量（通常为数万，比密集向量空间大得多），每个条目代表关键字与文档的相关性，同时考虑到该术语的频率及其在文档语料库中的稀有性。对于每个数据点，大多数条目都是零（表示未出现的单词），因此有“稀疏”一词。虽然底层实现不同，但使用 langchain-milvus 界面会变得非常相似。让我们看看它的实际效果：

```
sparse_embedding = BM25SparseEmbedding(corpus=documents)
vector_store = Milvus(
    embedding_function=sparse_embedding,
    connection_args={"uri": "./milvus_sparse.db"},
    auto_id=True,
)
vector_store.add_texts(documents)

query = "Does Hot cover weather changes during weekends?"
sparse_output = vector_store.similarity_search(query=query, k=1)
print(f"Sparse embeddings results:\n{sparse_output[0].page_content}\n")

# output: Sparse embeddings results:
#         In Israel, Hot is a TV provider that broadcast 7 days a week
```

BM25 对于精确关键字匹配非常有效，这对于缺乏明确语义含义的术语或名称非常有用。但是，它不会捕捉查询的意图，并且在需要语义理解的许多情况下会产生较差的结果。

> 注意：“稀疏嵌入”一词也指 SPLADE或 Elastic Elser 等高级方法。这些方法也可以与 Milvus 一起使用，并可以集成到混合搜索中！

![](https://www.hubwiz.com/blog/content/images/2024/11/image-1520.png)

## 3、混合搜索

如果你在上面两个示例之间交换查询，并将每个查询与另一个嵌入一起使用，则两者都会产生错误的结果。这表明每种方法都有其优点，但也有其缺点。混合搜索结合了两者，旨在充分利用两全其美。通过使用密集和稀疏嵌入对数据进行索引，我们可以执行考虑语义相关性和关键字匹配的搜索，并根据自定义权重平衡结果。同样，内部实现更复杂，但 langchain-milvus 使其使用起来非常简单。让我们看看它是如何工作的：

```
vector_store = Milvus(
    embedding_function=[
        sparse_embedding,
        dense_embedding,
    ],
    connection_args={"uri": "./milvus_hybrid.db"}, 
    auto_id=True,
)
vector_store.add_texts(documents)
```

在此设置中，稀疏和密集嵌入均适用。让我们测试具有相等权重的混合搜索：

```
query = "Does Hot cover weather changes during weekends?"
hybrid_output = vector_store.similarity_search(
    query=query,
    k=1,
    ranker_type="weighted",
    ranker_params={"weights": [0.49, 0.51]},  # Combine both results!
)
print(f"Hybrid search results:\n{hybrid_output[0].page_content}")

# output: Hybrid search results:
#         In Israel, Hot is a TV provider that broadcast 7 days a week
```

这会使用每个嵌入函数搜索类似结果，为每个分数赋予权重，并返回具有最佳加权分数的结果。我们可以看到，如果对密集嵌入赋予稍微多一点的权重，我们就会得到我们想要的结果。对于第二个查询也是如此。

如果我们对密集嵌入赋予更多权重，我们将再次得到不相关的结果，就像单独使用密集嵌入一样：

```
query = "When and where is Hot active?"
hybrid_output = vector_store.similarity_search(
    query=query,
    k=1,
    ranker_type="weighted",
    ranker_params={"weights": [0.2, 0.8]},  # Note -> the weights changed
)
print(f"Hybrid search results:\n{hybrid_output[0].page_content}")

# output: Hybrid search results:
#         Today was very warm during the day but cold at night
```

在密集和稀疏之间找到适当的平衡并非易事，可以看作是更广泛的超参数优化问题的一部分。目前正在进行的研究和工具试图解决该领域的此类问题，例如 IBM 的 [AutoAI for RAG](https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/autoai-programming-rag.html?context=wx&audience=wdp&ref=hubwiz.com#autorag-implement)。

你可以通过更多方式调整和使用混合搜索方法。例如，如果每个文档都有一个关联的标题，则可以使用两个密集嵌入函数（可能使用不同的模型）——一个用于标题，另一个用于文档内容——并对两个索引执行混合搜索。Milvus 目前支持最多 10 个不同的向量字段，为复杂的应用程序提供了灵活性。索引和重新排序方法还有其他配置。你可以查看[ Milvus 文档](https://milvus.io/docs/multi-vector-search.md?ref=hubwiz.com)，了解可用的参数和选项。

## 4、结束语

现在可以通过 LangChain 访问 Milvus 的多向量搜索功能，轻松地将混合搜索集成到你的应用程序中。这为在你的应用程序中应用不同的搜索策略开辟了新的可能性，使你可以很容易地定制搜索逻辑以适应特定的用例。对我们来说，这是一个为开源项目做出贡献的好机会。我们每天使用的许多库和工具都是开源的，回馈社区是件好事。希望这对其他人有用。

---

原文链接：[Dance Between Dense and Sparse Embeddings: Enabling Hybrid Search in LangChain-Milvus](https://towardsdatascience.com/dance-between-dense-and-sparse-embeddings-enabling-hybrid-search-in-langchain-milvus-7c8de54dda24?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处