AI系统性学习05—向量数据库

农民  论坛元老 | 2024-8-19 08:52:31 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1000|帖子 1000|积分 3000

1、Chroma向量数据库

Chroma是一款开源的向量数据库,它使用向量相似度搜索技术,可以快速有用地存储和检索大规模高维向量数据。它的应用场景包括推荐系统、图像和视频搜索、自然语言处置处罚等领域,可以资助用户快速地找到相似的数据和信息。
Chroma是一款应用嵌入式数据库,以包的情势嵌入到我们的代码,Chroma的长处就是简单,假如你在开发LLM应用必要一个向量数据库实现LLM记忆功能,必要支持文本相似语言搜索,又不想安装独立的向量数据库,Chroma是不错的选择。
1.1 安装Chroma

  1. pip install chromadb
复制代码
1.2 初始化Chroma客户端

  1. import chromadb
  2. chroma_client = chromadb.client()
复制代码
1.3 创建一个合集

合集(collection)在chroma数据库中的作用就雷同表,存储向量数据(包括文档和其他源数据)的地方,下面创建一个聚集:
  1. # 创建集合
  2. collection = chroma_client.create_collection(name="test")
复制代码
1.4 添加数据

Chroma会存储我们的数据,并根据文本数据的向量创建专门的向量索引方便后面查询。


  • 使用内置的嵌入模子盘算向量
  1. # 假设这里是需要存储的文本
  2. text1 = "This is a document"
  3. text2 = "This is another document"
  4. # 使用内置的嵌入模型计算向量
  5. collection.add(
  6.     documents=[text1,text2],
  7.     metadatas=[{"source": "my_source"}, {"source": "my_source"}],
  8.     ids=["id1", "id2"]
  9. )
复制代码
  

  • documents参数就是必要写入的文本数据数组,支持一次插入多条数据
  • metadatas是每条写入的数据关联的一些属性
  • ids 是每条写入数据的id
  

  • 添加数据的时间指定向量值
  1. # 指定向量值
  2. collection.add(
  3.     embeddings=[[1.2, 2.3, 4.5], [6.7, 8.2, 9.2]],
  4.     documents=[text1, text2],
  5.     metadatas=[{"source": "my_source"}, {"source": "my_source"}],
  6.     ids=["id1", "id2"]
  7. )
复制代码
1.5 查询数据

  1. results = collection.query(
  2.     query_texts=["This is a query document"],
  3.     n_results=2
  4. )
复制代码
此中n为n个最相似的效果。默认环境下,Chroma中的数据是存储在内存中,重起程序数据就丢了,当然你可以设置Chroma的数据持久化到硬盘,这样程序启动的时间会去加载磁盘中的数据。
1.6 持久化数据

  1. client = chromadb.PersistentClient(path="/data/tizi365.db")
复制代码
客户端对象一些常用的函数
  1. client.reset() # 清空并完全重置数据库
复制代码
1.7 聚集操作

前面提到过,chromadb中的聚集雷同mysql中的数据表,因此其定名自己也存在一些限制:


  • 名称长度必须介于3到63个字符之间。
  • 名称必须以小写字母或数字开头和末端,中间可以包含点、破折号和下划线。
  • 名称不能包含两个连续的点。
  • 名称不能是有用的IP地址。
    创建聚集,必要指定聚集名称和一个可选的向量盘算函数(也叫embedding嵌入函数)。假如提供了嵌入函数,则必须在每次获取集适时提供它。必要注意的是,假如你在创建时间指定了向量盘算函数,则获取集适时也应该提供向量盘算函数。
1.7.1 创建聚集

  1. # 通过embedding_function参数指定向量计算函数,不指定则使用内置的函数
  2. collection = client.create_collection(name="my_collection", embedding_function=emb_fn)
复制代码
创建时间,还可以指定向量盘算方法,雷同如下:
  1. collection = client.create_collection(
  2.         name="collection_name",
  3.         metadata={"hnsw:space": "cosine"} # l2 是默认的计算方法
  4.     )
