markdown_docs/server/knowledge_base/kb_cache/faiss_cache.md
_new_ds_search: 此函数的功能是根据提供的搜索字符串查找并返回相应的文档或未找到的信息。
参数:
search: 需要搜索的字符串,用于在内部字典中查找对应的文档。代码描述:
此函数接收一个名为search的参数,该参数是一个字符串,用于在内部维护的字典_dict中查找对应的条目。函数首先检查search是否存在于_dict中。如果不存在,函数将返回一个格式化的字符串,指出给定的ID未找到。如果找到了对应的条目,函数将进一步检查这个条目是否是一个Document类型的实例。如果是,函数将在该文档的元数据中添加一个id字段,其值为search参数的值。最后,无论条目是否为Document实例,函数都将返回这个条目。
注意:
Document类型或其他类型。_dict已经被正确初始化并填充了相应的数据。Document类型的实例时,其metadata将包含一个额外的id字段,其值对应于搜索字符串。输出示例:
_dict中找到,可能的返回值为:"ID 12345 not found."_dict中找到,并且对应的条目是一个Document实例,返回的将是这个被更新了metadata的Document实例。ThreadSafeFaiss: ThreadSafeFaiss 类的功能是提供一个线程安全的封装,用于操作和管理 FAISS 向量库。
属性:
key: 对象的键,用于标识特定的向量库。_obj: 存储实际 FAISS 向量库的对象。docs_count: 表示向量库中文档的数量。代码描述: ThreadSafeFaiss 类继承自 ThreadSafeObject,增加了与 FAISS 向量库相关的特定功能。这个类主要用于在多线线程环境中安全地操作 FAISS 向量库,包括文档计数、保存到磁盘和清空向量库等操作。
__repr__ 方法提供了类的字符串表示,包括类名、键、对象以及文档数量。docs_count 方法返回向量库中文档的数量,这是通过查询 _obj.docstore._dict 的长度来实现的。save 方法用于将向量库保存到指定的磁盘路径。如果路径不存在且 create_path 参数为真,则会创建该路径。保存操作完成后,会记录一条日志信息。clear 方法用于清空向量库中的所有文档。清空操作完成后,会记录一条日志信息。注意:
save 和 clear 方法时,会通过 acquire 方法获取锁,以确保线程安全。这意味着在这些操作执行期间,其他线程将无法访问该向量库对象。_obj 属性时,应通过 obj 属性的 setter 方法,以确保线程安全。输出示例:
假设有一个 ThreadSafeFaiss 实例,其 key 为 "example_key",_obj 为某个 FAISS 向量库对象,且向量库中有 100 个文档。调用 __repr__ 方法可能会返回如下字符串:
"<ThreadSafeFaiss: key: example_key, obj: <FAISS向量库对象的表示>, docs_count: 100>"
通过这个类,开发者可以在多线程环境中安全高效地管理和操作 FAISS 向量库,无需担心线程安全问题。
repr: 此函数的功能是生成并返回对象的字符串表示形式。
参数: 此函数没有参数。
代码描述: __repr__ 方法是 ThreadSafeFaiss 类的一个特殊方法,用于提供对象的官方字符串表示。这种表示形式通常用于调试和日志记录,使得开发者可以更容易地理解对象的状态。在这个方法中,首先通过 type(self).__name__ 获取对象的类名,然后通过访问对象的 key 属性和 _obj 属性,以及调用 docs_count 方法来获取文档数量,构造出一个格式化的字符串。这个字符串包含了对象的类名、键值、对应的对象以及文档数量,这些信息对于理解和调试 ThreadSafeFaiss 对象的状态非常有用。
key 属性提供了对象在缓存或其他数据结构中的唯一标识符,是通过访问对象的 _key 属性来获取的。docs_count 方法返回文档存储中文档的数量,是通过计算 _obj.docstore._dict 的长度来实现的。这里的 _obj 属性指向一个文档存储对象,_dict 是该存储对象中用于保存文档的字典。
通过这种方式,__repr__ 方法为 ThreadSafeFaiss 对象提供了一个详细且易于理解的字符串表示,包括了关键的状态信息,如对象的键值和存储中的文档数量。
注意: 在使用 __repr__ 方法时,需要确保 _obj 属性和 _key 属性已经被正确初始化,并且 _obj.docstore._dict 中包含了需要计数的文档。如果这些属性或字典未被正确初始化,可能会影响到字符串表示的准确性。
输出示例: 假设一个 ThreadSafeFaiss 对象的类名为 ThreadSafeFaiss,其键值为 "example_key",对应的 _obj 属性指向一个包含3个文档的文档存储对象,那么调用 __repr__ 方法可能返回如下字符串:
"<ThreadSafeFaiss: key: example_key, obj: <文档存储对象>, docs_count: 3>"
docs_count: 此函数的功能是返回文档存储中文档的数量。
参数: 此函数没有参数。
代码描述: docs_count 函数是 ThreadSafeFaiss 类的一个方法,用于获取当前对象中文档存储 _dict 的长度,即文档的数量。这里,self._obj.docstore 指向一个文档存储对象,而 _dict 是该存储对象中用于保存文档的字典。通过调用 len 函数计算 _dict 的长度,可以得到存储中文档的总数。此方法在 ThreadSafeFaiss 类的实例化对象中被调用,特别是在其 __repr__ 方法中,用于生成对象的字符串表示,其中包括了文档数量的信息。这样,当需要展示或记录 ThreadSafeFaiss 对象的状态时,可以直接通过其字符串表示来获取关键信息,包括文档数量。
注意: 使用此函数时,需要确保 self._obj.docstore._dict 已经正确初始化并包含了需要计数的文档。如果 _dict 是空的或者未被正确初始化,此函数将返回 0。
输出示例: 假设 _dict 中存储了3个文档,那么 docs_count() 的返回值将是 3。
save: 此函数的功能是将向量库保存到指定路径。
参数:
path: 字符串类型,表示向量库保存的目标路径。create_path: 布尔类型,默认为True,指示如果目标路径不存在,是否创建该路径。代码描述:
save 函数首先通过调用 acquire 方法来安全地获取资源,确保在多线程环境下的操作不会引起数据竞争或不一致的问题。在成功获取资源后,函数检查path参数指定的路径是否存在,如果不存在且create_path参数为True,则会创建该路径。随后,函数调用 _obj.save_local 方法将向量库保存到指定的路径。在保存过程中,会通过日志记录功能输出保存操作的信息,包括向量库的键值(通过调用 key 方法获取)和保存的目标路径。完成保存操作后,释放之前获取的资源,并返回 _obj.save_local 方法的返回值。
注意:
path参数是有效的文件系统路径,且当前运行环境有足够的权限在该路径下创建文件夹或写入文件。create_path参数设置为False,而指定的路径不存在,则不会创建新路径,可能会导致保存操作失败。输出示例: 由于此函数的主要作用是保存文件到磁盘,其返回值取决于 _obj.save_local 方法的实现,通常不直接输出信息。但在日志中,可以看到类似以下的信息:
已将向量库 example_key 保存到磁盘
这表明键值为example_key的向量库已成功保存到磁盘。
clear: 此函数的功能是清空向量库。
参数: 此函数没有参数。
代码描述: clear 函数负责清空当前对象所代表的向量库。它首先创建一个空列表 ret,用于存储删除操作的返回结果。通过使用 with self.acquire() 上下文管理器,函数确保在多线程环境下安全地访问和操作向量库。在这个上下文管理器内部,首先获取向量库中所有文档的ID列表,然后检查这个列表是否非空。如果非空,调用 _obj.delete(ids) 方法删除这些文档,并将返回结果存储到 ret 中。此外,函数通过断言 assert len(self._obj.docstore._dict) == 0 确保所有文档都已被删除,向量库被成功清空。最后,记录一条日志信息,表明已经清空了特定的向量库,其中 self.key 用于获取向量库的唯一标识符。
从功能角度来看,clear 函数与其调用的对象 acquire 和 key 密切相关。acquire 函数提供了一个线程安全的环境,确保在执行删除操作时不会发生数据竞争。key 函数则用于获取向量库的唯一标识符,这在日志记录时非常有用,帮助开发者和维护者追踪是哪个向量库被清空了。
注意: 在使用 clear 函数时,需要确保向量库的 _obj 属性已经被正确初始化,并且 _obj.docstore._dict 能够正确反映向量库中文档的存储状态。此外,考虑到函数中使用了断言来验证向量库是否被成功清空,因此在生产环境中使用时应当确保这一点,以避免因断言失败而导致的异常。
输出示例: 假设向量库中原本存储了若干文档,调用 clear 函数后,如果删除成功,函数将返回一个包含删除操作结果的列表。例如,如果删除成功,可能返回如下列表:
[True, True, ...]
如果向量库原本为空,或者在删除过程中没有实际删除任何文档,则返回一个空列表:
[]
_FaissPool: _FaissPool 类的功能是管理和操作基于FAISS库的向量存储。
属性:
CachePool,因此拥有 CachePool 的所有属性和方法。代码描述:
_FaissPool 类提供了三个主要方法来管理向量存储:new_vector_store、save_vector_store 和 unload_vector_store。
new_vector_store 方法用于创建一个新的向量存储。它接受嵌入模型名称和嵌入设备作为参数,使用 EmbeddingsFunAdapter 来适配不同的嵌入模型,并创建一个文档对象 doc 作为初始化数据。然后,它使用 FAISS.from_documents 方法根据这个文档对象和嵌入模型创建一个新的FAISS向量存储,同时设置L2归一化和距离策略。创建后,它会删除这个初始化文档对象,以便返回一个空的向量存储。
save_vector_store 方法用于保存指定名称的向量存储到磁盘。如果在缓存中找到了对应名称的向量存储,它会调用向量存储的 save 方法将其保存到指定路径。
unload_vector_store 方法用于从缓存中卸载并释放指定名称的向量存储。如果在缓存中找到了对应名称的向量存储,它会先从缓存中移除该向量存储,然后记录一条日志信息表示向量库已成功释放。
注意:
new_vector_store 方法创建向量存储时,需要确保传入的嵌入模型名称和嵌入设备是有效的,因为这将影响向量存储的创建和后续的向量检索性能。save_vector_store 方法保存向量存储时,如果没有提供保存路径,则需要确保向量存储对象已经配置了默认的保存路径。unload_vector_store 方法卸载向量存储之前,应确保没有其他操作正在使用该向量存储,以避免数据丢失或访问冲突。输出示例:
由于这些方法主要进行向量存储的管理操作,它们的输出通常不直接返回数据给用户。例如,new_vector_store 方法返回一个初始化后的空的FAISS向量存储对象,而 save_vector_store 和 unload_vector_store 方法则没有返回值,它们的执行结果主要通过日志信息和向量存储的状态变化来体现。
new_vector_store: 此函数的功能是创建一个新的向量存储空间。
参数:
embed_model: 字符串类型,默认值为 EMBEDDING_MODEL。用于指定嵌入模型的名称。embed_device: 字符串类型,默认值为 embedding_device() 函数的返回值。用于指定嵌入计算的设备类型。代码描述:
new_vector_store 函数首先通过 EmbeddingsFunAdapter 类实例化一个嵌入模型适配器,该适配器根据传入的 embed_model 参数来处理文本嵌入转换。接着,函数创建一个包含初始化内容和元数据的 Document 对象。此后,利用 FAISS.from_documents 方法,以该文档对象、嵌入模型适配器、L2归一化以及内积距离策略作为参数,创建一个新的FAISS向量存储实例。创建过程中,会先向该向量存储中添加一个文档,然后立即删除,目的是初始化一个空的向量存储空间。最后,函数返回这个初始化后的向量存储实例。
注意:
embed_model 指定的嵌入模型已经存在且可用。embed_device 参数应根据实际运行环境的硬件配置来设置,以确保嵌入计算能在最适合的设备上执行(如GPU、MPS或CPU)。输出示例: 由于此函数返回一个FAISS向量存储实例,而具体的实例内容依赖于运行时的环境和参数,因此不易提供一个具体的输出示例。但可以预期,返回的向量存储实例是一个初始化状态的FAISS对象,准备好接收和管理文档向量数据。
save_vector_store: 此函数的功能是保存向量存储。
参数:
kb_name: 字符串类型,指定要保存的知识库名称。path: 字符串类型,可选参数,指定保存向量存储的路径。如果未提供,则使用默认路径。代码描述:
save_vector_store 函数首先尝试通过调用 get 函数从缓存池中获取与给定知识库名称 (kb_name) 关联的线程安全对象。如果成功获取到对象,该函数将调用该对象的 save 方法,并将可选的路径参数 path 传递给它。这一过程实现了向量存储的保存操作。
从功能上看,get 函数是从缓存池中检索与给定键关联的线程安全对象的关键步骤。它确保了在进行保存操作之前,所需的对象已经被成功加载并处于可用状态。这一点对于确保数据的一致性和防止在保存过程中发生错误至关重要。
注意:
save_vector_store 函数时,应确保提供的知识库名称 (kb_name) 在缓存中存在。如果不存在,函数将不执行任何操作并返回 None。path) 应确保是有效的,如果路径无效或未提供,可能会导致保存操作失败或使用默认路径。输出示例:
假设存在一个名为 "example_kb" 的知识库对象,并且该对象已经被加载到缓存中。调用 save_vector_store("example_kb", "/path/to/store") 将会将该知识库对象的向量存储保存到指定的路径。如果 "example_kb" 不存在于缓存中,函数将不执行任何操作并返回 None。
unload_vector_store: 此函数的功能是从缓存池中卸载并释放指定的向量库。
参数:
kb_name: 字符串类型,指定要卸载并释放的向量库的名称。代码描述:
unload_vector_store 函数是 _FaissPool 类的一个方法,用于卸载并释放指定名称的向量库。该函数首先调用 get 方法尝试从缓存池中获取与给定名称 kb_name 关联的向量库对象。如果成功获取到对象,get 方法会确保该对象的加载状态已完成,这是通过对象的 wait_for_loading 方法实现的,从而确保在进行后续操作前,对象已经处于可用状态。
获取到对象后,函数接着调用 pop 方法,根据提供的向量库名称 kb_name 从缓存池中移除该对象。移除操作成功后,会通过日志记录一条信息,表明指定的向量库已成功释放。
在整个过程中,get 方法确保了只有在向量库对象确实存在且加载完成的情况下,才会进行卸载操作。而 pop 方法则负责实际的移除操作,并处理缓存池中对象的移除逻辑。
注意:
kb_name 在缓存池中确实存在。如果不存在,函数将不执行任何操作。get 方法的线程安全机制确保了在进行卸载操作前,对象的加载状态已经完成,避免了潜在的竞态条件。KBFaissPool: KBFaissPool 类的功能是管理和加载基于FAISS库的向量存储池。
属性:
_FaissPool 类,因此拥有 _FaissPool 的所有属性和方法。代码描述:
KBFaissPool 类主要提供了 load_vector_store 方法,用于加载或创建向量存储。该方法接受知识库名称(kb_name)、向量名称(vector_name)、是否创建新的向量存储(create)、嵌入模型名称(embed_model)和嵌入设备(embed_device)作为参数。
方法首先尝试从内部缓存中获取指定的向量存储。如果未找到,它将初始化一个新的 ThreadSafeFaiss 对象,并尝试从磁盘加载向量存储或根据参数创建一个新的向量存储。
如果指定路径下存在 index.faiss 文件,则从磁盘加载向量存储,并使用指定的嵌入模型和设备加载知识库嵌入。加载过程中,会对向量进行L2归一化,并设置距离策略为内积。
如果指定路径下不存在 index.faiss 文件且 create 参数为真,则会创建一个新的空向量存储,并保存到磁盘。
如果既不存在 index.faiss 文件,create 参数也为假,则抛出异常,表示指定的知识库不存在。
在加载或创建向量存储后,方法会将 ThreadSafeFaiss 对象存入内部缓存,并返回该对象。
注意:
load_vector_store 方法时,需要确保传入的知识库名称和向量名称是有效的,以便正确地加载或创建向量存储。输出示例:
调用 load_vector_store 方法可能返回的示例输出为一个 ThreadSafeFaiss 对象,该对象封装了FAISS向量存储的操作和管理,允许线程安全地访问和修改向量存储。
load_vector_store: 此函数用于加载或创建指定知识库的向量存储。
参数:
kb_name: 字符串类型,指定要加载或创建向量存储的知识库名称。vector_name: 字符串类型,可选参数,默认为None。指定向量存储的名称。如果未提供,则使用嵌入模型名称作为向量名称。create: 布尔类型,可选参数,默认为True。指示如果指定的向量存储不存在时,是否创建一个新的向量存储。embed_model: 字符串类型,可选参数,默认为EMBEDDING_MODEL。用于指定嵌入模型的名称。embed_device: 字符串类型,可选参数,默认由embedding_device()函数确定。用于指定嵌入计算的设备类型。代码描述:
此函数首先尝试获取一个互斥锁,以确保线程安全。然后,根据提供的知识库名称和向量名称(如果未提供向量名称,则使用嵌入模型名称)尝试从缓存中获取对应的向量存储。如果缓存中不存在该向量存储,则会根据create参数的值决定是创建一个新的向量存储还是抛出异常。创建向量存储的过程包括初始化一个ThreadSafeFaiss实例,并将其添加到缓存中。接着,根据向量存储是否已存在于磁盘上,选择是从磁盘加载向量存储还是创建一个新的空向量存储。加载或创建完成后,会将向量存储实例赋值给ThreadSafeFaiss实例的obj属性,并标记加载完成。如果向量存储已存在于缓存中,则直接释放互斥锁。最后,函数返回缓存中的向量存储实例。
注意:
create参数为False且指定的向量存储不存在,则会抛出运行时错误。kb_name和vector_name(如果提供)正确无误,因为它们直接影响向量存储的加载和创建。embedding_device()函数来确定嵌入计算的设备类型,因此需要确保相关硬件和软件配置正确。输出示例:
由于此函数返回一个ThreadSafeFaiss实例,而具体的实例内容依赖于运行时的环境和参数,因此不易提供一个具体的输出示例。但可以预期,返回的向量存储实例是一个初始化状态的ThreadSafeFaiss对象,准备好接收和管理文档向量数据。
MemoFaissPool: MemoFaissPool 类的功能是在内存中加载和管理基于FAISS库的向量存储池。
属性:
_FaissPool 类,因此拥有 _FaissPool 的所有属性和方法。代码描述:
MemoFaissPool 类通过继承 _FaissPool 类,提供了一种高效管理FAISS向量存储的方式。它主要通过 load_vector_store 方法来加载或初始化向量存储。
load_vector_store 方法接受三个参数:kb_name(知识库名称),embed_model(嵌入模型,默认为 EMBEDDING_MODEL),和 embed_device(嵌入设备,默认由 embedding_device() 函数确定)。该方法首先尝试从缓存中获取指定名称的向量存储。如果未找到,它将创建一个新的 ThreadSafeFaiss 对象,并将其添加到缓存中。在这个过程中,它使用了线程安全的锁机制来确保操作的原子性。
在初始化 ThreadSafeFaiss 对象时,会调用 _FaissPool 类的 new_vector_store 方法来创建一个空的向量存储。这个过程涉及到使用指定的嵌入模型和设备来创建向量存储,确保了向量存储的创建与配置的灵活性和可定制性。
完成向量存储的加载后,load_vector_store 方法会通过调用 finish_loading 方法来标记向量存储的加载状态,确保向量存储已经准备好被使用。
注意:
load_vector_store 方法时,需要确保传入的知识库名称、嵌入模型和嵌入设备参数正确无误,因为这些参数直接影响向量存储的创建和性能。MemoFaissPool 类继承自 _FaissPool,在使用该类之前,需要对 _FaissPool 类及其方法有一定的了解。输出示例:
由于 load_vector_store 方法的主要作用是加载或初始化向量存储,其直接的返回值是一个 ThreadSafeFaiss 对象。这个对象代表了一个已加载或新创建的向量存储,可以被进一步用于向量的检索或管理操作。例如,如果成功加载了名为 "knowledge_base" 的向量存储,那么返回的 ThreadSafeFaiss 对象将包含这个向量存储的所有相关信息和操作接口。
load_vector_store: 此函数的功能是加载或初始化一个向量存储库,并确保其线程安全。
参数:
kb_name: 字符串类型,用于指定知识库的名称。embed_model: 字符串类型,默认值为 EMBEDDING_MODEL。用于指定嵌入模型的名称。embed_device: 字符串类型,默认值为 embedding_device() 函数的返回值。用于指定嵌入计算的设备类型。代码描述:
此函数首先尝试获取一个原子锁,以确保线程安全。接着,尝试从缓存中获取与kb_name对应的向量存储对象。如果未找到,即cache为None,则会创建一个新的ThreadSafeFaiss实例,并将其与kb_name关联后设置到缓存中。在这个过程中,会初始化一个新的向量存储空间,这是通过调用new_vector_store函数实现的,该函数根据指定的嵌入模型和计算设备创建向量存储。完成向量存储的初始化后,会调用finish_loading方法标记加载过程完成。如果在缓存中找到了对应的向量存储对象,则直接释放原子锁。最后,函数返回从缓存中获取的向量存储对象。
注意:
输出示例:
由于此函数返回的是一个ThreadSafeFaiss实例,具体的实例内容依赖于运行时的环境和参数,因此不易提供一个具体的输出示例。但可以预期,返回的向量存储实例是一个经过初始化,准备好接收和管理文档向量数据的ThreadSafeFaiss对象。
在项目中,load_vector_store函数被upload_temp_docs函数调用,用于在上传文件并进行向量化处理时,加载或初始化临时向量库。这确保了上传的文档能够被正确地添加到向量库中,以支持后续的搜索和检索操作。
worker: 此函数用于处理向量存储中文档的添加、搜索和删除操作。
参数:
vs_name: 字符串类型,指定向量存储的名称。name: 字符串类型,表示执行当前操作的工作线程或用户的名称。代码描述:
worker函数首先将vs_name参数的值设置为"samples",这意味着所有操作都将在名为"samples"的向量存储中进行。接着,函数通过调用load_local_embeddings函数加载本地嵌入向量。这一步骤是必要的,因为无论是添加文档还是搜索文档,都需要使用到嵌入向量。
函数随机选择一个整数r,根据r的值决定执行添加文档、搜索文档还是删除文档的操作。具体来说,如果r等于1,则执行添加文档操作;如果r等于2,则执行搜索文档操作;如果r等于3,则执行删除文档操作。
在执行添加或搜索操作时,函数通过kb_faiss_pool.load_vector_store(vs_name).acquire(name)获取向量存储的上下文管理器,并确保操作的线程安全。在此上下文管理器内,根据r的值执行相应的操作。添加文档时,使用add_texts方法将文本和对应的嵌入向量添加到向量存储中,并打印添加的文档ID。搜索文档时,使用similarity_search_with_score方法根据提供的文本和嵌入向量搜索最相似的文档,并打印搜索结果。
如果r等于3,即执行删除文档操作,则在上下文管理器外部调用kb_faiss_pool.get(vs_name).clear()方法,清除指定向量存储中的所有文档。此操作通过日志记录执行删除操作的信息。
注意:
worker函数时,需要确保vs_name和name参数正确无误,因为它们直接影响向量存储的操作。load_local_embeddings函数的调用依赖于正确的嵌入模型配置和计算设备设置,因此在执行worker函数之前,应确保相关配置正确。worker函数通过随机选择操作类型(添加、搜索或删除文档),模拟了一个简单的向量存储操作场景。在实际应用中,可以根据具体需求调整操作逻辑。worker函数时,通过acquire方法获取的上下文管理器确保了操作的线程安全。