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

bfrts1fy  于 2023-06-20  发布在  Python
关注(0)|答案(2)|浏览(877)

我正在使用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()

但是如果我想一次添加一个文档呢?更具体地说,我想在添加文档之前检查它是否存在。这样我就不会一直添加重复项。
如果一个文档不存在,只有这样我才想获取嵌入并添加它。
我如何使用langchain实现这一点?我想我基本上理解了langchain,但不知道如何完成这样看似基本的任务。

q8l4jmvw

q8l4jmvw1#

我认为有更好的方法可以做到这一点,但这是我在阅读图书馆后发现的:
如果您看到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:

使用此参数,您可以为文档设置预定义的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]

因此,这里的解决方案是,您必须在存储文档时为各个文档设置一些唯一的ID/密钥。在我的例子中,我为每个文档使用了一个唯一的URL,将其转换为散列,并在id参数上传递它们。之后,当您再次存储文档时,检查每个文档的存储,如果它们存在于DB中,并将它们从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')
0qx6xfy6

0qx6xfy62#

仅根据文档内容过滤

这里有一个替代的过滤机制,它使用了一个很好的列表解析技巧,利用了与Python中or运算符相关的truthy求值:

# 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')

在第一行中,使用uuid.uuid5()函数为每个文档生成一个唯一的UUID,该函数使用名称空间标识符和名称字符串(在本例中为文档的内容)的SHA-1散列创建UUID。
列表解析中的if条件检查当前文档的ID是否存在于seen_ids集合中:

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

最后的or True对于if条件总是返回一个truthy值是必要的,因为seen_ids.add(id)返回None(这是falsy),即使一个元素被成功添加。
这种方法比使用URL或其他文档元数据生成ID更实用,因为它直接防止基于内容而不是依赖于元数据或手动检查添加重复文档。

相关问题