复制代码
1.7.2 获取聚集

  1. # 如果创建集合的使用指定了向量计算函数,引用集合的时候也要指定向量计算函数
  2. collection = client.get_collection(name="my_collection", embedding_function=emb_fn)
复制代码
1.7.3 删除聚集

  1. # 删除指定集合
  2. client.delete_collection(name="my_collection")
复制代码
1.7.4 其他操作

  1. collection.peek() # 返回集合中前 10 个数据的列表
  2. collection.count() # 返回集合中的数据总数
  3. collection.modify(name="new_name") # 重命名集合
复制代码
1.8 向聚集添加数据

使用.add方法将数据添加到Chroma,雷同如下:
  1. collection.add(
  2.     documents=["lorem ipsum...", "doc2", "doc3", ...],
  3.     metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
  4.     ids=["id1", "id2", "id3", ...]
  5. )
复制代码
假如 Chroma 收到一个文档列表(documents),它会主动使用聚集的嵌入函数对文档举行向量盘算(假如创建集适时未提供嵌入函数,则使用默认值)。Chroma 还会存储文档自己。假如文档太大,无法使用所选的嵌入函数盘算,则会出现非常。
每个文件都必须有一个唯一的ID(ids)。两次添加相同的 ID 会导致只存储初始值。可以为每个文档提供一个可选的元数据字典(metadatas)列表,以存储更多信息,用于支持查询的时间筛选数据。
或者,你也可以直接提供文档相关向量数据的列表,Chroma直接使用你填写的向量数据,而不会主动盘算向量。(但是必要注意的是提供的向量维度(长度)与聚集的维度不同等),则会出现非常。
你也可以将文档存储在其他地方,只需向 Chroma 提供向量数据和元数据列表即可。你可以使用 ids 将向量与存储在其他地方的文档关联起来。
  1. collection.add(
  2.     embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
  3.     metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
  4.     ids=["id1", "id2", "id3", ...]
  5. )
复制代码
  必要注意的是,向量数据库的焦点功能是基于向量数据的语义搜索,为减小向量数据库的大小,进步服从,我们可以选择在向量数据库存储向量数据和一些必要筛选的属性条件就行,其他数据,比方文章内容等数据,存储到其他专门的数据库中,只要通过id关联起来就可以了。
  1.9 查询聚集数据

  1. collection.query(
  2.     query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
  3.     n_results=10,
  4.     where={"metadata_field": "is_equal_to_this"},
  5.     where_document={"$contains":"search_string"}
  6. )
复制代码
查询将按序次返回与每个查询向量(query_embedding)最匹配的 n_results 个效果。可以提供一个可选的 where 过滤字典,根据与每个文档相关的元数据过滤效果。别的,还可提供一个可选的 where_document 过滤字典,用于根据文档内容过滤效果。
假如提供的 query_embeddings 与聚集的维度不同等,则会出现非常,为了确保向量维度同等,统一使用同一个文本嵌入模子盘算向量就行。
你也可以通过一组查询文本举行查询。Chroma 会首先使用聚集的嵌入函数盘算每一个查询文本的向量,然后使用生成的文本向量实行查询。
  1. # 直接通过文本查询,相似的内容,这里chroma会使用默认嵌入模型计算向量
  2. collection.query(
  3.     query_texts=["doc10", "thus spake zarathustra", ...],
  4.     n_results=10,
  5.     where={"metadata_field": "is_equal_to_this"},
  6.     where_document={"$contains":"search_string"}
  7. )
复制代码
另外可以使用.get从聚集中按照id查询数据
  1. collection.get(
  2.     ids=["id1", "id2", "id3", ...],
  3.     where={"style": "style1"}
  4. )
复制代码
.get 还支持 where 和 where_document 筛选器。假如没有提供 id,它将返回聚集中符合 where 和 where_document 筛选器的所有项目。
1.10 更新聚集数据

  1. # 根据id批量更新数据
  2. collection.update(
  3.     ids=["id1", "id2", "id3", ...],
  4.     embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
  5.     metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
  6.     documents=["doc1", "doc2", "doc3", ...],
  7. )
