ChromaDB教程

使用 Chroma DB,管理文本文档、将文本嵌入以及进行相似度搜索。

随着大型语言模型 (LLM) 及其应用的兴起,我们看到向量数据库越来越受欢迎。这是因为使用 LLM 需要一种与传统机器学习模型不同的方法。

LLM 的核心支持技术之一是向量嵌入。虽然计算机不能直接理解文本,但嵌入以数字表示文本。所有用户提供的文本都将转换为嵌入,用于生成响应。

将文本转换为嵌入是一个耗时的过程。为了避免这种情况,我们使用专门设计的矢量数据库,用于有效存储和检索矢量嵌入。在本教程中,我们将了解矢量存储和 Chroma DB,这是一个用于存储和管理嵌入的开源数据库。此外,我们将学习如何添加和删除文档、执行相似性搜索以及将文本转换为嵌入。

什么是矢量存储?

向量存储是专门为有效地存储和检索向量嵌入而设计的数据库。之所以需要它们,是因为像 SQL 这样的传统数据库没有针对存储和查询大型向量数据进行优化。

嵌入在高维空间中以数字向量格式表示数据(通常是非结构化数据,如文本)。传统的关系数据库不太适合存储和搜索这些向量表示。

向量存储可以使用相似性算法对相似的向量进行索引和快速搜索。它允许应用程序在给定目标向量查询的情况下查找相关向量。

在个性化聊天机器人的情况下,用户输入生成式 AI 模型的提示。然后,该模型使用相似性搜索算法在文档集合中搜索相似文本。然后,由此产生的信息用于生成高度个性化和准确的响应。这是通过在向量存储中嵌入和向量索引来实现的。

什么是ChromaDB?

Chroma DBicon-default.png?t=N7T8https://docs.trychroma.com/ChromaDB是一个开源矢量存储,用于存储和检索矢量嵌入。它的主要用途是保存嵌入和元数据,以便以后由大型语言模型使用。此外,它还可用于文本数据的语义搜索引擎。

Chroma DB主要特点:

  • 支持不同的底层存储选项,例如用于独立的 DuckDB 或用于可扩展性的 ClickHouse。
  • 提供 Python 和 JavaScript/TypeScript 的 SDK。
  • 专注于简单性、速度和支持性分析。

ChromaDB是如何工作的?

  1. 首先,必须创建一个类似于关系数据库中的表的集合。默认情况下,Chroma 使用 将文本转换为嵌入,但您可以修改集合以使用其他嵌入模型。all-MiniLM-L6-v2
  2. 将具有元数据和唯一 ID 的文本文档添加到新创建的集合中。当您的收藏收到文本时,它会自动将其转换为嵌入。
  3. 通过文本或嵌入查询集合以接收相似的文档。您还可以根据元数据筛选出结果。

在下一部分中,我们将使用 Chroma 和 OpenAI API 来创建我们自己的矢量数据库。

ChromaDB入门

在本节中,将创建一个向量数据库,添加集合,向集合添加文本,并执行查询搜索。

首先,我们将为向量数据库和更好的嵌入模型安装。确保您已设置 OpenAI API 密钥。

注意:Chroma 需要 SQLite 3.35 或更高版本。如果遇到问题,请升级到 Python 3.11 或安装旧版本的Chroma

# 环境安装
!pip install chromadb openai 

您可以通过创建不带设置的 Chroma DB 客户端来创建用于测试的内存数据库。

在我们的例子中,我们将创建一个持久数据库,该数据库将存储在“db/”目录中,并在后端使用 DuckDB。

import chromadb
from chromadb.config import Settingsclient = chromadb.Client(Settings(chroma_db_impl="duckdb+parquet",persist_directory="db/"))

之后,我们将使用客户端创建一个集合对象。它类似于在传统数据库中创建表。

collection = client.create_collection(name="Students")

为了将文本添加到我们的集合中,我们需要生成有关学生、俱乐部和大学的随机文本。您可以使用 ChatGPT 生成随机文本。这很简单。

