Langchain-Chatchat/markdown_docs/server/knowledge_base/utils.md

530 lines
47 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## FunctionDef validate_kb_name(knowledge_base_id)
**validate_kb_name**: 此函数用于验证知识库名称的合法性。
**参数**:
- knowledge_base_id: 字符串类型,表示待验证的知识库名称。
**代码描述**:
`validate_kb_name` 函数接收一个字符串参数 `knowledge_base_id`,该参数代表知识库的名称。函数的主要目的是检查这个名称是否包含潜在的安全风险,具体来说,就是检查名称中是否包含 "../" 这样的子串。如果包含,函数返回 `False`,表示名称不合法或存在安全风险;如果不包含,函数返回 `True`,表示名称合法。这种验证机制主要是为了防止路径遍历攻击,确保系统的安全性。
在项目中,`validate_kb_name` 函数被多个地方调用包括创建知识库、删除知识库、列出文件、上传文档、删除文档、更新知识库信息、更新文档和下载文档等API接口中。在这些接口中函数用于在执行核心逻辑之前验证传入的知识库名称的合法性。如果名称不合法API接口会直接返回错误响应阻止后续的操作执行从而增强了系统的安全性。
**注意**:
- 在使用此函数时,需要确保传入的参数是字符串类型。
- 函数的返回值是布尔类型,调用方需要根据返回值判断知识库名称是否合法,并据此执行相应的逻辑。
**输出示例**:
- 如果知识库名称合法,例如 "valid_kb_name",函数将返回 `True`
- 如果知识库名称不合法,例如包含 "../" 的 "invalid/../kb_name",函数将返回 `False`
## FunctionDef get_kb_path(knowledge_base_name)
**get_kb_path**: 此函数的功能是获取指定知识库的文件路径。
**参数**:
- knowledge_base_name: 字符串类型,表示知识库的名称。
**代码描述**:
`get_kb_path` 函数接受一个参数 `knowledge_base_name`,这是一个字符串,代表知识库的名称。函数的主要作用是构造并返回一个路径,这个路径是知识库名称与一个预定义的根路径 `KB_ROOT_PATH` 结合而成的完整文件路径。这里使用了 `os.path.join` 方法来确保路径的正确构造,无论是在不同的操作系统上,都能正确处理路径分隔符。
在项目中,`get_kb_path` 函数被多个地方调用,主要用于获取知识库相关文件的存储路径。例如,在 `KBService` 类的初始化方法中,通过调用 `get_kb_path` 来确定知识库文件的存储位置,并进一步使用这个位置来获取文档路径或向量存储路径。这表明 `get_kb_path` 函数是处理知识库文件路径的基础工具函数,为知识库服务的初始化和其他文件路径的获取提供了支持。
**注意**:
- 确保 `KB_ROOT_PATH` 已经被正确定义并指向了一个有效的文件系统路径,否则 `get_kb_path` 返回的路径可能无效。
- 调用此函数时传入的知识库名称应确保是唯一的,以避免路径冲突。
**输出示例**:
假设 `KB_ROOT_PATH` 被设置为 `/var/knowledge_bases`,且调用 `get_kb_path('my_knowledge_base')`,则函数将返回:
```
/var/knowledge_bases/my_knowledge_base
```
这个返回值表示了名为 `my_knowledge_base` 的知识库在文件系统中的存储路径。
## FunctionDef get_doc_path(knowledge_base_name)
**get_doc_path**: 此函数的功能是获取指定知识库的文档存储路径。
**参数**:
- knowledge_base_name: 字符串类型,表示知识库的名称。
**代码描述**:
`get_doc_path` 函数接受一个参数 `knowledge_base_name`,这是一个字符串,代表知识库的名称。函数通过调用 `get_kb_path` 函数获取知识库的根路径,然后将此根路径与字符串 "content" 结合,构造出知识库文档的存储路径。这里使用了 `os.path.join` 方法来确保路径的正确构造,无论是在不同的操作系统上,都能正确处理路径分隔符。
在项目中,`get_doc_path` 函数主要被用于确定知识库中文档的存储位置。例如,在 `KBService` 类的初始化方法中,通过调用 `get_doc_path` 来获取知识库文档的存储路径,并可能进一步使用这个路径来读取或存储文档数据。此外,`get_file_path` 和 `list_files_from_folder` 函数也调用了 `get_doc_path`,用于获取具体文档的路径或列出知识库文档目录下的所有文件,表明 `get_doc_path` 函数是处理知识库文档路径的基础工具函数,为知识库中文档的管理和操作提供了支持。
**注意**:
- 确保在调用此函数之前,`get_kb_path` 函数能够正确返回知识库的根路径,且该路径有效存在于文件系统中。
- 路径中的 "content" 是硬编码的,意味着知识库中存储文档的目录名称需要遵循这一约定。
**输出示例**:
假设 `get_kb_path('my_knowledge_base')` 返回的路径为 `/var/knowledge_bases/my_knowledge_base`,则调用 `get_doc_path('my_knowledge_base')` 将返回:
```
/var/knowledge_bases/my_knowledge_base/content
```
这个返回值表示了名为 `my_knowledge_base` 的知识库中文档存储的具体路径。
## FunctionDef get_vs_path(knowledge_base_name, vector_name)
**get_vs_path**: 此函数的功能是构造并返回知识库中向量存储的完整文件路径。
**参数**:
- knowledge_base_name: 字符串类型,表示知识库的名称。
- vector_name: 字符串类型,表示特定的向量名称。
**代码描述**:
`get_vs_path` 函数接受两个参数:`knowledge_base_name` 和 `vector_name`。这两个参数分别代表知识库的名称和向量的名称。函数首先调用 `get_kb_path` 函数,传入知识库名称 `knowledge_base_name` 来获取知识库的基础路径。然后,函数使用 `os.path.join` 方法将基础路径、字符串 "vector_store" 和向量名称 `vector_name` 连接起来,构造出向量存储的完整文件路径。这样做的目的是为了确保无论在哪种操作系统上,路径的构造都是正确的,避免了路径分隔符的问题。
在项目中,`get_vs_path` 函数主要被用于确定向量存储的位置。例如,在 `KBFaissPool` 类的 `load_vector_store` 方法中,通过调用 `get_vs_path` 来获取向量存储的路径,并根据这个路径来加载或创建向量存储。这表明 `get_vs_path` 函数是处理向量存储路径的关键工具函数,为向量存储的加载和创建提供了路径支持。
**注意**:
- 在调用此函数之前,确保 `knowledge_base_name``vector_name` 参数正确无误,因为它们直接影响到向量存储路径的构造。
- 此函数依赖于 `get_kb_path` 函数来获取知识库的基础路径,因此需要确保 `get_kb_path` 函数能够正常工作。
**输出示例**:
假设知识库名称为 `my_knowledge_base`,向量名称为 `my_vector``get_kb_path` 返回的路径为 `/var/knowledge_bases/my_knowledge_base`,则 `get_vs_path` 函数将返回:
```
/var/knowledge_bases/my_knowledge_base/vector_store/my_vector
```
这个返回值表示了名为 `my_vector` 的向量存储在文件系统中的完整路径。
## FunctionDef get_file_path(knowledge_base_name, doc_name)
**get_file_path**: 此函数的功能是构造并返回知识库中特定文档的完整文件路径。
**参数**:
- knowledge_base_name: 字符串类型,表示知识库的名称。
- doc_name: 字符串类型,表示文档的名称。
**代码描述**:
`get_file_path` 函数接受两个参数:`knowledge_base_name` 和 `doc_name`。这两个参数分别代表知识库的名称和文档的名称。函数首先调用 `get_doc_path` 函数,传入知识库名称以获取该知识库文档存储的根路径。然后,使用 `os.path.join` 方法将此根路径与文档名称 `doc_name` 结合,构造出完整的文件路径。这种方法确保了在不同操作系统上,路径分隔符能够被正确处理,从而生成有效的文件路径。
在项目中,`get_file_path` 函数被多个模块调用,用于获取知识库中特定文档的存储路径。例如,在文件上传、文档删除、文档检索等场景中,都需要先通过此函数获取文档的完整路径,然后进行后续的文件操作。这表明 `get_file_path` 函数是处理知识库中文档路径的关键工具函数,为知识库中文档的管理和操作提供了基础支持。
**注意**:
- 在调用 `get_file_path` 函数之前,需要确保 `get_doc_path` 函数能够正确返回知识库文档的根路径,并且该路径在文件系统中有效存在。
- 传入的文档名称 `doc_name` 应当是合法的文件名,避免包含可能导致路径构造失败的非法字符。
**输出示例**:
假设 `get_doc_path('my_knowledge_base')` 返回的路径为 `/var/knowledge_bases/my_knowledge_base/content`,且文档名称为 `example.docx`,则调用 `get_file_path('my_knowledge_base', 'example.docx')` 将返回:
```
/var/knowledge_bases/my_knowledge_base/content/example.docx
```
这个返回值表示了名为 `my_knowledge_base` 的知识库中名为 `example.docx` 文档的完整存储路径。
## FunctionDef list_kbs_from_folder
**list_kbs_from_folder**: 此函数的功能是列出知识库根路径下的所有目录。
**参数**: 此函数没有参数。
**代码描述**: `list_kbs_from_folder` 函数通过访问全局变量 `KB_ROOT_PATH`,使用 `os.listdir` 方法获取该路径下的所有文件和目录。然后,它通过列表推导式结合 `os.path.isdir` 方法筛选出所有的目录(即子文件夹),并将这些目录名称作为列表返回。这个函数在项目中主要被用于获取当前知识库根路径下存在的所有知识库目录名称,这对于知识库的管理和操作至关重要。
在项目中,`list_kbs_from_folder` 函数被多个地方调用:
-`get_kb_details` 函数中,它用于获取文件夹中的知识库列表,进而获取每个知识库的详细信息,包括它们是否存在于数据库中。
-`folder2db` 函数中,它用于获取所有需要迁移至数据库的知识库目录名称。根据迁移模式,这些知识库目录中的文件可能会被重新创建向量存储、更新数据库信息或仅对新增文件进行处理。
这些调用情况表明,`list_kbs_from_folder` 函数是知识库管理和迁移工作流中不可或缺的一部分,它提供了一个基础的目录检索功能,使得其他功能模块能够基于当前存在的知识库目录进行进一步的操作。
**注意**: 使用此函数时,需要确保 `KB_ROOT_PATH` 已被正确设置且指向一个有效的知识库根目录。此外,该函数仅返回目录名称,不包括任何文件或子目录的信息。
**输出示例**: 假设知识库根路径下存在两个目录 `kb1``kb2`,则函数的返回值可能如下:
```python
['kb1', 'kb2']
```
## FunctionDef list_files_from_folder(kb_name)
**list_files_from_folder**: 此函数的功能是列出指定知识库文件夹中的所有文件。
**参数**:
- kb_name: 字符串类型,表示知识库的名称。
**代码描述**:
`list_files_from_folder` 函数接受一个参数 `kb_name`,这是一个字符串,代表知识库的名称。函数首先通过调用 `get_doc_path` 函数获取知识库文档的存储路径。然后,它定义了两个内部函数 `is_skiped_path``process_entry` 用于过滤和处理文件夹中的条目。
- `is_skiped_path` 函数用于判断给定的路径是否应该被跳过,例如临时文件或隐藏文件。
- `process_entry` 函数递归地处理每一个文件夹条目,如果是符号链接,则解析目标路径并处理;如果是文件,则将其相对路径添加到结果列表中;如果是目录,则递归处理目录下的每一个条目。
最终,函数返回一个包含所有有效文件相对路径的列表,这些路径都是以 POSIX 格式表示的。
**注意**:
- 确保在调用此函数之前,`get_doc_path` 函数能够正确返回知识库文档的存储路径。
- 此函数会自动过滤掉临时文件、隐藏文件等不需要处理的文件。
- 返回的文件路径列表是基于知识库文档存储路径的相对路径,并且以 POSIX 格式表示。
**输出示例**:
假设知识库名为 "my_knowledge_base",且其文档存储路径下有三个文件 "doc1.txt", "doc2.txt", "tempfile.tmp",则调用 `list_files_from_folder('my_knowledge_base')` 将返回:
```
["doc1.txt", "doc2.txt"]
```
这个返回值表示了名为 "my_knowledge_base" 的知识库中有效文档文件的相对路径列表,注意 "tempfile.tmp" 被自动过滤掉了。
### FunctionDef is_skiped_path(path)
**is_skiped_path**: 此函数的功能是判断给定的路径是否应被跳过。
**参数**:
- path: 字符串类型,表示需要判断的文件或目录路径。
**代码描述**:
`is_skiped_path` 函数接收一个路径字符串作为参数,其目的是判断该路径是否指向一个应被忽略的文件或目录。函数首先使用 `os.path.basename` 方法获取路径的最后一部分(即文件名或目录名),并将其转换为小写,以便进行不区分大小写的比较。然后,函数遍历一个包含特定前缀的列表(如 "temp", "tmp", ".", "~$"),这些前缀被认为是应当被忽略的文件或目录的标志。如果路径的最后一部分以列表中的任何一个前缀开始,函数将返回 `True`,表示该路径应被跳过。如果遍历完列表后没有找到匹配的前缀,函数将返回 `False`,表示该路径不应被跳过。
在项目中,`is_skiped_path` 函数被 `process_entry` 函数调用,用于在处理文件系统条目(如文件或目录)时判断是否应忽略某些路径。这样做可以避免处理临时文件、隐藏文件或其他不需要处理的文件,从而提高处理效率和准确性。
**注意**:
- 在使用此函数时,需要确保传入的路径是字符串类型,并且是有效的文件系统路径。
- 函数的判断依据是路径的最后一部分(文件名或目录名)的前缀,因此在特定情况下可能需要根据实际需求调整忽略的前缀列表。
**输出示例**:
- 如果传入的路径为 "/path/to/tempfile.txt",函数将返回 `True`
- 如果传入的路径为 "/path/to/document.docx",函数将返回 `False`
***
### FunctionDef process_entry(entry)
**process_entry**: 此函数的功能是递归处理文件系统中的每一个条目,包括文件、目录和符号链接。
**参数**:
- entry: 一个代表文件系统条目的对象,该对象具有 `path` 属性以及 `is_symlink()`, `is_file()`, `is_dir()` 等方法,用于判断条目的类型。
**代码描述**:
`process_entry` 函数首先判断给定条目的路径是否应被跳过。这一判断通过调用 `is_skiped_path` 函数实现,如果该函数返回 `True`,则当前条目将被忽略,不进行进一步处理。这主要用于过滤掉临时文件、隐藏文件等不需要处理的文件或目录。
如果条目是一个符号链接symlink函数将解析该链接指向的实际路径并对该路径下的所有条目递归调用 `process_entry` 函数。这确保了符号链接指向的目录或文件被正确处理。
如果条目是一个文件,函数将计算该文件的相对路径(相对于文档根目录 `doc_path`),并将其转换为 POSIX 格式的路径字符串。然后,这个路径字符串被添加到全局的 `result` 列表中,用于后续处理或输出。
如果条目是一个目录,函数将遍历该目录下的所有条目,并对每个条目递归调用 `process_entry` 函数。这样可以确保目录下的所有文件和子目录都被递归处理。
**注意**:
- 在使用此函数之前,需要确保 `doc_path``result` 已经被正确初始化。`doc_path` 应为一个字符串,表示文档的根目录路径;`result` 应为一个列表,用于收集处理结果。
- 该函数递归处理文件系统条目,因此对于具有大量文件和目录的文件系统,需要注意递归深度和性能问题。
- 函数依赖于 `os.scandir` 来遍历目录,这是一个高效的目录遍历方法,但需要确保运行环境支持。
**输出示例**:
由于 `process_entry` 函数主要作用是修改全局的 `result` 列表,而不是直接返回值,因此没有直接的返回值示例。但在函数执行后,`result` 列表将包含所有不被忽略的文件的相对路径POSIX 格式),例如:
```python
['path/to/file1.txt', 'another/path/to/file2.jpg']
```
这个列表随后可以用于进一步的处理或输出。
***
## FunctionDef _new_json_dumps(obj)
**_new_json_dumps**: 该函数的功能是对对象进行JSON格式化同时确保结果中的ASCII字符不会被转义。
**参数**:
- obj: 需要进行JSON格式化的对象。
- **kwargs: 接受可变数量的关键字参数这些参数将直接传递给底层的JSON序列化函数。
**代码描述**:
`_new_json_dumps`函数是一个封装了JSON序列化过程的辅助函数。它接受一个Python对象`obj`和任意数量的关键字参数`**kwargs`。函数的主要作用是在调用原始的JSON序列化函数假设为`_origin_json_dumps`)之前,强制设置`ensure_ascii`参数为`False`。这样做的目的是确保在序列化过程中所有非ASCII字符如中文字符不会被转义成`\uXXXX`形式的ASCII字符串而是保持原样输出。这对于需要保持数据可读性的场景特别有用。
**注意**:
- `_origin_json_dumps`应该是一个已经存在的JSON序列化函数该函数能够接受`ensure_ascii`以及其他任何`json.dumps`支持的参数。
- 由于`ensure_ascii`被强制设置为`False`在处理包含非ASCII字符的数据时输出的JSON字符串将包含这些原生字符。使用者需要确保处理结果的环境支持这些字符。
- 该函数通过`**kwargs`接受额外的参数,这意味着用户可以传递任何`json.dumps`支持的参数来定制序列化行为,除了`ensure_ascii`,因为它已被预设。
**输出示例**:
假设有一个包含中文字符的对象`obj = {"name": "张三"}`,调用`_new_json_dumps(obj)`将返回一个字符串:`'{"name": "张三"}'`。注意,中文字符“张三”没有被转义,直接以原生形式出现在了结果字符串中。
## ClassDef JSONLinesLoader
**JSONLinesLoader**: JSONLinesLoader的功能是加载行式JSON文件这些文件的扩展名为.jsonl。
**属性**:
- `_json_lines`: 一个布尔值指示该加载器是否处理行式JSON数据。
**代码描述**:
JSONLinesLoader类是`langchain.document_loaders.JSONLoader`的子类专门用于处理行式JSON.jsonl文件。行式JSON文件是一种特殊的JSON文件其中每一行都是一个独立的JSON对象。这种格式特别适用于处理大量数据因为它允许逐行读取而不需要一次性加载整个文件到内存中。
构造函数`__init__`接受任意数量的位置参数和关键字参数,这些参数将被传递给父类`JSONLoader`的构造函数。在调用父类构造函数初始化基类属性之后,`JSONLinesLoader`类设置了一个内部属性`_json_lines`为`True`。这个属性的设置可能是用来标识该加载器实例为行式JSON数据的处理者或者用于在内部逻辑中区分行式JSON和其他类型的JSON数据处理。
**注意**:
- 使用JSONLinesLoader时需要确保传入的文件符合行式JSON格式即文件的每一行都是一个完整的JSON对象。
- 由于JSONLinesLoader继承自`JSONLoader`因此它也继承了父类的所有方法和属性。这意味着除了专门处理行式JSON数据的能力外它还可以使用父类提供的任何功能如加载和解析JSON数据。
- 在实际应用中使用JSONLinesLoader可以有效地处理大型的行式JSON文件因为它不需要一次性将整个文件加载到内存中从而减少了内存消耗。
### FunctionDef __init__(self)
**__init__**: 该函数用于初始化JSONLinesLoader类的实例。
**参数**:
- *args: 可变位置参数,用于传递给父类的初始化方法。
- **kwargs: 可变关键字参数,用于传递给父类的初始化方法。
**代码描述**:
`__init__`方法是JSONLinesLoader类的构造函数负责初始化类的实例。在这个方法中首先通过`super().__init__(*args, **kwargs)`调用父类的构造函数,确保父类被正确初始化。这是面向对象编程中常见的做法,特别是在继承体系中,确保父类的初始化逻辑得到执行。
接下来,该方法设置了一个实例变量`_json_lines`,并将其值设为`True`。这个变量的存在表明JSONLinesLoader类的实例将以处理JSON Lines格式的数据为主要功能。JSON Lines是一种便于处理大量结构化数据的格式每一行都是一个独立的JSON对象这种格式特别适合于数据流或数据湖场景。
**注意**:
- 在使用JSONLinesLoader类时应当意识到它默认处理的是JSON Lines格式的数据。如果你的数据不是这种格式可能需要进行相应的转换。
- 由于`__init__`方法中使用了`*args`和`**kwargs`这意味着在实例化JSONLinesLoader类时可以传递额外的参数给父类的构造函数。这提供了灵活性但同时也要求开发者对父类的构造函数有一定的了解以确保正确使用。
***
## FunctionDef get_LoaderClass(file_extension)
**get_LoaderClass**: 此函数的功能是根据文件扩展名返回相应的加载器类。
**参数**:
- **file_extension**: 文件扩展名,用于确定需要使用哪个加载器类。
**代码描述**:
`get_LoaderClass` 函数遍历一个名为 `LOADER_DICT` 的字典,该字典将加载器类映射到它们支持的文件扩展名列表。函数接收一个参数 `file_extension`,这是一个字符串,表示文件的扩展名。函数通过检查 `file_extension` 是否存在于 `LOADER_DICT` 字典的任一值(即支持的文件扩展名列表)中,来确定哪个加载器类支持该文件扩展名。如果找到匹配的文件扩展名,函数将返回相应的加载器类。
在项目中,`get_LoaderClass` 函数被 `KnowledgeFile` 类的构造函数调用,用于根据文件的扩展名确定如何加载文件内容。这是在处理知识库文件时的一个关键步骤,确保了文件能够被正确解析和处理,无论它们的格式如何。通过这种方式,系统能够灵活地支持多种文件格式,只要为这些格式提供了相应的加载器类。
**注意**:
- 确保 `LOADER_DICT` 字典在使用 `get_LoaderClass` 函数之前已经被正确定义和填充,且包含了所有支持的文件扩展名及其对应的加载器类。
- 如果传入的文件扩展名不在 `LOADER_DICT` 的任何值中,函数将返回 `None`。因此,调用此函数的代码需要能够处理这种情况,可能通过抛出异常或提供默认行为。
**输出示例**:
假设 `LOADER_DICT` 如下定义:
```python
LOADER_DICT = {
TextLoader: ['.txt', '.md'],
PDFLoader: ['.pdf']
}
```
如果调用 `get_LoaderClass('.pdf')`,则函数将返回 `PDFLoader` 类。
## FunctionDef get_loader(loader_name, file_path, loader_kwargs)
**get_loader**: 根据指定的加载器名称和文件路径或内容返回相应的文档加载器实例。
**参数**:
- **loader_name**: 字符串,指定要使用的加载器的名称。
- **file_path**: 字符串,指定要加载的文件的路径。
- **loader_kwargs**: 字典,可选参数,用于传递给加载器的额外参数。
**代码描述**:
`get_loader` 函数的主要功能是根据提供的加载器名称(`loader_name`)和文件路径(`file_path`),动态地导入并实例化相应的文档加载器。这个过程中,函数首先会根据加载器名称判断应该从哪个模块导入加载器类。如果加载器名称是`RapidOCRPDFLoader`、`RapidOCRLoader`、`FilteredCSVLoader`、`RapidOCRDocLoader`或`RapidOCRPPTLoader`中的任何一个,那么加载器将从`document_loaders`模块导入。否则,将从`langchain.document_loaders`模块导入。
在尝试导入加载器类时,如果遇到任何异常,将会记录错误信息,并改为导入默认的`UnstructuredFileLoader`加载器。
此外,函数还会根据不同的加载器名称对`loader_kwargs`参数进行特定的处理。例如,如果使用的是`UnstructuredFileLoader`,则会设置`autodetect_encoding`为`True`。如果是`CSVLoader`,则会尝试自动检测文件的编码类型,并设置相应的`encoding`参数。对于`JSONLoader`和`JSONLinesLoader`,则会设置默认的`jq_schema`和`text_content`参数。
最后,函数使用导入的加载器类和处理后的参数创建加载器实例,并返回该实例。
在项目中,`get_loader`函数被`file2docs`方法调用,用于根据文件路径和加载器名称动态加载文件内容,进而转换为文档对象。这种设计使得加载不同类型文件的过程更加灵活和可配置。
**注意**:
- 在使用`get_loader`函数时,需要确保传入的`loader_name`对应的加载器类已经正确实现,并且可以从指定的模块中导入。
- 对于`loader_kwargs`参数,应根据实际使用的加载器的需求,传入正确的参数值。
**输出示例**:
假设存在一个名为`RapidOCRLoader`的加载器类,调用`get_loader("RapidOCRLoader", "/path/to/file")`可能会返回一个`RapidOCRLoader`的实例,该实例已经被初始化,准备用于加载指定路径的文件。
## FunctionDef make_text_splitter(splitter_name, chunk_size, chunk_overlap, llm_model)
**make_text_splitter**: 此函数的功能是根据给定参数创建并返回一个特定的文本分词器实例。
**参数**:
- `splitter_name`: 字符串类型,默认为`TEXT_SPLITTER_NAME`。指定要创建的分词器名称。
- `chunk_size`: 整型,默认为`CHUNK_SIZE`。指定分词时每个文本块的大小。
- `chunk_overlap`: 整型,默认为`OVERLAP_SIZE`。指定分词时文本块之间的重叠大小。
- `llm_model`: 字符串类型,默认为`LLM_MODELS[0]`。指定使用的大型语言模型。
**代码描述**:
此函数首先根据`splitter_name`参数确定需要创建的文本分词器类型。如果未指定`splitter_name`,则默认使用`SpacyTextSplitter`。函数尝试根据分词器名称从用户自定义模块或`langchain.text_splitter`模块中导入相应的分词器类。对于特定的分词器,如`MarkdownHeaderTextSplitter`,会根据配置字典`text_splitter_dict`中的设置进行初始化。
根据分词器的来源(如`tiktoken`或`huggingface`),函数会采用不同的方式来创建分词器实例。例如,从`huggingface`加载时,会根据配置中的`tokenizer_name_or_path`来加载对应的分词器,并根据`chunk_size`和`chunk_overlap`参数进行初始化。如果在创建过程中遇到任何异常,函数会回退到使用`RecursiveCharacterTextSplitter`作为默认分词器。
此外函数中包含了一些注释指出如何使用GPU加速`SpacyTextSplitter`的分词过程,这对处理大规模文本数据特别有用。
**注意**:
- 确保在调用此函数之前,已经正确设置了`TEXT_SPLITTER_NAME`、`CHUNK_SIZE`、`OVERLAP_SIZE`等全局变量,以及`LLM_MODELS`列表。
- 如果需要从`tiktoken`或`huggingface`加载分词器,请确保相关的分词器名称或路径已经正确配置在`text_splitter_dict`字典中。
- 此函数依赖于`importlib`动态导入模块和类,因此需要确保目标分词器的模块已经安装在环境中。
**输出示例**:
调用`make_text_splitter(splitter_name="SpacyTextSplitter", chunk_size=100, chunk_overlap=20)`可能会返回一个`SpacyTextSplitter`的实例该实例配置了每个文本块大小为100文本块之间的重叠大小为20。
## ClassDef KnowledgeFile
**KnowledgeFile**: KnowledgeFile类用于表示和处理知识库中的文件。
**属性**:
- `kb_name`: 知识库的名称。
- `filename`: 文件的名称。
- `ext`: 文件的扩展名。
- `loader_kwargs`: 加载文件时使用的参数字典。
- `filepath`: 文件在磁盘上的完整路径。
- `docs`: 文件内容转换成的文档列表。
- `splited_docs`: 经过分割处理后的文档列表。
- `document_loader_name`: 用于加载文件内容的加载器类名。
- `text_splitter_name`: 用于分割文档文本的分割器名称。
**代码描述**:
KnowledgeFile类主要负责处理知识库中的文件包括文件的加载、文档的提取和文本的分割等功能。它首先检查文件格式是否受支持然后根据文件扩展名确定使用哪个文档加载器和文本分割器。通过`file2docs`方法,可以将文件内容加载为文档列表;通过`docs2texts`方法,可以将文档列表进一步处理成文本列表,支持中文标题加强和文本分块等功能;`file2text`方法则结合了加载和处理两个步骤,直接从文件生成处理后的文本列表。此外,该类还提供了检查文件存在性、获取文件修改时间和大小的方法。
在项目中KnowledgeFile类被多个模块调用用于处理上传的文件、更新知识库文档、删除知识库文档等场景。例如在文件上传处理中会创建KnowledgeFile实例来加载和处理上传的文件然后将处理结果存储到知识库中在知识库文档更新和删除操作中也会通过KnowledgeFile实例来操作具体的文件。
**注意**:
- 在使用KnowledgeFile类时需要确保传入的文件名和知识库名称正确且文件必须存在于磁盘上。
- 文件处理过程中,如果文件格式不受支持或者文档加载器、文本分割器出现问题,可能会抛出异常。
- 在处理大量文件或大型文件时,应注意性能和内存使用情况。
**输出示例**:
```python
# 假设有一个Markdown文件"example.md"以下是创建KnowledgeFile实例并加载文档的示例代码
kb_file = KnowledgeFile(filename="example.md", knowledge_base_name="demo_kb")
docs = kb_file.file2docs()
print(docs) # 输出处理后的文档列表
```
### FunctionDef __init__(self, filename, knowledge_base_name, loader_kwargs)
**__init__**: 此函数的功能是初始化KnowledgeFile对象用于处理知识库中的文件。
**参数**:
- **filename**: 字符串类型,指定了文件的名称。
- **knowledge_base_name**: 字符串类型,指定了知识库的名称。
- **loader_kwargs**: 字典类型,默认为空字典,用于传递给文件加载器的额外参数。
**代码描述**:
`__init__` 函数是 `KnowledgeFile` 类的构造函数,负责初始化处理知识库中文件的实例。首先,它将知识库名称存储在实例变量 `kb_name` 中。然后,使用 `Path` 类将文件名转换为POSIX风格的路径字符串并存储在实例变量 `filename` 中。接着,通过 `os.path.splitext` 方法提取文件的扩展名,并转换为小写存储在实例变量 `ext` 中。如果文件扩展名不在支持的扩展名列表 `SUPPORTED_EXTS` 中,则抛出 `ValueError` 异常,提示文件格式不被支持。
此外,`__init__` 函数还负责根据知识库名称和文件名,通过调用 `get_file_path` 函数获取文件的完整路径,并存储在实例变量 `filepath` 中。这一步骤是文件处理的基础,确保了后续操作能够针对正确的文件路径进行。
函数还初始化了几个用于后续文档处理的实例变量,如 `docs``splited_docs`,它们分别用于存储加载的文档内容和分割后的文档内容,初始值均为 `None`
最后,`__init__` 函数根据文件扩展名,通过调用 `get_LoaderClass` 函数确定适合该文件格式的加载器类,并将其名称存储在实例变量 `document_loader_name` 中。同时,将文本分割器的名称存储在实例变量 `text_splitter_name` 中,为后续的文档加载和处理提供必要的信息。
**注意**:
- 在使用 `__init__` 函数初始化 `KnowledgeFile` 对象之前,确保传入的文件名和知识库名称是有效的,且文件必须存在于磁盘上。
- 文件的扩展名必须包含在 `SUPPORTED_EXTS` 列表中,否则会抛出异常。
- `loader_kwargs` 参数提供了一种灵活的方式,允许在加载文件时传递额外的参数给加载器类,但默认为空字典。在需要特殊处理文件加载行为时,可以通过此参数传递必要的信息。
***
### FunctionDef file2docs(self, refresh)
**file2docs**: 该函数用于加载并返回文件内容的文档对象。
**参数**:
- **refresh**: 布尔值默认为False。如果设置为True则强制重新加载文档。
**代码描述**:
`file2docs`方法主要负责根据文件路径加载文件内容,并将其转换为文档对象。当对象的`docs`属性为None或者`refresh`参数为True时该方法会通过调用`get_loader`函数动态地获取一个文档加载器实例。加载器的选择依赖于对象的`document_loader_name`属性和`loader_kwargs`属性,这些属性分别指定了加载器的名称和传递给加载器的额外参数。加载器实例化后,会调用其`load`方法加载文件内容,并将加载的结果赋值给对象的`docs`属性。如果`docs`属性已经有值且`refresh`参数为False则直接返回`docs`属性的值,不会重新加载文档。
在整个过程中,会有日志记录当前使用的加载器名称和文件路径,以便于跟踪和调试。
**注意**:
- 使用`file2docs`方法时,需要确保对象的`document_loader_name`属性已正确设置,且对应的加载器类能够被成功导入和实例化。
- `loader_kwargs`属性应根据实际使用的加载器的需求,提前正确设置。
- 如果需要重新加载文档,可以将`refresh`参数设置为True。
**输出示例**:
调用`file2docs(refresh=True)`可能会返回一个文档对象列表这取决于文件内容和指定的加载器。例如如果文件是一个PDF文档且使用了`RapidOCRPDFLoader`加载器那么返回的可能是包含PDF中每一页内容的文档对象列表。
***
### FunctionDef docs2texts(self, docs, zh_title_enhance, refresh, chunk_size, chunk_overlap, text_splitter)
**docs2texts**: 此函数的功能是将文档对象列表转换为文本列表,可选地增强中文标题,并支持文本的分块处理。
**参数**:
- `docs`: 文档对象列表默认为None。如果未提供则会调用`file2docs`方法获取文档对象列表。
- `zh_title_enhance`: 布尔值,指示是否增强中文标题,默认值取决于全局变量`ZH_TITLE_ENHANCE`。
- `refresh`: 布尔值指示是否强制刷新文档对象列表默认为False。
- `chunk_size`: 整型,指定分块大小,默认值取决于全局变量`CHUNK_SIZE`。
- `chunk_overlap`: 整型,指定分块之间的重叠大小,默认值取决于全局变量`OVERLAP_SIZE`。
- `text_splitter`: 文本分割器实例默认为None。如果未提供则会根据`self.text_splitter_name`创建一个新的文本分割器实例。
**代码描述**:
此函数首先检查是否提供了`docs`参数,如果没有,则调用`file2docs`方法获取文档对象列表。接着检查文档列表是否为空如果为空则直接返回空列表。对于非CSV文件类型根据是否提供了`text_splitter`参数,使用`make_text_splitter`函数创建或使用提供的文本分割器实例进行文本分割。如果文本分割器名称为`MarkdownHeaderTextSplitter`,则仅分割第一个文档的页面内容;否则,对整个文档列表进行分割。分割后,如果启用了中文标题增强(`zh_title_enhance`为True),则对分割后的文档进行标题增强处理。最后,将分割(和可能增强)后的文档列表赋值给`self.splited_docs`属性,并返回该属性。
**注意**:
- 在调用此函数之前,确保相关的全局变量(如`ZH_TITLE_ENHANCE`、`CHUNK_SIZE`、`OVERLAP_SIZE`)已正确设置。
- 如果需要处理大量文档或大型文档,考虑合理设置`chunk_size`和`chunk_overlap`参数以优化性能和结果质量。
- 此函数支持通过`text_splitter`参数自定义文本分割器,使其能够灵活适应不同的文本处理需求。
**输出示例**:
调用`docs2texts(docs=my_docs, zh_title_enhance=True, refresh=True, chunk_size=200, chunk_overlap=50)`可能会返回一个文本列表其中每个文本块的大小为200个字符相邻文本块之间有50个字符的重叠并且对于包含中文标题的文档其标题已被增强处理。
***
### FunctionDef file2text(self, zh_title_enhance, refresh, chunk_size, chunk_overlap, text_splitter)
**file2text**: 此函数用于将文件内容转换为文本列表,支持中文标题增强、文档刷新、分块处理以及自定义文本分割器。
**参数**:
- `zh_title_enhance`: 布尔值,指示是否增强中文标题,默认值取决于全局变量`ZH_TITLE_ENHANCE`。
- `refresh`: 布尔值指示是否强制刷新文档对象列表默认为False。
- `chunk_size`: 整型,指定分块大小,默认值取决于全局变量`CHUNK_SIZE`。
- `chunk_overlap`: 整型,指定分块之间的重叠大小,默认值取决于全局变量`OVERLAP_SIZE`。
- `text_splitter`: 文本分割器实例默认为None。如果未提供则会根据`self.text_splitter_name`创建一个新的文本分割器实例。
**代码描述**:
`file2text`函数首先检查对象的`splited_docs`属性是否为None或者是否需要刷新`refresh`参数为True。如果是则调用`file2docs`方法加载文件内容并转换为文档对象列表。接着,调用`docs2texts`方法将文档对象列表转换为文本列表,同时可以选择是否增强中文标题、是否刷新文档对象列表、分块大小、分块之间的重叠大小以及是否使用自定义的文本分割器。最后,将转换得到的文本列表赋值给`splited_docs`属性,并返回该属性。
**注意**:
- 在调用`file2text`函数之前,确保相关的全局变量(如`ZH_TITLE_ENHANCE`、`CHUNK_SIZE`、`OVERLAP_SIZE`)已正确设置。
- 如果需要处理大量文档或大型文档,考虑合理设置`chunk_size`和`chunk_overlap`参数以优化性能和结果质量。
- 通过`text_splitter`参数可以自定义文本分割器,使其能够灵活适应不同的文本处理需求。
- 当`refresh`参数设置为True时将强制重新加载文档并进行文本转换处理这可能会增加处理时间。
**输出示例**:
调用`file2text(zh_title_enhance=True, refresh=True, chunk_size=200, chunk_overlap=50)`可能会返回一个文本列表其中每个文本块的大小为200个字符相邻文本块之间有50个字符的重叠并且对于包含中文标题的文档其标题已被增强处理。这个列表可以直接用于后续的文本分析或处理任务。
***
### FunctionDef file_exist(self)
**file_exist**: 此函数用于检查文件是否存在。
**参数**: 此函数不接受任何外部参数,但依赖于对象内的`filepath`属性。
**代码描述**: `file_exist`函数是`KnowledgeFile`类的一个方法,用于检查指定路径的文件是否存在。它通过调用`os.path.isfile`方法实现,该方法接受一个路径作为参数,并返回一个布尔值,指示该路径是否指向一个存在的文件。在这里,`self.filepath`是`KnowledgeFile`对象中存储文件路径的属性。如果文件存在于该路径,则函数返回`True`;如果文件不存在,则返回`False`。
**注意**: 使用此函数前,请确保`KnowledgeFile`对象已正确初始化,并且`filepath`属性已经被赋予了一个有效的文件路径。此外,此函数的返回值依赖于操作系统对文件系统的访问权限,如果没有足够的权限访问指定的文件路径,可能会影响结果的准确性。
**输出示例**: 假设`self.filepath`指向的文件存在,那么`file_exist()`将返回`True`。反之,如果文件不存在,将返回`False`。
***
### FunctionDef get_mtime(self)
**get_mtime**: 此函数的功能是获取文件的最后修改时间。
**参数**: 此函数没有参数。
**代码描述**: `get_mtime`函数是`KnowledgeFile`类的一个方法,用于获取与`KnowledgeFile`实例关联的文件的最后修改时间。它通过调用`os.path.getmtime`方法实现该方法接受一个路径作为参数并返回该路径所指文件的最后修改时间以秒为单位自1970年1月1日以来的时间。在这个场景中`self.filepath`代表了`KnowledgeFile`实例所关联的文件路径。此函数在项目中的主要作用是在更新或添加知识库文件到数据库时,获取文件的最新修改时间,以便进行相应的数据更新或记录。
在`server/db/repository/knowledge_file_repository.py/add_file_to_db`方法中,`get_mtime`被用来获取一个知识库文件的最后修改时间。这个时间随后被用来更新数据库中对应文件的`file_mtime`字段,如果文件已存在,则更新该文件的信息和版本号;如果文件不存在,则添加新文件时记录该时间。这样确保了数据库中文件的修改时间是最新的,有助于跟踪文件的更新历史。
**注意**: 使用`get_mtime`函数时,需要确保`self.filepath`是有效的且指向的文件存在,否则`os.path.getmtime`将抛出`FileNotFoundError`异常。
**输出示例**: 假设某文件最后修改时间为2023年4月1日12时0分0秒调用`get_mtime`函数将返回`1679856000.0`(这是一个示例值,实际值取决于文件的确切修改时间)。
***
### FunctionDef get_size(self)
**get_size**: 此函数的功能是获取文件的大小。
**参数**: 此函数没有参数。
**代码描述**: `get_size` 函数是 `KnowledgeFile` 类的一个方法,用于返回与该实例关联的文件的大小。它通过调用 `os.path.getsize` 方法实现,该方法接受一个文件路径作为参数,并返回该文件的大小(以字节为单位)。在这个场景中,`self.filepath` 表示的是 `KnowledgeFile` 实例所关联的文件路径。此功能在文件管理和处理中非常重要,尤其是在需要根据文件大小做出决策或进行优化的场景下。
在项目中,`get_size` 方法被 `add_file_to_db` 函数调用,用于获取待添加到数据库的知识文件的大小。这个大小信息随后被用于更新或创建数据库中的文件记录。具体来说,如果文件已存在于数据库中,则更新该文件的大小信息;如果文件不存在,则在创建新文件记录时包含文件大小信息。这样做可以确保数据库中的文件信息是最新的,同时也支持文件管理和版本控制的需求。
**注意**: 使用 `get_size` 方法时,需要确保 `self.filepath` 是有效的文件路径,且文件确实存在,否则 `os.path.getsize` 方法会抛出异常。
**输出示例**: 假设 `self.filepath` 指向的文件大小为 1024 字节,那么 `get_size` 方法的返回值将会是 `1024`
***
## FunctionDef files2docs_in_thread(files, chunk_size, chunk_overlap, zh_title_enhance)
**files2docs_in_thread**: 该函数的功能是利用多线程批量将磁盘文件转化成langchain Document。
**参数**:
- `files`: 文件列表,可以是`KnowledgeFile`实例、包含文件名和知识库名的元组,或者是包含文件信息的字典。
- `chunk_size`: 文档分块的大小,默认值为`CHUNK_SIZE`。
- `chunk_overlap`: 文档分块之间的重叠大小,默认值为`OVERLAP_SIZE`。
- `zh_title_enhance`: 是否开启中文标题加强,默认值为`ZH_TITLE_ENHANCE`。
**代码描述**:
`files2docs_in_thread`函数主要通过多线程的方式,将文件转化为文档对象。函数首先会遍历`files`参数中的每个文件,根据文件的类型(`KnowledgeFile`实例、元组或字典),提取或设置文件的相关信息,并构造`KnowledgeFile`实例。接着,为每个文件设置转化为文档所需的参数,包括文件本身、分块大小、分块重叠大小和中文标题加强选项,并将这些参数存储在`kwargs_list`列表中。
之后,函数调用`run_in_thread_pool`函数,将`file2docs`函数和`kwargs_list`作为参数传入,以多线程的方式执行文件到文档的转化过程。`run_in_thread_pool`函数会返回一个生成器,该生成器按顺序产生每个文件转化结果的状态和结果(包括知识库名、文件名和文档列表或错误信息)。
在转化过程中,如果遇到任何异常,函数会捕获这些异常并记录错误信息,同时生成器会产生包含错误信息的结果。
**注意**:
- 传入的文件列表中的文件必须存在于磁盘上,否则在创建`KnowledgeFile`实例时会抛出异常。
- `run_in_thread_pool`函数的使用需要确保线程安全,因此在`file2docs`函数中进行的操作应避免线程安全问题。
- 由于函数返回值是一个生成器,调用此函数时需要通过迭代来获取所有文件的转化结果。
**输出示例**:
```python
# 假设files参数包含了多个文件信息
results = files2docs_in_thread(files=[("example.txt", "sample_kb"), {"filename": "demo.txt", "kb_name": "demo_kb"}])
for status, result in results:
if status:
print(f"成功处理文件: {result[1]},文档数量: {len(result[2])}")
else:
print(f"处理文件失败: {result[1]},错误信息: {result[2]}")
```
在这个示例中,`files2docs_in_thread`函数被用于处理两个文件,一个通过元组指定,另一个通过字典指定。函数返回的生成器被迭代,以打印每个文件处理的结果。成功处理的文件会打印文件名和文档数量,处理失败的文件会打印文件名和错误信息。
### FunctionDef file2docs
**file2docs**: 此函数的功能是将文件转换为文档列表。
**参数**:
- `file`: KnowledgeFile类型的对象表示需要转换为文档的文件。
- `**kwargs`: 可变关键字参数,用于传递给`file.file2text`方法的额外参数。
**代码描述**:
`file2docs`函数接收一个`KnowledgeFile`对象作为参数,并尝试调用该对象的`file2text`方法来将文件内容转换为文本列表。这个过程中,`file2text`方法支持通过`**kwargs`传递额外的参数,以便在转换过程中进行定制化处理,例如中文标题增强、文档刷新、分块处理以及自定义文本分割器等。
如果转换成功,函数将返回一个元组,其中第一个元素为`True`,表示转换成功;第二个元素为另一个元组,包含知识库名称(`kb_name`)、文件名(`filename`)和转换得到的文档列表。
如果在转换过程中发生异常,函数将捕获异常并通过日志记录错误信息,然后返回一个元组,其中第一个元素为`False`,表示转换失败;第二个元素为另一个元组,包含知识库名称、文件名和错误信息。
此函数在项目中的作用是作为文件到文档转换过程的入口点,它依赖于`KnowledgeFile`对象的`file2text`方法来实现文件内容的读取和转换。这种设计使得文件到文档的转换过程可以灵活地适应不同类型的文件和处理需求。
**注意**:
- 在调用此函数之前,需要确保传入的`file`对象已经正确初始化,并且对应的文件确实存在。
- 转换过程中可能会因为文件格式不支持、文件内容问题或其他内部错误而失败,因此调用方需要检查返回值,以确定转换是否成功。
- 由于可能涉及到文件读取和文本处理,该过程可能会消耗一定的时间和资源,特别是处理大型文件时。
**输出示例**:
```python
# 假设转换成功
(True, ('知识库名称', '文件名.md', [文档对象1, 文档对象2, ...]))
# 假设转换失败
(False, ('知识库名称', '文件名.md', '加载文档时出错:错误信息'))
```
***