复制代码
假如在聚集中找不到 id,将记录错误并忽略更新。假如提供的文档没有相应的向量,将使用聚集的嵌入函数盘算向量。
1.11 删除聚集数据

Chroma 支持使用 .delete 按 id 从聚集中删除数据。与每个数据相关的向量、文档和元数据都将被删除。
  1. collection.delete(
  2.     ids=["id1", "id2", "id3",...],
  3.     where={"chapter": "20"}
  4. )
复制代码
1.12 向量盘算

默认环境下,Chroma 使用 Sentence Transformers的 all-MiniLM-L6-v2 模子盘算向量。该嵌入模子可以创建句子和文档向量。该嵌入模子功能在本地盘算机上运行,必要下载模子文件(这是主动完成的)。
前面的代码都是使用默认嵌入实现的,如今使用OpenAI提供的接口来完成嵌入并存入数据库中。
  1. import chromadb
  2. from chromadb.utils import embedding_functions
  3. from chromadb.api.types import Documents, EmbeddingFunction, Embeddings
  4. # 初始化客户端
  5. chroma_client = chromadb.Client()
  6. # 使用openai的嵌入接口
  7. openai_ef = embedding_functions.OpenAIEmbeddingFunction(
  8.     api_key="REPLACE BY YOUR KEY",
  9.     model_name="text-embedding-ada-002"
  10. )
  11. class MyEmbeddingFunction(EmbeddingFunction):
  12.     def __call__(self, texts: Documents) -> Embeddings:
  13.         return openai_ef.embed_with_retries(texts)
  14. # 创建集合
  15. collection = chroma_client.create_collection(name="test", embedding_function=MyEmbeddingFunction())
复制代码
2、Qdrant向量数据库

2.1 什么是Qdrant?

Qdrant是一个开源向量数据库,专为下一代AI应用程序计划。它是面向云原生的,并提供RESTful和gRPC API以管理嵌入。Qdrant的特性强盛,支持图像、语音和视频搜索,以及与AI引擎的集成。
2.2 什么是向量数据库?⭐️⭐️⭐️


向量数据库是一种专门计划用于高效存储和查询高维向量的数据库。在传统的OLTP和OLAP数据库中(如上图所示),数据以行和列的方式组织(这些被称为表),查询是基于这些列中的值举行的。然后,在某些应用中,如图像辨认、自然语言处置处罚和推荐系统,数据通常以高维空间中的向量表现,这些向量加上一个id和有用负载,就是我们存储在雷同于Qdrant的向量数据库中的元素。
在这个背景下,向量是对象或数据点(point)的数学表现,向量的每个元素对于对象的某个特征或者属性。比方,在图像辨认系统中,向量可以表现为一个图像,向量的每个元素代表像素值或该像素特征/描述符。在音乐推荐系统中,每个向量代表一首歌曲,向量的每个元素代表歌曲的每个特征,比如节奏、流派、歌词等。
向量数据库针对高维向量的高效存储和查询举行了优化,通常使用了专门的数据布局和索引技术,如条理式可导航小世界(HNSW,用于实现近似近来邻搜索)和乘积量化等。这些数据库能够在允许用户按照某个间隔度量尺度,找到与给定查询向量最接近的向量的同时,实现快速相似性和语义搜索。最常用的间隔度量尺度有欧式间隔、余弦相似度和点积,在Qdrant中这三种度量尺度得到了完全的支持。
以下是对这三种向量相似度算法的扼要先容:


  • 余弦相似度(Cosine Similarity) - 余弦相似度是一种权衡两个事物相似水平的方式。可以将其视为一把标尺,用于丈量两个点之间的间隔,但与其丈量间隔差异,它丈量的是两个事物之间的相似水平。它常用于文本中比较两个文档或句子之间的相似水平。余弦相似度的输出范围从0到1,此中0表现两个事物完全不相似,1表现两个事物完全相同。这是一种简单而有用的比较两个事物的方法!
  • 点积(Dot Product) - 点积相似度度量是另一种权衡两个事物相似水平的方式,雷同于余弦相似度。在处置处罚数字时,它通常用于机器学习和数据科学中。点积相似度通过将两组数字中的值相乘,然后将这些乘积加起来来盘算得到。和越高的总和意味着两组数字越相似。它就像一个权衡两组数字彼此匹配水平的比例尺。
  • 欧式间隔(Euclidean Distance) - 欧式间隔是一种丈量空间中两点之间间隔的方式,雷同于我们在舆图上丈量两个地方之间间隔的方式。它的盘算方式是找到两点坐标之间差值的平方和的平方根。这种间隔度量方式通常在机器学习中用于权衡两个数据点的相似性或差异性,换句话说,用于了解它们之间有多远。
