Langchain 和 Chroma 的集成
- 1. Chroma
- 2. 基本示例
- 3. 基本示例(包括保存到磁盘)
- 4. 将 Chroma Client 传递到 Langchain
- 5. 基本示例(使用 Docker 容器)
- 6. 更新和删除
- 7. 带分数的相似性搜索
1. Chroma
Chroma 是一个人工智能原生开源矢量数据库,专注于开发人员的生产力和幸福感。 Chroma 在 Apache 2.0 下获得许可。
安装 Chroma:
pip install chromadb
Chroma 以多种模式运行。请参阅下面每个与 LangChain 集成的示例。
in-memory
- 在 python 脚本或 jupyter 笔记本中in-memory with persistance
- 在脚本或笔记本中并保存/加载到磁盘in a docker container
- 作为运行本地计算机或在云中的服务器
与任何其他数据库一样,您可以:
.add
.get
.update
.upsert
.delete
.peek
.query
运行相似性搜索。
在 docs 中查看完整文档。要直接访问这些方法,您可以执行 ._collection_.method()
2. 基本示例
在这个基本示例中,我们获取最新的国情咨文地址,将其分成块,使用开源嵌入模型将其嵌入,将其加载到 Chroma,然后查询它。
先创建要给测试文档,命名为 sidamingzhu.txt
,里面包括了“三打白骨精”、“桃园结义”、"武松打虎"的故事。
《西游记》中“三打白骨精”的故事原文:
话说唐僧师徒四人西天取经,途经白虎岭。
白虎岭上有个妖怪,名叫白骨精。
白骨精是一个老妖怪,她已经死了几百年,只剩下一堆白骨。
她为了吃唐僧肉,就变幻成一个美丽的女子,来引诱唐僧。
孙悟空知道白骨精是妖怪,就去阻止她。
白骨精见孙悟空来,就变幻成一个村姑,说自己是来卖枣的。
孙悟空不相信,就用金箍棒打死了她。
白骨精死了,但她并没有死透。
她又变幻成一个老妇人,来找唐僧。
孙悟空又去阻止她,又用金箍棒打死了她。
白骨精死了两次,但她还是没有死透。
她又变幻成一个老公公,来找唐僧。
孙悟空又去阻止她,又用金箍棒打死了她。
唐僧见孙悟空三次打死人,就很生气。
他把孙悟空赶回了花果山。
孙悟空知道唐僧被妖怪迷惑,就再次赶来救唐僧。
他找到了白骨精,用金箍棒打死了她。
唐僧这才知道孙悟空是好心,就把孙悟空接回了队伍。
《三国演义》中“桃园三结义”的故事原文:
话说宴罢,天色已晚,众人散去。
刘备留下关张二人,以兄事之。
过了几日,谋曰:“吾与二君,虽异姓,然宗室也。
今天下大乱,正要人才。
若能俱发义心,救动仓皇;联合英雄,扶大道。
此吾三人之有也。
”张飞曰:“若要发大义,当如之何?”
刘备曰:“今日天色晚了,明日清早,我们同去桃园,契约志同。”
次日,三人同至桃园,刘备事先示意关张二人,各持一枝桃花,致告天地曰:
“吾等三人,虽异姓,宗室也;今天下大乱,列国混战,正当汉室衰微之秋。
此时天下豪杰,并起义兵,各据州郡。唯有美意,救汉室于危亡。
吾等三人,不求得州牧,不求得侯王,愿出心肝荐轸,誓将清君侧,兴复汉室!此心此义,使天日月为证,使星辰为鉴,无贰其志,殊死随之。
如背盟约,无妾百福!”
三人各自对天地、日月星辰发誓,然后两两互持桃枝彼此磕头,作兄弟之礼,场面极为隆重感人。
自此,刘关张三人正式结拜为交心之兄弟。
《水浒传》中“武松打虎”的故事原文:
武大郎忍痛抽筋,往后瞧时,只见那猛虎抡起铁棒,向自己直扑将来。
武大郎使开双戟,侧身让过。那猛虎扑了一空,回头又扑。
武大郎举戟架住,口中大呼:“我奉王命,捉你回去论罪!”
那猛虎被他这一架,戟钢扎疼了手,发起狠来,向武大郎直扑。
武大郎使开戟去迎战。二人战了十余合,打得难解难分。
这虎本是山中猛虫,十分凶悍。
这一场恶战,战不到五十合,武大郎手软筋麻,使不动戟,只得拔了武松的宝贝青龙偃月刀,向前迎敌。
这一场好杀:武大郎左闪右避,虎扑不着;虎右藏左藏,武大郎砍不着。
打到第三十合,那猛虎扑空,回头待扑,武大郎举刀往下一砍,砍断它的两只前腿。
那猛虎痛得嗷嗷乱叫,后腿着地,要向武大郎扑将来。
武大郎顺手又一刀,把它一只后腿也砍断。
示例代码,
# import
from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.document_loaders import TextLoader
# load the document and split it into chunks
loader = TextLoader(".\sidamingzhu.txt", encoding="utf-8")
documents = loader.load()
# split it into chunks
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
# create the open-source embedding function
embedding_function = SentenceTransformerEmbeddings(model_name="shibing624/text2vec-base-chinese")
# embedding_function = SentenceTransformerEmbeddings(model_name="GanymedeNil/text2vec-large-chinese")
# embedding_function = SentenceTransformerEmbeddings(model_name="moka-ai/m3e-large")
# load it into Chroma
db = Chroma.from_documents(docs, embedding_function)
# query it
query = "白骨精被打死几次?"
docs = db.similarity_search(query, k=3) # default k is 4
print(len(docs))
# print results
for doc in docs:
print("="*100)
print(doc.page_content)
输出结果,
示例代码,
# query it
query = "刘关张在桃园做什么?"
docs = db.similarity_search(query, k=3) # default k is 4
print(len(docs))
# print results
for doc in docs:
print("="*100)
print(doc.page_content)
输出结果,
示例代码,
# query it
query = "武大郎打的什么?"
docs = db.similarity_search(query, k=3) # default k is 4
print(len(docs))
# print results
for doc in docs:
print("="*100)
print(doc.page_content)
输出结果,
3. 基本示例(包括保存到磁盘)
扩展前面的示例,如果您想保存到磁盘,只需初始化 Chroma 客户端并传递您想要保存数据的目录即可。
Caution :Chroma 尽力自动将数据保存到磁盘,但是多个内存客户端可能会干扰彼此的工作。作为最佳实践,在任何给定时间,每个路径仅运行一个客户端。
示例代码,
# save to disk
db2 = Chroma.from_documents(docs, embedding_function, persist_directory="./chroma_db")
docs = db2.similarity_search(query, k=1) # default k is 4
print(docs[0].page_content)
输出结果,
示例代码,
# load from disk
db3 = Chroma(persist_directory="./chroma_db", embedding_function=embedding_function)
docs = db3.similarity_search(query, k=1) # default k is 4
print(docs[0].page_content)
输出结果,
4. 将 Chroma Client 传递到 Langchain
您还可以创建一个Chroma Client并将其传递给LangChain。如果您希望更轻松地访问底层数据库,这尤其有用。
您还可以指定您希望 LangChain 使用的集合名称。
示例代码,
import chromadb
persistent_client = chromadb.PersistentClient()
collection = persistent_client.get_or_create_collection("collection_name")
collection.add(ids=["1", "2", "3"], documents=["a", "b", "c"])
langchain_chroma = Chroma(
client=persistent_client,
collection_name="collection_name",
embedding_function=embedding_function,
)
print("There are", langchain_chroma._collection.count(), "in the collection")
输出结果,
Add of existing embedding ID: 1
Add of existing embedding ID: 2
Add of existing embedding ID: 3
Add of existing embedding ID: 1
Add of existing embedding ID: 2
Add of existing embedding ID: 3
Insert of existing embedding ID: 1
Add of existing embedding ID: 1
Insert of existing embedding ID: 2
Add of existing embedding ID: 2
Insert of existing embedding ID: 3
Add of existing embedding ID: 3
There are 3 in the collection
5. 基本示例(使用 Docker 容器)
略
6. 更新和删除
在构建实际应用程序时,您不仅需要添加数据,还需要更新和删除数据。
Chroma 让用户提供 ids
来简化此处的记账。 ids
可以是文件名,也可以是 filename_paragraphNumber
等组合。
Chroma 支持所有这些操作 - 尽管其中一些操作通过 LangChain 界面集成仍在进行中。很快就会添加其他工作流程改进。
这是一个基本示例,展示了如何执行各种操作:
# create simple ids
ids = [str(i) for i in range(1, len(docs) + 1)]
# add data
example_db = Chroma.from_documents(docs, embedding_function, ids=ids)
# print(example_db)
docs = example_db.similarity_search(query)
print(docs[0].metadata)
输出结果,
{'source': '.\\sidamingzhu.txt'}
示例代码,
# update the metadata for a document
docs[0].metadata = {
"source": "./sidamingzhu.txt",
"new_value": "你好,世界!",
}
example_db.update_document(ids[0], docs[0])
print(example_db._collection.get(ids=[ids[0]]))
输出结果,
{'ids': ['1'], 'embeddings': None, 'metadatas': [{'new_value': '你好,世界!', 'source': './sidamingzhu.txt'}], 'documents': ['这一场恶战,战不到五十合,武大郎手软筋麻,使不动戟,只得拔了武松的宝贝青龙偃月刀,向前迎敌。\n\n这一场好杀:武大郎左闪右避,虎扑不着;虎右藏左藏,武大郎砍不着。']}
示例代码,
# delete the last document
print("count before", example_db._collection.count())
example_db._collection.delete(ids=[ids[-1]])
print("count after", example_db._collection.count())
输出结果,
count before 17
count after 16
7. 带分数的相似性搜索
返回的距离分数是余弦距离。因此,分数越低越好。
示例代码,
docs = db.similarity_search_with_score(query)
docs[0]
输出结果,
(Document(page_content='这一场恶战,战不到五十合,武大郎手软筋麻,使不动戟,只得拔了武松的宝贝青龙偃月刀,向前迎敌。\n\n这一场好杀:武大郎左闪右避,虎扑不着;虎右藏左藏,武大郎砍不着。', metadata={'source': '.\\sidamingzhu.txt'}),
240.21286010742188)
refer: https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma
完结!