ChromaDb 添加单个文档,仅当它不存在时

use*_*793 12 python langchain chromadb

我正在使用 python 处理 langchain 和 ChromaDb。

现在,我知道如何使用文档加载器。例如,下面将一堆文档加载到 ChromaDb 中:

from langchain.embeddings.openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()

from langchain.vectorstores import Chroma
db = Chroma.from_documents(docs, embeddings, persist_directory='db')
db.persist()
Run Code Online (Sandbox Code Playgroud)

但是如果我想一次添加一个文档怎么办?更具体地说,我想在添加文档之前检查该文档是否存在。这样我就不会不断添加重复项。

如果文档不存在,只有那时我才想要获取嵌入并添加它。

我如何使用 langchain 来做到这一点?我想我主要了解 langchain,但不知道如何完成这样看似基本的任务。

Rij*_*nto 9

我认为有更好的方法可以做到这一点,但这是我在阅读图书馆后发现的:

如果您看到该Chroma.from_documents()方法,它需要ids参数。

def from_documents(
        cls: Type[Chroma],
        documents: List[Document],
        embedding: Optional[Embeddings] = None,
        ids: Optional[List[str]] = None, # <--------------- here
        collection_name: str = _LANGCHAIN_DEFAULT_COLLECTION_NAME,
        persist_directory: Optional[str] = None,
        client_settings: Optional[chromadb.config.Settings] = None,
        client: Optional[chromadb.Client] = None,
        **kwargs: Any,
    ) -> Chroma:
Run Code Online (Sandbox Code Playgroud)

id使用此参数,您可以为文档设置预定义。如果您不传递任何 id,它将创建一些随机 id。请参阅 langchain 库中的以下参考:

# TODO: Handle the case where the user doesn't provide ids on the Collection
if ids is None:
    ids = [str(uuid.uuid1()) for _ in texts]
Run Code Online (Sandbox Code Playgroud)

因此,这里的解决方法是您必须在存储单个文档时为它们设置一些唯一的 ID/密钥。就我而言,我为每个文档使用了唯一的 URL,将其转换为散列,并将它们传递给 id 参数。之后,当您再次存储文档时,检查每个文档的存储是否存在于数据库中并将它们从docs(参考示例代码)中删除,最后调用Chroma.from_documents()从列表中删除重复文档的方法。请参阅下面的示例并参考您的示例代码。

# step 1: generate some unique ids for your docs
# step 2: check your Chroma DB and remove duplicates
# step 3: store the docs without duplicates

# assuming your docs ids are in the ids list and your docs are in the docs list

db = Chroma.from_documents(docs, embeddings, ids=ids, persist_directory='db')
Run Code Online (Sandbox Code Playgroud)


Jus*_*rty 5

仅根据文档内容进行过滤

or这是另一种过滤机制,它使用了一个很好的列表理解技巧,该技巧利用了与 Python 中的运算符相关的真实评估:

# Create a list of unique ids for each document based on the content
ids = [str(uuid.uuid5(uuid.NAMESPACE_DNS, doc.page_content)) for doc in docs]
unique_ids = list(set(ids))

# Ensure that only docs that correspond to unique ids are kept and that only one of the duplicate ids is kept
seen_ids = set()
unique_docs = [doc for doc, id in zip(docs, ids) if id not in seen_ids and (seen_ids.add(id) or True)]

# Add the unique documents to your database
db = Chroma.from_documents(unique_docs, embeddings, ids=unique_ids, persist_directory='db')
Run Code Online (Sandbox Code Playgroud)

在第一行中,使用该uuid.uuid5()函数为每个文档生成唯一的 UUID,该函数使用命名空间标识符和名称字符串(在本例中为文档的内容)的 SHA-1 哈希创建 UUID。

列表推导式中的条件if检查集合中是否存在当前文档的 ID seen_ids

  • 如果它不存在,则意味着该文档是唯一的。它被添加到seen_idsusing中seen_ids.add(id),并且文档被包含在 中unique_docs
  • 如果确实存在,则该文档是重复的并被忽略。

最后or True必须始终向条件返回真值if,因为即使成功添加元素也会seen_ids.add(id)返回(这是假值)。None

这种方法比使用 URL 或其他文档元数据生成 ID 更实用,因为它直接防止基于内容添加重复文档,而不是依赖元数据或手动检查。