2.3 为什么必要向量数据库?

使用向量数据库的其他利益包括:


  • 高维数据的高效存储和索引。
  • 能够处置处罚数十亿个数据点的大规模数据集。
  • 支持实时分析和查询。
  • 能够处置处罚来自图像、视频和自然语言文本等复杂数据范例所导出的向量。
  • 进步机器学习和人工智能应用的性能并淘汰耽误。
  • 与构建自定义解决方案相比,淘汰开发和部署时间和成本。
2.4 Qdrant快速入门



  • 使用docker安装Qdrant
  1. docker pull qdrant/qdrant
  2. docker run -p 6333:6333 -p 6334:6334 -v ~/data:/qdrant.storage:z qdrant/qdrant
复制代码


  • 访问WebUI:localhost:6333

  • 创建聚集(collections)
    Qdrant向量数据库的聚集概念可以类比MYSQL的表布局,用于统一存储同一类向量数据,聚集中存储的每一条数据,在Qdrant中称为点(points),这里的点有数学多少空间的点雷同的意思,代表向量在多少空间中的表现(你就当成一条数据对待就行)。
  1. PUT /collections/{collection_name}
  2. {
  3.     "vectors": {
  4.       "size": 300,
  5.       "distance": "Cosine"
  6.     }
  7. }
复制代码
  参数阐明:
  

  • collection_name 聚集名字(必填)
  • vectors 参数定义

    • size:向量的长度(也叫维度)

  • distance:向量相似度算法,紧张有“Cosine”、“Euclid”、"Dot"三种算法。
  

  • 添加向量 (Points)
    创建好聚集之后,我们可以向聚集添加向量数据,在Qdrant中向量数据使用point表现,一条point数据包括三部分id、payload(关联数据)、向量数据(vector)三部分。
  1. PUT /collections/{collection_name}/points
  2. {
  3.     "points": [
  4.         {
  5.             "id": "5c56c793-69f3-4fbf-87e6-c4bf54c28c26", // id
  6.             "payload": {"color": "red"}, // 关联的属性数据,通常业务这里可以关联业务的属性,例如:订单ID、商品ID、标题等等属性
  7.             "vector": [0.9, 0.1, 0.1] // 向量数据,代表当前业务数据的特征
  8.         }
  9.     ]
  10. }
复制代码


  • 向量搜索
    添加向量数据之后,我们可以通过向量举行语义相似度搜索。
  1. POST /collections/{collection_name}/points/search
  2. {
  3.     "vector": [0.2, 0.1, 0.9, 0.7], // 向量参数
  4.     "limit": 3 // 返回相似度最高的3条数据
  5. }
复制代码
必要将你搜索的内容,先转换为向量,然后再根据该向量在向量数量数据库中搜索。


  • 属性过滤
  1. // collection_name - 集合名字
  2. POST /collections/{collection_name}/points/search
  3. {
  4.     "filter": { // 这里主要用于过滤payload的关联属性,整体语法格式类似elasticsearch语法,这个参数是可选的
  5.         "must": [ //筛选color=red的point数据
  6.             {
  7.                 "key": "color",
  8.                 "match": {
  9.                     "value": "red"
  10.                 }
  11.             }
  12.         ]
  13.     },
  14.     "vector": [0.2, 0.1, 0.9, 0.7], // 向量参数
  15.     "limit": 3
  16. }
