Langchain-Chatchat/markdown_docs/server/chat/file_chat.md

149 lines
12 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 _parse_files_in_thread(files, dir, zh_title_enhance, chunk_size, chunk_overlap)
**_parse_files_in_thread**: 该函数的功能是通过多线程将上传的文件保存到指定目录,并对文件内容进行处理。
**参数**:
- `files`: 一个`UploadFile`对象的列表,表示需要处理的上传文件。
- `dir`: 字符串,表示文件保存的目标目录。
- `zh_title_enhance`: 布尔值,指示是否开启中文标题加强功能。
- `chunk_size`: 整数,指定文本处理时单个块的大小。
- `chunk_overlap`: 整数,指定文本处理时相邻块之间的重叠长度。
**代码描述**:
该函数首先定义了一个内部函数`parse_file`,用于处理单个文件。`parse_file`尝试读取上传文件的内容,并将其保存到指定目录。如果目录不存在,则会创建该目录。之后,使用`KnowledgeFile`对象对文件内容进行处理,包括文本提取和可能的中文标题加强处理,根据`chunk_size`和`chunk_overlap`参数对文本进行分块处理。处理成功后,返回一个包含成功标志、文件名、成功消息和文档对象列表的元组;处理失败时,返回一个包含失败标志、文件名、错误消息和空列表的元组。
接下来,函数使用`run_in_thread_pool`函数并发地对`files`列表中的每个文件执行`parse_file`函数。`run_in_thread_pool`接受一个函数和一个参数列表,创建一个线程池并在其中并发执行该函数,最后以生成器的形式返回每个任务的结果。`_parse_files_in_thread`函数遍历这些结果,并将它们逐一返回。
**注意**:
- 确保传入的`dir`路径存在或该函数有权限创建目录。
- 由于使用了多线程,确保所有操作(特别是文件写入和文本处理)都是线程安全的。
- 调用此函数时,应通过迭代来处理返回的生成器,以获取所有文件的处理结果。
**输出示例**:
```python
[
(True, "example.txt", "成功上传文件 example.txt", [<文档对象>]),
(False, "error.txt", "error.txt 文件上传失败,报错信息为: 文件无法读取", [])
]
```
该输出示例展示了函数处理两个文件的可能结果:第一个文件成功处理,返回成功标志、文件名、成功消息和文档对象列表;第二个文件处理失败,返回失败标志、文件名、错误消息和一个空列表。
### FunctionDef parse_file(file)
**parse_file**: 此函数的功能是保存单个文件,并将其内容转换为文本列表。
**参数**:
- `file`: `UploadFile`类型,表示需要被解析和保存的上传文件。
**代码描述**:
`parse_file`函数首先从上传的文件中提取文件名,并构建文件应该被保存到的路径。然后,它会检查这个路径所在的目录是否存在,如果不存在,则创建该目录。接下来,函数以二进制写入模式打开目标路径的文件,并将上传的文件内容写入其中。
在文件成功保存之后,函数创建一个`KnowledgeFile`实例,用于处理和转换文件内容。通过调用`KnowledgeFile`类的`file2text`方法,文件内容被转换为文本列表。这一过程支持中文标题增强、分块处理以及自定义文本分割器,便于后续的文本分析或处理任务。
如果文件处理和转换过程中出现任何异常,函数将捕获这些异常,并返回一个包含错误信息的响应,指示文件上传失败。
**注意**:
- 确保上传的文件路径是有效的,并且服务器有足够的权限在指定位置创建文件和目录。
- `KnowledgeFile`类的使用需要确保文件格式被支持,且相关的处理参数(如中文标题增强、分块大小等)已正确设置。
- 异常处理部分对于识别和调试文件上传或处理过程中可能出现的问题非常重要。
**输出示例**:
调用`parse_file`函数可能会返回以下形式的元组:
```python
(True, "example.txt", "成功上传文件 example.txt", ["文档内容示例"])
```
如果遇到错误,则返回的元组可能如下:
```python
(False, "example.txt", "example.txt 文件上传失败,报错信息为: 文件格式不支持", [])
```
这个返回值分别表示处理的成功与否、文件名、相关消息以及处理后的文本列表(或在失败时为空列表)。
***
## FunctionDef upload_temp_docs(files, prev_id, chunk_size, chunk_overlap, zh_title_enhance)
**upload_temp_docs**: 该函数的功能是将文件保存到临时目录,并进行向量化处理。
**参数**:
- `files`: 上传的文件列表,类型为`List[UploadFile]`。支持多文件上传。
- `prev_id`: 前知识库ID类型为`str`。用于指定之前的临时目录ID如果提供则尝试复用该目录。
- `chunk_size`: 知识库中单段文本的最大长度,类型为`int`。用于在文本处理时指定单个块的大小。
- `chunk_overlap`: 知识库中相邻文本的重合长度,类型为`int`。用于在文本处理时指定相邻块之间的重叠长度。
- `zh_title_enhance`: 是否开启中文标题加强,类型为`bool`。用于指示是否对中文标题进行加强处理。
**代码描述**:
函数首先检查`prev_id`是否存在,如果存在,则从`memo_faiss_pool`中移除对应的临时向量库。接着,初始化失败文件列表`failed_files`和文档列表`documents`。通过调用`get_temp_dir`函数,根据`prev_id`获取或创建临时目录的路径和ID。然后使用`_parse_files_in_thread`函数并发处理上传的文件,该函数会将文件保存到指定的临时目录,并进行必要的文本处理和向量化。处理结果包括成功标志、文件对象、消息和文档列表。对于处理成功的文件,其文档列表会被添加到`documents`中;对于处理失败的文件,其文件名和错误消息会被添加到`failed_files`列表中。之后,通过`load_vector_store`函数加载或初始化临时向量库,并使用`acquire`上下文管理器确保线程安全。最后将文档列表添加到向量库中并返回包含临时目录ID和失败文件列表的`BaseResponse`对象。
**注意**:
- 在上传文件时,应确保文件类型和大小符合要求,以避免上传失败。
- 如果指定了`prev_id`,函数会尝试复用之前的临时目录,这可以减少不必要的目录创建操作。
- 在处理大量文件或大型文件时,应注意函数的执行时间,可能需要较长的处理时间。
- 使用`zh_title_enhance`参数可以针对中文标题进行加强处理,提高文本处理的质量。
**输出示例**:
```json
{
"code": 200,
"msg": "success",
"data": {
"id": "临时目录ID",
"failed_files": [
{"file1": "错误消息1"},
{"file2": "错误消息2"}
]
}
}
```
该输出示例展示了函数执行成功后的返回值其中包含了临时目录的ID和失败文件列表。如果所有文件都成功处理`failed_files`列表将为空。
## FunctionDef file_chat(query, knowledge_id, top_k, score_threshold, history, stream, model_name, temperature, max_tokens, prompt_name)
**file_chat**: 该函数用于处理用户通过文件聊天接口发送的查询,并返回相关的知识库文档内容以及基于这些内容的对话回复。
**参数**:
- `query`: 用户输入的查询内容,为字符串类型,必填项。
- `knowledge_id`: 临时知识库ID用于指定查询的知识库为字符串类型必填项。
- `top_k`: 匹配向量数,指定返回的相关文档数量,为整数类型。
- `score_threshold`: 知识库匹配相关度阈值取值范围在0-1之间用于筛选相关度高的文档为浮点数类型。
- `history`: 历史对话列表,包含用户和助手的对话历史,为列表类型。
- `stream`: 是否流式输出,为布尔类型,指定是否以流的形式返回数据。
- `model_name`: LLM 模型名称,用于指定生成回复时使用的语言模型,为字符串类型。
- `temperature`: LLM 采样温度,用于调整生成文本的多样性,为浮点数类型。
- `max_tokens`: 限制LLM生成Token数量为整数类型可选项。
- `prompt_name`: 使用的prompt模板名称用于指定生成回复时使用的模板为字符串类型。
**代码描述**:
该函数首先检查传入的`knowledge_id`是否存在于`memo_faiss_pool`中如果不存在则返回404错误。接着将传入的历史对话列表转换为`History`对象列表。函数定义了一个异步生成器`knowledge_base_chat_iterator`,用于生成对话回复和相关文档内容。在这个生成器中,首先根据`max_tokens`的值调整Token数量限制然后使用指定的LLM模型和温度参数创建一个聊天模型。通过`embed_func`将用户查询嵌入为向量,并使用`memo_faiss_pool`中的向量搜索功能找到最相关的文档。根据找到的文档和历史对话构建聊天提示然后使用LLM模型生成回复。最后根据`stream`参数的值决定是流式输出还是一次性返回所有数据。
**注意**:
- 在使用该函数之前,需要确保`memo_faiss_pool`已经初始化,并且包含了至少一个知识库。
- `history`参数中的历史对话记录应按照时间顺序排列,以便正确构建对话上下文。
- 设置`score_threshold`可以帮助过滤掉相关度较低的文档,提高回复的准确性。
- 如果`stream`参数设置为True将以服务器发送事件Server-Sent Events, SSE的形式流式返回数据适用于需要实时更新的场景。
**输出示例**:
```json
{
"answer": "这是基于您的查询和相关文档生成的回复。",
"docs": [
"出处 [1] [source_document.pdf] \n\n这是相关文档的内容。\n\n"
]
}
```
如果`stream`参数为True将分批次返回数据每次返回一个包含回复片段的JSON对象最后返回包含相关文档内容的JSON对象。
### FunctionDef knowledge_base_chat_iterator
**knowledge_base_chat_iterator**: 此函数的功能是异步迭代生成基于知识库的聊天回答。
**参数**:
- 无参数直接传入此函数,但函数内部使用了多个全局变量和其他对象的方法。
**代码描述**:
`knowledge_base_chat_iterator`函数是一个异步生成器,用于处理基于知识库的聊天回答。首先,它检查`max_tokens`是否为整数且小于等于0如果是则将`max_tokens`设置为None。接着使用`get_ChatOpenAI`函数初始化一个ChatOpenAI实例该实例用于生成聊天回答。此过程中`model_name`、`temperature`、`max_tokens`等参数被用于配置模型,而`callbacks`参数中包含了一个`AsyncIteratorCallbackHandler`实例,用于处理异步回调。
函数继续通过`EmbeddingsFunAdapter`类的`aembed_query`方法异步获取查询文本的嵌入向量。然后,使用`memo_faiss_pool.acquire`方法安全地从缓存池中获取知识库向量存储对象,并执行相似度搜索,搜索结果存储在`docs`变量中。
根据搜索到的文档,函数构建聊天上下文`context`。如果没有找到相关文档,将使用`get_prompt_template`函数获取空模板;否则,根据`prompt_name`获取相应模板。接着,使用`History`类和`ChatPromptTemplate`构建聊天提示。
通过`LLMChain`类函数将聊天提示和上下文传递给ChatOpenAI模型进行处理生成的回答通过`wrap_done`函数包装的异步任务进行管理。
最后,函数根据是否启用流式传输(`stream`变量),以不同方式生成回答。如果启用流式传输,将通过`callback.aiter()`异步迭代回答并以服务器发送事件server-sent-events的形式逐个发送如果未启用流式传输将收集完整的回答后一次性返回。
**注意**:
- 该函数是异步的,需要在支持异步的环境中运行。
- 使用`knowledge_base_chat_iterator`函数时,需要确保相关的全局变量(如`model_name`、`temperature`等)已正确设置。
- 函数内部使用了多个外部定义的对象和方法(如`get_ChatOpenAI`、`EmbeddingsFunAdapter`等),确保这些依赖项在调用此函数之前已正确初始化和配置。
- 在处理大量或复杂的查询时,函数的执行时间可能较长,因此在设计用户界面和交互流程时应考虑到潜在的延迟。
***