向量数据库Milvus理论

## 向量数据库

之前的实习中,曾经负责过构建向量数据库,当时使用的是milvus,相关代码在[ModelDataBase: Es和向量数据库Milvus的构建与数据存储 (gitee.com)](https://gitee.com/Liuxiaomj/ModelDataBase)和[milvus_support.py · 刘晓/ModelTraining - 码云 - 开源中国 (gitee.com)](https://gitee.com/Liuxiaomj/ModelTraining/blob/main/milvus_support.py)。训练数据集的清理和构建,相关代码在[DataClean: 模型训练Excel数据的清理 (gitee.com)](https://gitee.com/Liuxiaomj/DataClean)。

笔记开头,只介绍我曾经在构建和处理时遇到的一些问题。

首先,向量数据库的构建,我使用的embedding模型可在代码中找到,我用python写了对外的接口方便java程序调用(因为我熟悉使用java,没有第一时间考虑python构建),但是在后续构建中我发现,vector类型的向量vectorFloat在jdk版本低于16的时候不能用,stackflow中建议的加pom依赖也不行。其次,数据的结构和选择的索引也非常重要。java/python构建milvus的代码在仓库中,见上文链接。

以下为**C3/4 搭建并使用向量数据库**文章的学习和总结:

### 前序配置

这一部分参考上文中,milvus构建代码[milvus_support.py · 刘晓/ModelTraining - 码云 - 开源中国 (gitee.com)](https://gitee.com/Liuxiaomj/ModelTraining/blob/main/milvus_support.py)### 数据存储与计算流程

1. **数据库创建**:构建所需Fields,以embedding为单索引(之后加入function calling后可以使用embedding向量和timestamp标量的双索引模式进行数据查找)
2. **Field配置**:异步构建索引,后台构建,便于其他操作......
3. **匹配数据**:使用正则表达式匹配txt文件所需的数据......
4. **处理数据**:使用IO流以单个文件为单位读取数据并加以处理......
5. **Embedding**:python调用大模型,提供计算接口,将question传入,以此计算向量值,存入embedding......
6. **插入数据**:以单个文件为单位插入向量数据库中以保证数据的一致性......

### 内容

Milvus是向量数据库模型构建,EsServiceImpl是Es的构建,存储清理后的训练数据,检查查询效率,MilvusServiceImpl中存放向量数据库的构建代码。MilvusIndexConstans中是向量数据库的结构设计。embedding中是调用的专门计算embedding的小模型,对外提供接口,供java后端调用。

### Milvus

向Milvus向量数据库存储大模型问答对信息,python存储设置HNSW索引,对问题描述构建向量,修改索引参数但提升效果并不明显。调研发现,在少量不足百万数据下,构建合适的分区可以提升查询速度。

这里的数据已经读取并分割好存在excel表格中。

### 向量检索
**MMR检索**
最大边际相关性 (MMR, Maximum marginal relevance) 可以帮助我们在保持相关性的同时,增加内容的丰富度。

核心思想是在已经选择了一个相关性高的文档之后,再选择一个与已选文档相关性较低但是信息丰富的文档。这样可以在保持相关性的同时,增加内容的多样性,避免过于单一的结果。
Langchain的内置方法max_marginal_relevance_search已经帮我们首先了该算法,在执行max_marginal_relevance_search方法时,我们需要设置fetch_k参数,用来告诉向量数据库我们最终需要k个结果,向量数据库在搜索时会获取一个和问题相关的文档集,该文档集中的文档数量大于k,然后从中过滤出k个具有相关性同时兼顾多样性的文档。
```python
#向量数据库地址
persist_directory = 'docs/chroma/'
 
embedding = OpenAIEmbeddings()
 
vectordb = Chroma(
    persist_directory=persist_directory,
    embedding_function=embedding
)

#打印向量数据库中的文档数量
print(vectordb._collection.count())
```
然后先用similarity_search方法来查询一下,它应该会返回两篇相同的文档:
```python
question = "what did they say about matlab?"
docs_ss = vectordb.similarity_search(question,k=3)
 
docs_ss 
```
下面我们使用max_marginal_relevance_search方法来搜索:
```python
docs_mmr = vectordb.max_marginal_relevance_search(question,k=3)
 
docs_mmr
```
**单向量搜索**

指定目标集合名称、查询向量和所需的结果数。此操作返回一个结果集,其中包含最相似的向量、其 ID 以及与查询向量的距离。

下面是搜索与查询向量最相似的前 5 个实体的示例:

```python
# Single vector search
res = client.search(
    collection_name="test_collection", # Replace with the actual name of your collection
    # Replace with your query vector
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}} # Search parameters
)

# Convert the output to a formatted JSON string
result = json.dumps(res, indent=4)
print(result)
```

输出类似于以下内容:

```python
[
    [
        {
            "id": 0,
            "distance": 1.4093276262283325,
            "entity": {}
        },
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {}
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {}
        },
        {
            "id": 5,
            "distance": 0.7972343564033508,
            "entity": {}
        },
        {
            "id": 2,
            "distance": 0.5928734540939331,
            "entity": {}
        }
    ]
]
```

输出显示离查询向量最近的前 5 个相邻节点,包括其唯一 ID 和计算距离。

**批量向量搜索**

在批量向量搜索中,可以在字段中包含多个查询向量。系统并行处理这些向量,为每个查询向量返回一个单独的结果集,每个结果集都包含集合中找到的最接近的匹配项。

下面是从两个查询向量中搜索两组最相似实体的示例:

```python
# Bulk-vector search
res = client.search(
    collection_name="test_collection", # Replace with the actual name of your collection
    data=[
        [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104],
        [0.3172005263489739, 0.9719044792798428, -0.36981146090600725, -0.4860894583077995, 0.95791889146345]
    ], # Replace with your query vectors
    limit=2, # Max. number of search results to return
    search_params={"metric_type": "IP", "params": {}} # Search parameters
)

result = json.dumps(res, indent=4)
print(result)
```

输出类似于以下内容:

```python
[
    [
        {
            "id": 1,
            "distance": 1.3017789125442505,
            "entity": {}
        },
        {
            "id": 7,
            "distance": 1.2419954538345337,
            "entity": {}
        }
    ], # Result set 1
    [
        {
            "id": 3,
            "distance": 2.3358664512634277,
            "entity": {}
        },
        {
            "id": 8,
            "distance": 0.5642921924591064,
            "entity": {}
        }
    ] # Result set 2
]
```

结果包括两组最近邻,每个查询向量一组,展示了批量向量搜索一次处理多个查询向量的效率。

下表列出了搜索参数中所有可能的设置。

| **参数名称**          | **参数说明**                                                 |
| :-------------------- | :----------------------------------------------------------- |
| `metric_type`         | 如何测量向量嵌入之间的相似性。 可能的值为 、 和 ,默认为加载的索引文件的值。`IP``L2``COSINE` |
| `params.nprobe`       | 搜索期间要查询的单位数。 该值位于 [1, nlist[1]] 范围内。    |
| `params.level`        | 搜索精度级别。 可能的值为 、 和 ,默认值为 。值越高,结果越准确,但性能越慢。`1``2``3``1` |
| `params.radius`       | 查询向量和候选向量之间的最小相似度。 该值位于 [1, nlist[1]] 范围内。 |
| `params.range_filter` | 相似性范围,可以选择优化对属于该范围的向量的搜索。 该值位于 [top-K[2], ∞] 范围内。 |

(此图COPY官方文档)

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HalukiSan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值