复制代码
2.5 QDrant聚集(Collections)

同一聚集内每个点的向量都必须具有相同的维度,并通过单一度量举行比较。定名向量可用于在单个点中包含多个向量,每个向量都可以有自己的维度和度量要求。
间隔度量用于权衡向量之间的相似性。度量的选择取决于向量获取的方式,特殊是神经网络编码器练习的方法。


  • 设置多租户

    • 应该创建多少个聚集?
      大多数环境下,只必要使用一个带有基于有用负载的分区的聚集。这种方法称为多租户。对于大多数用户来说,这是高效的,但是必要额外配置。
    • 何时应该创建多个聚集?
      当您有有限的用户数并且必要隔离时。这种方法更灵活,但可能更加昂贵,因为创建大量聚集可能会导致资源开销。别的,您必要确保它们不以任何方式相互影响,包括性能方面。

  • 创建聚集
  1. PUT /collections/{collection_name}
  2. {
  3.     "vectors": {
  4.       "size": 300,
  5.       "distance": "Cosine"
  6.     }
  7. }
复制代码


  • 删除聚集
  1. DELETE /collections/{collection_name}
复制代码


  • 更新聚集
    向量都存储在内存中以便快速访问。针对每个向量,可以将on_disk设置为ture,以便始终将所有向量存储在磁盘上。这将启用内存映射,适用于摄取大量数据。以下命令为存储了超过10000k向量段启用索引。
  1. PATCH /collections/{collection_name}
  2. {
  3.     "optimizers_config": {
  4.         "indexing_threshold": 10000
  5.     }
  6. }
复制代码


  • 获取聚集信息
  1. GET /collections/{collection_name}
复制代码
2.6 Qdrant向量数据(Points)

点(points)是Qdrant操作的焦点实体。一个点是由向量(vector)和可选载荷(payload)构成的记录。
您可以根据向量(矢量)相似性搜索在一个聚集中分组的点。更详细的过程描述在搜索和过滤部分中。
本节先容如何创建和管理矢量(向量)。
任何点(point)的修改操作都是异步的,并且分为两个步骤。在第一阶段,操作将被写入预写日记中。
此刻开始,即使机器供电停止,服务也不会丢失数据。


  • 点ID
    Qdrant支持使用64位无符号整数和UUID作为点的标识符。
    这意味着在每个请求中,可以使用UUID字符串来替代数字ID
  1. PUT /collections/{collection_name}/points
  2. {
  3.     "points": [
  4.         {
  5.             "id": "5c56c793-69f3-4fbf-87e6-c4bf54c28c26",
  6.             "payload": {"color": "red"},
  7.             "vector": [0.9, 0.1, 0.1]
  8.         }
  9.     ]
  10. }
复制代码


  • 上传数据
    为了优化性能,Qdrant支持批量加载数据点。也就是说,您可以在一次API调用中加载多个数据点到服务中。批量加载可以最大水平地淘汰网络连接的开销。
Qdrant API支持两种批量创建方式 - 记录导向和列导向。在内部,这些选项没有区别,只是为了方便交互。
  1. PUT /collections/{collection_name}/points
  2. {
  3.     "points": [
  4.         {
  5.             "id": 1,
  6.             "payload": {"color": "red"},
  7.             "vector": [0.9, 0.1, 0.1]
  8.         },
  9.         {
  10.             "id": 2,
  11.             "payload": {"color": "green"},
  12.             "vector": [0.1, 0.9, 0.1]
  13.         },
  14.         {
  15.             "id": 3,
  16.             "payload": {"color": "blue"},
  17.             "vector": [0.1, 0.1, 0.9]
  18.         }
  19.     ]
  20. }