student_info = """
Alexandra Thompson, a 19-year-old computer science sophomore with a 3.7 GPA,
is a member of the programming and chess clubs who enjoys pizza, swimming, and hiking
in her free time in hopes of working at a tech company after graduating from the University of Washington.
"""club_info = """
The university chess club provides an outlet for students to come together and enjoy playing
the classic strategy game of chess. Members of all skill levels are welcome, from beginners learning
the rules to experienced tournament players. The club typically meets a few times per week to play casual games,
participate in tournaments, analyze famous chess matches, and improve members' skills.
"""university_info = """
The University of Washington, founded in 1861 in Seattle, is a public research university
with over 45,000 students across three campuses in Seattle, Tacoma, and Bothell.
As the flagship institution of the six public universities in Washington state,
UW encompasses over 500 buildings and 20 million square feet of space,
including one of the largest library systems in the world.

 现在,我们将使用该函数添加带有元数据和唯一 ID 的文本数据。之后,Chroma 将自动下载模型以将文本转换为嵌入并将其存储在“Students”集合中。addall-MiniLM-L6-v2

collection.add(documents = [student_info, club_info, university_info],metadatas = [{"source": "student info"},{"source": "club info"},{'source':'university info'}],ids = ["id1", "id2", "id3"]
)

要运行相似性搜索,您可以使用该函数并以自然语言提问。它会将查询转换为嵌入,并使用相似性算法得出类似的结果。在我们的例子中,它返回了两个类似的结果。query

results = collection.query(query_texts=["What is the student name?"],n_results=2
)results

嵌入

使用其它模型

from chromadb.utils import embedding_functions
openai_ef = embedding_functions.OpenAIEmbeddingFunction(model_name="text-embedding-ada-002")
students_embeddings = openai_ef([student_info, club_info, university_info])
print(students_embeddings)

更新和删除数据 

就像关系数据库一样,您可以更新或删除集合中的值。为了更新文本和元数据,我们将提供记录和新文本的特定 ID。

collection2.update(ids=["id1"],documents=["Kristiane Carina, a 19-year-old computer science sophomore with a 3.7 GPA"],metadatas=[{"source": "student info"}],
)

运行一个简单的查询以检查是否已成功进行更改。

results = collection2.query(query_texts=["What is the student name?"],n_results=2
)results

 验证结果

要从集合中删除记录,我们将使用“删除”功能并指定唯一 ID。

collection2.delete(ids = ['id1'])results = collection2.query(query_texts=["What is the student name?"],n_results=2
)results

 学生信息文本已被删除;取而代之的是,我们得到了下一个最好的结果。

其它管理 操作

# 创建客户端
# client = chromadb.Client() 内存模式
client = chromadb.PersistentClient(path="./chromac")  # 数据保存在磁盘
# chroma_client = chromadb.HttpClient(host="localhost", port=8000) docker客户端模式
# 遍历集合
client.list_collections()
# 创建新集合
collection = client.create_collection("testname")
# 获取集合
collection = client.get_collection("testname")
# 创建或获取集合
collection = client.get_or_create_collection("testname")
# 删除集合
client.delete_collection("testname")
# 创建或获取集合
collection = client.get_or_create_collection(name="my_collection2")
# collection = client.create_collection(name="my_collection2")
# collection = client.create_collection(name="my_collection", embedding_function=emb_fn)
# collection = client.get_collection(name="my_collection", embedding_function=emb_fn)
# Chroma集合创建时带有一个名称和一个可选的嵌入函数。如果提供了嵌入函数,则每次获取集合时都必须提供。
# 获取集合中最新的5条数据
collection.peek()
# 添加数据
collection.add(documents=["2022年2月2号,美国国防部宣布:将向欧洲增派部队,应对俄乌边境地区的紧张局势.", " 2月17号,乌克兰军方称:东部民间武装向政府军控制区发动炮击,而东部民间武装则指责乌政府军先动用了重型武器发动袭击,乌东地区紧张局势持续升级"],metadatas=[{"source": "my_source"}, {"source": "my_source"}],ids=["id1", "id2"]
)
# 如果 Chroma 收到一个文档列表,它会自动标记并使用集合的嵌入函数嵌入这些文档(如果在创建集合时没有提供嵌入函数,则使用默认值)。Chroma也会存储文档本身。如果文档过大,无法使用所选的嵌入函数嵌入,则会出现异常。
# 每个文档必须有一个唯一的相关ID。尝试.添加相同的ID两次将导致错误。可以为每个文档提供一个可选的元数据字典列表,以存储附加信息并进行过滤。
# 或者,您也可以直接提供文档相关嵌入的列表,Chroma将存储相关文档,而不会自行嵌入。
# collection.add(
#     embeddings=[[1.2, 2.3, 4.5], [6.7, 8.2, 9.2]],
#     documents=["This is a document", "This is another document"],
#     metadatas=[{"source": "my_source"}, {"source": "my_source"}],
#     ids=["id1", "id2"]
# )
# 改数据
# 更新所提供 id 的嵌入、元数据或文档。
def update(ids: OneOrMany[ID],embeddings: Optional[OneOrMany[Embedding]] = None,metadatas: Optional[OneOrMany[Metadata]] = None,documents: Optional[OneOrMany[Document]] = None) -> None
# 更新所提供 id 的嵌入、元数据或文档,如果不存在,则创建它们。
def upsert(ids: OneOrMany[ID],embeddings: Optional[OneOrMany[Embedding]] = None,metadatas: Optional[OneOrMany[Metadata]] = None,documents: Optional[OneOrMany[Document]] = None) -> None          
# 删除数据
# 根据 ID 和/或 where 过滤器删除嵌入数据
def delete(ids: Optional[IDs] = None,where: Optional[Where] = None,where_document: Optional[WhereDocument] = None) -> None
# collection.delete(ids=["3", "4", "5"])
# 查询数据
results = collection.query(query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],n_results=10,where={"metadata_field": "is_equal_to_this"},where_document={"$contains":"search_string"}
)
或者:
results = collection.query(query_texts=["俄乌战争发生在哪天?"],n_results=2
)
print(156, results)
156 {'ids': [['id1', 'id2']], 'embeddings': None, 'documents': [['2022年2月2号,美国国防部宣布:将向欧洲增派部队,应对俄乌边境地区的紧张局势.',' 2月17号,乌克兰军方称:东部民间武装向政府军控制区发动炮击,而东部民间武装则指责乌政府军先动用了重型武器发动袭击,乌东地区紧张局势持续升级']], 'metadatas': [[{'source': 'my_source'}, {'source': 'my_source'}]], 'distances': [[1.2127416133880615, 1.3881784677505493]]}

LangChanWithChromaDB

接下来查看LangChain中结合ChromaDB使用

# /home/knowqa/know_env/lib/python3.10/site-packages/langchain/vectorstores
from langchain.vectorstores import Chroma# langchain 默认文档 collections [Collection(name=langchain)]
# 持久化数据
persist_directory = './chromadb'
vectordb = Chroma.from_documents(documents=docs, embedding=embedding, persist_directory=persist_directory)
vectordb.persist()
# 直接加载数据
vectordb = Chroma(persist_directory="./chromadb", embedding_function=embeddings)
eg:
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.document_loaders import TextLoader
import os
os.environ["OPENAI_API_KEY"] = 'sk-xxxxxx'
loader = TextLoader('./russia.txt', encoding='gbk')  #中文必须带 encoding='gbk'
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=400, chunk_overlap=0)
# chunk_size=1000表示每次读取或写入数据时,数据的大小为400个字节, 约200~400个汉字
# 对于英文LangChain一般会使用RecursiveCharacterTextSplitter处理。由于中文的复杂性,会使用到jieba等处理工具预处理中文语句。
docs = text_splitter.split_documents(documents)
embedding = OpenAIEmbeddings()
vectordb = Chroma.from_documents(docs, embeddings)
query = "What did the president say about Ketanji Brown Jackson"
docs = vectordb.similarity_search(query)
print(docs[0].page_content)  # 默认是返回4条数据, k=4
# 直接加载数据库,然后查询相似度的文本
vectordb = Chroma(persist_directory=persist_directory, embedding_function=embedding)
query = "On what date did the war between Russia and Ukraine take place?"
retriever = vectordb.as_retriever(search_type="mmr")
s = retriever.get_relevant_documents(query)
print(123, s)
/
123 [Document(page_content='加意见和建议...乌克兰的战争”标语。', metadata={'source': './russiaX.pdf'}), Document(page_content='综合路透社、雅..导弹。', metadata={'source': './russiaX.pdf'}), Document(page_content='乌克兰东部问....
print(556, s[0].page_content)  # 选第一条的内容
# 或者这样查询
s = vectordb.similarity_search(query)
# print(s[0].page_content)
# 特别注意
在存入数据后有时不能立即查到新添加的数据,此时,关停后重启加载即可!
# 直接用get获取数据
res = vectordb.get(limit=2) 
print(266, res)
//266 {'ids': ['e8661882-358c-11ee-a7f1-fb75c83274a1', 'e8661883-358c-11ee-a7f1-fb75c83274a1'], 'embeddings': None, 'metadatas': [{'source': './uploads/dazhihui.txt'}, {'source': './uploads/dazhihui.txt'}], 'documents': ['大智汇健康科技...', '二、团队介绍...']}

ChromaDB

像Chroma DB这样的向量存储正在成为大型语言模型系统的重要组成部分。通过提供专用的存储和向量嵌入的高效检索,它们能够快速访问相关的语义信息,从而为 LLM 提供支持。

在本色度数据库教程中,我们介绍了创建集合、添加文档、将文本转换为嵌入、查询语义相似性以及管理集合的基础知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 文件/目录管理(头歌实训)

目录 任务描述 相关知识 Linux 创建文件 Linux 删除文件 编程要求 测试说明 任务描述 相关知识 Linux 创建目录 Linux 删除目录 编程要求 测试说明 任务描述 相关知识 Linux 拷贝文件 Linux 重命名文件 编程要求 测试说明 任务描述 相关知识 Linux 拷贝目…

初入数据库

SQL:操作关系型数据库的编程语言,定义了一套操作关系型数据库的统一标准。 DDL(Data Definition Language)数据定义语言 数据库 show databases;create database db01;use db01;select database(); 显示当前使用的数据库drop d…

Springboot的Test单元测试操作

Springboot的Test单元测试操作 简单总结需要操作的步骤 1&#xff0c;导入依赖 2&#xff0c;创建目录&#xff08;目录和启动类的目录保持一致&#xff09; 3&#xff0c;添加注解 4&#xff0c;写方法测试 1&#xff0c;导入依赖 <dependency><groupId>org.spri…

(八)小案例银行家应用程序-排序-数组排序

排序一直有很多的算法&#xff0c;今天我们仅仅来说JavaScript内置的排序方法 ● 字符串 const owners [Jonas, Zach, Adam, Martha]; console.log(owners.sort()); console.log(owners);但是注意&#xff0c;这个方法会改变原有的数组&#xff1b; ● 我们在试试数字 cons…

使用excel文件生成sql脚本

目录 1、excel文件脚本变量2、公式示例 前言&#xff1a;在系统使用初期有一些基础数据需要从excel中导入到数据库中&#xff0c;直接导入的话可能有些字段用不上&#xff0c;所以就弄一个excel生成sql的导入脚本&#xff0c;这样可以将需要的数据填到指定的列即可生成sql。 1、…

探索AI大模型在央国企的落地实践|爱分析活动

在这个人工智能技术迅猛发展的时代&#xff0c;AI大模型在央国企的落地实践正成为推动数字化转型和智能化升级的重要引擎。为了深入探讨AI大模型在央国企的应用场景、技术挑战与落地路径&#xff0c;爱分析邀请到一家头部互联网公司作为本次闭门研讨会的联合主办方&#xff0c;…

美国网站服务器解决方案

在当今互联网时代&#xff0c;网站是企业宣传、营销和销售的最好方式&#xff0c;因此&#xff0c;选择一个适合自己企业的网站服务器解决方案很重要。美国作为全球网络基础设施最发达的国家之一&#xff0c;其网站服务器解决方案具有以下特点&#xff1a; 一、安全性高 作为全…

IDEA使用中, 设置平展软件包。使用IDEA遇到的问题:src里为什么创建包为什么不在包里面

使用IDEA遇到的问题&#xff1a;src里为什么创建包为什么不在包里面 如下图所示 &#xff1a; 点击齿轮设置 如何搞回来&#xff1f; 看下面的Flatten Packages&#xff08;平展软件包&#xff09;取消掉。

【算法刷题 | 回溯思想 07】4.18(全排列、全排列 ||)

文章目录 11.全排列11.1题目11.2解法&#xff1a;回溯11.2.1回溯思路&#xff08;1&#xff09;函数返回值以及参数&#xff08;2&#xff09;函数返回值&#xff08;3&#xff09;遍历过程 11.2.2代码实现 12.全排列 ||12.1题目12.2解法&#xff1a;回溯12.2.1回溯思路12.2.3代…

【Redis 开发】缓存穿透解决

缓存穿透 缓存穿透缓存空对象布隆过滤缓存空对象实现其他缓解方式 缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存就永远不会生效&#xff0c;这些请求都会打到数据库 常见的解决方案有两种&#xff1a; 缓存空对象&#xff0c;布隆过…

Postman - 设置变量

场景&#xff1a; 比如你接口都有权限&#xff0c;访问需要每调一个接口都手动放token的值&#xff0c;这个时候就可以搞个全局的变量&#xff0c;只设置一次就可以了 1、设置变量 Environments -> Globals - > 设置key 、value 2、使用变量 {{你得变量名-key}} 3…

redis中的缓存穿透问题

缓存穿透 缓存穿透问题&#xff1a; 一般请求来到后端&#xff0c;都是先从缓存中查找数据&#xff0c;如果缓存中找不到&#xff0c;才会去数据库中查询数据。 而缓存穿透就是基于这一点&#xff0c;不断发送请求查询不存在的数据&#xff0c;从而使数据库压力过大&#xff…

MySQL主从的应用

说明&#xff1a;本文介绍MySQL主从在实际中的应用。主从搭建和问题参考下面两篇文章&#xff1a; MySQL主从结构搭建 搭建MySQL主从结构时的问题 数据迁移 当我们搭建完MySQL主从&#xff0c;第一步当然是把历史数据导入到主从结构中。有以下两种方式&#xff1a; 开启主从…

CST Studio初级教程 一

本教程将详细介绍CST Studio Project创建。 新建Project 1. 点击New and Recent&#xff0c;然后点击New Template。 然后依据我们的仿真属类&#xff0c;在下图中做选择需要的模板。 如果做高频连接器信号完整性&#xff08;SI&#xff09;仿真&#xff0c;我们就选Microwaves…

数据结构之二叉搜索树底层实现洞若观火!

目录 题外话 正题 二叉搜索树 底层实现 二叉搜索树查找操作 查找操作思路 查找代码实现详解 二叉搜索树插入操作 插入操作思路 插入代码详解 二叉搜索树删除操作 删除操作思路 删除代码详解 小结 题外话 我的一切都是党给的,都是人民给的,都是家人们给的!! 十分感…

Docker的数据管理、网络通信和dockerfile

目录 一、Docker的数据管理 1. 数据卷 1.1 数据卷定义 1.2 数据卷配置 2. 数据卷容器 2.1 创建数据卷容器 2.2 使用--volume-from来挂载test1 二、端口映射 三、容器互联 1. 创建容器互联 ​编辑2. 进入test2测试&#xff08;ping 容器名/别名&#xff09; 四、Dock…

c++11详解

目录 1.列表初始化 2.声明 3.右值引用和移动语句 4. c11新的类功能 5. 可变参数模板 6.lambda表达式 7.包装器 8. 后言 1. 列表初始化 1.1 {}的初始化 (1) c98标准规定可以使用{}对数组以及结构体进行统一的列表初始化. struct Point {int _x;int _y; };int main() {in…

【Unity】shader中参数传递

1、前言 unity shader这个对于我来说是真的有点难&#xff0c;今天这篇文章主要还是总结下最近学习到的一些东西&#xff0c;避免过段时间忘记了&#xff0c;可能有不对&#xff0c;欢迎留言纠正。 2、参数传递的两种方式 2.1 语义传递 语义传递这个相对来说是简单的 shad…

数组模拟几种基本的数据结构

文章目录 数组模拟单链表数组模拟双链表数组实现栈数组模拟队列总结 数组模拟单链表 首先类比结构体存储单链表&#xff0c;我们需要一个存放下一个节点下标的数组&#xff0c;还需要一个存储当前节点的值的数组&#xff0c;其次就是一个int类型的索引&#xff0c;这个索引指向…

Python 实现视频去抖动技术

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 视频去抖动是视频处理中的一项重要技术&#xff0c;它可以有效地减少视频中由于相机震动或手…