复制代码


  • 更新数据点
    未指定的向量将保持稳定。所有给定的点都必须存在。
  1. PUT /collections/{collection_name}/points/vectors
  2. {
  3.     "points": [
  4.         {
  5.             "id": 1,
  6.             "vector": {
  7.                 "image": [0.1, 0.2, 0.3, 0.4]
  8.             }
  9.         },
  10.         {
  11.             "id": 2,
  12.             "vector": {
  13.                 "text": [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2]
  14.             }
  15.         }
  16.     ]
  17. }
复制代码


  • 删除向量
    该方法仅从给定点中删除指定的向量。其他向量将保持稳定。不会删除点。
  1. POST /collections/{collection_name}/points/vectors/delete
  2. {
  3.     "points": [0, 3, 100],
  4.     "vectors": ["text", "image"]
  5. }
复制代码
2.7 Qdrant关联数据(Payload)

Qdrant的一个紧张特性之一是能够在向量之外存储附加信息(存储管理业务属性)。在Qdrant术语中,这些附加信息被称为“负载”。
Qdrant允许您存储任何可以使用JSON表现的信息。


  • payload 范例
    除了存储负载外,Qdrant还允许您基于某些特定范例的值举行搜索。这个特性实现为搜索过程中的附加过滤器,并且可以让您在语义相似性之上嵌入自定义逻辑。
在过滤过程中,Qdrant将检查那些符合过滤条件的值的条件。假如存储的值范例不符合过滤条件,则被认为是未满足条件的。
简单来说,你可以提前设想好,存放哪些数据到json格式的数据中,然后将这个数据设置为对应向量的payload


  • 负载索引
    为了更有用地举行过滤搜索,Qdrant允许您通过指定字段的名称和范例来为负载字段创建索引。
    索引字段也会影响向量索引。
    在实践中,我们发起在那些可能最多限制效果的字段上创建索引。比方,使用对象ID的索引将比使用颜色的索引更高效,因为对象ID对于每个记录是唯一的,而颜色只有几个可能的值。
    在涉及多个字段的复合查询中,Qdrant将尝试首先使用最具限制性的索引。
    要为字段创建索引,可以使用以下内容:
    1. PUT /collections/{collection_name}/index
    2. {
    3.     "field_name": "要创建索引的字段名称",
    4.     "field_schema": "keyword"
    5. }
    复制代码
2.8 Qdrant搜索⭐️⭐️⭐️



  • 相似度搜索
    在很多表现学习应用程序中,搜索近来的向量是焦点要素。当代神经网络被练习成将对象转化为向量,使得在向量空间中相近的物体在现实世界中也相近。比方,具有相似含义的文本、视觉上相似的图片,或是属于相同流派的歌曲。

  • 相似度度量
    有很多方法来评估向量之间的相似度。在Qdrant中,这些方法被称为相似度度量。选择哪种度量取决于向量的获取方式,尤其是神经网络编码器练习的方法。
    Qdrant支持以下最常见的度量范例:
  • 点积:Dot
  • 余弦相似度:Cosine
  • 欧几里得间隔:Euclid

    Qdrant通过两个步骤盘算该度量,从而实现更高的搜索速度。第一步是在将向量添加到集适时举行向量归一化。这只对每个向量举行一次。
第二步是向量比较。在这种环境下,它等同于点积运算-由于SIMD的快速操作。
  1. POST /collections/{collection_name}/points/search
  2. {
  3.     "filter": {
  4.         "must": [
  5.             {
  6.                 "key": "city",
  7.                 "match": {
  8.                     "value": "伦敦"
  9.                 }
  10.             }
  11.         ]
  12.     },
  13.     "params": {
  14.         "hnsw_ef": 128,
  15.         "exact": false
  16.     },
  17.     "vector": [0.2, 0.1, 0.9, 0.7],
  18.     "limit": 3
  19. }
复制代码


  • 分页
    搜索和推荐API允许跳过搜索效果的前几个效果,并仅返回从某个特定偏移量开始的效果。
  1. POST /collections/{collection_name}/points/search
  2. {
  3.     "vector": [0.2, 0.1, 0.9, 0.7],
  4.     "with_vectors": true,
  5.     "with_payload": true,
  6.     "limit": 10,
  7.     "offset": 100
  8. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表