From 341ee9db44ce8f3545067438e22d82842e83023b Mon Sep 17 00:00:00 2001 From: Qinyu Luo <62985169+LOGIC-10@users.noreply.github.com> Date: Mon, 15 Apr 2024 21:51:13 +0800 Subject: [PATCH] Generate repository-level Chinese code documentation by RepoAgent. (#3108) --- .../document_loaders/FilteredCSVloader.md | 107 ++ markdown_docs/document_loaders/mydocloader.md | 106 ++ markdown_docs/document_loaders/myimgloader.md | 71 + markdown_docs/document_loaders/mypdfloader.md | 89 ++ markdown_docs/document_loaders/mypptloader.md | 93 ++ markdown_docs/document_loaders/ocr.md | 17 + .../embeddings/add_embedding_keywords.md | 58 + markdown_docs/release.md | 46 + markdown_docs/server/agent/callbacks.md | 301 ++++ .../agent/custom_agent/ChatGLM3Agent.md | 296 ++++ markdown_docs/server/agent/custom_template.md | 128 ++ markdown_docs/server/agent/model_contain.md | 29 + markdown_docs/server/agent/tools/arxiv.md | 36 + markdown_docs/server/agent/tools/calculate.md | 32 + .../server/agent/tools/search_internet.md | 61 + .../tools/search_knowledgebase_complex.md | 202 +++ .../agent/tools/search_knowledgebase_once.md | 218 +++ .../tools/search_knowledgebase_simple.md | 45 + .../server/agent/tools/search_youtube.md | 39 + markdown_docs/server/agent/tools/shell.md | 34 + .../server/agent/tools/weather_check.md | 62 + markdown_docs/server/agent/tools/wolfram.md | 35 + markdown_docs/server/api.md | 116 ++ .../conversation_callback_handler.md | 87 + markdown_docs/server/chat/agent_chat.md | 71 + markdown_docs/server/chat/chat.md | 57 + markdown_docs/server/chat/completion.md | 50 + markdown_docs/server/chat/feedback.md | 32 + markdown_docs/server/chat/file_chat.md | 148 ++ .../server/chat/knowledge_base_chat.md | 64 + .../server/chat/search_engine_chat.md | 207 +++ markdown_docs/server/chat/utils.md | 102 ++ markdown_docs/server/db/models/base.md | 21 + .../server/db/models/conversation_model.md | 41 + .../server/db/models/knowledge_base_model.md | 54 + .../server/db/models/knowledge_file_model.md | 97 ++ .../db/models/knowledge_metadata_model.md | 41 + .../server/db/models/message_model.md | 44 + .../db/repository/conversation_repository.md | 25 + .../repository/knowledge_base_repository.md | 130 ++ .../repository/knowledge_file_repository.md | 251 +++ .../knowledge_metadata_repository.md | 108 ++ .../db/repository/message_repository.md | 126 ++ markdown_docs/server/db/session.md | 63 + markdown_docs/server/embeddings_api.md | 97 ++ markdown_docs/server/knowledge_base/kb_api.md | 95 ++ .../server/knowledge_base/kb_cache/base.md | 374 +++++ .../knowledge_base/kb_cache/faiss_cache.md | 302 ++++ .../server/knowledge_base/kb_doc_api.md | 417 +++++ .../server/knowledge_base/kb_service/base.md | 940 +++++++++++ .../kb_service/chromadb_kb_service.md | 306 ++++ .../kb_service/default_kb_service.md | 138 ++ .../kb_service/es_kb_service.md | 282 ++++ .../kb_service/faiss_kb_service.md | 327 ++++ .../kb_service/milvus_kb_service.md | 292 ++++ .../kb_service/pg_kb_service.md | 254 +++ .../kb_service/zilliz_kb_service.md | 280 ++++ .../server/knowledge_base/kb_summary/base.md | 134 ++ .../kb_summary/summary_chunk.md | 190 +++ .../server/knowledge_base/kb_summary_api.md | 169 ++ .../server/knowledge_base/migrate.md | 166 ++ .../knowledge_base/model/kb_document_model.md | 18 + markdown_docs/server/knowledge_base/utils.md | 529 +++++++ markdown_docs/server/llm_api.md | 202 +++ markdown_docs/server/llm_api_stale.md | 72 + .../memory/conversation_db_buffer_memory.md | 130 ++ markdown_docs/server/minx_chat_openai.md | 61 + .../server/model_workers/SparkApi.md | 108 ++ markdown_docs/server/model_workers/azure.md | 122 ++ .../server/model_workers/baichuan.md | 140 ++ markdown_docs/server/model_workers/base.md | 475 ++++++ .../server/model_workers/fangzhou.md | 124 ++ markdown_docs/server/model_workers/gemini.md | 161 ++ markdown_docs/server/model_workers/minimax.md | 205 +++ markdown_docs/server/model_workers/qianfan.md | 189 +++ markdown_docs/server/model_workers/qwen.md | 160 ++ .../server/model_workers/tiangong.md | 125 ++ markdown_docs/server/model_workers/xinghuo.md | 182 +++ markdown_docs/server/model_workers/zhipu.md | 161 ++ markdown_docs/server/reranker/reranker.md | 82 + markdown_docs/server/utils.md | 850 ++++++++++ markdown_docs/server/webui_allinone_stale.md | 45 + markdown_docs/startup.md | 339 ++++ .../text_splitter/ali_text_splitter.md | 65 + .../chinese_recursive_text_splitter.md | 101 ++ .../text_splitter/chinese_text_splitter.md | 102 ++ .../text_splitter/zh_title_enhance.md | 52 + .../webui_pages/dialogue/dialogue.md | 228 +++ .../knowledge_base/knowledge_base.md | 76 + .../webui_pages/model_config/model_config.md | 13 + markdown_docs/webui_pages/utils.md | 1404 +++++++++++++++++ 91 files changed, 15324 insertions(+) create mode 100644 markdown_docs/document_loaders/FilteredCSVloader.md create mode 100644 markdown_docs/document_loaders/mydocloader.md create mode 100644 markdown_docs/document_loaders/myimgloader.md create mode 100644 markdown_docs/document_loaders/mypdfloader.md create mode 100644 markdown_docs/document_loaders/mypptloader.md create mode 100644 markdown_docs/document_loaders/ocr.md create mode 100644 markdown_docs/embeddings/add_embedding_keywords.md create mode 100644 markdown_docs/release.md create mode 100644 markdown_docs/server/agent/callbacks.md create mode 100644 markdown_docs/server/agent/custom_agent/ChatGLM3Agent.md create mode 100644 markdown_docs/server/agent/custom_template.md create mode 100644 markdown_docs/server/agent/model_contain.md create mode 100644 markdown_docs/server/agent/tools/arxiv.md create mode 100644 markdown_docs/server/agent/tools/calculate.md create mode 100644 markdown_docs/server/agent/tools/search_internet.md create mode 100644 markdown_docs/server/agent/tools/search_knowledgebase_complex.md create mode 100644 markdown_docs/server/agent/tools/search_knowledgebase_once.md create mode 100644 markdown_docs/server/agent/tools/search_knowledgebase_simple.md create mode 100644 markdown_docs/server/agent/tools/search_youtube.md create mode 100644 markdown_docs/server/agent/tools/shell.md create mode 100644 markdown_docs/server/agent/tools/weather_check.md create mode 100644 markdown_docs/server/agent/tools/wolfram.md create mode 100644 markdown_docs/server/api.md create mode 100644 markdown_docs/server/callback_handler/conversation_callback_handler.md create mode 100644 markdown_docs/server/chat/agent_chat.md create mode 100644 markdown_docs/server/chat/chat.md create mode 100644 markdown_docs/server/chat/completion.md create mode 100644 markdown_docs/server/chat/feedback.md create mode 100644 markdown_docs/server/chat/file_chat.md create mode 100644 markdown_docs/server/chat/knowledge_base_chat.md create mode 100644 markdown_docs/server/chat/search_engine_chat.md create mode 100644 markdown_docs/server/chat/utils.md create mode 100644 markdown_docs/server/db/models/base.md create mode 100644 markdown_docs/server/db/models/conversation_model.md create mode 100644 markdown_docs/server/db/models/knowledge_base_model.md create mode 100644 markdown_docs/server/db/models/knowledge_file_model.md create mode 100644 markdown_docs/server/db/models/knowledge_metadata_model.md create mode 100644 markdown_docs/server/db/models/message_model.md create mode 100644 markdown_docs/server/db/repository/conversation_repository.md create mode 100644 markdown_docs/server/db/repository/knowledge_base_repository.md create mode 100644 markdown_docs/server/db/repository/knowledge_file_repository.md create mode 100644 markdown_docs/server/db/repository/knowledge_metadata_repository.md create mode 100644 markdown_docs/server/db/repository/message_repository.md create mode 100644 markdown_docs/server/db/session.md create mode 100644 markdown_docs/server/embeddings_api.md create mode 100644 markdown_docs/server/knowledge_base/kb_api.md create mode 100644 markdown_docs/server/knowledge_base/kb_cache/base.md create mode 100644 markdown_docs/server/knowledge_base/kb_cache/faiss_cache.md create mode 100644 markdown_docs/server/knowledge_base/kb_doc_api.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/base.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/chromadb_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/default_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/es_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/faiss_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/milvus_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/pg_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_service/zilliz_kb_service.md create mode 100644 markdown_docs/server/knowledge_base/kb_summary/base.md create mode 100644 markdown_docs/server/knowledge_base/kb_summary/summary_chunk.md create mode 100644 markdown_docs/server/knowledge_base/kb_summary_api.md create mode 100644 markdown_docs/server/knowledge_base/migrate.md create mode 100644 markdown_docs/server/knowledge_base/model/kb_document_model.md create mode 100644 markdown_docs/server/knowledge_base/utils.md create mode 100644 markdown_docs/server/llm_api.md create mode 100644 markdown_docs/server/llm_api_stale.md create mode 100644 markdown_docs/server/memory/conversation_db_buffer_memory.md create mode 100644 markdown_docs/server/minx_chat_openai.md create mode 100644 markdown_docs/server/model_workers/SparkApi.md create mode 100644 markdown_docs/server/model_workers/azure.md create mode 100644 markdown_docs/server/model_workers/baichuan.md create mode 100644 markdown_docs/server/model_workers/base.md create mode 100644 markdown_docs/server/model_workers/fangzhou.md create mode 100644 markdown_docs/server/model_workers/gemini.md create mode 100644 markdown_docs/server/model_workers/minimax.md create mode 100644 markdown_docs/server/model_workers/qianfan.md create mode 100644 markdown_docs/server/model_workers/qwen.md create mode 100644 markdown_docs/server/model_workers/tiangong.md create mode 100644 markdown_docs/server/model_workers/xinghuo.md create mode 100644 markdown_docs/server/model_workers/zhipu.md create mode 100644 markdown_docs/server/reranker/reranker.md create mode 100644 markdown_docs/server/utils.md create mode 100644 markdown_docs/server/webui_allinone_stale.md create mode 100644 markdown_docs/startup.md create mode 100644 markdown_docs/text_splitter/ali_text_splitter.md create mode 100644 markdown_docs/text_splitter/chinese_recursive_text_splitter.md create mode 100644 markdown_docs/text_splitter/chinese_text_splitter.md create mode 100644 markdown_docs/text_splitter/zh_title_enhance.md create mode 100644 markdown_docs/webui_pages/dialogue/dialogue.md create mode 100644 markdown_docs/webui_pages/knowledge_base/knowledge_base.md create mode 100644 markdown_docs/webui_pages/model_config/model_config.md create mode 100644 markdown_docs/webui_pages/utils.md diff --git a/markdown_docs/document_loaders/FilteredCSVloader.md b/markdown_docs/document_loaders/FilteredCSVloader.md new file mode 100644 index 000000000..290cfee31 --- /dev/null +++ b/markdown_docs/document_loaders/FilteredCSVloader.md @@ -0,0 +1,107 @@ +## ClassDef FilteredCSVLoader +**FilteredCSVLoader**: FilteredCSVLoader的功能是从CSV文件中加载并筛选指定列的数据,然后将这些数据转换为文档对象列表。 + +**属性**: +- `file_path`: 要加载的CSV文件的路径。 +- `columns_to_read`: 需要读取的列名列表。 +- `source_column`: 指定作为数据源信息列的列名,如果未指定,则使用文件路径作为数据源信息。 +- `metadata_columns`: 需要作为元数据读取的列名列表。 +- `csv_args`: 传递给csv阅读器的额外参数字典。 +- `encoding`: 文件的编码格式。 +- `autodetect_encoding`: 是否自动检测文件编码。 + +**代码描述**: +FilteredCSVLoader类继承自CSVLoader类,用于从CSV文件中加载数据,并根据指定的列名筛选数据。它重写了`__init__`方法以接收额外的参数,如`columns_to_read`,这是一个字符串列表,指定了需要从CSV文件中读取的列名。此外,它还提供了`load`方法来实际加载和处理CSV文件。 + +在`load`方法中,首先尝试打开指定的CSV文件。如果在读取文件时遇到`UnicodeDecodeError`错误,并且`autodetect_encoding`标志被设置为True,则会尝试自动检测文件编码并重新尝试读取文件。读取文件成功后,使用`csv.DictReader`读取CSV文件,根据`columns_to_read`中指定的列名筛选数据,并将筛选后的数据转换为文档对象列表。每个文档对象包含从指定列读取的内容和元数据,元数据中包含数据源信息和行号,以及`metadata_columns`中指定的任何其他元数据列的值。 + +**注意**: +- 确保`file_path`指向的CSV文件存在且可读。 +- 在`columns_to_read`中指定的列必须存在于CSV文件中,否则会抛出`ValueError`。 +- 如果设置了`autodetect_encoding`为True,但自动检测编码失败,则会抛出`RuntimeError`。 + +**输出示例**: +```python +[ + Document(page_content="这是第一行的内容", metadata={"source": "example.csv", "row": 0, "其他元数据列名": "值"}), + Document(page_content="这是第二行的内容", metadata={"source": "example.csv", "row": 1, "其他元数据列名": "值"}), + ... +] +``` +此输出示例展示了`load`方法返回的文档对象列表,每个文档对象包含从CSV文件指定列读取的内容和元数据。 +### FunctionDef __init__(self, file_path, columns_to_read, source_column, metadata_columns, csv_args, encoding, autodetect_encoding) +**__init__**: 此函数的功能是初始化FilteredCSVLoader对象。 + +**参数**: +- `file_path`: 要读取的CSV文件的路径。 +- `columns_to_read`: 需要读取的列名列表。 +- `source_column`: 指定作为数据源的列名,可选参数,默认为None。 +- `metadata_columns`: 包含元数据的列名列表,默认为空列表。 +- `csv_args`: 传递给CSV读取器的额外参数,为字典格式,可选参数,默认为None。 +- `encoding`: 指定文件编码的字符串,可选参数,默认为None。 +- `autodetect_encoding`: 是否自动检测文件编码,布尔值,默认为False。 + +**代码描述**: +此函数是`FilteredCSVLoader`类的构造函数,用于初始化一个`FilteredCSVLoader`实例。它首先调用父类的构造函数,传入`file_path`、`source_column`、`metadata_columns`、`csv_args`、`encoding`和`autodetect_encoding`参数,以完成基础的初始化工作。然后,它将`columns_to_read`参数的值赋给实例变量`self.columns_to_read`,以便后续操作中可以根据这些列名来读取CSV文件中的指定列。 + +**注意**: +- 在使用此函数时,`file_path`和`columns_to_read`参数是必需的,因为它们分别指定了CSV文件的位置和需要读取的列。 +- `metadata_columns`参数允许用户指定哪些列包含元数据,这些元数据列不会被视为数据源的一部分。 +- 如果`csv_args`参数被提供,它将允许用户自定义CSV读取过程中的行为,例如指定分隔符、引号字符等。 +- `encoding`和`autodetect_encoding`参数与文件编码相关,如果CSV文件的编码不是标准的UTF-8,这两个参数将非常有用。`autodetect_encoding`为True时,系统将尝试自动检测文件编码,这可能有助于处理编码不明确的文件。 +*** +### FunctionDef load(self) +**load**: 该函数的功能是加载数据并将其转换为文档对象列表。 + +**参数**: 该函数不接受任何外部参数,但依赖于类实例中的属性,如`file_path`和`encoding`。 + +**代码描述**: `load`函数负责从CSV文件中读取数据,并将这些数据转换为`Document`对象的列表。首先,函数尝试使用`open`函数以指定的编码方式打开文件路径`self.file_path`指定的CSV文件。文件成功打开后,调用`__read_file`私有方法来读取并处理CSV文件的内容。 + +如果在尝试打开文件时遇到`UnicodeDecodeError`编码错误,并且`self.autodetect_encoding`属性为真,则会尝试自动检测文件编码。这一过程通过调用`detect_file_encodings`函数实现,该函数返回一个可能的编码列表。然后,函数会尝试使用这些编码中的每一个重新打开并读取文件,直到成功读取文件或尝试完所有编码。 + +如果在文件处理过程中遇到任何其他异常,或者在自动检测编码后仍无法成功读取文件,`load`函数将抛出`RuntimeError`异常,指示文件加载过程中出现错误。 + +`load`函数调用的`__read_file`方法负责实际从CSV文件中读取数据,并将每行数据转换为`Document`对象。这一转换过程包括从CSV行中提取必要的内容和元数据,并将它们封装在`Document`对象中。 + +**注意**: +- `load`函数依赖于类实例的状态,如文件路径和编码设置,因此在调用此函数之前应确保这些属性已正确设置。 +- 如果CSV文件的编码不是在初始化时指定的编码,并且未启用自动检测编码功能,那么读取文件可能会失败。 +- 当CSV文件中缺少必需的列或格式不正确时,`__read_file`方法可能会抛出`ValueError`异常。 + +**输出示例**: 假设CSV文件正确读取并处理,`load`函数可能返回如下的`Document`对象列表: +```python +[ + Document(page_content="示例文本1", metadata={"source": "path/to/file.csv", "row": 0, "其他元数据": "值"}), + Document(page_content="示例文本2", metadata={"source": "path/to/file.csv", "row": 1, "其他元数据": "值"}) +] +``` +此列表中的每个`Document`对象包含从CSV文件中读取的一行数据,其中`page_content`属性存储了该行指定列的内容,而`metadata`字典包含了源信息以及其他可能的元数据信息。 +*** +### FunctionDef __read_file(self, csvfile) +**__read_file**: 该函数的功能是从CSV文件中读取数据,并将其转换为Document对象列表。 + +**参数**: +- csvfile: TextIOWrapper类型,表示打开的CSV文件对象。 + +**代码描述**: +`__read_file`函数是`FilteredCSVLoader`类的一个私有方法,用于读取CSV文件并将每行数据转换为`Document`对象。该函数首先创建一个空列表`docs`来存储转换后的`Document`对象。接着,使用`csv.DictReader`读取`csvfile`参数指定的CSV文件,其中`self.csv_args`包含了读取CSV文件时需要的参数设置。 + +对于CSV文件中的每一行,函数首先检查是否包含必需的列(由`self.columns_to_read[0]`指定)。如果该列存在,则从该列中提取内容作为`Document`对象的`page_content`。同时,尝试从行中获取源信息(由`self.source_column`指定),如果未指定`self.source_column`或该列不存在,则使用文件路径作为源信息。此外,还会从行中提取其他元数据列(由`self.metadata_columns`指定),并将这些信息一起存储在`metadata`字典中。 + +最后,使用提取的内容和元数据创建一个`Document`对象,并将其添加到`docs`列表中。如果在CSV文件中找不到必需的列,则抛出`ValueError`异常。 + +该函数被`FilteredCSVLoader`类的`load`方法调用,用于加载CSV文件并将其内容转换为一系列`Document`对象。`load`方法首先尝试以指定的编码打开文件,如果遇到编码错误且自动检测编码功能被启用,则尝试使用检测到的编码重新打开文件。如果在整个过程中遇到任何异常,`load`方法会抛出`RuntimeError`异常。 + +**注意**: +- 由于`__read_file`是一个私有方法,因此它仅在`FilteredCSVLoader`类内部使用,不应直接从类外部调用。 +- 当CSV文件中缺少必需的列时,该函数会抛出`ValueError`异常。 + +**输出示例**: +假设CSV文件包含以下内容,并且`columns_to_read`设置为`['content']`,`metadata_columns`设置为空列表,那么函数可能返回如下的`Document`对象列表: +```python +[ + Document(page_content="Hello, world!", metadata={"source": "path/to/file.csv", "row": 0}), + Document(page_content="Another example.", metadata={"source": "path/to/file.csv", "row": 1}) +] +``` +*** diff --git a/markdown_docs/document_loaders/mydocloader.md b/markdown_docs/document_loaders/mydocloader.md new file mode 100644 index 000000000..313cc2981 --- /dev/null +++ b/markdown_docs/document_loaders/mydocloader.md @@ -0,0 +1,106 @@ +## ClassDef RapidOCRDocLoader +**RapidOCRDocLoader**: RapidOCRDocLoader的功能是从Word文档中提取文本和图片内容,并使用OCR技术转换图片中的文本。 + +**属性**: +- 无特定公开属性,此类主要通过继承和方法实现功能。 + +**代码描述**: +RapidOCRDocLoader类继承自UnstructuredFileLoader,专门用于处理Word文档(.docx)文件,提取其中的文本和图片内容。它通过定义一个内部函数`_get_elements`来实现这一功能。该函数首先定义了一个辅助函数`doc2text`,用于打开和解析Word文档,然后提取文档中的文本和图片内容。 + +在`doc2text`函数中,使用了python-docx库来遍历文档中的所有段落和表格。对于文档中的每个段落,直接提取其文本内容;对于表格,遍历每个单元格并提取其中的文本。此外,对于段落中包含的图片,使用了PIL库和RapidOCR库来识别图片中的文本。 + +RapidOCR是一个基于ONNX Runtime的OCR工具,能够从图片中识别文本。在本类中,对于每个找到的图片,首先将其转换为numpy数组,然后使用RapidOCR进行文本识别,最后将识别的文本添加到响应字符串中。 + +最终,`_get_elements`函数通过调用`doc2text`函数获取文档中的所有文本(包括OCR识别的文本),然后使用`partition_text`函数对文本进行分段处理,返回处理后的文本列表。 + +**注意**: +- 使用RapidOCRDocLoader类之前,需要确保已安装python-docx、PIL、numpy和rapidocr_onnxruntime等依赖库。 +- 该类专门处理.docx格式的Word文档,不适用于其他类型的文档或图片文件。 +- OCR识别准确度受到图片质量的影响,对于低分辨率或图文混排的图片,识别结果可能不理想。 + +**输出示例**: +假设一个Word文档包含以下内容: +- 文本段落:“这是一个示例文档。” +- 包含文本的图片:图片中的文本为“图片中的示例文本”。 + +使用RapidOCRDocLoader处理该文档后,可能的返回值为: +``` +["这是一个示例文档。", "图片中的示例文本。"] +``` +这个返回值是一个列表,包含了文档中所有文本内容,包括通过OCR技术识别出的图片中的文本。 +### FunctionDef _get_elements(self) +**_get_elements**: 此函数的功能是从给定的Word文档中提取文本和图片内容,并将图片内容通过OCR技术转换为文本,最后将所有文本内容进行结构化分割。 + +**参数**: 此函数没有显式参数,但依赖于`self.file_path`和`self.unstructured_kwargs`两个对象属性。 +- `self.file_path`: 需要处理的Word文档的路径。 +- `self.unstructured_kwargs`: 用于文本结构化分割的参数。 + +**代码描述**: +1. `_get_elements`函数首先定义了一个内部函数`doc2text`,用于将Word文档转换为文本。 +2. `doc2text`函数利用`python-docx`库来解析Word文档,通过迭代文档中的段落和表格来提取文本内容。 +3. 对于文档中的图片,`doc2text`使用`xpath`来定位,并通过`PIL`库和`ImagePart`来读取图片内容。然后,使用`RapidOCR`库将图片内容转换为文本。 +4. 文档中的文本和通过OCR转换得到的文本被累加到一个字符串中。 +5. 使用`tqdm`库来显示处理进度,提高用户体验。 +6. `_get_elements`函数通过调用`doc2text`函数获取文本内容,然后使用`partition_text`函数对文本进行结构化分割,分割依据是`self.unstructured_kwargs`中的参数。 +7. 最终,函数返回一个包含分割后文本块的列表。 + +**注意**: +- 确保`self.file_path`指向的是一个有效的Word文档路径。 +- OCR转换对图片质量有一定要求,图片质量过低可能影响识别结果。 +- `self.unstructured_kwargs`参数需要正确配置以适应不同的文本结构化需求。 + +**输出示例**: +```python +[ + "这是文档的第一部分文本。", + "这是从图片中通过OCR技术识别出的文本。", + "这是文档的另一部分文本。" +] +``` +此输出示例展示了函数可能返回的分割后的文本块列表,包括直接从Word文档中提取的文本和通过OCR技术从图片中识别出的文本。 +#### FunctionDef doc2text(filepath) +**doc2text**: 该函数的功能是将Word文档中的文本和图片内容转换为纯文本字符串。 + +**参数**: +- filepath: Word文档的文件路径。 + +**代码描述**: +`doc2text`函数首先导入了必要的库和模块,包括处理Word文档的`docx`库,图像处理库`PIL`,以及用于执行OCR(光学字符识别)的`rapidocr_onnxruntime`库。函数接收一个文件路径作为参数,用于指定需要转换的Word文档。 + +函数内部,首先使用`Document`类从给定的文件路径加载Word文档。然后,定义了一个`iter_block_items`内部函数,用于遍历文档中的所有段落和表格。这个遍历过程利用了`docx`库的类型判断功能,以确定当前处理的是段落还是表格,并据此进行相应的处理。 + +在遍历文档内容的过程中,函数使用了`ocr`对象(由`RapidOCR`类实例化)对文档中的图片进行OCR处理,将图片中的文本转换为可读的字符串。对于文档中的文本内容,直接将其文本值添加到响应字符串中。 + +此外,函数还处理了文档中的表格,遍历每个表格中的行和单元格,将单元格中的文本内容提取出来,同样添加到响应字符串中。 + +最后,函数返回一个包含了文档中所有文本内容和图片中识别出的文本内容的字符串。 + +**注意**: +- 该函数依赖于`docx`、`PIL`和`rapidocr_onnxruntime`等库,使用前需要确保这些库已正确安装。 +- OCR处理可能不会100%准确,特别是对于图像质量较低或字体较小的图片,识别结果可能会有误差。 +- 函数的性能(包括OCR处理时间)会受到文档大小和内容复杂度的影响。 + +**输出示例**: +``` +这是文档中的一段文本。 + +这是从文档中的一张图片中识别出的文本。 +``` +##### FunctionDef iter_block_items(parent) +**iter_block_items**: 此函数的功能是遍历并生成文档中的段落和表格对象。 + +**参数**: +- **parent**: 可以是`Document`对象或`_Cell`对象,表示要遍历的文档或单元格。 + +**代码描述**: +`iter_block_items`函数是用于从Word文档中提取段落和表格的迭代器。它首先判断传入的`parent`参数类型。如果`parent`是`Document`类型,即整个文档,它会获取文档的主体部分。如果`parent`是`_Cell`类型,即表格中的单元格,它会获取该单元格的内容。函数通过遍历`parent_elm`的子元素,根据子元素的类型(段落或表格),生成对应的`Paragraph`或`Table`对象并返回。 + +在遍历过程中,使用`isinstance`函数检查每个子元素的类型。如果子元素是`CT_P`类型,表示它是一个段落,则创建并返回一个`Paragraph`对象。如果子元素是`CT_Tbl`类型,表示它是一个表格,则创建并返回一个`Table`对象。这样,使用此函数可以方便地从文档中提取出所有的段落和表格,以便进一步处理。 + +**注意**: +- 传入的`parent`参数必须是`Document`或`_Cell`类型,否则函数会抛出`ValueError`异常,提示"RapidOCRDocLoader parse fail"。 +- 此函数依赖于`docx.document.Document`、`_Cell`、`CT_P`(段落类型)和`CT_Tbl`(表格类型)等类,因此在使用前需要确保这些类已正确导入和定义。 +- 生成的`Paragraph`和`Table`对象可以用于进一步的文本提取或格式化操作,但需要注意处理它们的方法可能依赖于具体的实现细节。 +*** +*** +*** diff --git a/markdown_docs/document_loaders/myimgloader.md b/markdown_docs/document_loaders/myimgloader.md new file mode 100644 index 000000000..b992ffad8 --- /dev/null +++ b/markdown_docs/document_loaders/myimgloader.md @@ -0,0 +1,71 @@ +## ClassDef RapidOCRLoader +**RapidOCRLoader**: RapidOCRLoader的功能是将图像文件中的文本通过OCR技术提取出来,并将提取的文本进行结构化处理。 + +**属性**: +- 无特定公开属性,继承自UnstructuredFileLoader的属性。 + +**代码描述**: +RapidOCRLoader是一个继承自UnstructuredFileLoader的类,专门用于处理图像文件中的文本提取。它通过定义一个内部函数`img2text`来实现OCR(光学字符识别)功能。`img2text`函数接受一个文件路径作为输入,使用`get_ocr`函数获取OCR处理器,然后对指定的图像文件进行文本识别。识别结果是一个列表,其中每个元素包含识别的文本行。这些文本行随后被连接成一个字符串,作为函数的返回值。 + +在`_get_elements`方法中,调用了`img2text`函数处理类初始化时指定的文件路径,将图像文件中的文本提取出来。提取出的文本随后通过`partition_text`函数进行结构化处理,这个函数根据提供的参数(通过`self.unstructured_kwargs`传递)对文本进行分区,最终返回一个文本分区列表。 + +在项目中,RapidOCRLoader类被用于测试模块`test_imgloader.py`中,通过`test_rapidocrloader`函数进行测试。测试函数创建了一个RapidOCRLoader实例,传入了一个OCR测试用的图像文件路径,然后调用`load`方法加载处理结果。测试验证了RapidOCRLoader能够成功提取图像中的文本,并且返回值是一个包含至少一个元素的列表,列表中的每个元素都是一个包含提取文本的对象。 + +**注意**: +- 使用RapidOCRLoader之前,需要确保OCR处理器(通过`get_ocr`函数获取)已正确配置并可用。 +- 该类主要用于处理图像文件中的文本提取,不适用于非图像文件。 + +**输出示例**: +```python +[ + { + "page_content": "这是通过OCR技术提取的文本内容。" + } +] +``` +此输出示例展示了RapidOCRLoader处理图像文件并通过OCR技术提取文本后的可能返回值。返回值是一个列表,列表中的每个元素都是一个字典,其中`page_content`键对应的值是提取的文本内容。 +### FunctionDef _get_elements(self) +**_get_elements**: 该函数的功能是将图片文件中的文本内容提取出来,并根据给定的参数对提取出的文本进行分段处理。 + +**参数**: +- 无直接参数,但函数通过`self.file_path`访问图片路径,通过`self.unstructured_kwargs`访问用于文本分段的参数。 + +**代码描述**: +该函数首先定义了一个内部函数`img2text`,用于将指定路径的图片文件转换为文本。`img2text`函数通过调用`get_ocr()`函数获取OCR(光学字符识别)服务的实例,然后使用此实例对图片文件进行识别,将识别结果中的文本内容提取出来并返回。 + +在`_get_elements`函数的主体中,首先调用`img2text`函数,将`self.file_path`指定的图片文件转换为文本。然后,使用`partition_text`函数对提取的文本进行分段处理。`partition_text`函数接受一个文本字符串和一组分段参数(通过`self.unstructured_kwargs`提供),并返回分段后的文本列表。 + +**注意**: +- 确保`self.file_path`正确指向了需要处理的图片文件。 +- `self.unstructured_kwargs`应包含适用于`partition_text`函数的所有必要参数,以确保文本可以按预期进行分段处理。 +- OCR识别的准确性可能受到图片质量和内容复杂度的影响,因此在处理极其复杂或低质量的图片时可能会遇到识别准确度下降的问题。 + +**输出示例**: +假设图片中包含以下文本内容:“Hello World! Welcome to OCR processing.”,并且`partition_text`函数的参数设置为按句子分段,那么该函数可能返回如下列表: +```python +["Hello World!", "Welcome to OCR processing."] +``` +#### FunctionDef img2text(filepath) +**img2text**: 此函数的功能是将图片文件中的文字通过OCR技术识别出来,并以字符串形式返回。 + +**参数**: +- filepath: 字符串类型,指定需要进行文字识别的图片文件路径。 + +**代码描述**: +`img2text`函数是一个用于图像文字识别的高级封装。它首先调用`get_ocr`函数获取一个OCR对象,该对象是根据系统配置(是否使用CUDA加速)动态选择的OCR实现。随后,使用该OCR对象对传入的图片文件路径`filepath`指向的图片进行文字识别。识别结果是一个列表,其中每个元素是一个包含识别区域坐标和识别出的文字的元组。函数进一步处理这个列表,提取出所有识别到的文字,并将它们连接成一个单一的字符串,每行文字之间用换行符`\n`分隔。最后,返回这个字符串。 + +从功能角度看,`img2text`与其调用的`get_ocr`函数紧密相关。`get_ocr`负责提供OCR服务的对象,而`img2text`则利用这个对象完成具体的图像文字识别任务。这种设计使得`img2text`能够灵活适应不同的OCR技术实现,同时也便于在项目中重用OCR服务。 + +**注意**: +- 确保传入的`filepath`是有效的图片文件路径,且文件存在。否则,OCR识别过程可能失败。 +- OCR识别的准确性受到多种因素的影响,包括图片质量、文字清晰度和字体大小等,因此在使用时应考虑这些因素可能对识别结果的影响。 +- 根据`get_ocr`函数的说明,如果系统中未安装支持CUDA的OCR包或在不支持CUDA的环境中运行,应确保`get_ocr`函数的`use_cuda`参数被设置为False,以避免运行时错误。 + +**输出示例**: +``` +这是一个OCR识别的示例文本。 +第二行文字。 +``` +此输出示例展示了`img2text`函数处理后的可能输出,其中包含了从图片中识别出的文字,每行文字之间用换行符分隔。实际输出将根据输入图片中的文字内容而有所不同。 +*** +*** diff --git a/markdown_docs/document_loaders/mypdfloader.md b/markdown_docs/document_loaders/mypdfloader.md new file mode 100644 index 000000000..d819cba64 --- /dev/null +++ b/markdown_docs/document_loaders/mypdfloader.md @@ -0,0 +1,89 @@ +## ClassDef RapidOCRPDFLoader +**RapidOCRPDFLoader**: RapidOCRPDFLoader的功能是从PDF文件中提取文本和图片内容,并通过OCR技术将图片内容转换为文本。 + +**属性**: +- 无特定公开属性,该类主要通过方法实现功能。 + +**代码描述**: +RapidOCRPDFLoader类继承自UnstructuredFileLoader,专门用于处理PDF文件的加载和内容提取。该类通过定义的`_get_elements`方法实现了从PDF中提取文本和图片的功能,并且能够处理图片的旋转和OCR识别,最终将识别的文本内容进行结构化处理。 + +在`_get_elements`方法中,首先定义了`rotate_img`函数用于处理图片旋转,接着定义了`pdf2text`函数用于将PDF文件中的文本和图片内容提取出来。`pdf2text`函数使用了fitz库(pyMuPDF)来打开和处理PDF文件,通过遍历每一页,提取页面文本和图片信息。对于图片内容,首先检查图片尺寸是否超过设定的阈值,然后根据页面的旋转角度决定是否需要旋转图片,最后使用OCR技术将图片内容转换为文本。 + +该类的使用场景在于需要从PDF文件中提取文本信息,同时也需要处理PDF中的图片内容,尤其是当图片中包含了重要的文本信息时。通过OCR技术,可以将这些图片中的文本信息转换为可读的文本格式,进一步增强文本提取的准确性和完整性。 + +**注意**: +- 使用RapidOCRPDFLoader类之前,需要确保已经安装了fitz(pyMuPDF)库和OpenCV库,因为这两个库是处理PDF文件和图片旋转的关键。 +- OCR技术的准确性受到图片质量的影响,因此在处理高度压缩或质量较低的图片时,OCR的结果可能不够理想。 +- 该类在处理大型PDF文件时可能会消耗较多的计算资源,因此在资源受限的环境下使用时需要注意。 + +**输出示例**: +假设处理一个包含文本和图片的PDF文件,RapidOCRPDFLoader可能会返回如下格式的文本内容: +``` +第一页文本内容... +图片1识别的文本内容... +图片2识别的文本内容... +第二页文本内容... +图片3识别的文本内容... +... +``` +这个输出示例展示了RapidOCRPDFLoader如何将PDF文件中的文本和图片内容结合起来,提供一个连续的文本流,便于后续的处理和分析。 +### FunctionDef _get_elements(self) +**_get_elements**: 该函数的功能是从PDF文件中提取文本和图像内容,并对图像进行OCR识别,最后将识别的文本内容进行结构化处理。 + +**参数**: 此函数没有直接的参数,它通过类的实例访问成员变量。 + +**代码描述**: +- `_get_elements` 函数首先定义了两个内部函数:`rotate_img` 和 `pdf2text`。 +- `rotate_img` 函数用于旋转图像,接受图像和旋转角度作为参数,返回旋转后的图像。它通过OpenCV库计算旋转矩阵,并应用于输入图像以获得旋转后的图像。 +- `pdf2text` 函数负责将PDF文件的内容转换为文本。它使用`fitz`库(即PyMuPDF)打开PDF文件,遍历每一页,提取文本内容,并使用进度条(`tqdm`库)显示处理进度。对于每个页面上的图像,如果图像的尺寸超过了设定的阈值(`PDF_OCR_THRESHOLD`),则使用OCR(光学字符识别)技术识别图像中的文本。如果页面有旋转,则先对图像进行旋转校正,再进行OCR识别。 +- 在提取完所有页面的文本和图像内容后,`_get_elements` 函数使用`partition_text`函数对提取到的文本进行结构化处理,以便于后续的数据处理和分析。 + +**注意**: +- 本函数依赖于OpenCV和PyMuPDF库进行图像处理和PDF文件的读取,需要确保这些库已正确安装和配置。 +- OCR识别的准确性受到图像质量的影响,图像的清晰度和旋转校正的准确性对识别结果有重要影响。 +- 函数中使用的`PDF_OCR_THRESHOLD`变量需要根据实际情况进行调整,以优化OCR识别的效果和性能。 + +**输出示例**: +由于`_get_elements`函数的输出依赖于输入的PDF文件内容和OCR识别的结果,因此无法提供一个固定的输出示例。通常,该函数会返回一个包含结构化文本内容的列表,列表中的每个元素代表PDF中的一段文本内容,这些内容已经过OCR识别和结构化处理。 +#### FunctionDef rotate_img(img, angle) +**rotate_img**: 该函数的功能是旋转图像。 + +**参数**: +- img: 待旋转的图像。 +- angle: 旋转角度,正值表示逆时针旋转,负值表示顺时针旋转。 + +**代码描述**: +`rotate_img` 函数接收一个图像和一个旋转角度作为输入,返回旋转后的图像。首先,它计算图像的高度和宽度,然后确定旋转中心,即图像的中心点。接着,使用 `cv2.getRotationMatrix2D` 方法获取旋转矩阵,该方法需要旋转中心、旋转角度和缩放比例(本例中为1.0,表示保持原始大小)作为输入。然后,计算旋转后图像的新边界,以确保旋转后的图像不会丢失任何部分。最后,通过调整旋转矩阵中的平移参数,使用 `cv2.warpAffine` 方法应用旋转矩阵,得到旋转后的图像并返回。 + +在项目中,`rotate_img` 函数被 `pdf2text` 函数调用,用于处理PDF文档中的图像。当PDF页面有旋转角度时,`pdf2text` 函数会提取页面中的图像,然后调用 `rotate_img` 函数将图像旋转回正常的方向,以便进行后续的OCR(光学字符识别)处理。这样可以确保OCR处理的准确性,特别是在处理扫描文档和图像密集型PDF文件时。 + +**注意**: +- 在使用 `cv2.getRotationMatrix2D` 和 `cv2.warpAffine` 方法时,需要确保已经导入了OpenCV库(即cv2)。 +- 旋转图像可能会导致图像边缘的一部分被裁剪。因此,计算新边界并调整平移参数是确保图像完整性的关键步骤。 + +**输出示例**: +假设有一个图像 `img` 和旋转角度 `angle=90`,调用 `rotate_img(img, 90)` 后,将返回一个新的图像,其中原始图像已经逆时针旋转了90度。 +*** +#### FunctionDef pdf2text(filepath) +**pdf2text**: 该函数的功能是将PDF文件中的文本和图片内容转换为文本格式。 + +**参数**: +- filepath: PDF文件的路径。 + +**代码描述**: +`pdf2text` 函数首先导入必要的库,包括`fitz`(用于处理PDF文件)和`numpy`(用于处理图像数据)。然后,它调用`get_ocr`函数获取OCR对象,用于后续的图像文字识别。通过打开指定路径的PDF文件,函数遍历每一页,使用`fitz`库提取页面上的文本内容,并将其累加到响应字符串中。 + +对于每个页面上的图像,函数通过`get_image_info`方法获取图像信息,并检查每个图像的尺寸是否超过预设的阈值(`PDF_OCR_THRESHOLD`)。如果图像尺寸合适,函数将使用`fitz.Pixmap`读取图像数据。如果页面有旋转角度,函数会调用`rotate_img`函数将图像旋转回正常方向,以确保OCR的准确性。随后,使用OCR对象对图像进行文字识别,并将识别结果添加到响应字符串中。 + +整个过程中,使用`tqdm`库显示处理进度,为用户提供友好的进度反馈。 + +**注意**: +- 确保安装了`fitz`(也就是`PyMuPDF`)、`numpy`、`tqdm`等库。 +- `PDF_OCR_THRESHOLD`是一个预设的阈值,用于决定哪些图像需要进行OCR处理。该阈值需要根据实际情况进行调整。 +- 函数依赖于`get_ocr`和`rotate_img`两个函数,确保这些依赖函数正确实现并可用。 +- 由于OCR处理可能耗时,对于包含大量图像的PDF文件,执行该函数可能需要较长时间。 + +**输出示例**: +调用`pdf2text(filepath)`函数后,将返回一个字符串,其中包含了PDF文件中所有页面的文本内容,以及通过OCR识别的图像中的文字。例如,如果PDF文件包含了文本“欢迎使用OCR”和一张包含文字“图像识别” 的图片,函数将返回一个包含“欢迎使用OCR\n图像识别” 的字符串。 +*** +*** diff --git a/markdown_docs/document_loaders/mypptloader.md b/markdown_docs/document_loaders/mypptloader.md new file mode 100644 index 000000000..7f07ce3f4 --- /dev/null +++ b/markdown_docs/document_loaders/mypptloader.md @@ -0,0 +1,93 @@ +## ClassDef RapidOCRPPTLoader +**RapidOCRPPTLoader**: RapidOCRPPTLoader的功能是从PowerPoint文件中提取文本和图片内容,并使用OCR技术转换图片中的文本。 + +**属性**: +- 无特定公开属性,此类主要通过方法实现功能。 + +**代码描述**: +RapidOCRPPTLoader类继承自UnstructuredFileLoader,专门用于处理PowerPoint文件(.pptx)。它通过内部定义的`_get_elements`方法实现主要功能。该方法首先定义了一个内部函数`ppt2text`,用于将PowerPoint文件中的文本和图片内容提取出来。`ppt2text`函数使用了`python-pptx`库来读取PowerPoint文件,`PIL`库处理图片,以及`rapidocr_onnxruntime`库来执行图片中的文字识别(OCR)。 + +在提取过程中,`ppt2text`函数会遍历所有幻灯片,并对每个幻灯片中的形状(包括文本框、表格、图片和组合形状)进行处理。对于文本框和表格,直接提取文本内容;对于图片,使用RapidOCR进行文字识别;对于组合形状,递归地对其子形状进行相同的处理。所有提取的文本内容将被拼接成一个字符串。 + +最后,`_get_elements`方法使用`partition_text`函数(来自`unstructured.partition.text`模块)对提取的文本进行分段处理,返回一个分段后的文本列表,以便后续处理。 + +**注意**: +- 使用RapidOCRPPTLoader之前,需要确保安装了`python-pptx`、`PIL`、`numpy`、`tqdm`和`rapidocr_onnxruntime`等依赖库。 +- OCR技术的准确性受到图片质量的影响,因此在图片质量较低的情况下,文字识别的准确率可能会下降。 +- 由于OCR处理可能耗时较长,特别是在处理包含大量图片的PowerPoint文件时,应考虑执行时间和资源消耗。 + +**输出示例**: +由于RapidOCRPPTLoader的输出依赖于输入的PowerPoint文件内容,因此无法提供一个固定的输出示例。一般而言,如果输入的PowerPoint文件包含文本和图片,输出将是一个包含提取文本(包括图片中识别的文字)的字符串列表。每个列表项代表PowerPoint中的一段文本内容。 +### FunctionDef _get_elements(self) +**_get_elements**: 该函数的功能是从PPT文件中提取文本和图片内容,并将图片内容通过OCR技术转换为文本。 + +**参数**: 该函数没有显式参数,它是一个对象的方法,依赖于对象的状态。 + +**代码描述**: +- `_get_elements` 方法首先定义了一个内部函数 `ppt2text`,该函数负责打开并读取PPT文件的内容。 +- 使用 `pptx.Presentation` 加载PPT文件,遍历每一页幻灯片。 +- 对于幻灯片中的每个元素,根据其类型(文本框、表格、图片、组合),采取不同的处理方式来提取文本。 +- 文本框和表格中的文本直接提取。 +- 对于图片,使用 `RapidOCR` 进行图像识别,将图片内容转换为文本。 +- 对于组合类型的元素,递归地调用 `extract_text` 函数,处理组合内的每个子元素。 +- 使用 `tqdm` 库显示处理进度。 +- 最后,通过调用 `partition_text` 函数,对提取出的文本进行进一步的处理或分割,具体取决于 `self.unstructured_kwargs` 参数的配置。 + +**注意**: +- 该方法依赖于外部库 `pptx`、`PIL`、`numpy`、`io` 和 `rapidocr_onnxruntime`,在使用前需要确保这些库已经被安装。 +- OCR技术的准确性受到图片质量的影响,因此在图片质量较低的情况下,识别出的文本可能会有误差。 +- `partition_text` 函数的行为和输出取决于 `self.unstructured_kwargs` 参数的配置,这意味着该方法的输出可能会根据不同的配置而有所不同。 + +**输出示例**: +由于 `_get_elements` 函数的输出依赖于输入的PPT文件内容以及OCR的准确性,因此很难提供一个具体的输出示例。一般而言,输出将是一个文本列表,其中包含了从PPT文件中提取并通过OCR技术转换的文本内容。例如,如果PPT中包含了一张包含文字“欢迎来到AI世界”的图片,那么该方法可能会输出一个包含字符串“欢迎来到AI世界”的列表(假设OCR识别准确)。 +#### FunctionDef ppt2text(filepath) +**ppt2text**: 此函数的功能是将PowerPoint文件中的文本和图片转换为纯文本格式。 + +**参数**: +- filepath: PowerPoint文件的路径。 + +**代码描述**: +`ppt2text`函数首先导入必要的库,包括`pptx`用于读取PowerPoint文件,`PIL.Image`用于处理图片,`numpy`用于图片数据处理,`io.BytesIO`用于将字节流转换为文件,以及`rapidocr_onnxruntime.RapidOCR`用于执行OCR(光学字符识别)。 + +函数接收一个参数`filepath`,这是要处理的PowerPoint文件的路径。函数内部创建了一个`Presentation`对象来加载PowerPoint文件,并初始化一个空字符串`resp`用于存储最终的文本结果。 + +定义了一个内部函数`extract_text`,用于提取PowerPoint中的文本和图片。这个内部函数检查每个形状是否包含文本框、表格或图片,并相应地提取文本。对于图片,使用OCR技术将图片中的文本转换为可读文本。特别地,形状类型13代表图片,形状类型6代表组合。 + +使用`tqdm`库创建一个进度条,遍历所有幻灯片,并对每个幻灯片中的形状进行排序,以确保按照从上到下、从左到右的顺序处理形状。对于每个形状,调用`extract_text`函数提取文本。 + +最后,函数返回包含所有提取文本的字符串`resp`。 + +**注意**: +- 确保安装了`python-pptx`、`Pillow`、`numpy`、`tqdm`和`rapidocr_onnxruntime`等依赖库。 +- OCR准确性受到图片质量的影响,可能无法100%准确识别图片中的文本。 +- 函数处理大型文件时可能需要较长时间。 + +**输出示例**: +``` +"这是第一页的文本内容。 +这是从第一张图片中识别的文本。 +这是第二页的文本内容。 +这是从第二页的表格中提取的文本。" +``` +此输出示例展示了从一个包含文本、图片和表格的PowerPoint文件中提取的文本内容。 +##### FunctionDef extract_text(shape) +**extract_text**: 此函数的功能是从PowerPoint的特定形状中提取文本和图片中的文字。 + +**参数**: +- shape: 需要从中提取文本的PowerPoint形状对象。 + +**代码描述**: +`extract_text` 函数是为了从PowerPoint演示文稿中的不同形状(如文本框、表格、图片和组合形状)提取文本信息而设计的。该函数通过递归的方式处理形状,确保即使在组合形状中也能有效提取文本。 + +1. 首先,函数检查传入的形状是否有文本框(`has_text_frame`),如果有,则提取其中的文本并去除前后空格,之后添加到响应变量`resp`中。 +2. 接下来,函数检查形状是否包含表格(`has_table`)。对于表格中的每一行和每一个单元格,函数遍历其文本框中的段落,提取并清理文本,然后添加到`resp`。 +3. 函数还能处理图片类型的形状(形状类型代码为13)。对于图片,使用OCR(光学字符识别)技术提取图片中的文字。提取的文字结果被添加到`resp`中。 +4. 对于组合形状(形状类型代码为6),函数递归地调用自身,以提取组合内各个子形状的文本。 + +**注意**: +- 该函数使用了`nonlocal`关键字声明的`resp`变量来累积提取的文本。这意味着`resp`变量应在函数外部定义,并在调用`extract_text`之前初始化。 +- 对于图片中的文字提取,函数依赖于OCR技术。因此,需要确保相关的OCR库(如在代码中使用的`ocr`函数)已正确安装并配置。 +- 形状类型代码(如13代表图片,6代表组合形状)是根据PowerPoint对象模型定义的。了解这些代码有助于理解函数如何区分处理不同类型的形状。 +*** +*** +*** diff --git a/markdown_docs/document_loaders/ocr.md b/markdown_docs/document_loaders/ocr.md new file mode 100644 index 000000000..caae0ab24 --- /dev/null +++ b/markdown_docs/document_loaders/ocr.md @@ -0,0 +1,17 @@ +## FunctionDef get_ocr(use_cuda) +**get_ocr**: 此函数的功能是获取一个OCR对象,用于执行图像或PDF中的文字识别。 + +**参数**: +- use_cuda: 布尔值,指定是否使用CUDA加速。默认为True。 + +**代码描述**: +`get_ocr`函数旨在提供一个灵活的方式来获取文字识别(OCR)的功能对象。它首先尝试从`rapidocr_paddle`模块导入`RapidOCR`类,如果成功,将创建一个`RapidOCR`实例,其中的CUDA加速设置将根据`use_cuda`参数来决定。如果在尝试导入`rapidocr_paddle`时发生`ImportError`异常,表明可能未安装相应的包,函数则会尝试从`rapidocr_onnxruntime`模块导入`RapidOCR`类,并创建一个不指定CUDA加速的`RapidOCR`实例。这种设计使得函数能够在不同的环境配置下灵活工作,即使在缺少某些依赖的情况下也能尽可能地提供OCR服务。 + +在项目中,`get_ocr`函数被用于不同的场景来执行OCR任务。例如,在`document_loaders/myimgloader.py`的`img2text`方法中,它被用来将图片文件中的文字识别出来;而在`document_loaders/mypdfloader.py`的`pdf2text`方法中,它被用于识别PDF文件中的文字以及PDF中嵌入图片的文字。这显示了`get_ocr`函数在项目中的多功能性和重要性,它为处理不同类型的文档提供了统一的OCR解决方案。 + +**注意**: +- 在使用`get_ocr`函数时,需要确保至少安装了`rapidocr_paddle`或`rapidocr_onnxruntime`中的一个包,以便函数能够成功返回一个OCR对象。 +- 如果计划在没有CUDA支持的环境中使用,应将`use_cuda`参数设置为False,以避免不必要的错误。 + +**输出示例**: +由于`get_ocr`函数返回的是一个`RapidOCR`对象,因此输出示例将依赖于该对象的具体实现。一般而言,可以预期该对象提供了执行OCR任务的方法,如对图片或PDF中的文字进行识别,并返回识别结果。 diff --git a/markdown_docs/embeddings/add_embedding_keywords.md b/markdown_docs/embeddings/add_embedding_keywords.md new file mode 100644 index 000000000..9b39a7960 --- /dev/null +++ b/markdown_docs/embeddings/add_embedding_keywords.md @@ -0,0 +1,58 @@ +## FunctionDef get_keyword_embedding(bert_model, tokenizer, key_words) +**get_keyword_embedding**: 该函数的功能是获取关键词的嵌入表示。 + +**参数**: +- **bert_model**: 一个预训练的BERT模型,用于生成嵌入表示。 +- **tokenizer**: 与BERT模型相匹配的分词器,用于将关键词转换为模型能理解的格式。 +- **key_words**: 一个字符串列表,包含需要获取嵌入表示的关键词。 + +**代码描述**: +`get_keyword_embedding`函数首先使用传入的`tokenizer`将关键词列表`key_words`转换为模型能够处理的输入格式。这一步骤包括将关键词转换为对应的输入ID,并对输入进行填充和截断以满足模型的要求。随后,函数从`tokenizer`的输出中提取`input_ids`,并去除每个序列的首尾特殊标记,因为这些标记对于关键词的嵌入表示不是必需的。 + +接着,函数利用`bert_model`的`embeddings.word_embeddings`属性,根据`input_ids`获取对应的嵌入表示。由于可能传入多个关键词,函数对所有关键词的嵌入表示进行平均,以获得一个统一的表示形式。 + +在项目中,`get_keyword_embedding`函数被`add_keyword_to_model`函数调用,用于将自定义关键词的嵌入表示添加到预训练的BERT模型中。这一过程涉及读取关键词文件,生成关键词的嵌入表示,扩展模型的嵌入层以包含这些新的关键词,最后将修改后的模型保存到指定路径。这使得模型能够理解并有效处理这些新增的关键词,从而提高模型在特定任务上的性能。 + +**注意**: +- 确保传入的`bert_model`和`tokenizer`是匹配的,即它们来源于同一个预训练模型。 +- 关键词列表`key_words`应该是经过精心挑选的,因为这些关键词将直接影响模型的理解能力和性能。 +- 在调用此函数之前,应该已经准备好关键词文件,并确保其格式正确。 + +**输出示例**: +假设传入了两个关键词`["AI", "机器学习"]`,函数可能返回一个形状为`(2, embedding_size)`的张量,其中`embedding_size`是模型嵌入层的维度,表示这两个关键词的平均嵌入表示。 +## FunctionDef add_keyword_to_model(model_name, keyword_file, output_model_path) +**add_keyword_to_model**: 该函数的功能是将自定义关键词添加到预训练的嵌入模型中。 + +**参数**: +- **model_name**: 字符串类型,默认为`EMBEDDING_MODEL`。指定要使用的预训练嵌入模型的名称。 +- **keyword_file**: 字符串类型,默认为空字符串。指定包含自定义关键词的文件路径。 +- **output_model_path**: 字符串类型,可为`None`。指定添加了关键词后的模型保存路径。 + +**代码描述**: +首先,函数通过读取`keyword_file`文件,将文件中的每一行作为一个关键词添加到`key_words`列表中。接着,使用指定的`model_name`加载一个句子转换器模型(SentenceTransformer模型),并从中提取第一个模块作为词嵌入模型。通过这个词嵌入模型,可以获取到BERT模型及其分词器。 + +然后,函数调用`get_keyword_embedding`函数,传入BERT模型、分词器和关键词列表,以获取这些关键词的嵌入表示。接下来,函数将这些新的关键词嵌入添加到BERT模型的嵌入层中。这一步骤包括扩展分词器以包含新的关键词,调整BERT模型的嵌入层大小以适应新增的关键词,并将关键词的嵌入表示直接赋值给模型的嵌入层权重。 + +最后,如果提供了`output_model_path`参数,则函数会在该路径下创建必要的目录,并将更新后的词嵌入模型以及BERT模型保存到指定位置。这一过程确保了模型能够在后续的使用中,理解并有效处理这些新增的关键词。 + +**注意**: +- 确保`keyword_file`文件存在且格式正确,每行应包含一个关键词。 +- 由于模型的嵌入层大小会根据新增关键词进行调整,因此在添加关键词后,模型的大小可能会增加。 +- 在保存模型时,会使用`safetensors`格式保存BERT模型,确保模型的兼容性和安全性。 +- 添加关键词到模型是一个影响模型性能的操作,因此应谨慎选择关键词,并考虑到这些关键词在特定任务上的实际应用价值。 +## FunctionDef add_keyword_to_embedding_model(path) +**add_keyword_to_embedding_model**: 该函数的功能是将自定义关键词添加到指定的嵌入模型中。 + +**参数**: +- **path**: 字符串类型,默认为`EMBEDDING_KEYWORD_FILE`。指定包含自定义关键词的文件路径。 + +**代码描述**: +此函数首先通过`os.path.join(path)`获取关键词文件的完整路径。然后,它从配置中读取模型的名称和路径,这些配置通过`MODEL_PATH["embed_model"][EMBEDDING_MODEL]`获得。接着,函数计算模型所在的父目录,并生成一个包含当前时间戳的新模型名称,格式为`EMBEDDING_MODEL_Merge_Keywords_当前时间`,以确保输出模型名称的唯一性。 + +接下来,函数调用`add_keyword_to_model`,这是一个重要的调用关系,因为`add_keyword_to_model`负责实际将关键词添加到嵌入模型中。在调用`add_keyword_to_model`时,传入当前使用的模型名称、关键词文件路径以及新模型的保存路径。这一步骤完成了将自定义关键词集成到预训练嵌入模型中的核心功能。 + +**注意**: +- 确保传入的`path`参数指向一个有效的关键词文件,且该文件格式正确,每行包含一个要添加的关键词。 +- 该函数依赖于`add_keyword_to_model`函数,后者负责实际的关键词添加逻辑,包括读取关键词、更新模型的嵌入层以及保存更新后的模型。因此,了解`add_keyword_to_model`的具体实现对于理解整个关键词添加过程是非常重要的。 +- 生成的新模型名称包含时间戳,这有助于区分不同时间点生成的模型版本。 +- 在使用此函数时,应考虑到模型大小可能会因为添加新的关键词而增加,这可能会对模型加载和运行时的性能产生影响。 diff --git a/markdown_docs/release.md b/markdown_docs/release.md new file mode 100644 index 000000000..69f36d77c --- /dev/null +++ b/markdown_docs/release.md @@ -0,0 +1,46 @@ +## FunctionDef get_latest_tag +**get_latest_tag**: 此函数的功能是获取Git仓库中最新的标签。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `get_latest_tag` 函数首先使用 `subprocess.check_output` 方法执行 `git tag` 命令,以获取当前Git仓库中所有的标签。然后,通过对输出结果进行解码(UTF-8)和分割,将其转换成一个标签列表。接下来,使用 `sorted` 函数和一个自定义的排序键,基于标签的版本号(假设遵循 `v主版本号.次版本号.修订号` 的格式)对标签列表进行排序。排序键通过正则表达式 `re.match` 匹配每个标签的版本号,并将其转换为整数元组,以便进行比较。最后,函数返回排序后的最后一个元素,即最新的标签。 + +在项目中,`get_latest_tag` 函数被 `main` 函数调用,用于获取当前Git仓库中的最新标签,并在终端中显示。此外,`main` 函数还根据用户的输入决定如何递增版本号,并创建新的标签推送到远程仓库。因此,`get_latest_tag` 函数在自动化版本控制和发布流程中起着关键作用,它确保了版本号的正确递增和新版本标签的生成。 + +**注意**: 使用此函数时,需要确保当前环境已安装Git,并且函数调用是在一个Git仓库的根目录下进行的。此外,此函数假定标签遵循 `v主版本号.次版本号.修订号` 的命名约定,如果标签不遵循此格式,可能无法正确排序和识别最新标签。 + +**输出示例**: 假设Git仓库中的最新标签为 `v1.2.3`,则函数调用 `get_latest_tag()` 将返回字符串 `"v1.2.3"`。 +## FunctionDef update_version_number(latest_tag, increment) +**update_version_number**: 此函数用于根据最新的Git标签和用户指定的版本号递增规则来更新版本号。 + +**参数**: +- `latest_tag`: 最新的Git标签,字符串格式,预期为`vX.Y.Z`的形式,其中X、Y、Z分别代表主版本号、次版本号和修订号。 +- `increment`: 用户指定的版本号递增规则,接受的值为`'X'`、`'Y'`或`'Z'`,分别代表递增主版本号、次版本号或修订号。 + +**代码描述**: +函数首先通过正则表达式从`latest_tag`中提取出当前的主版本号、次版本号和修订号,并将它们转换为整数。根据`increment`参数的值,函数将相应的版本号部分递增。如果`increment`为`'X'`,则主版本号加一,次版本号和修订号重置为0。如果`increment`为`'Y'`,则次版本号加一,修订号重置为0。如果`increment`为`'Z'`,则修订号加一。最后,函数将更新后的版本号拼接成`vX.Y.Z`的格式并返回。 + +此函数在项目中被`main`函数调用。在`main`函数中,首先获取当前最新的Git标签,然后询问用户希望递增哪部分版本号(主版本号、次版本号或修订号)。用户输入后,`update_version_number`函数被调用以生成新的版本号。根据用户的确认,新的版本号可能会被用来创建Git标签并推送到远程仓库。 + +**注意**: +- 输入的`latest_tag`必须严格遵循`vX.Y.Z`的格式,否则正则表达式匹配将失败,函数将无法正确执行。 +- `increment`参数仅接受`'X'`、`'Y'`、`'Z'`三个值,任何其他输入都将导致函数无法按预期递增版本号。 + +**输出示例**: +如果`latest_tag`为`v1.2.3`且`increment`为`'Y'`,则函数将返回`v1.3.0`。 +## FunctionDef main +**main**: 此函数的功能是自动化Git版本控制流程,包括获取最新Git标签,递增版本号,并根据用户确认将新版本号作为标签推送到远程仓库。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `main` 函数首先通过调用 `get_latest_tag` 函数获取当前Git仓库中的最新标签,并将其打印出来。接着,函数提示用户选择要递增的版本号部分(主版本号X、次版本号Y或修订号Z)。用户的选择通过标准输入接收,并转换为大写字母以便后续处理。如果用户输入的不是X、Y或Z中的任何一个,系统会提示错误并要求用户重新输入,直到输入正确为止。 + +一旦获得有效输入,`main` 函数将调用 `update_version_number` 函数,传入最新的Git标签和用户选择的递增部分,以生成新的版本号。新版本号随后被打印出来,询问用户是否确认更新版本号并推送到远程仓库。用户的确认通过标准输入接收,并转换为小写字母进行判断。 + +如果用户确认(输入'y'),则使用 `subprocess.run` 方法执行Git命令,首先创建新的版本标签,然后将该标签推送到远程仓库。操作完成后,打印出相应的提示信息。如果用户不确认(输入'n'),则打印出操作已取消的信息。 + +**注意**: +- 在使用此函数之前,需要确保当前环境已安装Git,并且函数调用是在一个Git仓库的根目录下进行的。 +- 用户输入的处理是大小写不敏感的,即输入'X'、'x'均被视为有效输入,并且都会被转换为大写进行处理。 +- 在推送新标签到远程仓库之前,函数会要求用户进行确认。这是一个安全措施,以防止意外修改远程仓库。 +- 此函数依赖于`get_latest_tag`和`update_version_number`两个函数。`get_latest_tag`用于获取最新的Git标签,而`update_version_number`根据用户指定的递增规则更新版本号。这两个函数的正确执行是`main`函数能够正确工作的基础。 diff --git a/markdown_docs/server/agent/callbacks.md b/markdown_docs/server/agent/callbacks.md new file mode 100644 index 000000000..0046f05bf --- /dev/null +++ b/markdown_docs/server/agent/callbacks.md @@ -0,0 +1,301 @@ +## FunctionDef dumps(obj) +**dumps**: 该函数的功能是将字典对象转换为JSON格式的字符串。 + +**参数**: +- obj: 需要被转换为JSON字符串的字典对象。 + +**代码描述**: +`dumps`函数是一个简单但非常核心的功能,它接受一个字典对象作为输入参数,并使用`json.dumps`方法将该字典转换为一个JSON格式的字符串。在转换过程中,`ensure_ascii=False`参数确保了字符串中的非ASCII字符不会被转义,从而保持了原始数据的可读性和完整性。 + +在项目中,`dumps`函数被多个异步回调处理器中的方法调用,这些方法包括`on_tool_start`、`on_tool_end`、`on_tool_error`、`on_llm_new_token`、`on_llm_start`、`on_chat_model_start`、`on_llm_end`、`on_llm_error`和`on_agent_finish`。这些方法通常在处理某些事件(如工具开始、结束、出错等)时,需要将当前工具的状态或其他相关信息序列化为JSON字符串,并将其放入队列中等待进一步处理。通过使用`dumps`函数,确保了这些信息在序列化过程中的格式统一和准确性。 + +**注意**: +- 在使用`dumps`函数时,需要确保传入的对象是字典类型,因为`json.dumps`方法只能处理字典类型的数据。 +- 考虑到`ensure_ascii=False`参数的使用,确保在处理JSON字符串的环境中支持非ASCII字符。 + +**输出示例**: +假设有一个字典对象`{"name": "测试工具", "status": "运行中"}`,使用`dumps`函数处理后的输出示例为: +```json +{"name": "测试工具", "status": "运行中"} +``` +这个输出是一个标准的JSON格式字符串,可以被进一步用于网络传输、存储或其他需要JSON格式数据的场景中。 +## ClassDef Status +**Status**: Status 类用于定义不同状态的常量。 + +**属性**: +- `start`: 表示开始状态。 +- `running`: 表示运行中状态。 +- `complete`: 表示完成状态。 +- `agent_action`: 表示代理执行动作状态。 +- `agent_finish`: 表示代理完成状态。 +- `error`: 表示错误状态。 +- `tool_finish`: 表示工具执行完成状态。 + +**代码描述**: +Status 类在项目中扮演了重要的角色,它通过定义一系列的整型常量来表示不同的状态,这些状态在异步回调处理中被广泛使用,以便于跟踪和管理异步任务的执行流程。例如,在处理工具启动、结束、错误等事件时,会根据不同的事件类型更新当前工具的状态。这些状态不仅帮助开发者理解当前任务的执行阶段,还能够在出现错误或完成任务时提供明确的指示,进而采取相应的处理措施。 + +在项目中,Status 类的状态值被用于标识异步操作的不同阶段,如在工具开始执行时标记为 `agent_action`,在工具执行结束时标记为 `tool_finish`,在遇到错误时标记为 `error` 等。这些状态值在 `CustomAsyncIteratorCallbackHandler` 类的各个方法中被引用,以便于在异步操作过程中管理和响应不同的事件。 + +例如,在 `on_tool_start` 方法中,使用 `Status.agent_action` 来标记当前工具的状态为代理执行动作状态;在 `on_tool_end` 方法中,使用 `Status.tool_finish` 来更新工具状态为执行完成状态;在 `on_tool_error` 方法中,使用 `Status.error` 来标记错误状态。这种状态管理机制使得异步操作的管理变得更加清晰和有序。 + +**注意**: +- 在使用 Status 类时,开发者需要确保正确地引用了对应的状态常量,以保证异步操作的状态能够被准确地跟踪和管理。 +- 状态值的更新应该与实际的异步操作流程相匹配,以避免状态不一致导致的逻辑错误。 +- 在处理异步操作时,应该根据状态值来决定下一步的操作,如是否继续执行、是否需要处理错误等,以确保程序的健壮性。 +## ClassDef CustomAsyncIteratorCallbackHandler +**CustomAsyncIteratorCallbackHandler**: CustomAsyncIteratorCallbackHandler类的功能是作为异步迭代器回调处理器,用于处理工具的启动、结束、错误以及与长期语言模型(LLM)交互的各个阶段的回调。 + +**属性**: +- `queue`: 用于存储处理结果的异步队列。 +- `done`: 一个事件,用于标记处理完成。 +- `cur_tool`: 当前处理的工具信息。 +- `out`: 用于控制输出的标志。 + +**代码描述**: +CustomAsyncIteratorCallbackHandler类继承自AsyncIteratorCallbackHandler,提供了一系列异步方法来处理不同的事件,如工具的启动(on_tool_start)、结束(on_tool_end)、错误(on_tool_error)、与LLM交互的新令牌(on_llm_new_token)、LLM的启动(on_llm_start)和结束(on_llm_end)等。这些方法通过更新`cur_tool`字典和向`queue`队列中添加信息来记录每个事件的处理结果。 + +在处理工具启动事件时,该类会对输入字符串进行预处理,移除可能导致处理中断的特定停止词,然后将处理后的信息加入到队列中。在工具结束或发生错误时,也会相应地更新`cur_tool`字典,并将结果加入队列。对于LLM的交互,该类能够处理新令牌的接收、LLM的启动和结束事件,以及错误处理,同样通过更新`cur_tool`字典和队列来记录状态。 + +此类在项目中被用于处理与长期语言模型(LLM)的交互过程中的回调,特别是在`server/chat/agent_chat.py/agent_chat/agent_chat_iterator`中,它被用作回调处理器来管理异步聊天迭代器的状态。通过这种方式,它能够收集和整理从LLM和其他工具中得到的输出,为最终的用户交互提供必要的信息。 + +**注意**: +- 在使用此类时,需要注意其异步特性,确保在适当的异步环境中调用其方法。 +- 由于它处理的信息可能来自不同的来源(如LLM或其他工具),需要确保输入的数据格式正确,以避免处理过程中的错误。 + +**输出示例**: +假设处理了一个工具的启动和结束事件,队列中的一个可能的输出示例为: +```json +{ + "tool_name": "示例工具", + "input_str": "处理前的输入", + "output_str": "处理后的输出", + "status": "tool_finish", + "run_id": "示例运行ID", + "llm_token": "", + "final_answer": "", + "error": "" +} +``` +这表示一个工具已经完成了它的任务,其中包含了工具的名称、输入输出字符串、状态、运行ID等信息。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化CustomAsyncIteratorCallbackHandler类的实例。 + +**参数**: 该函数不接受任何外部参数。 + +**代码描述**: +此函数是CustomAsyncIteratorCallbackHandler类的构造函数,负责初始化类实例。在这个初始化过程中,首先通过`super().__init__()`调用父类的构造函数来继承父类的初始化逻辑。接着,函数创建了一个异步队列`self.queue`,这个队列用于存储异步操作的结果。此外,`self.done`是一个异步事件(`asyncio.Event`),用于标记异步操作何时完成。`self.cur_tool`是一个字典,用于存储当前工具的状态或数据。最后,`self.out`被设置为True,这可能表示某种输出状态或标志。 + +**注意**: +- 在使用CustomAsyncIteratorCallbackHandler类之前,了解异步编程和`asyncio`库的基本概念是非常重要的,因为该类的实现依赖于Python的异步编程特性。 +- `self.queue`用于异步任务之间的通信,确保在使用时正确处理队列中的数据。 +- `self.done`事件用于控制异步流程,特别是在需要等待某些异步操作完成时。 +- `self.cur_tool`字典的具体用途和结构应根据实际应用场景进行定义和使用。 +- `self.out`的具体含义和用途可能根据实际代码逻辑有所不同,开发者应根据上下文来理解和使用它。 +*** +### FunctionDef on_tool_start(self, serialized, input_str) +**on_tool_start**: 该函数的功能是在工具开始执行时进行初始化和预处理操作。 + +**参数**: +- serialized: 一个字典,包含序列化后的工具信息。 +- input_str: 字符串类型,表示工具的输入文本。 +- run_id: UUID类型,表示当前运行的唯一标识符。 +- parent_run_id: UUID类型或None,表示父运行的唯一标识符,可选参数。 +- tags: 字符串列表或None,表示与当前运行相关的标签,可选参数。 +- metadata: 字典或None,包含与当前运行相关的元数据,可选参数。 +- **kwargs: 接受任意额外的关键字参数。 + +**代码描述**: +`on_tool_start`函数是`CustomAsyncIteratorCallbackHandler`类的一个方法,它在工具开始执行时被调用。该方法首先对输入字符串`input_str`进行预处理,移除可能导致处理中断的特定停止词,如"Observation:", "Thought", 等。这一步骤是为了确保输入字符串在后续处理中不会因为包含特定词汇而提前中断。 + +接着,方法使用`serialized`参数中的工具名称和处理后的`input_str`,以及其他相关信息(如运行ID、状态等),构建一个表示当前工具状态的字典`cur_tool`。这个字典包括工具名称、输入输出字符串、状态、运行ID等关键信息。 + +最后,`on_tool_start`方法调用`dumps`函数将`cur_tool`字典序列化为JSON格式的字符串,并使用`queue.put_nowait`方法将其异步地放入队列中。这一步是为了将当前工具的状态信息传递给其他部分的处理流程,例如用于监控、日志记录或进一步的数据处理。 + +在整个过程中,`Status.agent_action`状态被用来标记当前工具的状态,表示代理正在执行动作。这与`Status`类中定义的其他状态一起,帮助系统跟踪和管理异步任务的执行流程。 + +**注意**: +- 在使用`on_tool_start`方法时,确保传入的`serialized`参数包含必要的工具信息,如工具名称。 +- 输入字符串`input_str`可能会根据预定义的停止词被截断,这一点在设计输入内容时需要考虑。 +- 该方法是异步的,因此在调用时需要使用`await`关键字。 +- 通过`**kwargs`参数,`on_tool_start`方法能够灵活接收并处理额外的关键字参数,这提供了更大的灵活性,但同时也要求调用者注意参数的正确性和相关性。 +*** +### FunctionDef on_tool_end(self, output) +**on_tool_end**: 该函数的功能是在工具执行结束时更新工具的状态并处理输出。 + +**参数**: +- `output`: 字符串类型,表示工具执行的输出内容。 +- `run_id`: UUID类型,表示当前运行的唯一标识符。 +- `parent_run_id`: UUID类型或None,表示父运行的唯一标识符,可选参数。 +- `tags`: 字符串列表或None,表示与当前运行相关的标签,可选参数。 +- `**kwargs`: 接收任意额外的关键字参数。 + +**代码描述**: +`on_tool_end`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,用于处理工具执行结束后的逻辑。该函数首先将实例变量`out`设置为True,表示输出已经准备好。然后,使用`cur_tool.update`方法更新当前工具的状态为`Status.tool_finish`,表示工具执行完成,并将工具的输出字符串中的"Answer:"部分替换为空字符串。最后,该函数将当前工具的状态和更新后的输出通过`dumps`函数序列化为JSON格式的字符串,并使用`queue.put_nowait`方法将其放入队列中,以便进一步处理。 + +该函数与`dumps`函数和`Status`类有直接的关联。`dumps`函数用于将字典对象转换为JSON格式的字符串,确保了工具状态和输出信息在序列化过程中的格式统一和准确性。`Status`类提供了一系列状态常量,其中`Status.tool_finish`表示工具执行完成的状态,用于在工具执行结束时更新当前工具的状态。 + +**注意**: +- 在调用`on_tool_end`函数时,必须确保传入的`output`和`run_id`参数有效,且`run_id`应为唯一标识符。 +- 可选参数`parent_run_id`和`tags`可以根据需要传入,以提供更多关于当前运行的上下文信息。 +- 在处理输出字符串时,`output.replace("Answer:", "")`操作是为了去除可能存在的前缀"Answer:",以获取纯净的输出内容。 +- 该函数是异步的,因此在调用时需要使用`await`关键字。 +- 在使用`queue.put_nowait`方法将信息放入队列时,应确保队列已经正确初始化并准备好接收数据。 +*** +### FunctionDef on_tool_error(self, error) +**on_tool_error**: 该函数的功能是处理工具执行过程中发生的错误。 + +**参数**: +- `error`: 异常或键盘中断的实例,表示发生的错误。 +- `run_id`: UUID格式,表示当前运行的唯一标识。 +- `parent_run_id`: UUID格式或None,表示父运行的唯一标识,如果存在的话。 +- `tags`: 字符串列表或None,表示与当前错误相关的标签。 +- `**kwargs`: 接受任意额外的关键字参数。 + +**代码描述**: +`on_tool_error`函数是`CustomAsyncIteratorCallbackHandler`类中的一个异步方法,用于处理在工具执行过程中发生的错误。当工具执行过程中遇到异常或键盘中断时,此方法会被调用。函数首先使用`self.cur_tool.update`方法更新当前工具的状态为`Status.error`,并记录错误信息。接着,它将当前工具的状态和错误信息序列化为JSON格式的字符串,并使用`self.queue.put_nowait`方法将该字符串放入队列中,以便后续处理。 + +该函数与`dumps`函数和`Status`类有直接的关联。`dumps`函数用于将字典对象转换为JSON格式的字符串,确保错误信息和工具状态以正确的格式被序列化和传输。`Status`类则提供了一个`error`状态常量,用于明确标识工具当前处于错误状态。这种设计使得错误处理过程既清晰又高效,便于后续的错误追踪和处理。 + +**注意**: +- 在调用此函数时,必须确保传入的`error`参数是一个异常或键盘中断的实例,以便正确记录错误信息。 +- `run_id`和`parent_run_id`参数应为有效的UUID格式,以确保能够准确追踪到具体的运行实例和其父实例(如果有)。 +- `tags`参数可以用于提供额外的错误上下文信息,有助于错误的分类和分析。 +- 该函数是异步的,调用时需要使用`await`关键字。 +*** +### FunctionDef on_llm_new_token(self, token) +**on_llm_new_token**: 该函数的功能是处理新的LLM(Large Language Model)生成的令牌。 + +**参数**: +- token: 字符串类型,表示LLM生成的新令牌。 +- **kwargs: 接收任意数量的关键字参数,这些参数可以在函数体内使用,但在当前函数实现中未直接使用。 + +**代码描述**: +`on_llm_new_token`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,主要用于处理由大型语言模型生成的新令牌。函数首先定义了一个名为`special_tokens`的列表,其中包含了特定的令牌字符串,如"Action"和"<|observation|>"。这些特殊令牌用于识别LLM生成的令牌中是否包含特定的动作或观察结果。 + +函数接着遍历`special_tokens`列表,检查传入的`token`是否包含列表中的任一特殊令牌。如果发现`token`中包含特殊令牌,函数将执行以下操作: +1. 使用`split`方法分割`token`,以特殊令牌为界,取分割后的第一部分作为`before_action`。 +2. 调用`self.cur_tool.update`方法更新当前工具的状态为`Status.running`,并将`before_action`加上换行符后设置为`llm_token`。 +3. 使用`dumps`函数将`self.cur_tool`对象转换为JSON格式的字符串,并通过`self.queue.put_nowait`方法将其放入队列中。 +4. 设置`self.out`为`False`,并终止循环。 + +如果`token`非空且`self.out`为`True`(即未找到特殊令牌),则直接将`token`作为`llm_token`更新到`self.cur_tool`中,并同样将其序列化后放入队列。 + +此函数通过检查LLM生成的令牌是否包含特定的动作或观察结果,来决定是否更新当前工具的状态和内容,并将更新后的信息放入队列中,以供后续处理。 + +**注意**: +- 函数中使用了`dumps`函数将字典对象序列化为JSON字符串,这一步骤是为了确保队列中的数据格式统一,便于后续的处理和传输。 +- `Status.running`是从`Status`类中引用的一个状态值,表示当前工具或任务正在运行中。在更新工具状态时,需要确保使用正确的状态值。 +- 函数的异步性质要求调用者在使用时配合`await`关键字,以确保异步操作的正确执行。 +- 函数实现中未直接使用`**kwargs`参数,这意味着函数设计上允许接收额外的关键字参数,以便于未来扩展或在不同上下文中灵活使用。 +*** +### FunctionDef on_llm_start(self, serialized, prompts) +**on_llm_start**: 该函数的功能是在长期学习模型(LLM)启动时更新当前工具的状态并将其序列化后放入队列中。 + +**参数**: +- `serialized`: 一个字典,包含序列化信息,其类型为`Dict[str, Any]`。 +- `prompts`: 一个字符串列表,包含提示信息,其类型为`List[str]`。 +- `**kwargs`: 接收任意数量的关键字参数,其类型为`Any`。 + +**代码描述**: +`on_llm_start`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,主要用于处理长期学习模型(LLM)启动时的逻辑。在该方法中,首先通过调用`self.cur_tool.update`方法更新当前工具的状态为`Status.start`,并将`llm_token`设置为空字符串。这表示当前工具已经开始执行,但尚未生成或接收到任何LLM令牌。 + +接下来,该方法使用`dumps`函数将`self.cur_tool`对象序列化为JSON格式的字符串。`dumps`函数是一个核心功能,它接受一个字典对象作为输入,并将其转换为JSON格式的字符串,确保了非ASCII字符的可读性和完整性。在本方法中,`dumps`函数的使用确保了当前工具状态的序列化信息格式统一和准确性。 + +最后,序列化后的字符串通过`self.queue.put_nowait`方法立即放入队列中,等待进一步处理。这一步骤是异步操作的一部分,确保了即使在高并发环境下,也能高效地处理大量的任务。 + +**注意**: +- 在使用`on_llm_start`方法时,需要确保传入的`serialized`参数是正确格式的字典,以及`prompts`参数是一个字符串列表。这些参数对于方法的执行至关重要。 +- 该方法是异步的,因此在调用时需要使用`await`关键字。 +- 更新状态和序列化操作应该与实际的LLM启动逻辑相匹配,以确保状态的准确性和信息的完整性。 +- 在处理异步任务时,应当注意异常处理,确保即使在遇到错误的情况下,也能保证程序的稳定运行。 +*** +### FunctionDef on_chat_model_start(self, serialized, messages) +**on_chat_model_start**: 该函数的功能是在聊天模型开始时进行初始化设置。 + +**参数**: +- `serialized`: 一个字典类型参数,包含序列化信息。 +- `messages`: 一个列表类型参数,包含消息列表。 +- `run_id`: 一个UUID类型参数,表示运行的唯一标识。 +- `parent_run_id`: 一个可选的UUID类型参数,表示父运行的唯一标识。 +- `tags`: 一个可选的字符串列表类型参数,包含标签信息。 +- `metadata`: 一个可选的字典类型参数,包含元数据信息。 +- `**kwargs`: 接收任意额外的关键字参数。 + +**代码描述**: +`on_chat_model_start`函数是`CustomAsyncIteratorCallbackHandler`类的一个方法,它主要用于处理聊天模型开始时的初始化工作。在这个方法中,首先通过`self.cur_tool.update`方法更新当前工具的状态为`Status.start`,并将`llm_token`设置为空字符串。这表示聊天模型开始执行,且当前没有任何长寿命模型(Long-Lived Model)的令牌。接着,使用`self.queue.put_nowait`方法将`self.cur_tool`的序列化信息(通过`dumps`函数转换为JSON格式的字符串)立即放入队列中,以便后续处理。 + +这个方法中调用了两个重要的对象:`Status`和`dumps`。`Status`类用于定义不同的状态常量,其中`Status.start`表示开始状态,用于标识聊天模型的启动。`dumps`函数用于将字典对象转换为JSON格式的字符串,这里它被用来序列化`self.cur_tool`的信息,以便将这些信息以字符串形式放入队列中。 + +**注意**: +- 在调用`on_chat_model_start`方法时,需要确保传入的参数符合要求,特别是`run_id`必须是有效的UUID。 +- `serialized`参数应包含所有必要的序列化信息,以确保聊天模型可以正确初始化。 +- 使用`tags`和`metadata`参数可以提供额外的上下文信息,但它们是可选的。 +- 该方法是异步的,因此在调用时需要使用`await`关键字。 +- 在实际应用中,应注意`**kwargs`参数的使用,确保不会传入意外的关键字参数,以避免潜在的错误。 +*** +### FunctionDef on_llm_end(self, response) +**on_llm_end**: 该函数的功能是在LLM(大型语言模型)任务结束时更新当前工具的状态并将其放入队列中。 + +**参数**: +- `response`: LLMResult类型,表示LLM任务的结果。 +- `**kwargs`: 接受任意额外的关键字参数,提供了函数调用的灵活性。 + +**代码描述**: +`on_llm_end`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,它在大型语言模型(LLM)任务结束时被调用。此函数首先使用`self.cur_tool.update`方法更新当前工具的状态为`Status.complete`,表示任务已完成,并设置`llm_token`为换行符("\n")。这一步骤是为了标记当前处理的工具或任务已经完成,准备进行下一步操作。 + +接着,函数使用`self.queue.put_nowait`方法将`self.cur_tool`的JSON字符串表示(通过调用`dumps`函数转换得到)放入队列中,以便后续处理。`dumps`函数将`self.cur_tool`字典对象转换为JSON格式的字符串,确保了信息在序列化过程中的格式统一和准确性。这一步骤是异步处理流程中的一个关键环节,它确保了任务状态的更新和信息的传递能够及时且准确地完成。 + +在整个项目中,`dumps`函数和`Status`类是与`on_llm_end`函数紧密相关的两个对象。`dumps`函数负责将字典对象序列化为JSON字符串,而`Status`类提供了一组预定义的状态常量,用于标识异步操作的不同阶段。这些工具和机制共同支持了`on_llm_end`函数的实现,使其能够有效地管理和传递LLM任务的结束状态。 + +**注意**: +- 在调用`on_llm_end`函数时,需要确保传入的`response`参数是`LLMResult`类型,以保证函数能够正确处理LLM任务的结果。 +- 函数内部使用了`**kwargs`来接受任意额外的关键字参数,这提供了调用时的灵活性,但调用者应注意只传递需要的参数,避免不必要的混淆。 +- 更新状态和放入队列的操作是异步执行的,调用此函数时应注意处理可能出现的异步执行相关的问题,如并发控制和异常处理。 +*** +### FunctionDef on_llm_error(self, error) +**on_llm_error**: 该函数的功能是处理LLM错误事件。 + +**参数**: +- `error`: 接收一个异常对象,可以是`Exception`或`KeyboardInterrupt`类型,表示发生的错误。 +- `**kwargs`: 接收任意数量的关键字参数,提供额外的灵活性以处理不同的错误情况。 + +**代码描述**: +`on_llm_error`函数是`CustomAsyncIteratorCallbackHandler`类的一个方法,专门用于处理LLM(长寿命模型)在执行过程中遇到的错误。当LLM执行过程中发生错误时,此函数会被触发。 + +在函数内部,首先通过`self.cur_tool.update`方法更新当前工具的状态为`Status.error`,并记录错误信息。这里的`Status.error`是一个从`Status`类中定义的常量,表示当前工具处于错误状态。错误信息则通过将`error`参数转换为字符串形式来记录。 + +接下来,函数使用`self.queue.put_nowait`方法将当前工具的状态信息异步地放入队列中。在放入队列之前,使用`dumps`函数将工具状态信息序列化为JSON格式的字符串。`dumps`函数是一个关键的功能,它将字典对象转换为JSON格式的字符串,确保了信息在网络传输或存储过程中的格式统一和准确性。 + +**注意**: +- 在处理LLM错误时,确保传递给`on_llm_error`函数的`error`参数包含了足够的错误信息,以便于准确记录和后续处理。 +- 使用`**kwargs`参数提供了额外的灵活性,但在调用时需要注意传递的关键字参数应与错误处理逻辑相匹配。 +- 在更新工具状态和序列化状态信息时,应确保操作的原子性和错误处理机制,避免因异常处理不当导致的进一步错误。 +- 考虑到`dumps`函数的使用,确保传入的对象符合JSON序列化的要求,并注意处理非ASCII字符的情况。 +*** +### FunctionDef on_agent_finish(self, finish) +**on_agent_finish**: 该函数的功能是在代理执行完成时更新当前工具的状态,并将其最终结果放入队列中。 + +**参数**: +- `finish`: 一个`AgentFinish`类型的对象,包含代理执行的最终结果。 +- `run_id`: 一个`UUID`类型的对象,表示当前运行的唯一标识。 +- `parent_run_id`: 一个可选的`UUID`类型的对象,表示父运行的唯一标识。 +- `tags`: 一个可选的字符串列表,包含与当前运行相关的标签。 +- `**kwargs`: 接受任意额外的关键字参数。 + +**代码描述**: +`on_agent_finish`函数是`CustomAsyncIteratorCallbackHandler`类的一个异步方法,它在代理执行完成时被调用。该方法首先使用`finish.return_values["output"]`获取代理执行的最终输出结果,并将当前工具的状态更新为`Status.agent_finish`,同时设置最终答案为代理的输出结果。然后,它使用`dumps`函数将当前工具的状态序列化为JSON格式的字符串,并使用`put_nowait`方法将这个字符串放入队列中,以便后续处理。最后,`cur_tool`被重置为空字典,为下一次代理执行做准备。 + +在这个过程中,`dumps`函数负责将字典对象转换为JSON格式的字符串,确保了信息在序列化过程中的格式统一和准确性。`Status`类提供了`agent_finish`状态,标识代理执行已完成,这对于跟踪和管理异步任务的执行流程至关重要。 + +**注意**: +- 确保`finish`参数提供了有效的代理执行结果,特别是`finish.return_values["output"]`能够正确获取到输出结果。 +- 使用`dumps`函数时,需要确保传入的对象是字典类型,以避免序列化错误。 +- 在将信息放入队列时,使用`put_nowait`方法可以避免阻塞,但需要确保队列处理速度足以应对放入的速度,避免队列溢出。 + +**输出示例**: +由于`on_agent_finish`方法没有返回值,其主要作用是更新状态并将信息放入队列,因此没有直接的输出示例。但可以假设在代理执行完成后,队列中将包含一个类似于以下的JSON格式字符串: +```json +{"status": 5, "final_answer": "代理执行的输出结果"} +``` +这表示当前工具的状态已更新为代理完成状态,且最终答案已设置为代理的输出结果。 +*** diff --git a/markdown_docs/server/agent/custom_agent/ChatGLM3Agent.md b/markdown_docs/server/agent/custom_agent/ChatGLM3Agent.md new file mode 100644 index 000000000..12d65544f --- /dev/null +++ b/markdown_docs/server/agent/custom_agent/ChatGLM3Agent.md @@ -0,0 +1,296 @@ +## ClassDef StructuredChatOutputParserWithRetries +**StructuredChatOutputParserWithRetries**: 该类的功能是为结构化聊天代理提供带有重试机制的输出解析。 + +**属性**: +- base_parser: 使用的基础解析器。 +- output_fixing_parser: 使用的输出修正解析器,可选。 + +**代码描述**: +StructuredChatOutputParserWithRetries 类继承自 AgentOutputParser,主要用于解析结构化聊天代理的输出。它通过定义两个主要属性——base_parser 和 output_fixing_parser 来实现其功能。base_parser 是一个 StructuredChatOutputParser 实例,用于基本的输出解析。output_fixing_parser 是一个可选的 OutputFixingParser 实例,用于在必要时修正输出。 + +该类的核心方法是 parse,它接受一个字符串 text 作为输入,并尝试解析这个字符串以生成一个代理动作(AgentAction)或代理完成信号(AgentFinish)。解析过程首先尝试找到特殊标记(如 "Action:" 或 "<|observation|>")的位置,然后根据是否包含 "tool_call" 来决定如何处理文本。如果包含 "tool_call",则进一步解析以提取动作和参数;否则,直接将文本作为最终答案处理。解析完成后,根据 output_fixing_parser 的存在与否,选择相应的解析器进行最终解析。 + +在项目中,StructuredChatOutputParserWithRetries 被 StructuredGLM3ChatAgent 类作为默认的输出解析器使用。通过 StructuredGLM3ChatAgent 类的 _get_default_output_parser 方法,可以看出 StructuredChatOutputParserWithRetries 被用于构建结构化聊天代理,以处理语言模型(LLM)的输出并将其转换为适合代理处理的格式。 + +**注意**: +- 在使用 StructuredChatOutputParserWithRetries 类时,需要确保传入的文本格式符合预期,特别是当涉及到特殊标记和工具调用格式时。 +- 如果提供了 output_fixing_parser,它将用于在基础解析失败或需要修正时进行二次解析。 + +**输出示例**: +```json +Action: +``` +{ + "action": "Final Answer", + "action_input": "这是解析后的文本" +} +``` +在这个示例中,假设传入的文本不包含 "tool_call",则 parse 方法将直接将文本视为最终答案,并构建相应的 JSON 字符串作为输出。 +### FunctionDef parse(self, text) +**parse**: 此函数的功能是解析文本并生成相应的动作或最终答案。 + +**参数**: +- `text`: 需要解析的文本,类型为字符串。 + +**代码描述**: +此函数首先定义了一个包含特殊标记的列表`special_tokens`,这些特殊标记用于在文本中查找特定的位置。接着,它会找到这些特殊标记中第一个出现的位置,并将文本截断到这个位置,以便进一步处理。 + +如果文本中包含"tool_call",则认为这是一个需要执行的动作。函数会找到动作描述结束的位置(即"```"的位置),并提取出动作名称和参数。参数会被解析成键值对的形式,并存储在一个字典中。然后,这些信息会被组织成一个JSON对象,准备进行下一步的解析。 + +如果文本中不包含"tool_call",则认为这是一个最终答案,直接将文本作为动作输入,动作名称设为"Final Answer"。 + +之后,函数会根据是否存在`output_fixing_parser`来决定使用哪个解析器进行解析。如果存在,就使用`output_fixing_parser`解析器,否则使用`base_parser`解析器。解析的结果会被返回。 + +**注意**: +- 在使用此函数时,需要确保传入的文本格式正确,特别是当文本中包含动作描述时,需要遵循特定的格式(例如,动作和参数的正确分隔)。 +- 如果在解析过程中遇到任何异常,函数会抛出`OutputParserException`异常,异常信息中会包含无法解析的原始文本。 + +**输出示例**: +假设文本内容为一个动作调用,解析后可能的返回值为: +```json +{ + "action": "tool_call_example", + "action_input": { + "param1": "value1", + "param2": "value2" + } +} +``` +如果文本内容为最终答案,解析后可能的返回值为: +```json +{ + "action": "Final Answer", + "action_input": "这是一个最终答案的示例文本。" +} +``` +*** +### FunctionDef _type(self) +**_type**: 该函数的功能是返回一个特定的字符串。 + +**参数**: 此函数没有参数。 + +**代码描述**: `_type` 函数是一个非常简单的方法,其主要目的是返回一个预定义的字符串。这个字符串代表了一个特定的类型标识,即 "structured_chat_ChatGLM3_6b_with_retries"。这个标识通常用于区分不同的处理逻辑或数据格式。在这个上下文中,它可能表示使用了特定配置或策略的聊天模型,特别是指一个结构化的聊天输出解析器,该解析器配置了重试机制。这种类型的标识对于维护代码的清晰度和可维护性非常重要,因为它允许开发者快速识别和理解代码块的用途和行为。 + +**注意**: 使用此函数时,需要注意它返回的字符串是硬编码的,这意味着如果未来需要更改类型标识,将需要直接修改此函数的返回值。因此,维护此部分代码时应谨慎,确保任何更改都不会影响依赖此标识的其他代码逻辑。 + +**输出示例**: 调用 `_type` 函数将返回以下字符串: +``` +"structured_chat_ChatGLM3_6b_with_retries" +``` +*** +## ClassDef StructuredGLM3ChatAgent +**StructuredGLM3ChatAgent**: 该类的功能是实现一个结构化的聊天代理,用于处理和响应基于ChatGLM3-6B模型的对话。 + +**属性**: +- output_parser: 用于解析代理输出的解析器,默认为StructuredChatOutputParserWithRetries实例。 +- observation_prefix: 用于在ChatGLM3-6B观察结果前添加的前缀字符串。 +- llm_prefix: 用于在语言模型调用前添加的前缀字符串。 + +**代码描述**: +StructuredGLM3ChatAgent 类继承自 Agent 类,提供了结构化聊天代理的实现。它通过定义特定的属性和方法来处理与语言模型(LLM)的交互,生成提示(prompt),并解析LLM的输出。 + +- **属性定义**: + - `output_parser` 属性指定了用于解析代理输出的解析器,其默认值为 StructuredChatOutputParserWithRetries 类的实例,该解析器提供了带有重试机制的输出解析功能。 + - `observation_prefix` 和 `llm_prefix` 属性分别定义了在观察结果和语言模型调用前添加的前缀字符串,用于格式化生成的提示。 + +- **方法分析**: + - `_construct_scratchpad` 方法用于构建代理的草稿本,它基于中间步骤生成一个字符串,用于记录代理的工作过程。 + - `_get_default_output_parser` 类方法返回一个默认的输出解析器实例,用于解析语言模型的输出。 + - `create_prompt` 类方法用于根据提供的工具和输入变量生成提示模板,该方法将工具的信息和其他输入变量格式化为一个字符串模板,用于生成语言模型的输入。 + - `from_llm_and_tools` 类方法用于根据语言模型和工具集合构建一个StructuredGLM3ChatAgent实例,它通过组合语言模型、工具和其他参数来初始化代理。 + +**注意**: +- 在使用 StructuredGLM3ChatAgent 类时,需要确保提供的工具和语言模型与代理的目标任务相匹配。 +- 输出解析器(output_parser)应该能够准确解析语言模型的输出,以便代理能够正确响应用户的输入。 +- 在构建提示时,应注意格式化字符串模板,确保它们能够正确地被语言模型理解和处理。 + +**输出示例**: +假设代理接收到的输入是一个简单的问答任务,输出示例可能如下: +``` +{ + "action": "Final Answer", + "action_input": "这是代理基于语言模型输出解析后的回答" +} +``` +在这个示例中,代理通过解析语言模型的输出,生成了一个包含最终回答的动作(Action)和相应输入(action_input)的JSON对象。 +### FunctionDef observation_prefix(self) +**observation_prefix**: 此函数的功能是生成并返回ChatGLM3-6B观察的前缀字符串。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `observation_prefix`函数是`StructuredGLM3ChatAgent`类的一个方法,它的主要作用是为ChatGLM3-6B模型的观察提供一个统一的前缀。这个前缀用于在处理聊天或对话数据时,标识出哪些内容是观察到的信息。在这个函数中,返回的字符串是"Observation:",这意味着所有通过此方法处理的观察数据将以"Observation:"作为开头。这有助于模型识别和处理输入数据,确保数据格式的一致性和准确性。 + +**注意**: 使用此函数时,需要注意它返回的前缀字符串是固定的。如果在不同的上下文或应用中需要不同的前缀,可能需要对此函数进行相应的修改或扩展。 + +**输出示例**: 调用`observation_prefix`函数将返回以下字符串: +``` +Observation: +``` +*** +### FunctionDef llm_prefix(self) +**llm_prefix函数功能**: 该函数的功能是生成并返回一个用于在调用大型语言模型(llm)时附加的前缀字符串。 + +**参数**: 该函数没有参数。 + +**代码描述**: `llm_prefix`函数定义在`StructuredGLM3ChatAgent`类中,是一个简单的成员函数,不接受任何参数,并且返回一个固定的字符串`"Thought:"`。这个字符串作为前缀,其目的是在向大型语言模型(llm)发起调用时,附加到实际的查询或命令之前,以此来可能影响或指定模型的回应方式。这种做法在与大型语言模型交互时很常见,用于引导模型的回应更加符合期望的上下文或风格。 + +**注意**: 使用`llm_prefix`函数时,需要注意的是,返回的前缀字符串`"Thought:"`是硬编码的,这意味着在不同的应用场景下,如果需要不同的前缀来引导大型语言模型的回应,可能需要修改这个函数的返回值。此外,这个前缀的有效性和适用性可能会随着大型语言模型的不同或者模型训练数据的更新而变化,因此在实际应用中需要根据模型的具体表现来调整。 + +**输出示例**: 调用`llm_prefix`函数将返回字符串`"Thought:"`。 + +通过上述分析,开发者和初学者可以了解到`llm_prefix`函数的作用、使用方法以及需要注意的事项。这有助于在使用`StructuredGLM3ChatAgent`类与大型语言模型进行交互时,能够更有效地引导模型的回应,从而提高交互的质量和效果。 +*** +### FunctionDef _construct_scratchpad(self, intermediate_steps) +**_construct_scratchpad**: 此函数的功能是构建并返回一个代表中间步骤的字符串。 + +**参数**: +- **intermediate_steps**: 一个列表,包含元组,每个元组由AgentAction和字符串组成,代表中间的操作步骤。 + +**代码描述**: +`_construct_scratchpad` 函数首先调用其父类的 `_construct_scratchpad` 方法,传入中间步骤的数据(`intermediate_steps`),并接收返回的字符串(`agent_scratchpad`)。此字符串代表了到目前为止的工作进展。函数接着检查 `agent_scratchpad` 是否为字符串类型,如果不是,则抛出 `ValueError` 异常,确保后续操作的数据类型正确性。 + +如果 `agent_scratchpad` 非空,函数将返回一个格式化的字符串,该字符串以一种友好的方式向用户展示之前的工作成果,即使实际上这个函数并没有直接访问到这些成果,只是通过参数传递得到的信息。如果 `agent_scratchpad` 为空,则直接返回该空字符串。 + +**注意**: +- 确保传入的 `intermediate_steps` 参数格式正确,即列表中包含的元素为元组,且元组包含的是 `AgentAction` 和字符串。 +- 此函数假设父类的 `_construct_scratchpad` 方法已正确实现并能返回一个字符串。如果父类方法的实现发生变化,可能需要相应地调整此函数。 + +**输出示例**: +如果 `intermediate_steps` 包含了一系列的操作步骤,且父类方法返回了这些步骤的字符串表示,例如 "Step 1: Do something; Step 2: Do something else;",那么此函数可能返回的字符串示例为: + +``` +"This was your previous work (but I haven't seen any of it! I only see what you return as final answer): +Step 1: Do something; Step 2: Do something else;" +``` +*** +### FunctionDef _get_default_output_parser(cls, llm) +**_get_default_output_parser**: 该函数的功能是获取默认的输出解析器。 + +**参数**: +- `llm`: 可选参数,类型为 `BaseLanguageModel`,表示基础语言模型。 +- `**kwargs`: 接受任意数量的关键字参数。 + +**代码描述**: `_get_default_output_parser` 函数是 `StructuredGLM3ChatAgent` 类的一个类方法,用于获取默认的输出解析器。该方法接受一个可选的语言模型实例 `llm` 和任意数量的关键字参数 `**kwargs`。函数体内部,它创建并返回一个 `StructuredChatOutputParserWithRetries` 实例,将 `llm` 作为参数传递给该实例。`StructuredChatOutputParserWithRetries` 类是专门为结构化聊天代理设计的输出解析器,具有重试机制,能够处理语言模型的输出并将其转换为适合代理处理的格式。 + +在项目中,`_get_default_output_parser` 方法被 `from_llm_and_tools` 方法调用,以获取默认的输出解析器实例。如果在创建 `StructuredGLM3ChatAgent` 实例时没有明确指定输出解析器,则会通过调用 `_get_default_output_parser` 方法来获取默认的输出解析器实例,并将其用于处理语言模型的输出。 + +**注意**: +- 在使用 `_get_default_output_parser` 方法时,需要确保传入的 `llm` 参数(如果有)是一个有效的语言模型实例。 +- 该方法设计为灵活接受任意数量的关键字参数 `**kwargs`,但在当前实现中并未直接使用这些额外的参数。开发者在扩展或修改方法时可以根据需要利用这些参数。 + +**输出示例**: 由于 `_get_default_output_parser` 方法返回的是一个 `StructuredChatOutputParserWithRetries` 实例,因此输出示例将依赖于该实例的具体实现。假设 `llm` 参数为 `None`,调用 `_get_default_output_parser` 方法将返回一个不带语言模型实例的 `StructuredChatOutputParserWithRetries` 实例。 +*** +### FunctionDef _stop(self) +**_stop函数的功能**: `_stop`函数的目的是结束当前的会话并返回一个特定的标记列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `_stop`函数是`StructuredGLM3ChatAgent`类的一个私有方法,用于在聊天代理的会话中标记结束点。当调用此函数时,它会返回一个包含单个字符串元素`"<|observation|>"`的列表。这个返回值通常用于指示聊天模型的会话已经结束,或者需要进行某种形式的重置或观察。在聊天代理的上下文中,这个特定的字符串可能被用作一个信号或标记,以触发特定的行为或处理逻辑。 + +**注意**: 虽然`_stop`函数的实现看起来简单,但它在聊天代理的逻辑中可能扮演着关键角色。使用时需要确保聊天模型或处理逻辑能够正确识别并处理返回的`"<|observation|>"`标记。此外,由于`_stop`是一个私有方法,它仅在`StructuredGLM3ChatAgent`类的内部被调用,不应该直接从类的实例外部访问或调用。 + +**输出示例**: 调用`_stop`函数可能会返回如下列表: +```python +["<|observation|>"] +``` +这个列表包含一个字符串元素,即`"<|observation|>"`,用于表示聊天会话的结束或需要进行观察的状态。 +*** +### FunctionDef create_prompt(cls, tools, prompt, input_variables, memory_prompts) +**create_prompt**: 此函数的功能是基于提供的工具和模板参数构建聊天提示模板。 + +**参数**: +- `tools`: 一个实现了BaseTool接口的对象序列,代表聊天代理可以使用的工具。 +- `prompt`: 一个字符串模板,用于格式化最终的提示信息。 +- `input_variables`: 一个字符串列表,指定输入变量的名称,默认为None。 +- `memory_prompts`: 一个BasePromptTemplate对象的列表,用于提供记忆提示,默认为None。 + +**代码描述**: +`create_prompt`函数首先遍历`tools`参数中的每个工具,提取其名称、描述和参数模式,并将这些信息格式化为一个简化的JSON结构。这个结构包括工具的名称、描述和参数。接着,函数将这些工具信息格式化为一个字符串,其中每个工具的信息占据一行,包括其名称、描述和参数。这个格式化的字符串以及其他提供的模板参数(如工具名称列表、历史记录、输入和代理草稿板)被用来填充`prompt`模板字符串。 + +如果`input_variables`未指定,则默认为`["input", "agent_scratchpad"]`。`memory_prompts`参数允许将额外的提示信息加入到最终的提示模板中,这些信息可以是之前的对话历史或其他重要信息。 + +最后,函数使用格式化后的提示信息和输入变量列表创建一个`ChatPromptTemplate`对象,并将其返回。这个返回的对象可以直接用于生成聊天代理的提示信息。 + +在项目中,`create_prompt`函数被`from_llm_and_tools`方法调用,用于根据语言模型(LLM)和工具集合构建一个聊天代理。这表明`create_prompt`函数在构建聊天代理的初始化过程中起着核心作用,特别是在准备聊天代理的提示模板方面。 + +**注意**: +- 确保`prompt`参数提供的模板字符串正确地使用了所有预期的变量,以避免格式化时出现错误。 +- `tools`参数中的工具对象需要实现`BaseTool`接口,确保它们具有`name`、`description`和`args_schema`属性。 + +**输出示例**: +假设有两个工具,分别为"Calculator"和"Translator",且`prompt`参数为"Available tools: {tools}\nInput: {input}",则函数可能返回的`ChatPromptTemplate`对象中的`messages`属性可能包含以下字符串: + +``` +Available tools: +Calculator: A simple calculator, args: {'number1': 'Number', 'number2': 'Number'} +Translator: Translates text from one language to another, args: {'text': 'String', 'target_language': 'String'} +Input: {input} +``` +*** +### FunctionDef from_llm_and_tools(cls, llm, tools, prompt, callback_manager, output_parser, human_message_template, input_variables, memory_prompts) +**from_llm_and_tools**: 该函数的功能是从语言模型(LLM)和工具集合构建一个聊天代理。 + +**参数**: +- `cls`: 类方法的第一个参数,指代当前类。 +- `llm`: `BaseLanguageModel`的实例,表示基础语言模型。 +- `tools`: 实现了`BaseTool`接口的对象序列,代表聊天代理可以使用的工具。 +- `prompt`: 字符串类型,用于格式化最终的提示信息,默认为None。 +- `callback_manager`: `BaseCallbackManager`的实例,用于管理回调函数,默认为None。 +- `output_parser`: `AgentOutputParser`的实例,用于解析代理输出,默认为None。 +- `human_message_template`: 字符串类型,表示人类消息模板,默认为`HUMAN_MESSAGE_TEMPLATE`。 +- `input_variables`: 字符串列表,指定输入变量的名称,默认为None。 +- `memory_prompts`: `BasePromptTemplate`对象的列表,用于提供记忆提示,默认为None。 +- `**kwargs`: 接受任意数量的关键字参数。 + +**代码描述**: +`from_llm_and_tools`函数首先验证提供的工具集合是否有效。然后,它调用`create_prompt`方法来创建聊天提示模板,该模板基于提供的工具、提示、输入变量和记忆提示。接着,使用`llm`、生成的`prompt`和`callback_manager`创建一个`LLMChain`实例。此外,函数从工具集合中提取工具名称,并尝试获取默认的输出解析器,如果未提供`output_parser`参数,则调用`_get_default_output_parser`方法获取默认解析器。最后,使用这些组件构建并返回一个`StructuredGLM3ChatAgent`实例。 + +**注意**: +- 确保提供的`llm`和`tools`参数是有效的实例,且`tools`中的每个工具都实现了`BaseTool`接口。 +- 如果在调用时未指定`output_parser`,则会自动使用默认的输出解析器。 +- `**kwargs`参数提供了额外的灵活性,允许在创建代理时传递额外的配置选项。 + +**输出示例**: +由于`from_llm_and_tools`函数返回的是一个`StructuredGLM3ChatAgent`实例,因此输出示例将依赖于该实例的具体实现。例如,如果使用默认参数调用此函数,将返回一个配置了基础语言模型、指定工具集合和默认输出解析器的`StructuredGLM3ChatAgent`实例。这个实例可以直接用于处理聊天对话,执行工具命令,并解析语言模型的输出。 +*** +### FunctionDef _agent_type(self) +**_agent_type**: 该函数的功能是抛出一个 ValueError 异常。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `_agent_type` 函数是 `StructuredGLM3ChatAgent` 类的一个私有方法,其设计初衷是为了在子类中被重写,用以指定或返回特定的代理类型字符串。在其原始形态中,此函数直接抛出一个 `ValueError` 异常,这表明如果直接调用此方法而没有在子类中进行适当的重写,则会明确地指出这一点。这是一种常见的编程模式,用于强制要求子类实现特定的方法。 + +**注意**: 在使用 `StructuredGLM3ChatAgent` 类或其任何子类时,开发者需要确保 `_agent_type` 方法被正确重写以避免运行时错误。此方法的存在强调了一个设计原则,即某些方法是专门设计给子类来实现的,而不是直接在父类中使用。因此,如果你在开发过程中遇到了 `ValueError`,这可能是因为你尝试调用了一个应该被子类重写的方法,但是没有这样做。 +*** +## FunctionDef initialize_glm3_agent(tools, llm, prompt, memory, agent_kwargs) +**initialize_glm3_agent**: 该函数的功能是初始化一个基于GLM3模型的聊天代理。 + +**参数**: +- `tools`: 实现了`BaseTool`接口的对象序列,代表聊天代理可以使用的工具。 +- `llm`: `BaseLanguageModel`的实例,表示基础语言模型。 +- `prompt`: 字符串类型,用于格式化最终的提示信息,默认为None。 +- `memory`: `ConversationBufferWindowMemory`的实例,用于存储聊天历史,默认为None。 +- `agent_kwargs`: 字典类型,包含创建聊天代理时需要的额外参数,默认为None。 +- `tags`: 字符串序列,用于标记或分类代理,默认为None。 +- `**kwargs`: 接受任意数量的关键字参数,提供额外的配置选项。 + +**代码描述**: +`initialize_glm3_agent`函数首先检查是否提供了`tags`参数,并将其转换为列表形式。然后,检查`agent_kwargs`参数是否为None,如果是,则将其初始化为空字典。接下来,使用`StructuredGLM3ChatAgent.from_llm_and_tools`类方法创建一个`StructuredGLM3ChatAgent`实例,该实例基于提供的语言模型、工具集合、提示信息以及`agent_kwargs`中的其他参数。最后,使用`AgentExecutor.from_agent_and_tools`方法创建并返回一个`AgentExecutor`实例,该实例包含了刚刚创建的聊天代理、工具集合、聊天历史以及标签。 + +**注意**: +- 在使用`initialize_glm3_agent`函数时,确保提供的`tools`和`llm`参数是有效的实例,且`tools`中的每个工具都实现了`BaseTool`接口。 +- `prompt`参数允许自定义聊天代理的提示信息,可以根据需要提供。 +- `memory`参数用于存储和管理聊天历史,有助于实现更连贯的对话。 +- `agent_kwargs`和`**kwargs`提供了额外的灵活性,允许在创建聊天代理时传递额外的配置选项。 + +**输出示例**: +假设调用`initialize_glm3_agent`函数并提供了必要的参数,可能会返回如下的`AgentExecutor`实例: +``` +AgentExecutor( + agent=StructuredGLM3ChatAgent(...), + tools=[...], + memory=ConversationBufferWindowMemory(...), + tags=['example_tag'] +) +``` +在这个示例中,`AgentExecutor`实例包含了一个配置好的`StructuredGLM3ChatAgent`聊天代理,以及相关的工具集合、聊天历史和标签。这个实例可以直接用于处理聊天对话,执行工具命令,并解析语言模型的输出。 diff --git a/markdown_docs/server/agent/custom_template.md b/markdown_docs/server/agent/custom_template.md new file mode 100644 index 000000000..39dcbebfa --- /dev/null +++ b/markdown_docs/server/agent/custom_template.md @@ -0,0 +1,128 @@ +## ClassDef CustomPromptTemplate +**CustomPromptTemplate**: CustomPromptTemplate类的功能是根据提供的模板和工具列表,格式化生成一个定制化的提示字符串。 + +**属性**: +- `template`: 字符串类型,用于定义提示信息的模板。 +- `tools`: Tool对象的列表,每个Tool对象包含工具的名称和描述。 + +**代码描述**: +CustomPromptTemplate类继承自StringPromptTemplate,主要用于生成定制化的提示信息。它通过`format`方法接收关键字参数,其中`intermediate_steps`是一个列表,包含了动作和观察的元组。该方法首先将`intermediate_steps`中的信息格式化为字符串,然后将其以及工具的名称和描述添加到模板中,最后返回格式化后的字符串。 + +在项目中,CustomPromptTemplate类被用于`server/chat/agent_chat.py/agent_chat/agent_chat_iterator`中,以生成与用户交互的提示信息。通过提供的模板和工具列表,CustomPromptTemplate能够生成包含工具使用说明和中间步骤描述的提示信息,这对于指导用户如何与代理进行交互是非常有用的。特别是在异步的聊天环境中,准确和详细的提示信息能够极大地提升用户体验。 + +**注意**: +- 在使用CustomPromptTemplate时,需要确保传递给`format`方法的`intermediate_steps`参数格式正确,即包含动作和观察的元组列表。 +- 工具列表`tools`应包含所有可能会在提示信息中提及的工具,每个工具都应有名称和描述。 + +**输出示例**: +假设有以下模板和工具列表: +- 模板:`"请使用以下工具:{tools}\n{agent_scratchpad}"` +- 工具列表:`[Tool(name="Tool1", description="This is tool 1"), Tool(name="Tool2", description="This is tool 2")]` +- `intermediate_steps`:`[("action1", "observation1"), ("action2", "observation2")]` + +调用`format`方法后,可能返回的字符串为: +``` +请使用以下工具: +Tool1: This is tool 1 +Tool2: This is tool 2 +action1 +Observation: observation1 +Thought: action2 +Observation: observation2 +Thought: +``` +### FunctionDef format(self) +**功能**: `format` 函数的功能是根据提供的参数和内部逻辑,格式化并返回一个字符串。 + +**参数**: +- `**kwargs`: 关键字参数,可以接受多个命名参数,用于动态传递给模板和内部逻辑处理。 + +**代码描述**: +该函数首先从传入的关键字参数(`kwargs`)中提取出`intermediate_steps`参数。`intermediate_steps`应该是一个包含动作和观察结果的元组列表。函数遍历这个列表,将每个动作的日志和对应的观察结果格式化为字符串,并拼接到`thoughts`字符串中。 + +接下来,函数将`thoughts`字符串添加到`kwargs`字典中,键名为`agent_scratchpad`。此外,还会处理`self.tools`,这是一个工具对象列表。函数将每个工具的名称和描述格式化为字符串,并将这些字符串以换行符连接,结果赋值给`kwargs`字典中的`tools`键。同时,将所有工具的名称提取出来,以逗号和空格连接成一个字符串,赋值给`kwargs`字典中的`tool_names`键。 + +最后,函数使用`self.template.format(**kwargs)`语句,将处理好的`kwargs`字典作为参数,传递给模板的`format`方法,并返回格式化后的字符串。 + +**注意**: +- 确保传入的`kwargs`中包含`intermediate_steps`键,且其值格式正确。 +- `self.tools`应该是一个包含有`name`和`description`属性的对象列表。 +- 该函数依赖于`self.template`的`format`方法,确保`self.template`已正确初始化并可以接受`kwargs`作为参数。 + +**输出示例**: +```plaintext +Action: Move Forward +Observation: Wall detected +Thought: +Tool1: Used for cutting +Tool2: Used for digging +Tool Names: Tool1, Tool2 +``` +*** +## ClassDef CustomOutputParser +**CustomOutputParser**: CustomOutputParser类的功能是解析大模型输出,并根据输出内容决定下一步操作。 + +**属性**: +- `begin`: 一个布尔值,用于指示解析过程是否应该开始或停止。 + +**代码描述**: +CustomOutputParser类继承自AgentOutputParser,是一个专门用于解析大模型输出的解析器。它通过分析模型的输出内容,来决定是继续执行某些操作,还是结束会话。具体来说,它会检查模型输出中是否包含特定的关键词或短语,如"Final Answer:"或"Action:",并据此返回相应的操作指令。 + +在初始化时,`begin`属性被设置为True,表示解析器准备开始解析输出。在`parse`方法中,首先检查是否所有支持的代理模型都不在模型容器中,并且`begin`为True。如果条件满足,它会查找输出中的停止词(如"Observation:"),并根据这些停止词截断输出,以准备进一步的解析。 + +如果输出中包含"Final Answer:",则表示大模型已经给出了最终答案,解析器将重置`begin`为True,并返回一个包含最终答案的AgentFinish对象。如果输出中包含"Action:",则解析器会解析出相应的操作和输入,尝试执行该操作,并返回一个AgentAction对象。如果解析过程中遇到异常,或者输出不符合预期的格式,解析器将返回一个包含错误信息的AgentFinish对象。 + +**注意**: +- 在使用CustomOutputParser时,需要确保大模型的输出格式与解析器预期的格式相匹配,否则可能无法正确解析出操作指令。 +- 解析器依赖于输出中的特定关键词或短语来决定操作,因此在设计大模型的输出格式时,需要考虑这一点。 + +**输出示例**: +假设大模型的输出为"Final Answer: 42",CustomOutputParser解析后可能返回的对象为: +``` +AgentFinish(return_values={"output": "42"}, log="Final Answer: 42") +``` +如果大模型的输出为"Action: Calculate Action Input: 42 + 1",解析后可能返回的对象为: +``` +AgentAction(tool="Calculate", tool_input="42 + 1", log="Action: Calculate Action Input: 42 + 1") +``` + +在项目中,CustomOutputParser被用于解析大模型在与用户交互过程中的输出,以决定是否需要调用特定的工具或服务来辅助完成用户的请求。这使得整个系统能够更加智能和灵活地处理各种不同的用户需求。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化CustomOutputParser对象。 + +**参数**: 该函数不接受任何外部参数。 + +**代码描述**: 在CustomOutputParser类的__init__方法中,首先通过`super().__init__()`调用父类的构造函数来确保父类被正确初始化。接着,该方法设置了一个实例变量`self.begin`并将其初始化为True。这个变量可能用于标记解析开始,或者用于控制某些只在初始化时需要执行的操作。 + +**注意**: 在使用CustomOutputParser类时,不需要手动传递任何参数给__init__方法。创建对象后,可以根据实际需求修改`self.begin`的值,但通常情况下,该变量的初始值True已足够满足大多数使用场景。此外,如果CustomOutputParser类继承自一个具有复杂初始化逻辑的父类,`super().__init__()`确保了这些逻辑不会被遗漏。 +*** +### FunctionDef parse(self, llm_output) +**parse**: 此函数的功能是解析从大型语言模型(LLM)输出的文本,并根据输出内容决定下一步的操作。 + +**参数**: +- `llm_output`: 字符串类型,代表从大型语言模型(LLM)接收到的输出文本。 + +**代码描述**: +此函数首先检查是否有支持的代理模型存在于`model_container.MODEL`中,并且是否是开始解析。如果是开始解析且没有支持的代理模型,它会查找输出中的停止词(例如"Observation:"),并截取至第一个停止词之前的文本作为新的输出文本。 + +如果输出文本中包含"Final Answer:",则表示大型语言模型已经给出了最终答案。此时,函数会将"Final Answer:"之后的文本作为输出,并标记为解析结束。 + +如果输出文本中包含"Action:",则表示需要执行特定的动作。函数会解析出动作名称和动作输入,然后尝试执行该动作。如果执行成功,会返回一个`AgentAction`对象,包含动作名称、动作输入和原始日志。 + +如果上述条件都不满足,或者在解析动作时遇到异常,函数会返回一个`AgentFinish`对象,表示解析结束,同时包含错误信息或大模型自身的回答。 + +**注意**: +- 在使用此函数时,需要确保`model_container.MODEL`和`SUPPORT_AGENT_MODEL`已正确设置,以便函数能够正确判断是否有支持的代理模型。 +- 函数的返回值类型可能是`AgentFinish`、`tuple[dict[str, str], str]`或`AgentAction`,调用者需要根据返回值类型进行相应的处理。 + +**输出示例**: +假设`llm_output`为"Final Answer: 42",则函数可能返回的示例为: +```python +AgentFinish(return_values={"output": "42"}, log="Final Answer: 42") +``` + +如果`llm_output`为"Action: Email Action Input: john.doe@example.com",则函数可能返回的示例为: +```python +AgentAction(tool="Email", tool_input="john.doe@example.com", log="Action: Email Action Input: john.doe@example.com") +``` +*** diff --git a/markdown_docs/server/agent/model_contain.md b/markdown_docs/server/agent/model_contain.md new file mode 100644 index 000000000..4988eb262 --- /dev/null +++ b/markdown_docs/server/agent/model_contain.md @@ -0,0 +1,29 @@ +## ClassDef ModelContainer +**ModelContainer**: ModelContainer 类的功能是作为模型和数据库的容器。 + +**属性**: +- MODEL: 用于存储模型实例。初始值为 None,表示在创建 ModelContainer 实例时,并没有预设的模型。 +- DATABASE: 用于存储数据库连接实例。初始值同样为 None,表示在创建 ModelContainer 实例时,并没有预设的数据库连接。 + +**代码描述**: +ModelContainer 类是一个简单的容器类,设计用来存储模型实例和数据库连接实例。这个类通过定义两个属性 `MODEL` 和 `DATABASE` 来实现其功能。这两个属性在类的初始化方法 `__init__` 中被设置为 None,这意味着在创建 ModelContainer 的实例时,这两个属性都不会持有任何值。这种设计允许开发者在创建 ModelContainer 实例后,根据需要将模型实例和数据库连接实例分别赋值给这两个属性。 + +**注意**: +- 在使用 ModelContainer 类时,开发者需要注意,`MODEL` 和 `DATABASE` 属性在初始状态下是 None。因此,在尝试访问这些属性或其方法之前,需要确保它们已被正确赋值,以避免遇到 `NoneType` 对象没有该方法的错误。 +- ModelContainer 类提供了一种灵活的方式来管理模型和数据库连接,但它本身不提供任何方法来初始化 `MODEL` 和 `DATABASE` 属性。开发者需要根据自己的需求,手动为这两个属性赋值。 +- 由于 ModelContainer 类的设计相对简单,它可以根据项目的需要进行扩展,例如添加更多的属性或方法来满足更复杂的需求。 +### FunctionDef __init__(self) +**__init__**: 此函数用于初始化ModelContainer类的实例。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: 在ModelContainer类的实例被创建时,`__init__`函数会被自动调用。此函数主要完成以下几点初始化操作: +- 将`MODEL`属性设置为`None`。这意味着在实例化后,该属性暂时不关联任何模型,需要后续根据具体需求进行赋值。 +- 将`DATABASE`属性也设置为`None`。这表明在实例化的初始阶段,该属性不关联任何数据库,同样需要在后续操作中根据需要进行关联。 + +通过这种方式,`__init__`函数为ModelContainer类的实例提供了一个清晰、干净的初始状态,便于后续的属性赋值和方法调用。 + +**注意**: +- 在使用ModelContainer类创建实例后,需要根据实际情况给`MODEL`和`DATABASE`属性赋予具体的模型和数据库实例,以便于进行后续的操作。 +- 由于`MODEL`和`DATABASE`在初始化时都被设置为`None`,在对这两个属性进行操作前,建议先检查它们是否已被正确赋值,以避免在使用未初始化的属性时引发错误。 +*** diff --git a/markdown_docs/server/agent/tools/arxiv.md b/markdown_docs/server/agent/tools/arxiv.md new file mode 100644 index 000000000..fb0c8bfd9 --- /dev/null +++ b/markdown_docs/server/agent/tools/arxiv.md @@ -0,0 +1,36 @@ +## FunctionDef arxiv(query) +**arxiv**: 该函数用于执行对Arxiv的查询操作。 + +**参数**: +- **query**: 字符串类型,表示要在Arxiv上执行的查询内容。 + +**代码描述**: +`arxiv`函数是一个简单但功能强大的接口,用于在Arxiv数据库中执行查询。它首先创建了一个`ArxivQueryRun`的实例,然后调用该实例的`run`方法来执行查询。查询的具体内容由参数`query`指定,该参数应为一个字符串,表示用户希望在Arxiv上搜索的关键词或查询表达式。 + +在项目结构中,`arxiv`函数位于`server/agent/tools/arxiv.py`路径下,并且是`arxiv.py`模块中定义的核心功能之一。尽管在当前项目的其他部分,如`server/agent/tools/__init__.py`和`server/agent/tools_select.py`中没有直接的调用示例,但可以推断`arxiv`函数设计为被这些模块或其他项目部分调用,以实现对Arxiv数据库的查询功能。 + +**注意**: +- 在使用`arxiv`函数时,需要确保传入的查询字符串`query`是有效的,即它应该符合Arxiv的查询语法和要求。 +- 该函数的执行结果依赖于`ArxivQueryRun`类的`run`方法的实现,因此需要确保该方法能够正确处理传入的查询字符串,并返回期望的查询结果。 + +**输出示例**: +假设对`arxiv`函数的调用如下: +```python +result = arxiv("deep learning") +``` +则该函数可能返回一个包含查询结果的对象,例如包含多篇关于深度学习的论文的列表。具体的返回值格式将取决于`ArxivQueryRun`类的`run`方法的实现细节。 +## ClassDef ArxivInput +**ArxivInput**: ArxivInput类的功能是定义一个用于搜索查询的输入模型。 + +**属性**: +- query: 表示搜索查询标题的字符串。 + +**代码描述**: +ArxivInput类继承自BaseModel,这意味着它是一个模型类,用于定义数据结构。在这个类中,定义了一个名为`query`的属性,该属性是一个字符串类型,用于存储用户的搜索查询标题。通过使用`Field`函数,为`query`属性提供了一个描述,即"The search query title",这有助于理解该属性的用途。 + +在项目中,ArxivInput类作为一个数据模型,被用于处理与arXiv相关的搜索查询。尽管在提供的代码调用情况中没有直接的示例,但可以推断,该类可能会被用于在`server/agent/tools`目录下的其他模块中,作为接收用户搜索请求的输入参数。这样的设计使得代码更加模块化,便于维护和扩展。 + +**注意**: +- 在使用ArxivInput类时,需要确保传入的`query`参数是一个有效的字符串,因为它将直接影响搜索结果的相关性和准确性。 +- 由于ArxivInput继承自BaseModel,可以利用Pydantic库提供的数据验证功能,确保输入数据的合法性。 +- 考虑到ArxivInput类可能会被用于网络请求,应当注意处理潜在的安全问题,如SQL注入或跨站脚本攻击(XSS),确保用户输入被适当地清理和验证。 diff --git a/markdown_docs/server/agent/tools/calculate.md b/markdown_docs/server/agent/tools/calculate.md new file mode 100644 index 000000000..60839594c --- /dev/null +++ b/markdown_docs/server/agent/tools/calculate.md @@ -0,0 +1,32 @@ +## ClassDef CalculatorInput +**CalculatorInput**: CalculatorInput类的功能是定义计算器输入的数据结构。 + +**属性**: +- `query`: 表示计算器查询的字符串,是一个必填字段。 + +**代码描述**: +CalculatorInput类继承自BaseModel,这表明它是使用Pydantic库创建的,用于数据验证和设置。在这个类中,定义了一个属性`query`,它是一个字符串类型的字段。通过使用`Field()`函数,我们可以为这个字段添加额外的验证或描述信息,虽然在当前的代码示例中没有显示出来。这个类的主要作用是作为计算器服务的输入数据模型,确保传入的查询是有效且符合预期格式的字符串。 + +从项目结构来看,CalculatorInput类位于`server/agent/tools/calculate.py`文件中,但是在提供的项目信息中,并没有直接的代码示例显示这个类是如何被其他对象调用的。然而,基于它的定义和位置,我们可以推断CalculatorInput类可能被用于处理来自于`server/agent/tools`目录下其他模块的计算请求。例如,它可能被用于验证和解析用户输入,然后这些输入将被传递给实际执行计算的逻辑。 + +**注意**: +- 使用CalculatorInput类时,需要确保传入的`query`字段是一个有效的字符串,因为这是进行计算前的必要条件。 +- 由于CalculatorInput使用了Pydantic库,开发者需要熟悉Pydantic的基本使用方法,以便正确地定义和使用数据模型。 +- 虽然当前的CalculatorInput类定义相对简单,但开发者可以根据实际需求,通过添加更多的字段或使用Pydantic提供的更高级的验证功能来扩展它。 +## FunctionDef calculate(query) +**calculate**: 此函数的功能是执行数学计算查询。 + +**参数**: +- `query`: 字符串类型,表示需要进行计算的数学查询语句。 + +**代码描述**: +`calculate` 函数是一个用于执行数学计算的函数。它首先从`model_container`中获取一个模型实例,该模型被假定为已经加载并准备好处理数学计算查询。接着,使用`LLMMathChain.from_llm`方法创建一个`LLMMathChain`实例,这个实例能够利用提供的模型(`model`)来处理数学计算。在创建`LLMMathChain`实例时,会传入模型和一个标志`verbose=True`以及一个提示`PROMPT`,这表明在执行计算时会有更详细的输出信息。最后,通过调用`LLMMathChain`实例的`run`方法,传入用户的查询(`query`),执行实际的计算,并将计算结果返回。 + +在项目中,尽管`server/agent/tools/__init__.py`和`server/agent/tools_select.py`这两个对象的代码和文档未提供详细信息,但可以推断`calculate`函数可能被设计为一个核心的数学计算工具,供项目中的其他部分调用以执行具体的数学计算任务。这种设计使得数学计算功能模块化,便于在不同的上下文中重用和维护。 + +**注意**: +- 确保在调用此函数之前,`model_container.MODEL`已正确加载并初始化,因为这是执行计算的关键。 +- 由于函数使用了`verbose=True`,调用时会产生详细的日志输出,这对于调试和分析计算过程很有帮助,但在生产环境中可能需要根据实际情况调整。 + +**输出示例**: +假设传入的`query`为"2 + 2",函数可能返回一个类似于`"4"`的字符串,表示计算结果。实际返回值将依赖于模型的具体实现和处理能力。 diff --git a/markdown_docs/server/agent/tools/search_internet.md b/markdown_docs/server/agent/tools/search_internet.md new file mode 100644 index 000000000..a4dab1388 --- /dev/null +++ b/markdown_docs/server/agent/tools/search_internet.md @@ -0,0 +1,61 @@ +## FunctionDef search_engine_iter(query) +**search_engine_iter**: 该函数用于通过指定的搜索引擎异步检索查询内容,并生成相关的回答。 + +**参数**: +- `query`: 用户输入的查询内容,类型为字符串。 + +**代码描述**: +`search_engine_iter`函数是一个异步函数,主要用于处理用户的查询请求。它首先调用`search_engine_chat`函数,向指定的搜索引擎(本例中为Bing)发送查询请求,并设置了一系列参数,包括模型名称、温度值、历史记录、返回结果的数量、最大Token数、提示名称以及是否以流式传输的方式返回结果。这些参数的设置旨在优化搜索结果的相关性和质量。 + +在调用`search_engine_chat`后,函数通过异步迭代器`response.body_iterator`遍历响应体。每次迭代返回的数据是一个JSON字符串,包含了搜索引擎返回的答案和相关文档。函数解析这些JSON字符串,提取出答案和文档信息,并将答案内容累加到`contents`变量中。 + +最终,函数返回累加后的`contents`变量,即包含了所有相关答案的字符串。 + +**注意**: +- 该函数是异步的,因此在调用时需要使用`await`关键字或在异步环境中调用。 +- 函数的执行依赖于外部的搜索引擎服务和LLM模型,因此执行时间可能受到网络状况和服务响应时间的影响。 +- 在使用该函数之前,需要确保已经配置了相应的搜索引擎API密钥和LLM模型。 + +**输出示例**: +```json +"根据您的查询,这里是生成的回答。" +``` +该输出示例展示了函数可能返回的答案内容。实际返回的内容将根据查询内容和搜索引擎返回的结果而有所不同。 +## FunctionDef search_internet(query) +**search_internet**: 该函数用于通过异步方式调用搜索引擎,检索用户查询的内容。 + +**参数**: +- `query`: 用户输入的查询内容,类型为字符串。 + +**代码描述**: +`search_internet`函数是一个简洁的接口,用于触发对指定查询内容的互联网搜索。它通过调用`search_engine_iter`函数实现,后者是一个异步函数,负责具体的搜索操作和处理逻辑。在`search_internet`函数中,使用`asyncio.run`方法来运行`search_engine_iter`函数,这允许同步代码中方便地调用异步函数,并等待其结果。 + +`search_engine_iter`函数详细描述了搜索过程,包括向搜索引擎发送请求、处理返回的数据,并最终将累加的答案内容作为字符串返回。这个过程涉及到异步编程的知识,特别是在处理网络请求和响应时的异步迭代。 + +**注意**: +- 由于`search_internet`函数内部使用了`asyncio.run`,它不应该被用在已经运行的异步函数或事件循环中,以避免抛出异常。 +- 函数的执行效率和结果质量依赖于外部搜索引擎的响应速度和准确性,因此在网络状况不佳或搜索引擎服务不稳定时,可能会影响使用体验。 +- 在使用之前,确保相关的搜索引擎API密钥和配置已经正确设置,以保证搜索功能的正常工作。 + +**输出示例**: +假设用户查询的内容为“Python 异步编程”,函数可能返回的字符串示例为: +``` +"Python异步编程是一种编程范式,旨在提高程序的并发性和性能。这里是一些关于Python异步编程的基础知识和实践指南。" +``` +该示例展示了函数可能返回的答案内容,实际返回的内容将根据查询内容和搜索引擎返回的结果而有所不同。 +## ClassDef SearchInternetInput +**SearchInternetInput**: SearchInternetInput类的功能是定义一个用于互联网搜索的输入模型。 + +**属性**: +- location: 用于互联网搜索的查询字符串。 + +**代码描述**: +SearchInternetInput类继承自BaseModel,这意味着它是一个模型类,通常用于处理数据的验证、序列化和反序列化。在这个类中,定义了一个名为`location`的属性,该属性用于存储用户希望进行搜索的查询字符串。通过使用Pydantic库中的`Field`函数,为`location`属性提供了一个描述性文本,即"Query for Internet search",这有助于理解该属性的用途。 + +该类在项目中的作用是作为搜索互联网功能的输入数据模型。它的设计允许开发者在调用搜索互联网相关功能时,能够以结构化的方式提供必要的输入信息,即用户想要搜索的内容。这种方式提高了代码的可读性和易用性,同时也便于后续的数据验证和处理。 + +从项目结构来看,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`两个文件中没有直接提到SearchInternetInput类的使用,但可以推断,SearchInternetInput类可能会被项目中负责处理搜索请求的部分调用。具体来说,开发者可能会在处理搜索请求的函数或方法中,实例化SearchInternetInput类,然后根据用户的输入构造location属性,最后使用这个实例来执行搜索操作。 + +**注意**: +- 在使用SearchInternetInput类时,开发者需要确保提供的`location`值是有效的搜索查询字符串,因为这将直接影响搜索结果的相关性和准确性。 +- 考虑到数据验证的需求,开发者在使用此类时应当熟悉Pydantic库的基本用法,以便充分利用模型验证等功能。 diff --git a/markdown_docs/server/agent/tools/search_knowledgebase_complex.md b/markdown_docs/server/agent/tools/search_knowledgebase_complex.md new file mode 100644 index 000000000..4f603707b --- /dev/null +++ b/markdown_docs/server/agent/tools/search_knowledgebase_complex.md @@ -0,0 +1,202 @@ +## FunctionDef search_knowledge_base_iter(database, query) +**search_knowledge_base_iter**: 该函数用于异步迭代地搜索知识库并获取相关信息。 + +**参数**: +- `database`: 字符串类型,指定要搜索的知识库名称。 +- `query`: 字符串类型,用户的查询字符串。 + +**代码描述**: +`search_knowledge_base_iter` 函数是一个异步函数,它接受两个参数:`database` 和 `query`。这个函数主要通过调用 `knowledge_base_chat` 函数来实现与知识库的交互。在调用 `knowledge_base_chat` 时,会传入相关参数,包括知识库名称、查询字符串、模型名称、温度参数、历史记录、向量搜索的 top_k 值、最大 token 数、prompt 名称、分数阈值以及是否以流的形式输出。这些参数的具体值部分来自于全局变量或函数外部的变量。 + +函数内部通过异步迭代 `response.body_iterator` 来逐个处理返回的数据。每次迭代得到的数据是一个 JSON 字符串,包含了回答和相关文档信息。函数将这些回答累加起来,并在最后返回累加后的字符串。 + +**注意**: +- 该函数是异步的,因此在调用时需要使用 `await` 关键字。 +- 函数内部处理了 JSON 数据,因此需要导入 `json` 模块。 +- 在使用该函数之前,需要确保 `knowledge_base_chat` 函数及其所需的环境和参数已经正确配置和初始化。 + +**输出示例**: +调用 `search_knowledge_base_iter` 函数可能返回的字符串示例: +``` +"这是根据您的查询生成的回答。出处 [1] [文档名称](文档链接) \n\n文档内容\n\n未找到相关文档,该回答为大模型自身能力解答!" +``` +该字符串包含了所有回答的累加结果,如果有相关文档,还会包含文档的链接和内容。如果没有找到相关文档,会有相应的提示信息。 +## FunctionDef search_knowledge_multiple(queries) +**search_knowledge_multiple**: 该函数用于异步地搜索多个知识库并获取相关信息。 + +**参数**: +- `queries`: 一个列表,包含多个元组,每个元组包含一个数据库名称和一个查询字符串。 + +**代码描述**: +`search_knowledge_multiple` 函数是一个异步函数,它接收一个包含多个(数据库名称,查询字符串)元组的列表作为参数。函数内部首先会为列表中的每个查询创建一个异步任务,这些任务是通过调用 `search_knowledge_base_iter` 函数实现的,该函数负责与指定的知识库进行交互并获取查询结果。之后,使用 `asyncio.gather` 函数并行执行这些异步任务,并等待所有任务完成,收集它们的结果。 + +对于每个查询的结果,函数会生成一个包含自定义消息和查询结果的字符串。这个自定义消息包括了知识库的名称,以及一个提示信息,表明这些信息是从哪个知识库查询到的。所有这些生成的字符串会被收集到一个列表中,并作为函数的返回值。 + +**注意**: +- 由于 `search_knowledge_multiple` 是一个异步函数,因此在调用它时需要使用 `await` 关键字。 +- 函数的执行依赖于 `search_knowledge_base_iter` 函数,后者需要正确配置和初始化,包括知识库的访问设置和查询参数。 +- 该函数的设计使得可以同时对多个知识库进行查询,提高了查询效率。 + +**输出示例**: +调用 `search_knowledge_multiple` 函数可能返回的列表示例: +``` +[ + "\n查询到 database1 知识库的相关信息:\n这是根据您的查询生成的回答。出处 [1] [文档名称](文档链接) \n\n文档内容\n\n未找到相关文档,该回答为大模型自身能力解答!", + "\n查询到 database2 知识库的相关信息:\n这是根据您的查询生成的回答。出处 [1] [文档名称](文档链接) \n\n文档内容\n\n未找到相关文档,该回答为大模型自身能力解答!" +] +``` +该输出示例展示了当对两个不同的知识库进行查询时,每个查询结果前都会添加一个指明知识库来源的自定义消息,随后是查询到的具体信息。 +## FunctionDef search_knowledge(queries) +Doc is waiting to be generated... +## ClassDef LLMKnowledgeChain +Doc is waiting to be generated... +### ClassDef Config +**Config**: Config 类的功能是定义一个严格的配置模式,用于pydantic对象。 + +**属性**: +- `extra`: 控制额外字段的处理方式。 +- `arbitrary_types_allowed`: 允许使用任意类型的字段。 + +**代码描述**: +Config 类是一个配置类,专门用于在使用pydantic库时定义模型的配置。在这个类中,定义了两个重要的配置项: + +1. `extra = Extra.forbid`:这个配置项用于指定当传入的数据包含模型未声明的字段时应如何处理。通过设置为`Extra.forbid`,表示禁止传入额外的字段,如果尝试传入未在模型中声明的字段,将会引发错误。这有助于确保数据的严格匹配和类型安全,避免因数据错误或不匹配而导致的问题。 + +2. `arbitrary_types_allowed = True`:这个配置项允许在模型中使用任意类型的字段。默认情况下,pydantic要求所有字段的类型都是预先定义好的,但开启这个选项后,可以使用任何类型的字段,包括自定义类型。这提供了更大的灵活性,允许开发者根据需要在模型中使用各种复杂或自定义的数据类型。 + +**注意**: +- 使用`extra = Extra.forbid`时,需要确保所有传入的数据严格匹配模型定义的字段,否则会引发错误。这要求开发者在设计模型和处理数据时需要更加小心和精确。 +- 开启`arbitrary_types_allowed = True`可以提高模型的灵活性,但同时也需要开发者确保自定义类型的正确使用和处理,以避免类型错误或其他潜在问题。 +*** +### FunctionDef raise_deprecation(cls, values) +**raise_deprecation**: 此函数的功能是在使用已弃用方法实例化LLMKnowledgeChain时发出警告,并在适当的情况下自动转换为推荐的实例化方法。 + +**参数**: +- `cls`: 类方法的第一个参数,表示类本身。 +- `values`: 一个字典,包含实例化LLMKnowledgeChain时传递的参数。 + +**代码描述**: +`raise_deprecation` 函数首先检查传入的 `values` 字典中是否包含键 `"llm"`。如果存在,这意味着尝试使用已弃用的方法直接通过 `llm` 参数实例化 `LLMKnowledgeChain`。此时,函数会发出一个警告,提示开发者这种实例化方法已弃用,并建议使用 `llm_chain` 参数或 `from_llm` 类方法作为替代。 + +如果在 `values` 中同时不存在 `"llm_chain"` 键,且 `"llm"` 键对应的值不为 `None`,函数会进一步处理。它会尝试从 `values` 中获取 `"prompt"` 键的值,如果不存在,则使用全局变量 `PROMPT` 的值。然后,利用 `llm` 和 `prompt` 的值创建一个 `LLMChain` 实例,并将这个实例赋值给 `values` 字典中的 `"llm_chain"` 键。 + +最后,函数返回更新后的 `values` 字典。 + +**注意**: +- 使用此函数时,应确保传入的 `values` 字典中的 `"llm"` 键(如果存在)对应的值是有效的,因为这将影响到 `LLMChain` 实例的创建。 +- 应避免直接使用已弃用的实例化方法,以免在未来的版本中遇到兼容性问题。 + +**输出示例**: +假设传入的 `values` 字典为 `{"llm": some_llm_object}`,且 `PROMPT` 为默认提示文本,函数可能返回如下的字典: +```python +{ + "llm": some_llm_object, + "llm_chain": LLMChain(llm=some_llm_object, prompt=默认提示文本) +} +``` +这表明,即使最初尝试使用已弃用的方法实例化,函数也会自动调整,确保以推荐的方式实例化 `LLMKnowledgeChain`。 +*** +### FunctionDef input_keys(self) +**函数功能**: `input_keys` 的功能是返回期望的输入键列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `input_keys` 函数是 `LLMKnowledgeChain` 类的一个方法,它的主要作用是返回一个包含单个元素的列表,这个元素是该实例的 `input_key` 属性。这个方法被标记为私有,意味着它仅在 `LLMKnowledgeChain` 类的内部使用,不建议在类的外部直接调用这个方法。这种设计通常用于封装和隐藏类的内部实现细节,确保类的公共接口的简洁性和稳定性。 + +**注意**: 由于 `input_keys` 方法被标记为私有(通过 `:meta private:` 注释指示),在使用 `LLMKnowledgeChain` 类时,应避免直接调用此方法。相反,应通过类提供的其他公共方法来间接访问或修改 `input_key` 的值。 + +**输出示例**: +```python +["example_input_key"] +``` +在这个示例中,假设 `LLMKnowledgeChain` 实例的 `input_key` 属性值为 `"example_input_key"`,那么调用 `input_keys` 方法将返回一个包含这个字符串的列表。这表明该实例期望的输入键仅有一个,即 `"example_input_key"`。 +*** +### FunctionDef output_keys(self) +**output_keys**: 此函数的功能是返回一个包含输出键的列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `output_keys` 函数是 `LLMKnowledgeChain` 类的一个成员方法,它的作用是返回一个列表,这个列表中包含了一个元素,即 `self.output_key`。这里的 `self.output_key` 是 `LLMKnowledgeChain` 实例的一个属性,代表了某种输出的关键字。此函数被标记为私有方法(通过 `:meta private:` 注释),这意味着它主要供类内部其他方法调用,而不是设计给外部使用。 + +**注意**: 由于此函数被标记为私有,因此在使用 `LLMKnowledgeChain` 类时,应避免直接调用 `output_keys` 方法,而是通过类提供的其他公共接口来间接获取所需的输出键信息。 + +**输出示例**: +```python +['desired_output_key'] +``` +在这个示例中,`'desired_output_key'` 是 `self.output_key` 的值,表示此实例期望得到的输出键。返回值是一个列表,即使只有一个输出键,也会以列表的形式返回,这样做可以保持接口的一致性和扩展性。 +*** +### FunctionDef _evaluate_expression(self, queries) +Doc is waiting to be generated... +*** +### FunctionDef _process_llm_result(self, llm_output, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _aprocess_llm_result(self, llm_output, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _call(self, inputs, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _acall(self, inputs, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _chain_type(self) +**函数名**: _chain_type + +**函数功能**: 返回链类型的字符串表示。 + +**参数**: 此函数没有参数。 + +**代码描述**: `_chain_type`函数是`LLMKnowledgeChain`类的一个私有方法,用于返回表示链类型的字符串。在这个上下文中,链类型被固定定义为`"llm_knowledge_chain"`,这意味着该函数返回的字符串用于标识或表示一个基于长期记忆模型(Long-term Language Model,简称LLM)的知识链。这个标识符可以被用来在处理不同类型的知识链时,区分出是基于LLM的知识链。由于这是一个私有方法,它主要被类内部的其他方法调用,而不是被类的外部直接调用。 + +**注意**: 由于`_chain_type`是一个私有方法,它应该只在`LLMKnowledgeChain`类的内部被使用。尝试从类的外部直接调用这个方法可能会导致访问控制错误或不被期待的行为。 + +**输出示例**: +```python +"llm_knowledge_chain" +``` +此输出示例展示了调用`_chain_type`方法时会返回的字符串。这个字符串可以被视为一个标识符,用于在可能存在多种类型的知识链时,识别出特定的基于LLM的知识链。 +*** +### FunctionDef from_llm(cls, llm, prompt) +**from_llm**: 此函数的功能是从语言模型创建一个知识链对象。 + +**参数**: +- `cls`: 类方法的第一个参数,指代当前类,用于创建类的实例。 +- `llm`: BaseLanguageModel的实例,代表要使用的语言模型。 +- `prompt`: BasePromptTemplate的实例,默认为PROMPT,用于生成查询时的提示模板。 +- `**kwargs`: 接受任意数量的关键字参数,这些参数将传递给LLMKnowledgeChain的构造函数。 + +**代码描述**: +`from_llm`是一个类方法,它接受一个语言模型实例和可选的提示模板,以及其他任意关键字参数。此方法首先创建一个`LLMChain`实例,该实例封装了语言模型和提示模板的细节。然后,它使用这个`LLMChain`实例和任何其他提供的关键字参数来创建并返回一个`LLMKnowledgeChain`实例。这个过程允许将语言模型和相关配置封装为一个可用于执行复杂知识搜索任务的链式对象。 + +在项目中,`from_llm`方法被`search_knowledgebase_complex`函数调用。在这个调用中,它使用从模型容器中获取的模型实例和一个`verbose`关键字参数来创建一个`LLMKnowledgeChain`实例。然后,这个实例被用来对一个查询执行运行操作,以获取答案。这展示了`from_llm`方法如何允许灵活地构建知识链,以便在复杂的知识搜索任务中使用。 + +**注意**: +- 确保传递给`from_llm`的`llm`参数是一个有效的`BaseLanguageModel`实例,因为它是执行知识搜索所必需的。 +- `prompt`参数虽然是可选的,但正确设置它可以显著影响知识搜索的效果,因此建议根据具体的应用场景进行适当配置。 +- 通过`**kwargs`传递的任何额外参数应该与`LLMKnowledgeChain`的构造函数兼容,以确保它们可以正确地被使用。 + +**输出示例**: +假设`from_llm`方法被正确调用,它可能返回如下的`LLMKnowledgeChain`实例: +``` +LLMKnowledgeChain(llm_chain=LLMChain(llm=, prompt=), verbose=True) +``` +这个实例随后可以用于执行具体的知识搜索任务。 +*** +## FunctionDef search_knowledgebase_complex(query) +Doc is waiting to be generated... +## ClassDef KnowledgeSearchInput +**KnowledgeSearchInput**: KnowledgeSearchInput类的功能是定义一个用于搜索知识库的输入模型。 + +**属性**: +- location: 用于搜索的查询字符串。 + +**代码描述**: +KnowledgeSearchInput类继承自BaseModel,这表明它是一个模型类,用于定义数据结构和类型。在这个类中,定义了一个名为`location`的属性,该属性被标记为一个字符串类型。通过使用`Field`函数,为`location`属性提供了额外的描述信息,即“要被搜索的查询”。这样的设计使得KnowledgeSearchInput类不仅仅是一个数据容器,还通过属性描述增强了代码的可读性和易用性。 + +在项目中,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`这两个对象中没有直接提到KnowledgeSearchInput类的使用,但可以推断,KnowledgeSearchInput类作为一个数据模型,可能会被项目中负责搜索知识库功能的部分调用。具体来说,它可能被用于封装用户输入的搜索查询,然后这个封装好的查询被传递给执行搜索的函数或方法,以便根据`location`属性中的值来检索相关的知识库条目。 + +**注意**: +- 在使用KnowledgeSearchInput类时,需要确保传递给`location`属性的值是一个合法的字符串,因为这将直接影响到搜索的结果。 +- 由于KnowledgeSearchInput类继承自BaseModel,因此可以利用Pydantic库提供的数据验证功能来确保输入数据的有效性。这意味着在实例化KnowledgeSearchInput对象时,如果传递的数据类型不符合预期,将会抛出错误,从而帮助开发者及早发现并修正问题。 diff --git a/markdown_docs/server/agent/tools/search_knowledgebase_once.md b/markdown_docs/server/agent/tools/search_knowledgebase_once.md new file mode 100644 index 000000000..e658b2a6f --- /dev/null +++ b/markdown_docs/server/agent/tools/search_knowledgebase_once.md @@ -0,0 +1,218 @@ +## FunctionDef search_knowledge_base_iter(database, query) +**search_knowledge_base_iter**: 该函数用于异步迭代地搜索知识库并获取相关回答。 + +**参数**: +- `database`: 知识库的名称,类型为字符串。 +- `query`: 用户的查询语句,类型为字符串。 + +**代码描述**: +`search_knowledge_base_iter` 函数是一个异步函数,它接收两个参数:`database` 和 `query`。这个函数首先调用 `knowledge_base_chat` 函数,向指定的知识库发送查询请求,并设置了一系列参数,如模型名称、温度值、历史记录、向量搜索的 top_k 值、最大 token 数、提示名称、分数阈值以及是否以流的形式输出。这些参数的设置是为了精确控制知识库搜索和回答生成的行为。 + +函数内部,通过异步迭代 `response.body_iterator`,处理每一块返回的数据。每一块数据被假定为一个 JSON 字符串,其中包含了回答和相关文档的信息。函数解析这些 JSON 数据,提取出回答内容,并将它们拼接起来。同时,也会处理相关文档的信息,但在当前代码实现中,文档信息 (`docs`) 被提取出来之后并没有被进一步使用。 + +**注意**: +- 在使用此函数时,需要确保 `database` 参数指定的知识库存在,否则可能无法正常获取回答。 +- 由于函数内部涉及异步操作,调用此函数时需要使用 `await` 关键字。 +- 函数返回的是拼接后的回答内容,如果需要获取更详细的信息(如相关文档信息),可能需要对函数进行适当的修改。 + +**输出示例**: +调用 `search_knowledge_base_iter` 函数可能返回的示例: +```json +"这是根据您的查询生成的回答。" +``` +这个输出示例仅展示了回答内容的一部分。实际返回的回答内容将根据查询语句和知识库的内容而有所不同。 +## ClassDef LLMKnowledgeChain +Doc is waiting to be generated... +### ClassDef Config +**Config**: Config 类的功能是定义一个严格的配置对象模型。 + +**属性**: +- `extra`: 控制额外字段的处理方式。 +- `arbitrary_types_allowed`: 允许使用任意类型的字段。 + +**代码描述**: +Config 类是一个配置对象,它使用 Pydantic 库来定义。Pydantic 是一个数据验证和设置管理的库,它允许开发者以标准的Python类型提示方式来定义数据结构,同时提供强大的数据验证功能。 + +在这个 Config 类中,有两个关键的配置项被设置: + +1. `extra = Extra.forbid`:这个设置指定了如果传入的数据包含了模型未声明的字段,则会抛出错误。这是一种严格的数据验证方式,确保了数据对象的纯净性和一致性,防止了意外的数据被接受进来。 + +2. `arbitrary_types_allowed = True`:这个设置允许模型字段使用任意类型。默认情况下,Pydantic 要求所有的字段类型都是标准的Python类型或者是 Pydantic 定义的类型。通过启用这个选项,开发者可以使用更加灵活的类型定义,比如自定义类或者其他复杂的数据结构。 + +**注意**: +- 使用 Config 类时,需要注意数据的严格性和类型的灵活性之间的平衡。虽然允许任意类型可以提供更大的灵活性,但也可能增加数据处理的复杂性。 +- 在实际应用中,应当根据具体需求来决定是否启用 `arbitrary_types_allowed` 选项。如果项目中使用了大量自定义类型,那么启用这个选项可能是有益的。反之,如果项目主要使用标准类型,可能不需要启用这个选项。 +- `extra = Extra.forbid` 的设置使得 Config 类非常适合用于需要高数据一致性和安全性的场景。开发者应当在设计API或数据交互接口时考虑到这一点。 +*** +### FunctionDef raise_deprecation(cls, values) +**raise_deprecation**: 此函数的功能是在使用已弃用的方式实例化LLMKnowledgeChain时发出警告,并在适当的情况下自动转换为推荐的实例化方式。 + +**参数**: +- `cls`: 类方法的第一个参数,指代当前类。 +- `values`: 一个字典,包含实例化LLMKnowledgeChain时传入的参数。 + +**代码描述**: +此函数检查`values`字典中是否包含键`llm`。如果存在,首先会发出一个警告,提示用户直接使用`llm`参数实例化LLMKnowledgeChain已被弃用,并建议使用`llm_chain`参数或`from_llm`类方法进行实例化。接着,如果`values`中不存在`llm_chain`键且`llm`键对应的值不为`None`,函数会从`values`中获取`prompt`键的值(如果不存在,则使用默认提示`PROMPT`),并使用`llm`和`prompt`的值创建一个`LLMChain`实例,将其赋值给`values`字典中的`llm_chain`键。最后,函数返回更新后的`values`字典。 + +**注意**: +- 使用此函数时,应确保传入的`values`字典中的`llm`键(如果存在)对应的值是预期的,因为该函数会基于该值创建`LLMChain`实例。 +- 调用此函数后,应检查返回的`values`字典,以确认是否已按照推荐方式更新了实例化参数。 + +**输出示例**: +假设传入的`values`字典为`{"llm": some_llm_object, "prompt": "Example prompt"}`,且`PROMPT`为默认提示,则函数可能返回的`values`字典为: +``` +{ + "llm": some_llm_object, + "prompt": "Example prompt", + "llm_chain": LLMChain(llm=some_llm_object, prompt="Example prompt") +} +``` +在这个示例中,`llm_chain`键被添加到字典中,其值为一个使用`some_llm_object`和`"Example prompt"`实例化的`LLMChain`对象。 +*** +### FunctionDef input_keys(self) +**input_keys**: 此函数的功能是返回一个包含单个输入键的列表。 + +**参数**: 此函数没有参数。 + +**函数描述**: `input_keys` 函数是一个私有方法,设计用于内部使用,不建议在类的外部直接调用。它的主要作用是提供一个包含单个元素的列表,该元素是此实例的 `input_key` 属性值。这个方法的存在可能是为了与其他需要返回多个键的方法保持一致的接口,或者为了将来的扩展保留空间。 + +**注意**: 由于此方法被标记为私有(通过 `:meta private:` 注释),它主要用于类的内部逻辑,而不是作为类的公共接口的一部分。因此,在类的外部调用此方法时应当谨慎,因为它的行为或签名在未来的版本中可能会改变,而不会有任何向后兼容性的保证。 + +**输出示例**: +```python +['example_input_key'] +``` +在这个示例中,假设实例的 `input_key` 属性被设置为 `'example_input_key'`,那么调用 `input_keys` 方法将会返回一个只包含字符串 `'example_input_key'` 的列表。 +*** +### FunctionDef output_keys(self) +**output_keys**: 此函数的功能是返回一个包含输出键的列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `output_keys`函数是`LLMKnowledgeChain`类的一个方法,它被标记为私有方法,意味着它主要供类内部使用,而不是设计给外部调用。此方法的目的是提供一个包含单个输出键的列表。这里的`self.output_key`是`LLMKnowledgeChain`类的一个属性,此方法通过将该属性包装在列表中返回,提供了对输出键的访问。这种设计允许将来的扩展性,例如,如果需要返回多个输出键,可以在不改变方法签名的情况下进行调整。 + +**注意**: 由于此方法被标记为私有(通过`:meta private:`标记),它主要用于类的内部逻辑,不建议在类的外部直接调用此方法。在使用时应注意,尽管它目前返回的是单个输出键的列表,但设计上允许返回多个键,这意味着在处理返回值时应考虑到可能的未来变化。 + +**输出示例**: +```python +['output_key_value'] +``` +在这个示例中,`output_key_value`代表`self.output_key`属性的值。实际的值将取决于`LLMKnowledgeChain`实例在其生命周期中对`self.output_key`属性的赋值。 +*** +### FunctionDef _evaluate_expression(self, dataset, query) +**_evaluate_expression**: 该函数的功能是基于给定的数据集和查询语句,异步搜索知识库并返回搜索结果。 + +**参数**: +- `dataset`: 数据集名称,类型为字符串。它指定了要搜索的知识库。 +- `query`: 查询语句,类型为字符串。它是用户希望在知识库中搜索的问题或关键词。 + +**代码描述**: +`_evaluate_expression` 函数首先尝试调用 `search_knowledge_base_iter` 函数,以异步方式搜索知识库。该函数接收两个参数:`dataset` 和 `query`,分别代表知识库的名称和用户的查询语句。如果搜索成功,`search_knowledge_base_iter` 函数将返回搜索到的结果;如果在搜索过程中遇到任何异常(例如,知识库不存在或查询语句有误),则会捕获这些异常,并将输出设置为“输入的信息有误或不存在知识库”。最终,函数返回搜索结果或错误信息。 + +**注意**: +- 在调用此函数之前,需要确保提供的 `dataset`(知识库名称)是存在的,否则可能会导致搜索失败。 +- 由于 `search_knowledge_base_iter` 是一个异步函数,`_evaluate_expression` 函数内部使用了 `asyncio.run` 来运行它。这意味着 `_evaluate_expression` 函数本身是同步的,但它内部执行了异步操作。 + +**输出示例**: +调用 `_evaluate_expression` 函数可能返回的示例: +``` +"这是根据您的查询生成的回答。" +``` +这个示例展示了一个简单的回答内容。实际返回的内容将根据查询语句和知识库的内容而有所不同。如果遇到错误,可能会返回: +``` +"输入的信息有误或不存在知识库" +``` +这表示提供的信息有误,或者指定的知识库不存在。 +*** +### FunctionDef _process_llm_result(self, llm_output, llm_input, run_manager) +**_process_llm_result**: 此函数的功能是处理语言模型的输出结果,并返回格式化的答案。 + +**参数**: +- `llm_output`: 字符串类型,表示语言模型的原始输出。 +- `llm_input`: 字符串类型,表示传递给语言模型的原始输入。 +- `run_manager`: `CallbackManagerForChainRun`类型,用于管理回调函数的执行。 + +**代码描述**: +`_process_llm_result` 函数首先通过 `run_manager` 的 `on_text` 方法以绿色文本输出语言模型的原始输出,并设置是否详细输出。接着,函数尝试通过正则表达式匹配输出中的文本块。如果匹配成功,将提取文本块内容,并调用 `_evaluate_expression` 函数处理这部分内容和原始输入,生成最终的答案。如果原始输出以 "Answer:" 开头,或包含 "Answer:",则直接将其作为答案。如果以上条件都不满足,则返回一个错误信息,指出输入格式不正确。最后,函数返回一个字典,包含处理后的答案或错误信息。 + +**注意**: +- `_process_llm_result` 函数依赖于 `_evaluate_expression` 函数来处理提取的文本块内容。因此,确保 `_evaluate_expression` 函数能正确执行是使用此函数的前提。 +- 此函数处理的输出格式特定于语言模型的输出结构,因此在不同的模型输出中可能需要调整正则表达式或处理逻辑。 +- 函数返回的字典中包含的键由 `self.output_key` 决定,这意味着在使用此函数之前,需要确保 `self.output_key` 已经被正确设置。 + +**输出示例**: +调用 `_process_llm_result` 函数可能返回的示例之一: +``` +{"output_key": "Answer: 这是根据您的查询生成的回答。"} +``` +如果输入的格式不正确,可能会返回: +``` +{"output_key": "输入的格式不对: 原始语言模型输出内容"} +``` +这个示例展示了函数如何根据不同的情况返回不同的处理结果。实际返回的内容将根据语言模型的输出和输入的处理逻辑而有所不同。 +*** +### FunctionDef _aprocess_llm_result(self, llm_output, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _call(self, inputs, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _acall(self, inputs, run_manager) +Doc is waiting to be generated... +*** +### FunctionDef _chain_type(self) +**函数名称**: _chain_type + +**函数功能**: 返回链类型的字符串表示。 + +**参数**: 此函数没有参数。 + +**代码描述**: `_chain_type`函数是`LLMKnowledgeChain`类的一个私有方法,用于返回表示链类型的字符串。在这个上下文中,链类型被固定定义为`"llm_knowledge_chain"`,这意味着该函数返回的字符串用于标识或表示一个基于长期记忆模型(Long-term Language Model,LLM)的知识链。这种类型的知识链可能涉及到使用大型语言模型来处理和链接知识库中的信息。由于这是一个私有方法,它主要用于`LLMKnowledgeChain`类内部,可能用于日志记录、调试或者在类的其他方法中区分处理不同类型的知识链。 + +**注意**: 由于`_chain_type`是一个私有方法,它不应该直接从类的实例外部调用。它的设计初衷是为了类内部使用,以提供一种一致的方式来引用链类型。如果需要在类外部获取链类型信息,应该通过类提供的公共接口或方法来实现。 + +**输出示例**: 调用`_chain_type`方法将返回字符串`"llm_knowledge_chain"`。 +*** +### FunctionDef from_llm(cls, llm, prompt) +**from_llm**: 此函数的功能是从语言模型创建一个知识链对象。 + +**参数**: +- `cls`: 类方法的传统参数,表示要实例化的类本身。 +- `llm`: `BaseLanguageModel`类型,代表要使用的语言模型。 +- `prompt`: `BasePromptTemplate`类型,默认为`PROMPT`,代表用于语言模型的提示模板。 +- `**kwargs`: 接受任意额外的关键字参数,这些参数将传递给`LLMKnowledgeChain`的构造函数。 + +**代码描述**: +`from_llm`函数是`LLMKnowledgeChain`类的一个类方法,它接受一个语言模型实例`llm`和一个可选的提示模板`prompt`作为输入。此函数首先使用提供的语言模型和提示模板创建一个`LLMChain`实例。然后,它使用这个`LLMChain`实例和任何其他提供的关键字参数来创建并返回一个`LLMKnowledgeChain`实例。这个过程允许`LLMKnowledgeChain`对象直接从一个语言模型实例化,简化了使用语言模型进行知识搜索和处理的流程。 + +在项目中,`from_llm`函数被`search_knowledgebase_once`函数调用。在这个调用中,`model`(一个语言模型实例)和`PROMPT`(一个提示模板)被传递给`from_llm`,同时还传递了`verbose=True`作为关键字参数。这表明在创建`LLMKnowledgeChain`实例时,会启用详细模式。然后,`search_knowledgebase_once`函数使用返回的`LLMKnowledgeChain`实例来执行对给定查询的搜索,展示了如何在实际应用中利用`from_llm`方法来处理和搜索知识。 + +**注意**: +- 确保传递给`from_llm`的`llm`参数是一个有效的`BaseLanguageModel`实例,以保证知识链的正确构建和操作。 +- 在使用`**kwargs`传递额外参数时,应确保这些参数是`LLMKnowledgeChain`构造函数所支持的,以避免运行时错误。 + +**输出示例**: +由于`from_llm`返回的是一个`LLMKnowledgeChain`实例,因此输出示例将取决于`LLMKnowledgeChain`类的具体实现和初始化时传递的参数。假设`LLMKnowledgeChain`有一个方法`run`,可以接受一个查询并返回相关的答案,一个可能的使用示例可能如下: +```python +llm_knowledge_chain = LLMKnowledgeChain.from_llm(model, prompt=PROMPT, verbose=True) +answer = llm_knowledge_chain.run("这是一个查询示例") +print(answer) # 输出将展示查询的答案 +``` +*** +## FunctionDef search_knowledgebase_once(query) +Doc is waiting to be generated... +## ClassDef KnowledgeSearchInput +**KnowledgeSearchInput**: KnowledgeSearchInput类的功能是定义一个搜索知识库的输入模型。 + +**属性**: +- location: 表示要搜索的查询字符串。 + +**代码描述**: +KnowledgeSearchInput类继承自BaseModel,这表明它是一个模型类,用于定义数据结构。在这个类中,定义了一个名为`location`的属性,该属性用于存储要在知识库中搜索的查询字符串。通过使用`Field`函数,为`location`属性提供了描述信息,即"The query to be searched",这有助于理解该属性的用途。 + +此类在项目中的作用是作为搜索知识库操作的输入数据模型。它通过定义必要的输入字段(在本例中为查询位置),使得其他部分的代码可以构建基于这些输入的搜索请求。尽管在提供的信息中没有直接的调用示例,但可以推断,该类的实例将被创建并填充相应的搜索查询,然后传递给执行搜索操作的函数或方法。 + +**注意**: +- 在使用KnowledgeSearchInput类时,需要确保`location`属性被正确赋值,因为它是执行搜索操作所必需的。 +- 由于这个类继承自BaseModel,可以利用Pydantic库提供的数据验证功能来确保输入数据的有效性。例如,如果有特定格式或值范围的要求,可以通过修改Field函数的参数来实现。 +- 在实际应用中,可能需要根据知识库的具体结构和搜索需求,对KnowledgeSearchInput类进行扩展,添加更多的属性和验证逻辑。 diff --git a/markdown_docs/server/agent/tools/search_knowledgebase_simple.md b/markdown_docs/server/agent/tools/search_knowledgebase_simple.md new file mode 100644 index 000000000..9e7860eb4 --- /dev/null +++ b/markdown_docs/server/agent/tools/search_knowledgebase_simple.md @@ -0,0 +1,45 @@ +## FunctionDef search_knowledge_base_iter(database, query) +**search_knowledge_base_iter**: 该函数用于异步迭代地搜索知识库并获取回答。 + +**参数**: +- `database`: 知识库的名称,类型为字符串。 +- `query`: 用户的查询内容,类型为字符串。 + +**代码描述**: +`search_knowledge_base_iter` 函数是一个异步函数,它接受两个参数:`database` 和 `query`。这个函数首先调用 `knowledge_base_chat` 函数,传入相应的参数,包括知识库名称、查询内容、模型名称、温度参数、历史记录、向量搜索的 top_k 值、最大 token 数量、prompt 名称、分数阈值以及是否流式输出的标志。`knowledge_base_chat` 函数负责处理用户的查询请求,并与知识库进行交互,返回一个响应对象。 + +函数内部通过异步迭代 `response.body_iterator` 来处理响应体中的数据。每次迭代得到的 `data` 是一个 JSON 字符串,表示一部分的查询结果。函数使用 `json.loads` 方法将 JSON 字符串解析为字典对象,然后从中提取出答案和相关文档信息。最终,函数返回最后一次迭代得到的答案内容。 + +**注意**: +- 由于 `search_knowledge_base_iter` 是一个异步函数,因此在调用时需要使用 `await` 关键字。 +- 函数返回的是最后一次迭代得到的答案内容,如果需要处理每一次迭代得到的数据,需要在迭代过程中添加相应的处理逻辑。 +- 确保传入的知识库名称在系统中已经存在,否则可能无法正确处理查询请求。 + +**输出示例**: +调用 `search_knowledge_base_iter` 函数可能返回的示例: +```json +"这是根据您的查询生成的回答。" +``` +此输出示例仅表示函数可能返回的答案内容的格式,实际返回的内容将根据查询内容和知识库中的数据而有所不同。 +## FunctionDef search_knowledgebase_simple(query) +**search_knowledgebase_simple**: 此函数用于简化地搜索知识库并获取回答。 + +**参数**: +- `query`: 用户的查询内容,类型为字符串。 + +**代码描述**: +`search_knowledgebase_simple` 函数是一个简化的接口,用于对知识库进行搜索。它接受一个参数 `query`,即用户的查询内容。函数内部通过调用 `search_knowledge_base_iter` 函数来实现对知识库的搜索。`search_knowledge_base_iter` 是一个异步函数,负责异步迭代地搜索知识库并获取回答。`search_knowledgebase_simple` 函数通过使用 `asyncio.run` 方法来运行异步的 `search_knowledge_base_iter` 函数,从而实现同步调用的效果。 + +由于 `search_knowledge_base_iter` 函数需要数据库名称和查询内容作为参数,但在 `search_knowledgebase_simple` 函数中只提供了查询内容 `query`,这意味着在 `search_knowledge_base_iter` 函数的实现中,数据库名称可能是预设的或通过其他方式获取。 + +**注意**: +- `search_knowledgebase_simple` 函数提供了一个简化的接口,使得开发者可以不必直接处理异步编程的复杂性,而是通过一个简单的同步函数调用来搜索知识库。 +- 由于内部调用了异步函数 `search_knowledge_base_iter`,确保在使用此函数时,相关的异步环境和配置已正确设置。 +- 考虑到 `search_knowledge_base_iter` 函数的异步特性和可能的迭代处理,调用 `search_knowledgebase_simple` 函数时应注意可能的延迟或异步执行的影响。 + +**输出示例**: +调用 `search_knowledgebase_simple` 函数可能返回的示例: +``` +"这是根据您的查询生成的回答。" +``` +此输出示例表示函数可能返回的答案内容的格式,实际返回的内容将根据查询内容和知识库中的数据而有所不同。 diff --git a/markdown_docs/server/agent/tools/search_youtube.md b/markdown_docs/server/agent/tools/search_youtube.md new file mode 100644 index 000000000..8f031d4f7 --- /dev/null +++ b/markdown_docs/server/agent/tools/search_youtube.md @@ -0,0 +1,39 @@ +## FunctionDef search_youtube(query) +**search_youtube**: 此函数的功能是根据提供的查询字符串搜索YouTube视频。 + +**参数**: +- query: 字符串类型,表示要在YouTube上搜索的查询字符串。 + +**代码描述**: +`search_youtube`函数接受一个名为`query`的参数,这个参数是一个字符串,代表用户希望在YouTube上进行搜索的关键词或短语。函数内部首先创建了一个`YouTubeSearchTool`的实例,命名为`tool`。然后,它调用了`tool`的`run`方法,将`query`作为输入参数传递给这个方法。最终,函数返回`run`方法的执行结果。 + +此函数是项目中用于与YouTube API交互的一部分,特别是在`server/agent/tools`路径下。它被设计为一个轻量级的接口,允许其他项目部分,如`server/agent/tools_select.py`,通过简单地调用此函数并传递相应的查询字符串,来实现YouTube搜索功能的集成。这种设计使得在不同的项目部分之间共享功能变得简单,同时也保持了代码的模块化和可维护性。 + +**注意**: +- 确保在调用此函数之前,`YouTubeSearchTool`类已经正确实现,并且其`run`方法能够接受一个字符串类型的输入参数并返回搜索结果。 +- 此函数的性能和返回结果直接依赖于`YouTubeSearchTool`类的实现细节以及YouTube API的响应。 + +**输出示例**: +假设`YouTubeSearchTool`的`run`方法返回的是一个包含搜索结果视频标题和URL的列表,那么`search_youtube`函数的一个可能的返回值示例为: +```python +[ + {"title": "如何使用Python搜索YouTube", "url": "https://www.youtube.com/watch?v=example1"}, + {"title": "Python YouTube API教程", "url": "https://www.youtube.com/watch?v=example2"} +] +``` +这个返回值展示了一个包含两个搜索结果的列表,每个结果都是一个字典,包含视频的标题和URL。 +## ClassDef YoutubeInput +**YoutubeInput**: YoutubeInput类的功能是定义用于YouTube视频搜索的输入参数模型。 + +**属性**: +- location: 用于视频搜索的查询字符串。 + +**代码描述**: +YoutubeInput类继承自BaseModel,这表明它是一个模型类,用于定义数据结构。在这个类中,定义了一个名为`location`的属性,该属性用于存储用户进行YouTube视频搜索时输入的查询字符串。通过使用`Field`函数,为`location`属性提供了一个描述,即"Query for Videos search",这有助于理解该属性的用途。 + +在项目中,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`两个文件中并没有直接提到`YoutubeInput`类的使用,但可以推断,`YoutubeInput`类作为一个数据模型,可能会在处理YouTube视频搜索请求的过程中被用到。具体来说,它可能被用于解析和验证用户的搜索请求参数,确保传递给YouTube API的查询字符串是有效和格式正确的。 + +**注意**: +- 在使用`YoutubeInput`类时,需要确保传递给`location`属性的值是一个有效的字符串,因为这将直接影响到YouTube视频搜索的结果。 +- 由于`YoutubeInput`类继承自`BaseModel`,可以利用Pydantic库提供的数据验证和序列化功能,以简化数据处理流程。 +- 虽然当前文档中没有提到`YoutubeInput`类在项目中的具体调用情况,开发者在实际使用时应考虑如何将此类集成到视频搜索功能中,以及如何处理可能出现的数据验证错误。 diff --git a/markdown_docs/server/agent/tools/shell.md b/markdown_docs/server/agent/tools/shell.md new file mode 100644 index 000000000..c15fc3f53 --- /dev/null +++ b/markdown_docs/server/agent/tools/shell.md @@ -0,0 +1,34 @@ +## FunctionDef shell(query) +**shell**: shell函数的功能是执行一个shell查询并返回结果。 + +**参数**: +- query: 字符串类型,表示要执行的shell查询命令。 + +**代码描述**: +该shell函数定义在`server/agent/tools/shell.py`文件中,是项目中用于执行shell命令的核心函数。函数接收一个名为`query`的字符串参数,该参数是需要执行的shell命令。函数内部首先创建了一个`ShellTool`类的实例`tool`,然后调用这个实例的`run`方法执行传入的`query`命令。最终,函数返回`run`方法的执行结果。 + +在项目的结构中,虽然`server/agent/tools/__init__.py`和`server/agent/tools_select.py`这两个文件中没有直接的代码示例或文档说明如何调用`shell`函数,但可以推断,`shell`函数作为工具模块中的一部分,可能会被项目中的其他部分调用以执行特定的shell命令。这种设计使得执行shell命令的逻辑被封装在一个单独的函数中,便于维护和重用。 + +**注意**: +- 在使用`shell`函数时,需要确保传入的`query`命令是安全的,避免执行恶意代码。 +- 该函数的执行结果取决于`ShellTool`类的`run`方法如何实现,因此需要了解`ShellTool`的具体实现细节。 + +**输出示例**: +假设`ShellTool`的`run`方法简单地返回执行命令的输出,如果调用`shell("echo Hello World")`,那么可能的返回值为: +``` +Hello World +``` +## ClassDef ShellInput +**ShellInput**: ShellInput类的功能是定义一个用于封装Shell命令的数据模型。 + +**属性**: +- query: 一个字符串类型的属性,用于存储可以在Linux命令行中执行的Shell命令。该属性通过Field方法定义,其中包含一个描述信息,说明这是一个可执行的Shell命令。 + +**代码描述**: +ShellInput类继承自BaseModel,这表明它是一个基于Pydantic库的模型,用于数据验证和管理。在这个类中,定义了一个名为`query`的属性,这个属性必须是一个字符串。通过使用Field方法,为`query`属性提供了一个描述,即“一个能在Linux命令行运行的Shell命令”,这有助于理解该属性的用途和功能。 + +在项目的上下文中,虽然当前提供的信息没有直接展示ShellInput类如何被其他对象调用,但可以推断,ShellInput类可能被用于封装用户输入或者其他来源的Shell命令,之后这些封装好的命令可能会在项目的其他部分,如服务器的代理工具中被执行。这样的设计使得Shell命令的处理更加模块化和安全,因为Pydantic模型提供了一层数据验证,确保只有合法和预期的命令才会被执行。 + +**注意**: +- 使用ShellInput类时,需要确保传入的`query`字符串是有效且安全的Shell命令。考虑到Shell命令的强大功能和潜在的安全风险,应当避免执行来自不可信源的命令。 +- 由于ShellInput类基于Pydantic库,使用该类之前需要确保项目中已经安装了Pydantic。此外,熟悉Pydantic库的基本使用和数据验证机制将有助于更有效地利用ShellInput类。 diff --git a/markdown_docs/server/agent/tools/weather_check.md b/markdown_docs/server/agent/tools/weather_check.md new file mode 100644 index 000000000..7cc6d5b96 --- /dev/null +++ b/markdown_docs/server/agent/tools/weather_check.md @@ -0,0 +1,62 @@ +## FunctionDef weather(location, api_key) +**weather**: 此函数的功能是获取指定地点的当前天气信息。 + +**参数**: +- location: 字符串类型,表示查询天气信息的地点。 +- api_key: 字符串类型,用于访问天气API的密钥。 + +**代码描述**: +`weather` 函数通过构造一个请求URL,使用 `requests.get` 方法向 `seniverse.com` 的天气API发送请求,以获取指定地点的当前天气信息。此URL包含了API密钥(api_key)、地点(location)、语言设置(默认为简体中文)和温度单位(摄氏度)。如果请求成功(HTTP状态码为200),函数将解析响应的JSON数据,提取温度和天气描述信息,然后以字典形式返回这些信息。如果请求失败,则抛出异常,异常信息包含了失败的HTTP状态码。 + +在项目中,`weather` 函数被 `weathercheck` 函数调用。`weathercheck` 函数接受一个地点作为参数,并使用项目中预定义的 `SENIVERSE_API_KEY` 作为API密钥来调用 `weather` 函数。这表明 `weather` 函数是项目中用于获取天气信息的核心功能,而 `weathercheck` 函数提供了一个更简便的接口,使得其他部分的代码无需直接处理API密钥即可请求天气信息。 + +**注意**: +- 确保提供的 `api_key` 是有效的,否则请求将失败。 +- 由于网络请求的性质,此函数的执行时间可能受到网络状况的影响。 + +**输出示例**: +```python +{ + "temperature": "22", + "description": "多云" +} +``` +此示例展示了函数返回值的可能外观,其中包含了温度和天气描述信息。 +## FunctionDef weathercheck(location) +**weathercheck**: 此函数的功能是使用预定义的API密钥获取指定地点的当前天气信息。 + +**参数**: +- location: 字符串类型,表示查询天气信息的地点。 + +**代码描述**: +`weathercheck` 函数是一个简化的接口,用于获取指定地点的天气信息。它接受一个地点名称作为参数,并内部调用了 `weather` 函数,后者是实际执行天气信息获取操作的函数。在调用 `weather` 函数时,`weathercheck` 使用了预定义的 `SENIVERSE_API_KEY` 作为API密钥参数。这意味着使用 `weathercheck` 函数时,用户无需直接处理API密钥,从而简化了获取天气信息的过程。 + +`weather` 函数负责构造请求URL,并通过HTTP GET请求向 `seniverse.com` 的天气API发送请求。如果请求成功,它将解析响应的JSON数据,并提取出温度和天气描述信息,然后以字典形式返回这些信息。如果请求失败,`weather` 函数将抛出异常,包含失败的HTTP状态码。 + +**注意**: +- 使用 `weathercheck` 函数时,确保预定义的 `SENIVERSE_API_KEY` 是有效的。无效的API密钥将导致请求失败。 +- 获取天气信息的过程涉及网络请求,因此执行时间可能受到网络状况的影响。在网络状况不佳的情况下,响应时间可能会较长。 + +**输出示例**: +由于 `weathercheck` 函数内部调用了 `weather` 函数并直接返回其结果,因此输出示例与 `weather` 函数的输出示例相同。以下是一个可能的返回值示例: +```python +{ + "temperature": "22", + "description": "多云" +} +``` +此示例展示了函数返回值的可能外观,其中包含了温度和天气描述信息。 +## ClassDef WeatherInput +**WeatherInput**: WeatherInput类的功能是定义一个用于天气查询的输入模型。 + +**属性**: +- location: 表示查询天气的城市名称,包括城市和县。 + +**代码描述**: +WeatherInput类继承自BaseModel,这是一个常见的做法,用于创建具有类型注解的数据模型。在这个类中,定义了一个名为`location`的属性,该属性用于存储用户希望查询天气的城市名称。通过使用`Field`函数,为`location`属性提供了额外的描述信息,即"City name, include city and county",这有助于理解该属性的用途和预期的值格式。 + +在项目的上下文中,尽管具体的调用情况未在提供的信息中明确,但可以推断WeatherInput类被设计为在天气查询功能中使用。它可能被用于从用户那里接收输入,然后这些输入将被用于查询特定城市的天气信息。这种设计允许天气查询功能以一种结构化和类型安全的方式处理用户输入。 + +**注意**: +- 在使用WeatherInput类时,需要确保传递给`location`属性的值是一个格式正确的字符串,即包含城市和县的名称。这是因为该模型可能会被用于向天气API发送请求,而这些API通常要求准确的地理位置信息以返回正确的天气数据。 +- 由于WeatherInput类继承自BaseModel,因此可以利用Pydantic库提供的各种功能,如数据验证、序列化和反序列化等。这使得处理和转换用户输入变得更加容易和安全。 diff --git a/markdown_docs/server/agent/tools/wolfram.md b/markdown_docs/server/agent/tools/wolfram.md new file mode 100644 index 000000000..31c69acdc --- /dev/null +++ b/markdown_docs/server/agent/tools/wolfram.md @@ -0,0 +1,35 @@ +## FunctionDef wolfram(query) +**wolfram**: 此函数的功能是执行对Wolfram Alpha API的查询并返回结果。 + +**参数**: +- `query`: 字符串类型,表示要查询的内容。 + +**代码描述**: +`wolfram`函数首先创建了一个`WolframAlphaAPIWrapper`对象,该对象是对Wolfram Alpha API的一个封装。在创建这个对象时,需要提供一个`wolfram_alpha_appid`,这是调用Wolfram Alpha服务所需的应用程序ID。随后,函数使用`run`方法执行传入的查询`query`。最后,函数返回查询结果。 + +在项目中,`wolfram`函数作为`server/agent/tools/wolfram.py`模块的一部分,虽然其被调用的具体情况在提供的文档中没有直接说明,但可以推断这个函数可能被设计为一个工具函数,供项目中其他部分调用以获取Wolfram Alpha查询的结果。这样的设计使得项目中的其他模块可以轻松地利用Wolfram Alpha提供的强大计算和知识查询功能,而无需关心API调用的具体细节。 + +**注意**: +- 使用此函数前,需要确保已经获得了有效的Wolfram Alpha应用程序ID(`wolfram_alpha_appid`),并且该ID已经正确配置在创建`WolframAlphaAPIWrapper`对象时。 +- 查询结果的具体格式和内容将依赖于Wolfram Alpha API的返回值,可能包括文本、图像或其他数据类型。 + +**输出示例**: +假设对Wolfram Alpha进行了一个查询“2+2”,函数可能返回如下的结果: +``` +4 +``` +这只是一个简化的示例,实际返回的结果可能包含更多的信息和数据类型,具体取决于查询的内容和Wolfram Alpha API的响应。 +## ClassDef WolframInput +**WolframInput**: WolframInput类的功能是封装了用于Wolfram语言计算的输入数据。 + +**属性**: +- location: 表示需要进行计算的具体问题的字符串。 + +**代码描述**: +WolframInput类继承自BaseModel,这表明它是一个用于数据验证和序列化的模型类。在这个类中,定义了一个名为`location`的属性,该属性用于存储一个字符串,这个字符串代表了需要使用Wolfram语言进行计算的具体问题。通过使用Pydantic库中的`Field`函数,为`location`属性提供了一个描述,增强了代码的可读性和易用性。 + +在项目的结构中,WolframInput类位于`server/agent/tools/wolfram.py`文件中,这意味着它是服务端代理工具中的一部分,专门用于处理与Wolfram语言相关的输入数据。尽管在提供的信息中,`server/agent/tools/__init__.py`和`server/agent/tools_select.py`两个文件中没有直接提到WolframInput类的调用情况,但可以推测,WolframInput类可能会被这些模块或其他相关模块中的代码所使用,以便于处理和传递需要用Wolfram语言解决的问题。 + +**注意**: +- 在使用WolframInput类时,需要确保`location`属性中的问题描述是准确和有效的,因为这将直接影响到Wolfram语言计算的结果。 +- 由于WolframInput类继承自BaseModel,因此可以利用Pydantic提供的数据验证功能来确保输入数据的有效性。在实际应用中,可以根据需要对WolframInput类进行扩展,增加更多的属性和验证逻辑,以满足不同的计算需求。 diff --git a/markdown_docs/server/api.md b/markdown_docs/server/api.md new file mode 100644 index 000000000..6a545eae7 --- /dev/null +++ b/markdown_docs/server/api.md @@ -0,0 +1,116 @@ +## FunctionDef document +**document**: 此函数的功能是重定向到文档页面。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `document` 函数是一个异步函数,其主要作用是将用户的请求重定向到服务器上的文档页面。在这个项目中,当用户访问服务器的根路径("/")时,通过调用此函数实现自动跳转到文档页面。这是通过返回一个 `RedirectResponse` 对象实现的,该对象中包含了目标URL(即文档页面的URL)。在这个例子中,目标URL被硬编码为 "/docs",意味着当此函数被触发时,用户的浏览器将会被重定向到服务器的 "/docs" 路径,通常这个路径下托管着API的交互式文档,如Swagger UI或Redoc。 + +此函数被 `mount_app_routes` 函数调用,作为FastAPI应用的一部分,用于在应用启动时设置路由。在 `mount_app_routes` 函数中,`document` 函数被注册为处理根路径("/")请求的处理器。这样,当用户访问应用的根路径时,他们会被自动重定向到API文档页面,从而提供了一种用户友好的方式来探索和测试API。 + +**注意**: 使用此函数时,需要确保 "/docs" 路径下确实存在文档页面。在FastAPI中,默认情况下,API文档通常是自动生成的,并且可以通过 "/docs"(Swagger UI)或 "/redoc"(Redoc)路径访问。如果你更改了文档页面的路径或使用了自定义文档页面,需要相应地更新此函数中的URL。 + +**输出示例**: 由于此函数的作用是进行页面重定向,因此它不直接产生可视化的输出。但在浏览器中,当访问根路径("/")时,浏览器的地址栏将会显示为 "/docs",并展示相应的API文档页面。 +## FunctionDef create_app(run_mode) +Doc is waiting to be generated... +## FunctionDef mount_app_routes(app, run_mode) +**mount_app_routes**: 该函数用于在FastAPI应用中挂载应用路由。 + +**参数**: +- `app`: FastAPI应用实例,用于注册路由。 +- `run_mode`: 运行模式,用于区分应用的运行环境,例如开发环境或生产环境。 + +**代码描述**: +`mount_app_routes`函数主要负责在FastAPI应用实例中注册各种API路由。这些路由包括对话、搜索引擎对话、聊天记录反馈、知识库管理、LLM模型管理、服务器状态查询等功能的接口。通过调用`app.get`和`app.post`方法,将特定的URL路径与处理函数绑定,从而实现API的路由功能。此外,函数还调用了`mount_knowledge_routes`和`mount_filename_summary_routes`两个函数,分别用于挂载知识库相关和文件名摘要相关的路由。在注册路由的过程中,为每个API接口设置了标签(tags)、摘要(summary)等信息,以便于在API文档中进行分类和说明。 + +**注意**: +- 在使用`mount_app_routes`函数之前,需要确保已经创建了FastAPI应用实例,并且所有处理函数都已正确定义。 +- 该函数是API路由注册的入口点,通过它可以将应用的各种功能接口集成到FastAPI应用中。 +- 在实际部署和使用时,应注意API接口的安全性,避免未授权的访问和操作。 +- `run_mode`参数可以用于根据不同的运行环境调整API的行为,例如在开发环境中启用调试模式,在生产环境中优化性能。 + +**输出示例**: +由于`mount_app_routes`函数的作用是注册路由而不直接返回数据,因此它没有直接的输出示例。函数执行成功后,FastAPI应用将能够响应对应路由的HTTP请求,并根据请求的URL路径调用相应的处理函数。例如,当用户通过HTTP POST请求访问`/chat/chat`路径时,FastAPI应用将调用`chat`函数处理该请求,并返回处理结果。 +### FunctionDef get_server_prompt_template(type, name) +**get_server_prompt_template**: 该函数用于根据提供的类型和名称参数,动态加载并返回相应的模板内容。 + +**参数**: +- type: 字面量类型,可选值为"llm_chat"、"knowledge_base_chat"、"search_engine_chat"、"agent_chat",用于指定模板的类型。默认值为"llm_chat"。 +- name: 字符串类型,用于指定模板的名称。默认值为"default"。 + +**代码描述**: +`get_server_prompt_template`函数是API层面用于处理模板加载请求的入口。该函数接收两个参数:`type`和`name`,分别代表模板的类型和名称。函数内部调用了`get_prompt_template`函数,传入相同的`type`和`name`参数,以获取指定的模板内容。 + +`get_prompt_template`函数位于`server/utils.py`文件中,负责从配置中加载指定类型和名称的模板内容。它首先从`configs`模块导入`prompt_config`配置,然后使用`importlib.reload`方法重新加载`prompt_config`,以确保获取到最新的配置信息。通过`type`参数从`prompt_config.PROMPT_TEMPLATES`中索引到对应类型的模板字典,再使用`name`参数从该字典中获取具体的模板内容。如果指定的`name`在字典中不存在,则返回`None`。 + +在项目结构中,`get_server_prompt_template`函数位于`server/api.py/mount_app_routes`路径下,作为API接口的一部分,允许前端或其他服务通过HTTP请求动态获取不同类型和名称的模板内容,从而支持灵活的聊天模式或功能需求。 + +**注意**: +- 调用`get_server_prompt_template`函数时,需要确保`type`和`name`参数的值正确无误,并且所请求的模板已经在`prompt_config`中定义。 +- 由于`get_prompt_template`函数依赖于外部的配置文件`prompt_config`,在修改配置文件后,可能需要重启服务或动态重新加载配置,以确保更改生效。 + +**输出示例**: +假设存在以下模板配置: +```python +PROMPT_TEMPLATES = { + "llm_chat": { + "default": "你好,请问有什么可以帮助你的?" + } +} +``` +当调用`get_server_prompt_template(type="llm_chat", name="default")`时,将返回字符串`"你好,请问有什么可以帮助你的?"`。 +*** +## FunctionDef mount_knowledge_routes(app) +**mount_knowledge_routes**: 该函数的功能是在FastAPI应用中挂载知识库相关的路由。 + +**参数**: 该函数接受一个参数: +- `app`: FastAPI应用实例,用于注册路由。 + +**代码描述**: `mount_knowledge_routes` 函数主要负责将知识库管理和操作相关的API接口注册到FastAPI应用中。通过导入不同的处理函数,如`knowledge_base_chat`、`upload_temp_docs`、`file_chat`、`agent_chat`等,并使用`app.post`或`app.get`方法将这些处理函数与特定的URL路径绑定,从而实现API的路由功能。此外,函数还为每个API接口设置了标签(tags)、摘要(summary)等信息,以便于在API文档中进行分类和说明。 + +该函数涵盖了知识库的创建、删除、文件上传、文件删除、文档搜索、文档更新、下载文档、重建向量库等多个功能。每个功能都通过特定的URL路径进行访问,例如,通过`/knowledge_base/create_knowledge_base`路径可以访问创建知识库的接口。 + +**注意**: +- 在使用`mount_knowledge_routes`函数之前,需要确保已经创建了FastAPI应用实例,并且所有处理函数都已正确定义。 +- 该函数是知识库管理功能在FastAPI框架中的入口点,通过它可以将知识库相关的操作集成到FastAPI应用中。 +- 在实际部署和使用时,应注意API接口的安全性,避免未授权的访问和操作。 +## FunctionDef mount_filename_summary_routes(app) +**mount_filename_summary_routes**: 此函数的功能是在FastAPI应用中挂载处理文件名摘要的路由。 + +**参数**: +- `app`: FastAPI应用实例,用于注册路由。 + +**代码描述**: +`mount_filename_summary_routes`函数主要负责在FastAPI应用中注册三个与文件名摘要相关的POST路由。这些路由分别用于处理单个知识库根据文件名称摘要、根据doc_ids摘要以及重建单个知识库文件摘要的请求。 + +1. `/knowledge_base/kb_summary_api/summary_file_to_vector_store`路由用于处理根据文件名称对单个知识库进行摘要,并将摘要结果存储到向量存储中。此路由使用`summary_file_to_vector_store`函数处理请求。 + +2. `/knowledge_base/kb_summary_api/summary_doc_ids_to_vector_store`路由用于处理根据文档ID列表生成单个知识库的文档摘要,并将摘要信息存储到向量存储中。此路由使用`summary_doc_ids_to_vector_store`函数处理请求,并指定`response_model`为`BaseResponse`,以规范化响应格式。 + +3. `/knowledge_base/kb_summary_api/recreate_summary_vector_store`路由用于处理重建单个知识库文件摘要的请求。此路由使用`recreate_summary_vector_store`函数处理请求。 + +每个路由都通过`app.post`方法注册,并指定了路由的路径、处理函数、标签(tags)和摘要(summary)。这些信息有助于生成自动化的API文档,提高API的可发现性和可理解性。 + +**注意**: +- 在使用这些API接口之前,确保相关的处理函数已经正确实现,并且知识库服务已经配置妥当。 +- 通过指定`response_model`为`BaseResponse`,可以统一API的响应格式,使得响应数据更加规范化,便于客户端处理。 +- 这些路由主要用于处理知识库文件摘要的生成和管理,因此在调用这些API时,需要提供正确的知识库名称、文件名称或文档ID列表等信息。 +- 在项目中,`mount_filename_summary_routes`函数被`mount_app_routes`函数调用,意味着这些文件名摘要相关的路由是作为应用的一部分被自动挂载和注册的。这有助于保持路由注册的集中管理和应用结构的清晰。 +## FunctionDef run_api(host, port) +**run_api**: 此函数的功能是启动API服务。 + +**参数**: +- **host**: 服务器的主机名或IP地址。 +- **port**: 服务器监听的端口号。 +- **kwargs**: 关键字参数,可选,用于提供SSL证书文件路径。 + +**代码描述**: +`run_api`函数负责启动API服务。它接受三个参数:`host`、`port`以及可选的关键字参数`kwargs`。这些参数用于指定服务器的监听地址和端口,以及配置SSL加密连接所需的证书文件路径。 + +函数首先检查`kwargs`中是否提供了`ssl_keyfile`和`ssl_certfile`这两个关键字参数。如果这两个参数都被提供,函数将使用这些证书文件启动一个支持SSL加密的API服务。这是通过调用`uvicorn.run`函数并传入相应的参数来实现的,包括应用实例`app`、主机名`host`、端口号`port`、SSL密钥文件路径`ssl_keyfile`和SSL证书文件路径`ssl_certfile`。 + +如果`kwargs`中没有提供SSL相关的参数,`run_api`函数将启动一个不使用SSL加密的API服务。这同样是通过调用`uvicorn.run`函数实现的,但此时只传入应用实例`app`、主机名`host`和端口号`port`作为参数。 + +**注意**: +- 确保在启动支持SSL的API服务之前,已经正确生成并指定了SSL证书文件和密钥文件的路径。 +- 在没有提供SSL证书文件路径的情况下,API服务将以非加密模式运行,这可能不适合生产环境中处理敏感信息。 +- `uvicorn.run`是Uvicorn库的一部分,Uvicorn是一个轻量级、超快的ASGI服务器,用于Python异步web应用。确保在使用`run_api`函数之前已经安装了Uvicorn库。 diff --git a/markdown_docs/server/callback_handler/conversation_callback_handler.md b/markdown_docs/server/callback_handler/conversation_callback_handler.md new file mode 100644 index 000000000..5ee1b1457 --- /dev/null +++ b/markdown_docs/server/callback_handler/conversation_callback_handler.md @@ -0,0 +1,87 @@ +## ClassDef ConversationCallbackHandler +**ConversationCallbackHandler**: ConversationCallbackHandler类的功能是在聊天过程中处理回调,特别是在使用大型语言模型(LLM)生成回应后更新消息内容。 + +**属性**: +- `conversation_id`: 字符串类型,表示对话的唯一标识符。 +- `message_id`: 字符串类型,表示消息的唯一标识符。 +- `chat_type`: 字符串类型,表示聊天的类型。 +- `query`: 字符串类型,表示用户的查询或输入。 +- `start_at`: 初始化为None,可用于记录某些操作的开始时间。 +- `raise_error`: 布尔类型,默认为True,表示是否在处理过程中遇到错误时抛出异常。 + +**代码描述**: +ConversationCallbackHandler继承自BaseCallbackHandler,是一个专门设计用于处理聊天应用中的回调逻辑的类。它通过接收对话ID、消息ID、聊天类型和用户查询等参数进行初始化。此类中定义了一个属性`always_verbose`,始终返回True,表示无论verbose参数如何设置,都会调用详细的回调函数。此外,它还包含两个方法`on_llm_start`和`on_llm_end`,这两个方法分别在大型语言模型(LLM)开始处理和结束处理时被调用。`on_llm_end`方法中,它会从LLM的响应中提取生成的文本,并调用`update_message`函数更新消息内容。 + +在项目中,ConversationCallbackHandler被用于`server/chat/chat.py/chat/chat_iterator`中,以处理和更新使用大型语言模型进行聊天时生成的回应。在聊天迭代器中,创建了ConversationCallbackHandler实例,并将其添加到回调列表中。这样,每当LLM处理完成,就会通过`on_llm_end`方法更新对应的消息内容。 + +**注意**: +- 在使用ConversationCallbackHandler时,需要确保提供的`conversation_id`、`message_id`、`chat_type`和`query`参数正确无误,因为这些信息将用于消息更新和回调处理的关键环节。 +- `on_llm_start`方法目前留空,但可以根据需要进行扩展,以存储更多与LLM处理相关的信息。 + +**输出示例**: +由于ConversationCallbackHandler主要负责回调处理,不直接产生输出,因此没有具体的输出示例。但在其作用下,一条消息的内容可能会从用户的原始查询更新为LLM生成的回应文本。 +### FunctionDef __init__(self, conversation_id, message_id, chat_type, query) +**__init__**: __init__函数的功能是初始化ConversationCallbackHandler类的实例。 + +**参数**: +- conversation_id: 会话ID,标识特定的对话。 +- message_id: 消息ID,用于标识对话中的特定消息。 +- chat_type: 聊天类型,描述聊天的性质(如私聊、群聊等)。 +- query: 查询字符串,用于处理或响应特定的查询请求。 + +**代码描述**: +此__init__函数是ConversationCallbackHandler类的构造函数,用于创建类的实例时初始化其属性。在这个函数中,接收四个参数:conversation_id、message_id、chat_type和query,这些参数分别用于初始化实例的相应属性。此外,还有一个属性start_at,它在此函数中被初始化为None,可能用于记录会话开始的时间或其他与时间相关的信息,但具体用途取决于类的其他部分或方法如何使用它。 + +**注意**: +- 在使用ConversationCallbackHandler类创建实例时,必须提供conversation_id、message_id、chat_type和query这四个参数,它们对于实例的功能至关重要。 +- start_at属性在初始化时没有设置具体值(设为None),这意味着如果需要使用到这个属性,应在类的其他方法中对其进行适当的设置。 +- 此构造函数不返回任何值,仅用于初始化实例的状态。 +*** +### FunctionDef always_verbose(self) +**always_verbose**: 此函数的功能是决定是否在verbose模式为False时也调用verbose回调。 + +**参数**: 此函数没有参数。 + +**代码描述**: `always_verbose` 函数是 `ConversationCallbackHandler` 类的一个方法,旨在控制回调处理器的行为。具体来说,它指示回调处理器在处理回调时是否应始终采用详细模式,即使在全局设置中未启用详细(verbose)模式。该方法通过返回一个布尔值 `True` 来实现这一行为,表明无论全局的verbose设置如何,都应调用verbose回调。这对于开发者在调试或需要详尽日志信息的场景下非常有用,因为它允许单独的回调处理器忽略全局的verbose设置,始终以详细模式运行。 + +**注意**: 使用此功能时,开发者应当意识到,即使全局verbose设置为False,启用 `always_verbose` 方法的回调处理器仍将产生详细的日志输出。这可能会导致日志信息量显著增加,因此建议仅在调试或特定需要详细日志的情况下使用。 + +**输出示例**: 由于 `always_verbose` 方法返回的是一个布尔值 `True`,因此在调用此方法时,其输出示例将简单地为: + +```python +True +``` +*** +### FunctionDef on_llm_start(self, serialized, prompts) +**on_llm_start**: 该函数用于处理与大型语言模型(LLM)会话开始相关的逻辑。 + +**参数**: +- `serialized`: 一个字典类型参数,包含了需要序列化的信息。其键值对的类型为`str`到`Any`,即键是字符串类型,而值可以是任何类型。 +- `prompts`: 一个字符串列表,包含了启动大型语言模型会话时的提示信息。 +- `**kwargs`: 接收任意额外的关键字参数。这些参数的类型不固定,可以根据实际需要传递给函数。 + +**代码描述**: +`on_llm_start`函数的主要作用是在大型语言模型(LLM)会话开始时执行必要的逻辑处理。这包括但不限于初始化会话、设置会话参数、记录会话信息等。函数接收两个主要参数:`serialized`和`prompts`。`serialized`参数是一个字典,用于传递需要序列化的信息,这可能包括会话的配置信息、用户的身份信息等。`prompts`参数是一个字符串列表,提供了启动会话时的提示信息,这些信息可能用于引导语言模型生成回复。此外,函数还可以接收任意数量的关键字参数(`**kwargs`),这为函数提供了高度的灵活性,允许在不修改函数签名的情况下添加更多的功能或处理逻辑。 + +**注意**: +- 在实际使用`on_llm_start`函数时,开发者需要注意`serialized`和`prompts`参数的内容和格式,确保它们符合大型语言模型处理的要求。 +- 函数中的注释提示“如果想存更多信息,则prompts也需要持久化”,这意味着如果在会话过程中需要记录额外的信息,那么开发者应考虑将这些信息添加到`prompts`中,并确保它们能够被适当地序列化和存储。 +- 由于函数目前的实现为空(`pass`),开发者在将其集成到项目中时需要根据具体需求完成相应的逻辑实现。 +*** +### FunctionDef on_llm_end(self, response) +**on_llm_end**: 此函数的功能是在语言模型处理结束后,更新聊天记录的回复内容。 + +**参数**: +- `response`: LLMResult类型,包含语言模型生成的结果。 +- `**kwargs`: 接受任意数量的关键字参数,提供额外的灵活性。 + +**代码描述**: +`on_llm_end`方法首先从`response`对象中提取出语言模型生成的第一条回复文本。此文本是通过访问`response.generations[0][0].text`获得的,其中`generations`是一个嵌套列表,包含了所有生成的回复。随后,该方法调用`update_message`函数,将提取出的回复文本更新到数据库中对应的聊天记录里。在调用`update_message`时,传入的参数包括`self.message_id`和提取的回复文本`answer`。`self.message_id`是需要更新的聊天记录的唯一标识ID,而`answer`则是新的回复内容。 + +`update_message`函数是定义在`server/db/repository/message_repository.py`中的一个函数,其主要功能是更新数据库中已有的聊天记录。它通过`message_id`定位到特定的聊天记录,并根据提供的新回复内容或元数据进行更新。在`on_llm_end`方法中,`update_message`的调用实现了在语言模型处理结束后,将生成的回复内容及时更新到数据库中,确保聊天记录保持最新状态。 + +**注意**: +- 确保`response`参数是有效的LLMResult对象,且至少包含一个生成的回复,以避免访问不存在的索引导致错误。 +- 在实际应用中,需要确保`self.message_id`对应的聊天记录存在于数据库中,以便`update_message`函数能够正确地找到并更新该记录。 +- `**kwargs`参数提供了额外的灵活性,但在当前的实现中未被直接使用。开发者可以根据需要在未来的版本中扩展该方法的功能,利用这些额外的参数。 +*** diff --git a/markdown_docs/server/chat/agent_chat.md b/markdown_docs/server/chat/agent_chat.md new file mode 100644 index 000000000..e1fdb700d --- /dev/null +++ b/markdown_docs/server/chat/agent_chat.md @@ -0,0 +1,71 @@ +## FunctionDef agent_chat(query, history, stream, model_name, temperature, max_tokens, prompt_name) +**agent_chat**: 该函数用于处理与代理的异步聊天对话。 + +**参数**: +- `query`: 用户输入的查询字符串,必填参数。 +- `history`: 历史对话列表,每个元素为一个`History`对象。 +- `stream`: 是否以流式输出的方式返回数据,默认为`False`。 +- `model_name`: 使用的LLM模型名称,默认为`LLM_MODELS`列表中的第一个模型。 +- `temperature`: LLM采样温度,用于调整生成文本的随机性,默认值由`TEMPERATURE`常量决定,取值范围为0.0到1.0。 +- `max_tokens`: 限制LLM生成Token的数量,默认为`None`,代表使用模型的最大值。 +- `prompt_name`: 使用的prompt模板名称,默认为"default"。 + +**代码描述**: +`agent_chat`函数是一个异步函数,主要负责处理用户与代理的聊天对话。它首先将传入的历史对话列表`history`转换为`History`对象列表。然后,定义了一个异步迭代器`agent_chat_iterator`,用于生成聊天回复。在`agent_chat_iterator`中,根据传入的参数和配置,初始化相应的LLM模型和工具,处理历史对话记录,并根据用户的查询生成回复。 + +如果设置了`stream`参数为`True`,则函数以流式输出的方式返回数据,适用于需要实时更新聊天内容的场景。在流式输出模式下,函数会根据不同的状态(如工具调用开始、完成、错误等)生成不同的JSON格式数据块,并通过`yield`语句异步返回给调用者。 + +在非流式输出模式下,函数会收集所有生成的聊天回复,并在最终将它们整合为一个JSON格式的响应体返回。 + +**注意**: +- 在使用`agent_chat`函数时,需要确保传入的`history`参数格式正确,即每个元素都应为`History`对象或能够转换为`History`对象的数据结构。 +- `stream`参数的设置会影响函数的返回方式,根据实际应用场景选择合适的模式。 +- 函数依赖于配置好的LLM模型和prompt模板,确保在调用前已正确配置这些依赖项。 + +**输出示例**: +在非流式输出模式下,假设用户的查询得到了一系列的聊天回复,函数可能返回如下格式的JSON数据: +```json +{ + "answer": "这是聊天过程中生成的回复文本。", + "final_answer": "这是最终的回复文本。" +} +``` +在流式输出模式下,函数会逐块返回数据,每块数据可能如下所示: +```json +{ + "tools": [ + "工具名称: 天气查询", + "工具状态: 调用成功", + "工具输入: 北京今天天气", + "工具输出: 北京今天多云,10-14摄氏度" + ] +} +``` +或者在得到最终回复时: +```json +{ + "final_answer": "这是最终的回复文本。" +} +``` +### FunctionDef agent_chat_iterator(query, history, model_name, prompt_name) +**agent_chat_iterator**: 此函数的功能是异步迭代生成代理聊天的响应。 + +**参数**: +- `query`: 字符串类型,用户的查询或输入。 +- `history`: 可选的`List[History]`类型,表示对话历史记录。 +- `model_name`: 字符串类型,默认为`LLM_MODELS`列表中的第一个模型,用于指定使用的语言模型。 +- `prompt_name`: 字符串类型,用于指定提示模板的名称。 + +**代码描述**: +`agent_chat_iterator`函数是一个异步生成器,用于处理代理聊天的逻辑。首先,函数检查`max_tokens`是否为整数且小于等于0,如果是,则将其设置为`None`。接着,使用`get_ChatOpenAI`函数初始化一个聊天模型实例,并通过`get_kb_details`函数获取知识库列表,将其存储在模型容器的数据库中。如果存在`Agent_MODEL`,则使用该模型初始化另一个聊天模型实例,并将其存储在模型容器中;否则,使用之前初始化的模型。 + +函数通过`get_prompt_template`函数获取指定的提示模板,并使用`CustomPromptTemplate`类创建一个自定义提示模板实例。然后,使用`CustomOutputParser`类创建一个输出解析器实例,并根据模型名称决定使用`initialize_glm3_agent`函数初始化GLM3代理执行器,或者使用`LLMSingleActionAgent`和`AgentExecutor`创建一个代理执行器。 + +在异步循环中,函数尝试创建一个任务,使用`wrap_done`函数包装代理执行器的调用,并在完成时通过回调通知。如果设置了`stream`参数,则函数会异步迭代回调处理器的输出,并根据状态生成不同的响应数据,最终以JSON格式产生输出。如果未设置`stream`参数,则会收集所有输出数据,并在最后生成一个包含答案和最终答案的JSON对象。 + +**注意**: +- 在使用此函数时,需要确保提供的`history`参数格式正确,且每个历史记录项都应为`History`类的实例。 +- `model_name`和`prompt_name`参数应根据实际需要选择合适的模型和提示模板。 +- 函数内部使用了多个异步操作和自定义类,如`CustomAsyncIteratorCallbackHandler`、`CustomPromptTemplate`和`CustomOutputParser`,需要确保这些组件的正确实现和配置。 +- 此函数设计为与前端实现实时或异步的聊天交互,因此在集成到聊天系统时,应考虑其异步特性和对外部回调的处理方式。 +*** diff --git a/markdown_docs/server/chat/chat.md b/markdown_docs/server/chat/chat.md new file mode 100644 index 000000000..d4d009aed --- /dev/null +++ b/markdown_docs/server/chat/chat.md @@ -0,0 +1,57 @@ +## FunctionDef chat(query, conversation_id, history_len, history, stream, model_name, temperature, max_tokens, prompt_name) +**chat**: 此函数用于实现与LLM模型的对话功能。 + +**参数**: +- `query`: 用户输入的查询字符串。 +- `conversation_id`: 对话框ID,用于标识一个对话会话。 +- `history_len`: 从数据库中取历史消息的数量。 +- `history`: 历史对话记录,可以是一个整数或一个历史记录列表。 +- `stream`: 是否以流式输出的方式返回对话结果。 +- `model_name`: LLM模型名称。 +- `temperature`: LLM采样温度,用于控制生成文本的随机性。 +- `max_tokens`: 限制LLM生成Token的数量。 +- `prompt_name`: 使用的prompt模板名称。 + +**代码描述**: +此函数主要负责处理用户与LLM模型之间的对话。它首先通过`add_message_to_db`函数将用户的查询和对话信息保存到数据库中。然后,根据传入的参数,如历史对话记录、模型名称、温度等,构建一个适合LLM模型的输入提示(prompt)。接着,使用`LLMChain`对象发起对话请求,并通过`AsyncIteratorCallbackHandler`处理模型的异步响应。如果启用了流式输出,函数将逐个Token地返回响应结果;否则,会等待所有响应完成后,一次性返回整个对话结果。最后,通过`EventSourceResponse`将结果以服务器发送事件(SSE)的形式返回给客户端。 + +**注意**: +- 在使用`history`参数时,可以直接传入历史对话记录的列表,或者传入一个整数,函数会从数据库中读取指定数量的历史消息。 +- `stream`参数控制输出模式,当设置为True时,对话结果将以流式输出,适用于需要实时显示对话过程的场景。 +- `max_tokens`参数用于限制LLM模型生成的Token数量,有助于控制生成文本的长度。 + +**输出示例**: +假设函数以非流式模式运行,并且返回了一条简单的对话响应: +```json +{ + "text": "好的,我明白了。", + "message_id": "123456" +} +``` +这表示LLM模型对用户的查询给出了回复“好的,我明白了。”,并且该对话消息在数据库中的ID为"123456"。 +### FunctionDef chat_iterator +**chat_iterator**: 此函数的功能是异步迭代聊天过程,生成并流式传输聊天响应。 + +**参数**: +- 无参数直接传递给此函数,但函数内部使用了多个外部定义的变量和对象。 + +**代码描述**: +`chat_iterator`是一个异步生成器函数,用于处理聊天会话,生成聊天响应并以流的形式传输。函数首先定义了一个`callback`对象,该对象是`AsyncIteratorCallbackHandler`的实例,用于处理异步迭代的回调。接着,创建了一个回调列表`callbacks`,并将`callback`对象添加到其中。 + +函数通过调用`add_message_to_db`函数,将聊天请求添加到数据库中,并创建了一个`conversation_callback`对象,该对象是`ConversationCallbackHandler`的实例,用于处理聊天过程中的回调,并将其添加到回调列表中。 + +根据`max_tokens`的值调整生成文本的最大token数量,如果`max_tokens`为非正整数,则将其设置为`None`。 + +接下来,通过调用`get_ChatOpenAI`函数,初始化一个聊天模型`model`,并根据聊天历史(如果有)或会话ID(如果指定)来构建聊天提示`chat_prompt`。如果没有提供历史或会话ID,则使用默认的提示模板。 + +然后,创建了一个`LLMChain`对象`chain`,它负责将聊天提示传递给聊天模型,并开始一个异步任务,该任务使用`wrap_done`函数包装了`chain.acall`的调用,以便在任务完成时通过`callback.done`方法进行通知。 + +最后,根据`stream`变量的值决定是流式传输每个生成的token,还是等待所有token生成后一次性返回。在流式传输模式下,使用`json.dumps`将生成的token和消息ID封装成JSON格式并逐个yield返回;在非流式传输模式下,将所有生成的token拼接后一次性yield返回。 + +**注意**: +- `chat_iterator`函数是异步的,因此在调用时需要使用`await`关键字或在其他异步函数中调用。 +- 函数内部使用了多个外部定义的变量和对象,如`history`、`max_tokens`等,这要求在调用`chat_iterator`之前,这些变量和对象必须已经被正确初始化和配置。 +- 函数依赖于多个外部定义的函数和类,如`AsyncIteratorCallbackHandler`、`add_message_to_db`、`ConversationCallbackHandler`、`get_ChatOpenAI`等,确保这些依赖项在项目中已正确实现。 +- 在处理聊天响应时,函数考虑了多种情况,包括有无聊天历史、是否从数据库获取历史消息等,这要求调用者根据实际情况提供正确的参数和配置。 +- 使用此函数时,应注意异常处理和资源管理,确保在聊天会话结束时释放所有资源。 +*** diff --git a/markdown_docs/server/chat/completion.md b/markdown_docs/server/chat/completion.md new file mode 100644 index 000000000..a40efc84c --- /dev/null +++ b/markdown_docs/server/chat/completion.md @@ -0,0 +1,50 @@ +## FunctionDef completion(query, stream, echo, model_name, temperature, max_tokens, prompt_name) +**completion**: 此函数用于处理用户输入,生成并返回由LLM模型补全的文本。 + +**参数**: +- `query`: 用户输入的文本。 +- `stream`: 是否以流式输出结果。 +- `echo`: 是否在输出结果中回显输入文本。 +- `model_name`: 使用的LLM模型名称。 +- `temperature`: LLM模型采样温度,用于控制生成文本的随机性。 +- `max_tokens`: 限制LLM模型生成的Token数量。 +- `prompt_name`: 使用的prompt模板名称。 + +**代码描述**: +此函数首先定义了一个异步生成器`completion_iterator`,该生成器负责实际的文本生成逻辑。它使用`get_OpenAI`函数初始化一个LLM模型,并根据提供的参数配置模型。然后,它使用`get_prompt_template`函数获取指定的prompt模板,并将用户输入的`query`传递给LLM模型进行处理。根据`stream`参数的值,此函数可以以流式方式逐个返回生成的Token,或者等待所有Token生成完成后一次性返回结果。最后,使用`EventSourceResponse`包装`completion_iterator`生成器,以适合流式输出的HTTP响应格式返回结果。 + +在项目中,`completion`函数通过`/other/completion`路由在`server/api.py`文件中被注册为一个POST请求的处理器。这表明它设计用于处理来自客户端的文本补全请求,客户端可以通过发送POST请求到此路由,并在请求体中提供相应的参数,来获取LLM模型基于用户输入生成的补全文本。 + +**注意**: +- 确保`model_name`参数对应的LLM模型已正确配置且可用。 +- `temperature`参数应在0.0到1.0之间,以控制生成文本的随机性。 +- 如果`max_tokens`设为负数或0,将不会限制Token数量。 + +**输出示例**: +如果`stream`参数为`False`,并且用户输入为"今天天气如何",一个可能的返回值示例为: +``` +"今天天气晴朗,适合外出。" +``` +如果`stream`参数为`True`,则可能逐个返回上述文本中的每个字或词。 +### FunctionDef completion_iterator(query, model_name, prompt_name, echo) +**completion_iterator**: 此函数的功能是异步迭代生成基于给定查询的完成文本。 + +**参数**: +- `query`: 字符串类型,用户的查询输入。 +- `model_name`: 字符串类型,默认为LLM_MODELS列表中的第一个模型,指定使用的语言模型名称。 +- `prompt_name`: 字符串类型,指定使用的提示模板名称。 +- `echo`: 布尔类型,指示是否回显输入。 + +**代码描述**: +`completion_iterator`函数是一个异步生成器,用于根据用户的查询输入生成文本。首先,函数检查`max_tokens`参数是否为整数且小于等于0,如果是,则将其设置为None。接着,通过`get_OpenAI`函数初始化一个配置好的OpenAI模型实例,其中包括模型名称、温度、最大令牌数、回调函数列表以及是否回显输入等参数。然后,使用`get_prompt_template`函数加载指定类型和名称的提示模板,并通过`PromptTemplate.from_template`方法创建一个`PromptTemplate`实例。之后,创建一个`LLMChain`实例,将提示模板和语言模型作为参数传入。 + +函数接下来创建一个异步任务,使用`asyncio.create_task`方法将`chain.acall`方法的调用包装起来,并通过`wrap_done`函数与一个回调函数关联,以便在任务完成时进行通知。根据`stream`变量的值,函数将以不同的方式生成文本。如果`stream`为真,则通过`callback.aiter()`异步迭代每个生成的令牌,并使用服务器发送事件(server-sent-events)来流式传输响应。如果`stream`为假,则将所有生成的令牌累加到一个字符串中,然后一次性生成整个答案。 + +最后,函数等待之前创建的异步任务完成,确保所有生成的文本都已处理完毕。 + +**注意**: +- 使用此函数时,需要确保`query`参数正确无误,因为它直接影响生成文本的内容。 +- `model_name`和`prompt_name`参数应根据需要选择合适的模型和提示模板,以获得最佳的文本生成效果。 +- 在使用流式传输功能时,应考虑客户端如何处理流式数据,以确保用户体验。 +- 此函数依赖于`get_OpenAI`和`get_prompt_template`等函数,因此在使用前应确保相关配置和模板已正确设置。 +*** diff --git a/markdown_docs/server/chat/feedback.md b/markdown_docs/server/chat/feedback.md new file mode 100644 index 000000000..241408ff1 --- /dev/null +++ b/markdown_docs/server/chat/feedback.md @@ -0,0 +1,32 @@ +## FunctionDef chat_feedback(message_id, score, reason) +**chat_feedback**: 此函数用于处理用户对聊天记录的反馈。 + +**参数**: +- `message_id`: 聊天记录的唯一标识ID,用于定位需要反馈的聊天记录。此参数最大长度为32个字符。 +- `score`: 用户对聊天记录的评分,满分为100。评分越高表示用户对聊天记录的满意度越高。 +- `reason`: 用户提供的评分理由,例如聊天记录不符合事实等。 + +**代码描述**: +`chat_feedback`函数首先尝试调用`feedback_message_to_db`函数,将用户的反馈信息(包括聊天记录ID、评分和评分理由)存储到数据库中。如果在执行过程中遇到任何异常,函数将捕获这些异常,并通过`logger.error`记录错误信息,同时返回一个包含错误信息的`BaseResponse`对象,状态码为500,表示服务器内部错误。如果没有发生异常,函数将返回一个状态码为200的`BaseResponse`对象,表示用户反馈已成功处理,并附带消息“已反馈聊天记录 {message_id}”。 + +**注意**: +- 在调用此函数之前,确保传入的`message_id`是有效的,并且在数据库中存在对应的聊天记录。 +- `score`参数应在0到100之间,以确保评分的有效性。 +- 在实际应用中,可能需要对用户的评分理由`reason`进行长度或内容的校验,以避免存储无效或不恰当的信息。 +- 此函数通过捕获异常并记录错误信息,提高了代码的健壮性。开发者应关注日志输出,以便及时发现并处理潜在的问题。 + +**输出示例**: +如果用户反馈成功处理,函数可能返回如下的`BaseResponse`对象示例: +```json +{ + "code": 200, + "msg": "已反馈聊天记录 1234567890abcdef" +} +``` +如果处理过程中发生异常,函数可能返回如下的`BaseResponse`对象示例: +```json +{ + "code": 500, + "msg": "反馈聊天记录出错:[异常信息]" +} +``` diff --git a/markdown_docs/server/chat/file_chat.md b/markdown_docs/server/chat/file_chat.md new file mode 100644 index 000000000..917d8a873 --- /dev/null +++ b/markdown_docs/server/chat/file_chat.md @@ -0,0 +1,148 @@ +## 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`等),确保这些依赖项在调用此函数之前已正确初始化和配置。 +- 在处理大量或复杂的查询时,函数的执行时间可能较长,因此在设计用户界面和交互流程时应考虑到潜在的延迟。 +*** diff --git a/markdown_docs/server/chat/knowledge_base_chat.md b/markdown_docs/server/chat/knowledge_base_chat.md new file mode 100644 index 000000000..4d1974eeb --- /dev/null +++ b/markdown_docs/server/chat/knowledge_base_chat.md @@ -0,0 +1,64 @@ +## FunctionDef knowledge_base_chat(query, knowledge_base_name, top_k, score_threshold, history, stream, model_name, temperature, max_tokens, prompt_name, request) +**knowledge_base_chat**: 该函数用于处理用户与知识库的交互对话。 + +**参数**: +- `query`: 用户的输入查询,类型为字符串。 +- `knowledge_base_name`: 知识库的名称,类型为字符串。 +- `top_k`: 匹配向量数,类型为整数。 +- `score_threshold`: 知识库匹配相关度阈值,取值范围在0-1之间,类型为浮点数。 +- `history`: 历史对话列表,每个元素为一个`History`对象。 +- `stream`: 是否以流式输出,类型为布尔值。 +- `model_name`: LLM模型名称,类型为字符串。 +- `temperature`: LLM采样温度,类型为浮点数。 +- `max_tokens`: 限制LLM生成Token数量,类型为整数或None。 +- `prompt_name`: 使用的prompt模板名称,类型为字符串。 +- `request`: 当前的请求对象,类型为`Request`。 + +**代码描述**: +函数首先通过`KBServiceFactory.get_service_by_name`方法获取指定名称的知识库服务实例。如果未找到对应的知识库,将返回404状态码的响应。然后,将传入的历史对话数据转换为`History`对象列表。接下来,定义了一个异步生成器`knowledge_base_chat_iterator`,用于处理知识库查询和LLM模型生成回答的逻辑。在这个生成器中,首先根据条件调整`max_tokens`的值,然后创建LLM模型实例,并执行文档搜索。如果启用了重排序(reranker),则对搜索结果进行重排序处理。根据搜索结果构建上下文,并生成LLM模型的输入提示。最后,使用LLM模型生成回答,并根据`stream`参数决定是以流式输出还是一次性输出所有结果。 + +**注意**: +- 在调用此函数时,需要确保传入的知识库名称在系统中已经存在,否则会返回404错误。 +- `history`参数允许传入空列表,表示没有历史对话。 +- `stream`参数控制输出模式,当设置为True时,将以流式输出回答和文档信息;否则,将一次性返回所有内容。 +- 函数内部使用了多个异步操作,因此在调用时需要使用`await`关键字。 + +**输出示例**: +调用`knowledge_base_chat`函数可能返回的JSON格式示例: +```json +{ + "answer": "这是根据您的查询生成的回答。", + "docs": [ + "出处 [1] [文档名称](文档链接) \n\n文档内容\n\n", + "未找到相关文档,该回答为大模型自身能力解答!" + ] +} +``` +如果启用了流式输出,每个生成的回答片段和文档信息将作为独立的JSON对象逐个发送。 +### FunctionDef knowledge_base_chat_iterator(query, top_k, history, model_name, prompt_name) +**knowledge_base_chat_iterator**: 此函数的功能是异步迭代生成基于知识库的聊天回答。 + +**参数**: +- `query`: 字符串类型,用户的查询内容。 +- `top_k`: 整型,指定返回的最相关文档数量。 +- `history`: 可选的历史记录列表,每个历史记录是一个`History`对象。 +- `model_name`: 字符串类型,默认为`model_name`,指定使用的模型名称。 +- `prompt_name`: 字符串类型,默认为`prompt_name`,指定使用的提示模板名称。 + +**代码描述**: +`knowledge_base_chat_iterator`函数是一个异步生成器,用于处理用户的查询请求,并基于知识库内容异步生成聊天回答。首先,函数检查`max_tokens`的有效性,并根据需要调整其值。接着,使用`get_ChatOpenAI`函数初始化一个聊天模型实例,该模型配置了模型名称、温度、最大token数和回调函数。 + +函数通过`run_in_threadpool`异步运行`search_docs`函数,根据用户的查询内容在知识库中搜索相关文档。如果启用了重排序功能(`USE_RERANKER`),则使用`LangchainReranker`类对搜索结果进行重排序,以提高结果的相关性。 + +根据搜索到的文档数量,函数选择相应的提示模板。如果没有找到相关文档,使用“empty”模板;否则,使用指定的`prompt_name`模板。然后,将历史记录和用户的查询请求转换为聊天提示模板。 + +使用`LLMChain`类创建一个聊天链,并通过`wrap_done`函数包装异步任务,以便在任务完成时进行回调处理。函数还生成了源文档的信息,包括文档的出处和内容。 + +最后,根据是否启用流式传输(`stream`),函数以不同方式异步生成聊天回答。如果启用流式传输,使用服务器发送事件(server-sent-events)逐个发送回答的token;否则,将所有token拼接后一次性返回。 + +**注意**: +- 在使用此函数时,需要确保提供的`model_name`和`prompt_name`在系统中已配置且有效。 +- 当启用重排序功能时,需要确保`LangchainReranker`类的配置正确,包括模型路径和设备类型。 +- 函数的异步特性要求调用者使用`async`和`await`关键字进行调用,以确保异步操作的正确执行。 +- 在处理大量查询请求时,合理配置`top_k`和重排序参数可以有效提高处理效率和回答质量。 +*** diff --git a/markdown_docs/server/chat/search_engine_chat.md b/markdown_docs/server/chat/search_engine_chat.md new file mode 100644 index 000000000..87ecb0b0d --- /dev/null +++ b/markdown_docs/server/chat/search_engine_chat.md @@ -0,0 +1,207 @@ +## FunctionDef bing_search(text, result_len) +**bing_search**: 此函数用于通过Bing搜索引擎进行文本搜索并返回搜索结果。 + +**参数**: +- `text`: 需要搜索的文本内容。 +- `result_len`: 返回的搜索结果数量,默认为`SEARCH_ENGINE_TOP_K`。 +- `**kwargs`: 接受额外的关键字参数,用于扩展或自定义搜索行为。 + +**代码描述**: +`bing_search`函数首先检查环境变量中是否设置了`BING_SEARCH_URL`和`BING_SUBSCRIPTION_KEY`。如果这两个环境变量未设置,函数将返回一个包含错误信息的字典,提示用户需要设置这些环境变量。错误信息包括一个提示信息、一个标题以及一个链接,该链接指向相关的帮助文档。 + +如果环境变量设置正确,函数将创建一个`BingSearchAPIWrapper`实例,使用提供的`BING_SUBSCRIPTION_KEY`和`BING_SEARCH_URL`。然后,使用此实例调用`results`方法,传入需要搜索的文本(`text`)和结果数量(`result_len`)。最后,返回搜索结果。 + +**注意**: +- 确保在使用此函数之前已正确设置环境变量`BING_SEARCH_URL`和`BING_SUBSCRIPTION_KEY`,否则将无法执行搜索操作。 +- `result_len`参数允许调用者自定义返回的搜索结果数量,但实际返回结果也受Bing搜索API的限制。 +- 通过`**kwargs`参数,可以传递额外的搜索选项给Bing搜索API,但需要确保这些选项是API支持的。 + +**输出示例**: +```python +[ + { + "snippet": "这是搜索结果的摘要", + "title": "搜索结果标题", + "link": "https://example.com/search-result" + }, + { + "snippet": "这是另一个搜索结果的摘要", + "title": "另一个搜索结果标题", + "link": "https://example.com/another-search-result" + } +] +``` +此示例展示了函数可能返回的搜索结果列表,每个结果包含`snippet`(摘要)、`title`(标题)和`link`(链接)。 +## FunctionDef duckduckgo_search(text, result_len) +**duckduckgo_search**: 此函数用于通过DuckDuckGo搜索引擎执行文本搜索并返回结果。 + +**参数**: +- `text`: 需要搜索的文本。 +- `result_len`: 返回结果的数量,默认值为`SEARCH_ENGINE_TOP_K`,这是一个预设的常量,用于指定默认的返回结果数量。 +- `**kwargs`: 接受额外的关键字参数,这些参数可以用于扩展或自定义搜索行为。 + +**代码描述**: +`duckduckgo_search`函数首先创建了一个`DuckDuckGoSearchAPIWrapper`的实例,这是一个封装了DuckDuckGo搜索API调用的类。通过这个实例,函数使用`results`方法执行搜索。`text`参数是用户希望搜索的文本内容,而`result_len`参数指定了希望返回的搜索结果数量。如果调用时没有指定`result_len`,则会使用`SEARCH_ENGINE_TOP_K`作为默认值。此外,函数还接受任何额外的关键字参数(`**kwargs`),这提供了额外的灵活性,允许调用者根据需要传递更多的参数给搜索API。 + +**注意**: +- 确保在使用此函数之前已正确设置和配置了`DuckDuckGoSearchAPIWrapper`类,包括任何必要的认证信息或API密钥。 +- `SEARCH_ENGINE_TOP_K`是一个预定义常量,需要在使用此函数之前定义。它决定了在未明确指定结果数量时返回的默认结果数量。 +- 由于`**kwargs`提供了额外的参数传递功能,使用时应注意只包含DuckDuckGo搜索API支持的参数,以避免发生错误。 + +**输出示例**: +```python +[ + {"title": "DuckDuckGo", "snippet": "DuckDuckGo是一个注重隐私的搜索引擎。", "url": "https://duckduckgo.com"}, + {"title": "DuckDuckGo隐私政策", "snippet": "了解DuckDuckGo如何保护您的隐私。", "url": "https://duckduckgo.com/privacy"} +] +``` +此输出示例展示了一个可能的返回值,其中包含了搜索结果的列表。每个结果是一个字典,包含标题(`title`)、摘要(`snippet`)和URL(`url`)。实际返回的结果将根据搜索的文本和结果数量的指定而有所不同。 +## FunctionDef metaphor_search(text, result_len, split_result, chunk_size, chunk_overlap) +**metaphor_search**: 此函数的功能是基于给定文本进行隐喻搜索,并返回搜索结果的列表。 + +**参数**: +- `text`: 需要搜索的文本,类型为字符串。 +- `result_len`: 返回结果的最大数量,默认为`SEARCH_ENGINE_TOP_K`。 +- `split_result`: 是否将搜索结果分割成更小的文本块,默认为`False`。 +- `chunk_size`: 分割文本块的大小,默认为500个字符。 +- `chunk_overlap`: 分割文本块时的重叠字符数,默认为`OVERLAP_SIZE`。 + +**代码描述**: +此函数首先检查是否提供了`METAPHOR_API_KEY`,如果没有提供,则直接返回空列表。如果提供了,函数将使用此API密钥创建一个`Metaphor`客户端,并使用该客户端对给定的文本进行搜索。搜索结果的数量由`result_len`参数控制,且默认启用自动提示功能。 + +搜索结果中的每个条目都会通过`markdownify`函数转换其摘要部分,以便更好地展示。 + +如果`split_result`参数为`True`,函数将对每个搜索结果的内容进行分割,以生成更小的文本块。这些文本块通过`RecursiveCharacterTextSplitter`根据给定的分割符和`chunk_size`、`chunk_overlap`参数进行分割。然后,基于与原始搜索文本的相似度,选择相似度最高的`result_len`个文本块作为最终结果。 + +如果`split_result`为`False`,则直接返回搜索结果的摘要、链接和标题。 + +**注意**: +- 确保在使用此函数之前已正确设置`METAPHOR_API_KEY`。 +- `SEARCH_ENGINE_TOP_K`和`OVERLAP_SIZE`需要根据实际情况预先定义。 +- 分割结果的功能适用于需要对长文本进行进一步分析的场景。 + +**输出示例**: +```python +[ + { + "snippet": "这是搜索结果的一个示例文本片段。", + "link": "https://example.com/link-to-source", + "title": "示例文本标题" + }, + # 更多搜索结果... +] +``` +此输出示例展示了当`split_result`为`False`时,函数可能返回的搜索结果的格式。每个结果包含了文本片段(`snippet`)、源链接(`link`)和标题(`title`)。 +## FunctionDef search_result2docs(search_results) +**search_result2docs**: 此函数的功能是将搜索结果转换为文档列表。 + +**参数**: +- search_results: 搜索结果的列表,每个结果是一个包含至少一个“snippet”、“link”和“title”键的字典。 + +**代码描述**: +`search_result2docs`函数接收一个搜索结果列表作为输入,遍历这个列表,并为每个结果创建一个`Document`对象。这个`Document`对象包含页面内容(由结果中的“snippet”键提供,如果不存在则为空字符串)、来源链接(由“link”键提供,如果不存在则为空字符串)和文件名(由“title”键提供,如果不存在则为空字符串)。这些信息被存储在`Document`对象的`page_content`和`metadata`属性中。最后,所有创建的`Document`对象被收集到一个列表中并返回。 + +在项目中,`search_result2docs`函数被`lookup_search_engine`函数调用,用于处理从特定搜索引擎返回的搜索结果。`lookup_search_engine`函数首先根据给定的查询参数和搜索引擎名称,通过搜索引擎获取搜索结果,然后调用`search_result2docs`函数将这些搜索结果转换为`Document`对象的列表,以便进一步处理或展示。 + +**注意**: +- 确保传入的搜索结果列表格式正确,每个结果字典至少包含“snippet”、“link”和“title”三个键。 +- 函数的输出依赖于输入的搜索结果的质量和完整性。 + +**输出示例**: +假设`search_results`参数是以下列表: +```python +[ + {"snippet": "这是搜索结果的摘要", "link": "https://example.com", "title": "示例标题"}, + {"snippet": "第二个搜索结果的摘要", "link": "https://example2.com", "title": "第二个示例标题"} +] +``` +那么函数的返回值可能是一个包含两个`Document`对象的列表,每个对象的`page_content`分别是"这是搜索结果的摘要"和"第二个搜索结果的摘要",`metadata`包含相应的"source"和"filename"信息。 +## FunctionDef lookup_search_engine(query, search_engine_name, top_k, split_result) +**lookup_search_engine**: 此函数的功能是异步查询指定搜索引擎并返回搜索结果转换后的文档列表。 + +**参数**: +- `query`: 字符串类型,表示要在搜索引擎中查询的关键词。 +- `search_engine_name`: 字符串类型,指定要查询的搜索引擎的名称。 +- `top_k`: 整型,默认值为`SEARCH_ENGINE_TOP_K`,表示返回的搜索结果的最大数量。 +- `split_result`: 布尔类型,默认为`False`,指示是否拆分搜索结果。 + +**代码描述**: +`lookup_search_engine`函数首先通过`search_engine_name`参数从`SEARCH_ENGINES`字典中获取对应的搜索引擎函数。然后,它使用`run_in_threadpool`函数异步运行该搜索引擎函数,传入`query`、`result_len=top_k`和`split_result=split_result`作为参数,以获取搜索结果。获取到的搜索结果随后被传递给`search_result2docs`函数,该函数将搜索结果转换为文档(`Document`)对象的列表。最终,这个文档列表被返回。 + +在项目中,`lookup_search_engine`函数被`search_engine_chat_iterator`函数调用,用于获取搜索引擎的查询结果,并将这些结果转换为文档列表,以便在聊天迭代器中生成基于搜索引擎结果的聊天回复。 + +**注意**: +- 确保`search_engine_name`参数对应的搜索引擎已经在`SEARCH_ENGINES`字典中定义。 +- `top_k`参数控制返回的搜索结果数量,根据需要调整以获取最优的搜索体验。 +- `split_result`参数可以控制搜索结果是否需要被拆分,这取决于搜索引擎函数的具体实现和需求。 + +**输出示例**: +假设搜索查询返回了两个结果,函数的返回值可能是如下格式的文档列表: +```python +[ + Document(page_content="这是搜索结果的摘要", metadata={"source": "https://example.com", "filename": "示例标题"}), + Document(page_content="第二个搜索结果的摘要", metadata={"source": "https://example2.com", "filename": "第二个示例标题"}) +] +``` +这个列表中的每个`Document`对象包含了搜索结果的摘要、来源链接和标题,可用于进一步的处理或展示。 +## FunctionDef search_engine_chat(query, search_engine_name, top_k, history, stream, model_name, temperature, max_tokens, prompt_name, split_result) +**search_engine_chat**: 该函数用于通过搜索引擎检索信息,并结合历史对话和LLM模型生成回答。 + +**参数**: +- `query`: 用户输入的查询内容,类型为字符串。 +- `search_engine_name`: 指定使用的搜索引擎名称,类型为字符串。 +- `top_k`: 检索结果的数量,类型为整数。 +- `history`: 历史对话列表,每个元素为一个`History`对象。 +- `stream`: 是否以流式输出结果,类型为布尔值。 +- `model_name`: 指定使用的LLM模型名称,类型为字符串。 +- `temperature`: LLM模型采样温度,用于控制生成文本的多样性,类型为浮点数。 +- `max_tokens`: 限制LLM生成Token的数量,类型为整数或None。 +- `prompt_name`: 使用的prompt模板名称,类型为字符串。 +- `split_result`: 是否对搜索结果进行拆分,主要用于metaphor搜索引擎,类型为布尔值。 + +**代码描述**: +该函数首先检查指定的搜索引擎是否支持,如果不支持或需要的配置项未设置,将返回错误信息。然后,将历史对话列表中的数据转换为`History`对象列表。接着,定义了一个异步迭代器`search_engine_chat_iterator`,用于执行搜索操作和生成回答。在这个迭代器中,首先根据条件调整`max_tokens`的值,然后创建LLM模型实例,并执行搜索引擎查询。查询结果和历史对话将被用于构建LLM模型的输入提示,以生成回答。根据`stream`参数的值,函数将以不同的方式输出结果:如果为True,则以流式形式输出每个生成的Token和最终的文档列表;如果为False,则将所有生成的Token拼接成完整的回答后一次性输出,同时附上文档列表。最后,返回一个`EventSourceResponse`对象,包含异步迭代器的执行结果。 + +**注意**: +- 在使用该函数时,需要确保指定的搜索引擎已经在项目中支持,并且相关配置项(如API密钥)已正确设置。 +- `history`参数应为`History`对象的列表,每个对象代表一条历史对话记录。 +- 该函数支持流式输出,适用于需要实时展示生成结果的场景。 +- 函数的执行依赖于外部的LLM模型和搜索引擎服务,因此执行时间可能受到网络状况和服务响应时间的影响。 + +**输出示例**: +```json +{ + "answer": "根据您的查询,这里是生成的回答。", + "docs": [ + "出处 [1] [来源链接](http://example.com)\n\n相关文档内容。\n\n", + "出处 [2] [来源链接](http://example.com)\n\n相关文档内容。\n\n" + ] +} +``` +如果`stream`为True,输出将以多个json字符串的形式逐步发送,每个字符串包含一个Token或文档列表。如果为False,将输出一个包含完整回答和文档列表的json字符串。 +### FunctionDef search_engine_chat_iterator(query, search_engine_name, top_k, history, model_name, prompt_name) +**search_engine_chat_iterator**: 此函数的功能是异步迭代搜索引擎查询结果,并生成基于这些结果的聊天回复。 + +**参数**: +- `query`: 字符串类型,用户的查询请求。 +- `search_engine_name`: 字符串类型,指定要查询的搜索引擎名称。 +- `top_k`: 整型,指定返回的搜索结果的最大数量。 +- `history`: 可选的`List[History]`类型,表示对话历史记录。 +- `model_name`: 字符串类型,默认为`LLM_MODELS[0]`,指定使用的语言模型名称。 +- `prompt_name`: 字符串类型,指定使用的提示模板名称。 + +**代码描述**: +`search_engine_chat_iterator`函数首先检查`max_tokens`的值,如果为非正整数,则将其设置为`None`。接着,通过`get_ChatOpenAI`函数初始化一个`ChatOpenAI`实例,该实例用于生成基于语言模型的聊天回复。函数使用`lookup_search_engine`异步查询指定的搜索引擎,获取搜索结果,并将这些结果转换为文本形式的上下文。 + +接下来,函数通过`get_prompt_template`获取指定的提示模板,并结合对话历史记录,构造出完整的聊天提示。这个提示将作为语言模型的输入,以生成聊天回复。函数创建一个异步任务,使用`wrap_done`函数包装这个任务,以便在任务完成或发生异常时进行通知。 + +函数还处理了搜索结果的文档来源信息,将其格式化为特定的字符串列表。如果没有找到相关文档,会添加一条特定的消息表示未找到相关文档。 + +最后,根据`stream`变量的值,函数可能以流式传输的方式逐个生成聊天回复,或者将所有回复合并后一次性返回。在流式传输模式下,每个生成的回复都会被立即发送给客户端,而在非流式模式下,则会等待所有回复生成完成后统一返回。 + +**注意**: +- 在使用此函数时,需要确保提供的`search_engine_name`对应于已配置的搜索引擎。 +- `history`参数允许包含对话的历史记录,这对于生成更加连贯和上下文相关的回复非常重要。 +- 函数利用了异步编程模式,因此在调用此函数时应注意使用`await`关键字。 +- 在处理大量或复杂的查询时,函数的执行时间可能较长,因此在设计用户界面和交互逻辑时应考虑到潜在的延迟。 +*** diff --git a/markdown_docs/server/chat/utils.md b/markdown_docs/server/chat/utils.md new file mode 100644 index 000000000..b78f65dbd --- /dev/null +++ b/markdown_docs/server/chat/utils.md @@ -0,0 +1,102 @@ +## ClassDef History +**History**: History 类用于表示对话历史记录。 + +**属性**: +- `role`: 表示发言角色,类型为字符串。 +- `content`: 表示发言内容,类型为字符串。 + +**代码描述**: +History 类继承自 BaseModel,用于封装对话中的单条历史记录,包括发言角色和发言内容。它提供了将历史记录转换为消息元组的方法 `to_msg_tuple`,以及将历史记录转换为消息模板的方法 `to_msg_template`。此外,还提供了一个类方法 `from_data`,用于从不同类型的数据结构(列表、元组、字典)创建 History 实例。 + +在项目中,History 类被广泛用于处理和存储对话历史记录。例如,在 `agent_chat` 和 `chat` 等功能中,通过将用户输入和历史对话记录作为参数传递给模型,以生成相应的回复。这些历史记录通过 History 类的实例来管理和传递,确保了数据的一致性和易用性。 + +**注意**: +- 在使用 `to_msg_tuple` 方法时,如果 `role` 属性为 "assistant",则返回的元组中角色部分为 "ai",否则为 "human",这有助于在处理对话时区分用户和助手的发言。 +- `to_msg_template` 方法支持根据是否需要原始内容(`is_raw` 参数)来调整内容的格式,这在需要对内容进行特定格式处理时非常有用。 +- `from_data` 类方法提供了灵活的数据转换功能,允许从多种数据源创建 History 实例,增加了代码的通用性和灵活性。 + +**输出示例**: +假设有以下历史记录数据: +```python +data = {"role": "user", "content": "你好"} +``` +使用 History 类创建实例并转换为消息元组: +```python +h = History.from_data(data) +print(h.to_msg_tuple()) +``` +可能的输出为: +``` +('human', '你好') +``` +转换为消息模板时,假设不需要原始内容处理: +```python +print(h.to_msg_template(is_raw=False)) +``` +输出将根据实际的模板格式化内容,其中角色和内容将被相应地替换和处理。 +### FunctionDef to_msg_tuple(self) +**to_msg_tuple**: 此函数的功能是将消息对象转换为一个包含角色和内容的元组。 + +**参数**: 此函数没有显式参数,但隐式使用了self参数,代表调用此函数的History对象实例。 + +**代码描述**: `to_msg_tuple`函数是History类的一个方法,用于将消息对象的角色和内容转换成一个元组。此函数首先检查消息对象的`role`属性。如果`role`属性值为"assistant",则元组的第一个元素为字符串"ai";否则,第一个元素为字符串"human"。元组的第二个元素是消息对象的`content`属性值,即消息的内容。这样,通过`to_msg_tuple`方法可以快速地获取消息的角色和内容信息,便于后续处理或显示。 + +**注意**: 使用此函数时,需要确保调用它的History对象实例已经正确设置了`role`和`content`属性,否则可能会遇到属性不存在的错误。 + +**输出示例**: 假设一个History对象实例的`role`属性为"assistant",`content`属性为"你好,我是AI助手。",那么调用`to_msg_tuple`方法的返回值将会是: + +```python +("ai", "你好,我是AI助手。") +``` + +如果`role`属性为其他值,比如"user",并且`content`属性为"这是一个用户消息。",那么返回值将会是: + +```python +("human", "这是一个用户消息。") +``` + +这种方式使得消息的角色和内容可以被快速地识别和使用,对于消息处理和展示非常有用。 +*** +### FunctionDef to_msg_template(self, is_raw) +**to_msg_template**: 该函数的功能是将历史消息转换为特定的消息模板格式。 + +**参数**: +- `is_raw`: 布尔值,指示是否将消息内容作为原始文本处理。默认为True。 + +**代码描述**: +`to_msg_template`函数是`History`类的一个方法,用于将历史消息转换为`ChatMessagePromptTemplate`格式,以便进一步处理和使用。该函数首先定义了一个角色映射字典`role_maps`,将"ai"映射为"assistant",将"human"映射为"user"。然后,根据`History`对象的`role`属性查找相应的角色,如果找不到,则使用`role`属性的原始值。 + +根据`is_raw`参数的值,函数决定是否将消息内容包裹在"{% raw %}"和"{% endraw %}"标签中。这主要用于处理消息内容中可能包含的Jinja2模板标签,以避免在后续处理中被错误地解释或执行。如果`is_raw`为True,则消息内容被包裹;否则,保持原样不变。 + +最后,函数使用`ChatMessagePromptTemplate.from_template`方法,将处理后的内容、"jinja2"字符串(表示使用的模板类型)和角色作为参数,创建并返回一个`ChatMessagePromptTemplate`对象。 + +在项目中,`to_msg_template`方法被多个异步迭代器函数调用,这些函数负责处理不同类型的聊天会话,如`chat_iterator`、`knowledge_base_chat_iterator`和`search_engine_chat_iterator`等。在这些函数中,`to_msg_template`方法用于将历史消息或用户输入转换为适合模型处理的格式,进而生成聊天提示或查询模板。 + +**注意**: +- 当使用`to_msg_template`方法时,需要注意`is_raw`参数的使用场景。如果消息内容中包含需要保留的模板标签,则应将`is_raw`设置为True。 +- 该方法依赖于`ChatMessagePromptTemplate.from_template`方法,因此需要确保`ChatMessagePromptTemplate`类及其方法的正确实现。 + +**输出示例**: +假设有一个`History`对象,其`role`为"human",`content`为"Hello, AI!",调用`to_msg_template(False)`可能会返回如下`ChatMessagePromptTemplate`对象: +```python +ChatMessagePromptTemplate(content="Hello, AI!", template_type="jinja2", role="user") +``` +*** +### FunctionDef from_data(cls, h) +**from_data**: 该函数用于根据提供的数据创建一个History对象。 + +**参数**: +- `h`: 可以是列表、元组或字典类型,用于初始化History对象的数据。 + +**代码描述**: +`from_data`函数是一个类方法,用于根据不同类型的输入数据创建一个History对象。该函数接受一个参数`h`,这个参数可以是列表、元组或字典类型。如果`h`是列表或元组,并且长度至少为2,那么会使用列表或元组的前两个元素作为History对象的`role`和`content`属性进行初始化。如果`h`是字典类型,那么会将字典中的键值对作为参数通过解包的方式传递给History类的构造函数,从而创建History对象。无论输入数据的类型如何,该函数最终都会返回一个History对象。 + +在项目中,`from_data`函数被多个地方调用,用于将用户的输入或历史对话数据转换为History对象,以便后续处理。例如,在`agent_chat`、`chat_iterator`、`file_chat`、`knowledge_base_chat`和`search_engine_chat`等函数中,都可以看到`from_data`函数的调用,它们通过这个函数将传入的历史对话列表转换为History对象列表,以便进行进一步的处理和分析。 + +**注意**: +- 当输入参数`h`为列表或元组时,至少需要包含两个元素,分别代表角色和内容,否则无法正确创建History对象。 +- 当输入参数`h`为字典时,需要确保字典中包含的键与History类的构造函数参数相匹配,以便正确初始化对象。 + +**输出示例**: +假设输入参数`h`为列表`["user", "今天天气怎么样?"]`,则函数返回的History对象将具有属性`role="user"`和`content="今天天气怎么样?"`。如果输入参数`h`为字典`{"role": "assistant", "content": "今天是晴天。"}`,则返回的History对象将具有相同的属性值。 +*** diff --git a/markdown_docs/server/db/models/base.md b/markdown_docs/server/db/models/base.md new file mode 100644 index 000000000..c712fd0ce --- /dev/null +++ b/markdown_docs/server/db/models/base.md @@ -0,0 +1,21 @@ +## ClassDef BaseModel +**BaseModel**: BaseModel 的功能是提供一个数据库模型的基础结构。 + +**属性**: +- `id`: 主键ID,用于唯一标识每个记录。 +- `create_time`: 记录的创建时间。 +- `update_time`: 记录的最后更新时间。 +- `create_by`: 记录的创建者。 +- `update_by`: 记录的最后更新者。 + +**代码描述**: +BaseModel 类定义了一个数据库模型的基础结构,它包含了几个常见且重要的字段。这些字段包括: +- `id` 字段使用 `Column` 函数定义,其类型为 `Integer`,并且被设置为主键(`primary_key=True`),同时启用索引(`index=True`),以便提高查询效率。此外,该字段还有一个注释(`comment="主键ID"`),用于说明字段的用途。 +- `create_time` 字段记录了数据被创建的时间,其类型为 `DateTime`。该字段的默认值通过 `datetime.utcnow` 函数设置,以确保使用的是创建记录时的UTC时间。此字段同样有一个注释(`comment="创建时间"`)。 +- `update_time` 字段记录了数据最后一次被更新的时间,类型也是 `DateTime`。不同的是,它的默认值设置为 `None`,并且通过 `onupdate=datetime.utcnow` 参数设置,当记录更新时,此字段会自动更新为当前的UTC时间。该字段也有相应的注释(`comment="更新时间"`)。 +- `create_by` 和 `update_by` 字段用于记录数据的创建者和最后更新者的信息,它们的类型都是 `String`。默认值为 `None`,并且各自有对应的注释(`comment="创建者"` 和 `comment="更新者"`),用于说明字段的用途。 + +**注意**: +- 使用BaseModel时,需要注意`create_time`和`update_time`字段默认使用的是UTC时间,这意味着如果应用程序在不同的时区运行,可能需要进行相应的时区转换。 +- `id`字段被设置为主键和索引,这对于数据库性能优化是非常重要的。确保每个模型都有一个唯一的标识符。 +- `create_by` 和 `update_by` 字段的默认值为 `None`,在实际应用中,根据业务需求,可能需要在数据创建或更新时,显式地设置这些字段的值。 diff --git a/markdown_docs/server/db/models/conversation_model.md b/markdown_docs/server/db/models/conversation_model.md new file mode 100644 index 000000000..e11157993 --- /dev/null +++ b/markdown_docs/server/db/models/conversation_model.md @@ -0,0 +1,41 @@ +## ClassDef ConversationModel +**ConversationModel**: ConversationModel类的功能是定义一个聊天记录模型,用于数据库中存储聊天会话的详细信息。 + +**属性**: +- `id`: 对话框ID,是每个对话框的唯一标识符,使用String类型。 +- `name`: 对话框名称,存储对话框的名称,使用String类型。 +- `chat_type`: 聊天类型,标识聊天的类型(如普通聊天、客服聊天等),使用String类型。 +- `create_time`: 创建时间,记录对话框创建的时间,使用DateTime类型,默认值为当前时间。 + +**代码描述**: +ConversationModel类继承自Base类,是一个ORM模型,用于映射数据库中的`conversation`表。该模型包含四个字段:`id`、`name`、`chat_type`和`create_time`,分别用于存储对话框的唯一标识符、名称、聊天类型和创建时间。其中,`id`字段被设置为主键。此外,该类还重写了`__repr__`方法,以便在打印实例时能够清晰地显示出实例的主要信息。 + +在项目中,ConversationModel类被用于创建和管理聊天记录的数据。例如,在`server/db/repository/conversation_repository.py`中的`add_conversation_to_db`函数中,通过创建ConversationModel的实例并将其添加到数据库会话中,实现了聊天记录的新增功能。这显示了ConversationModel类在项目中用于处理聊天记录数据的重要角色。 + +**注意**: +- 在使用ConversationModel进行数据库操作时,需要确保传入的参数类型与字段定义相匹配,避免类型不匹配的错误。 +- 创建ConversationModel实例时,`id`字段可以不传入,由数据库自动生成唯一标识符,但在`add_conversation_to_db`函数中,如果没有提供`conversation_id`,则会使用`uuid.uuid4().hex`生成一个。 + +**输出示例**: +假设创建了一个ConversationModel实例,其属性值如下: +- id: "1234567890abcdef" +- name: "客服对话" +- chat_type: "agent_chat" +- create_time: "2023-04-01 12:00:00" + +则该实例的`__repr__`方法输出可能如下: +``` + +``` +### FunctionDef __repr__(self) +**__repr__**: 该函数的功能是生成并返回一个代表会话对象的字符串。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `__repr__` 方法是一个特殊方法,用于定义一个对象的“官方”字符串表示。在这个场景中,`__repr__` 被定义在 `ConversationModel` 类中,目的是为了提供一个清晰且易于理解的会话对象表示。当调用此方法时,它会返回一个格式化的字符串,其中包含了会话对象的几个关键属性:`id`、`name`、`chat_type` 和 `create_time`。这些属性通过 `self` 关键字访问,表示它们属于当前的会话实例。字符串使用 f-string 格式化,这是 Python 3.6 及以上版本中引入的一种字符串格式化机制,允许将表达式的值直接嵌入到字符串常量中。 + +**注意**: 使用 `__repr__` 方法的一个重要原则是,其返回的字符串应尽可能地反映出对象的重要信息,且最好能够通过执行这个字符串(假设环境中有正确的上下文)来重新创建出该对象。虽然在许多实际情况下,直接执行 `__repr__` 返回的字符串来复制对象并不是必需的,但这一原则仍然是一个很好的指导思想。此外,当你在调试过程中打印对象或在交互式环境中查看对象时,`__repr__` 方法返回的字符串将会被显示,这有助于快速识别对象的状态。 + +**输出示例**: 假设有一个会话对象,其 `id` 为 "123",`name` 为 "Test Conversation",`chat_type` 为 "group",`create_time` 为 "2023-04-01",则调用 `__repr__` 方法将返回如下字符串: +`""` +*** diff --git a/markdown_docs/server/db/models/knowledge_base_model.md b/markdown_docs/server/db/models/knowledge_base_model.md new file mode 100644 index 000000000..d47c826db --- /dev/null +++ b/markdown_docs/server/db/models/knowledge_base_model.md @@ -0,0 +1,54 @@ +## ClassDef KnowledgeBaseModel +**KnowledgeBaseModel**: KnowledgeBaseModel 类的功能是定义知识库的数据模型,用于在数据库中存储和管理知识库的相关信息。 + +**属性**: +- `id`: 知识库ID,是每个知识库的唯一标识。 +- `kb_name`: 知识库名称,用于标识和检索特定的知识库。 +- `kb_info`: 知识库简介,提供关于知识库的基本信息,用于Agent。 +- `vs_type`: 向量库类型,指定知识库使用的向量库的类型。 +- `embed_model`: 嵌入模型名称,指定用于知识库的嵌入模型。 +- `file_count`: 文件数量,记录知识库中包含的文件数目。 +- `create_time`: 创建时间,记录知识库被创建的时间。 + +**代码描述**: +KnowledgeBaseModel 类继承自 Base 类,是一个ORM模型,用于映射数据库中的 `knowledge_base` 表。该类定义了知识库的基本属性,包括知识库ID、名称、简介、向量库类型、嵌入模型名称、文件数量和创建时间。通过这些属性,可以在数据库中有效地存储和管理知识库的相关信息。 + +在项目中,KnowledgeBaseModel 类被多个函数调用,以实现对知识库的增删查改操作。例如,在 `add_kb_to_db` 函数中,使用KnowledgeBaseModel 来创建新的知识库实例或更新现有知识库的信息。在 `list_kbs_from_db` 函数中,通过查询KnowledgeBaseModel 来获取满足特定条件的知识库列表。此外,`kb_exists`、`load_kb_from_db`、`delete_kb_from_db` 和 `get_kb_detail` 等函数也都涉及到对KnowledgeBaseModel 类的操作,以实现检查知识库是否存在、加载知识库信息、删除知识库和获取知识库详细信息等功能。 + +**注意**: +在使用KnowledgeBaseModel 类进行数据库操作时,需要注意确保传入的参数类型和值符合定义的属性类型和业务逻辑要求,以避免数据类型错误或逻辑错误。 + +**输出示例**: +假设数据库中有一个知识库实例,其属性值如下: +``` + +``` +这表示有一个ID为1的知识库,名称为“技术文档库”,简介为“存储技术相关文档”,使用的向量库类型为ElasticSearch,嵌入模型为BERT,包含100个文件,创建时间为2023年4月1日12点。 +### FunctionDef __repr__(self) +**__repr__**: __repr__函数的功能是提供KnowledgeBaseModel对象的官方字符串表示。 + +**参数**: 此函数没有接受额外参数,它仅使用self来访问对象的属性。 + +**代码描述**: +`__repr__`方法定义在KnowledgeBaseModel类中,用于生成该对象的官方字符串表示。这个字符串表示包含了对象的关键信息,使得开发者和调试者能够更容易地识别对象。具体来说,它返回一个格式化的字符串,其中包含了KnowledgeBaseModel对象的多个属性值,包括: +- `id`:对象的唯一标识符。 +- `kb_name`:知识库的名称。 +- `kb_info`:知识库的简介。 +- `vs_type`:知识库的版本类型。 +- `embed_model`:嵌入模型的名称。 +- `file_count`:知识库中文件的数量。 +- `create_time`:知识库创建的时间。 + +这个方法通过f-string格式化字符串的方式,将对象属性嵌入到预定义的字符串模板中,从而生成易于阅读和理解的表示形式。 + +**注意**: +- `__repr__`方法通常用于调试和日志记录,它应该返回一个明确且无歧义的对象表示。 +- 在Python中,当你尝试将对象转换为字符串时(例如使用`str()`函数或在打印时),如果没有定义`__str__`方法,Python会回退到使用`__repr__`方法。 +- 保证`__repr__`方法返回的字符串包含足够的信息,可以用来识别对象中的关键信息。 + +**输出示例**: +```python + +``` +此示例展示了一个KnowledgeBaseModel对象的`__repr__`方法返回值的可能形式,其中包含了对象的id, kb_name, kb_intro, vs_type, embed_model, file_count, 和 create_time属性的值。 +*** diff --git a/markdown_docs/server/db/models/knowledge_file_model.md b/markdown_docs/server/db/models/knowledge_file_model.md new file mode 100644 index 000000000..18677edfd --- /dev/null +++ b/markdown_docs/server/db/models/knowledge_file_model.md @@ -0,0 +1,97 @@ +## ClassDef KnowledgeFileModel +**KnowledgeFileModel**: KnowledgeFileModel类用于表示知识库中的文件信息。 + +**属性**: +- `id`: 知识文件的唯一标识ID。 +- `file_name`: 文件名。 +- `file_ext`: 文件扩展名。 +- `kb_name`: 所属知识库的名称。 +- `document_loader_name`: 文档加载器的名称。 +- `text_splitter_name`: 文本分割器的名称。 +- `file_version`: 文件版本。 +- `file_mtime`: 文件的最后修改时间。 +- `file_size`: 文件大小。 +- `custom_docs`: 标识是否为自定义文档。 +- `docs_count`: 切分文档的数量。 +- `create_time`: 文件的创建时间。 + +**代码描述**: +KnowledgeFileModel类继承自Base类,是一个ORM模型,用于映射数据库中的`knowledge_file`表。该模型定义了与知识文件相关的各种属性,包括文件名、文件扩展名、所属知识库名称、文档加载器名称、文本分割器名称等。此外,还包括文件的版本、修改时间、大小、是否自定义文档、切分文档数量以及创建时间等信息。 + +在项目中,KnowledgeFileModel类被多个函数调用,主要涉及到知识文件的增删查改操作。例如,`count_files_from_db`函数用于统计某个知识库中的文件数量,`list_files_from_db`函数用于列出某个知识库中的所有文件名,`add_file_to_db`函数用于向数据库中添加新的知识文件或更新现有文件的信息,`delete_file_from_db`和`delete_files_from_db`函数用于从数据库中删除指定的文件或某个知识库中的所有文件,`file_exists_in_db`函数用于检查某个文件是否已存在于数据库中,`get_file_detail`函数用于获取某个文件的详细信息。 + +**注意**: +- 在使用KnowledgeFileModel进行数据库操作时,需要确保传入的参数符合字段定义的类型和约束。 +- 对于文件版本、修改时间和大小等信息,在更新文件信息时应注意正确维护这些字段的值,以保证数据的准确性和一致性。 + +**输出示例**: +由于KnowledgeFileModel是一个ORM模型,直接操作该类的实例不会产生简单的输出结果。但是,当使用`__repr__`方法打印KnowledgeFileModel的实例时,可能会得到如下格式的字符串表示: +``` + +``` +### FunctionDef __repr__(self) +**__repr__**: 此函数的功能是生成KnowledgeFileModel对象的官方字符串表示。 + +**参数**: 此函数不接受除self之外的任何参数。 + +**代码描述**: `__repr__`方法是Python中的一个特殊方法,用于定义对象的“官方”字符串表示。在这个上下文中,`__repr__`方法被用于KnowledgeFileModel类,这是一个数据库模型类,代表知识文件。当调用此方法时,它会返回一个格式化的字符串,其中包含了KnowledgeFileModel对象的关键信息,包括:id、file_name(文件名)、file_ext(文件扩展名)、kb_name(知识库名称)、document_loader_name(文档加载器名称)、text_splitter_name(文本分割器名称)、file_version(文件版本)和create_time(创建时间)。这种字符串表示形式非常有用,尤其是在调试和日志记录中,因为它提供了对象的快速概览。 + +**注意**: `__repr__`方法返回的字符串应该尽可能地反映对象的状态,同时保持简洁明了。在实际应用中,开发者可能会根据需要调整包含在`__repr__`返回值中的属性。此外,虽然`__repr__`的主要目的是为了调试和开发,但它也可以被用于用户界面显示,尤其是在需要快速展示对象信息的场景中。 + +**输出示例**: 假设有一个KnowledgeFileModel对象,其属性值如下: +- id: 1 +- file_name: "example.pdf" +- file_ext: ".pdf" +- kb_name: "General Knowledge" +- document_loader_name: "DefaultLoader" +- text_splitter_name: "SimpleSplitter" +- file_version: "v1.0" +- create_time: "2023-04-01 12:00:00" + +调用此对象的`__repr__`方法将返回以下字符串: +`""` +*** +## ClassDef FileDocModel +**FileDocModel**: FileDocModel类用于表示文件与向量库文档之间的关系模型。 + +**属性**: +- `id`: 唯一标识符,自增长的整数,用于唯一标识每个文档。 +- `kb_name`: 知识库名称,字符串类型,表示该文档所属的知识库。 +- `file_name`: 文件名称,字符串类型,表示该文档对应的原始文件名。 +- `doc_id`: 向量库文档ID,字符串类型,用于标识向量库中的文档。 +- `meta_data`: 元数据,JSON类型,默认为空字典,用于存储文档的额外信息。 + +**代码描述**: +FileDocModel类继承自Base类,是一个ORM模型,用于映射数据库中的`file_doc`表。该模型定义了与文件和向量库文档相关的基本信息字段,包括知识库名称、文件名称、文档ID以及元数据。此外,通过定义`__repr__`方法,可以提供该模型实例的友好字符串表示,便于调试和日志记录。 + +在项目中,FileDocModel类被多个函数调用,主要用于处理与数据库中文档相关的操作,如添加、查询、删除文档信息。例如,在`add_docs_to_db`函数中,通过创建FileDocModel的实例并添加到数据库会话中,实现了将文档信息添加到数据库的功能。在`list_file_num_docs_id_by_kb_name_and_file_name`函数中,通过查询FileDocModel实例,实现了根据知识库名称和文件名称列出所有对应文档ID的功能。此外,`delete_docs_from_db`和`list_docs_from_db`等函数也展示了如何利用FileDocModel进行文档的查询和删除操作。 + +**注意**: +- 在使用FileDocModel进行数据库操作时,需要确保传入的参数类型和字段约束条件符合定义,以避免数据类型错误或约束违反的问题。 +- 在处理元数据(meta_data)字段时,考虑到其为JSON类型,应当注意正确的数据格式和解析方法,以保证元数据的有效存储和查询。 + +**输出示例**: +假设数据库中有一条记录,其字段值如下: +- id: 1 +- kb_name: "知识库1" +- file_name: "文件1.pdf" +- doc_id: "doc123" +- meta_data: {"author": "张三", "year": "2021"} + +则该记录的`__repr__`方法输出可能为: +`` +### FunctionDef __repr__(self) +**__repr__**: 此函数的功能是生成对象的官方字符串表示。 + +**参数**: 此函数没有参数。 + +**代码描述**: `__repr__` 方法是 Python 中的一个特殊方法,用于定义对象的“官方”字符串表示。在这个特定的实现中,`__repr__` 方法被用于 `FileDocModel` 类,该类可能代表一个与知识库文件相关的模型。此方法返回一个格式化的字符串,其中包含了对象的几个关键属性:`id`、`kb_name`(知识库名称)、`file_name`(文件名)、`doc_id`(文档ID)以及`metadata`(元数据)。这种格式化的字符串表示使得开发者能够快速识别对象的主要属性,特别是在调试过程中或者将对象输出到控制台时非常有用。 + +**注意**: 使用 `__repr__` 方法时,应确保返回的字符串能够准确反映对象的关键信息。此外,虽然此方法主要用于调试和开发,但也应注意保持返回字符串的可读性。 + +**输出示例**: 假设有一个 `FileDocModel` 对象,其属性如下:`id=1`,`kb_name='KnowledgeBase1'`,`file_name='document1.pdf'`,`doc_id='12345'`,`metadata='{"author": "John Doe", "date": "2023-04-01"}'`。调用此对象的 `__repr__` 方法将返回以下字符串: + +``` + +``` +*** diff --git a/markdown_docs/server/db/models/knowledge_metadata_model.md b/markdown_docs/server/db/models/knowledge_metadata_model.md new file mode 100644 index 000000000..ec31d6b22 --- /dev/null +++ b/markdown_docs/server/db/models/knowledge_metadata_model.md @@ -0,0 +1,41 @@ +## ClassDef SummaryChunkModel +**SummaryChunkModel**: SummaryChunkModel 类的功能是用于存储和管理文档中每个文档标识符(doc_id)的摘要信息。 + +**属性**: +- `id`: 唯一标识符,用于标识每个摘要信息的ID。 +- `kb_name`: 知识库名称,表示该摘要信息属于哪个知识库。 +- `summary_context`: 总结文本,存储自动生成或用户输入的文档摘要。 +- `summary_id`: 总结矢量id,用于后续的矢量库构建和语义关联。 +- `doc_ids`: 向量库id关联列表,存储与该摘要相关的文档标识符列表。 +- `meta_data`: 元数据,以JSON格式存储额外的信息,如页码信息等。 + +**代码描述**: +SummaryChunkModel 类定义了一个用于存储文档摘要信息的数据模型。该模型包括了文档的基本信息如知识库名称、摘要文本、摘要矢量ID、相关文档ID列表以及额外的元数据。这些信息主要来源于用户上传文件时的描述或程序自动切分文档生成的摘要。此外,该模型还支持后续的矢量库构建和语义关联任务,通过对summary_context创建索引和计算语义相似度来实现。 + +在项目中,SummaryChunkModel 被 knowledge_metadata_repository.py 文件中的多个函数调用,包括添加、删除、列出和统计知识库中的摘要信息。这些函数通过操作 SummaryChunkModel 实例来实现对数据库中摘要信息的管理,如添加新的摘要信息、删除特定知识库的摘要信息、根据知识库名称列出摘要信息以及统计特定知识库的摘要数量。 + +**注意**: +- 在使用 SummaryChunkModel 进行数据库操作时,需要确保传入的参数类型和格式正确,特别是 `meta_data` 字段,它应以正确的JSON格式存储。 +- 在进行矢量库构建和语义关联任务时,应注意 `summary_id` 和 `doc_ids` 字段的正确使用和关联。 + +**输出示例**: +假设数据库中有一个摘要信息实例,其可能的表示如下: +``` + +``` +这表示一个ID为1的摘要信息,属于“技术文档”知识库,摘要文本为“这是一个关于AI技术的摘要”,关联的文档标识符为doc1和doc2,没有额外的元数据信息。 +### FunctionDef __repr__(self) +**__repr__**: 此函数的功能是生成并返回一个代表对象状态的字符串。 + +**参数**: 此函数不接受除`self`之外的任何参数。 + +**代码描述**: `__repr__`函数是`SummaryChunkModel`类的一个特殊方法,用于创建一个代表该对象实例状态的字符串。这个字符串包含了`SummaryChunkModel`实例的几个关键属性:`id`、`kb_name`、`summary_context`、`doc_ids`以及`metadata`。这些属性通过访问实例的相应属性并将它们格式化为一个特定格式的字符串来展示。这个字符串格式遵循``的形式,其中每个`...`会被实例相应属性的实际值替换。这种表示方式便于开发者在调试过程中快速识别对象的状态。 + +**注意**: `__repr__`方法通常用于调试和日志记录,它应该返回一个明确且易于理解的对象状态描述。返回的字符串应该尽可能地反映出对象的关键属性。此外,虽然`__repr__`的主要目的不是被终端用户直接看到,但它的设计应确保在需要时能够提供足够的信息来识别对象的具体状态。 + +**输出示例**: 假设有一个`SummaryChunkModel`实例,其`id`为`123`,`kb_name`为`"KnowledgeBase1"`,`summary_context`为`"Context1"`,`doc_ids`为`"doc1, doc2"`,`metadata`为`"{'author': 'John Doe'}"`。调用此实例的`__repr__`方法将返回以下字符串: + +``` + +``` +*** diff --git a/markdown_docs/server/db/models/message_model.md b/markdown_docs/server/db/models/message_model.md new file mode 100644 index 000000000..d850c7dd1 --- /dev/null +++ b/markdown_docs/server/db/models/message_model.md @@ -0,0 +1,44 @@ +## ClassDef MessageModel +**MessageModel**: MessageModel类的功能是定义聊天记录的数据模型。 + +**属性**: +- `id`: 聊天记录的唯一标识ID。 +- `conversation_id`: 对话框ID,用于标识一次会话。 +- `chat_type`: 聊天类型,如普通聊天、客服聊天等。 +- `query`: 用户的提问或输入。 +- `response`: 系统或模型的回答。 +- `meta_data`: 存储额外信息的JSON字段,如知识库ID等,便于后续扩展。 +- `feedback_score`: 用户对聊天回答的评分,满分为100。 +- `feedback_reason`: 用户评分的理由。 +- `create_time`: 记录的创建时间。 + +**代码描述**: +MessageModel类继承自Base,用于定义聊天记录的数据结构。它包含了聊天记录的基本信息,如聊天ID、会话ID、聊天类型、用户问题、模型回答、元数据、用户反馈等。此类通过定义SQLAlchemy的Column字段来映射数据库中的`message`表结构。其中,`__tablename__`属性指定了数据库中对应的表名为`message`。每个属性都通过Column实例来定义,其中包括数据类型、是否为主键、默认值、索引创建、注释等信息。 + +在项目中,MessageModel类被用于server/db/repository/message_repository.py文件中的几个函数调用中,主要涉及到聊天记录的增加、查询和反馈。例如,`add_message_to_db`函数用于新增聊天记录,它创建了一个MessageModel实例并将其添加到数据库中。`get_message_by_id`函数通过聊天记录ID查询聊天记录。`feedback_message_to_db`函数用于更新聊天记录的用户反馈信息。`filter_message`函数则是根据对话框ID过滤聊天记录,并返回最近的几条记录。 + +**注意**: +- 在使用MessageModel进行数据库操作时,需要确保传入的参数类型与定义的字段类型相匹配。 +- 对于`meta_data`字段,虽然默认值为一个空字典,但在实际使用中可以根据需要存储任意结构的JSON数据。 +- 在进行数据库操作如添加、查询、更新记录时,应确保操作在正确的数据库会话(session)上下文中执行。 + +**输出示例**: +由于MessageModel是一个数据模型类,它本身不直接产生输出。但是,当它被实例化并用于数据库操作时,例如通过`add_message_to_db`函数添加一条新的聊天记录,可能会返回如下的聊天记录ID: +``` +'1234567890abcdef1234567890abcdef' +``` +### FunctionDef __repr__(self) +**__repr__**: 此函数的功能是生成并返回一个代表消息对象的字符串。 + +**参数**: 此函数没有参数。 + +**代码描述**: `__repr__` 方法是一个特殊方法,用于定义对象的“官方”字符串表示。在这个具体的实现中,它返回一个格式化的字符串,该字符串包含了消息对象的多个属性,包括:`id`, `conversation_id`, `chat_type`, `query`, `response`, `meta_data`, `feedback_score`, `feedback_reason`, 以及 `create_time`。这些属性通过使用 `self` 关键字访问,表示它们是对象的实例变量。字符串使用了 f-string 格式化,这是 Python 3.6 及以上版本中引入的一种字符串格式化机制,允许将表达式的值直接嵌入到字符串常量中。 + +**注意**: `__repr__` 方法的返回值应该尽可能地返回一个明确的对象表示,以便于调试和日志记录。返回的字符串应该尽量遵循 Python 对象表示的惯例,即 `` 的格式。此外,虽然这个方法主要用于调试和开发,但它也可以被用于日志记录或其他需要对象字符串表示的场景。 + +**输出示例**: 假设有一个消息对象,其属性值如下:`id=1`, `conversation_id=2`, `chat_type='group'`, `query='天气如何'`, `response='晴朗'`, `meta_data='{}'`, `feedback_score=5`, `feedback_reason='准确'`, `create_time='2023-04-01 12:00:00'`。调用此对象的 `__repr__` 方法将返回以下字符串: + +``` + +``` +*** diff --git a/markdown_docs/server/db/repository/conversation_repository.md b/markdown_docs/server/db/repository/conversation_repository.md new file mode 100644 index 000000000..100b90c7b --- /dev/null +++ b/markdown_docs/server/db/repository/conversation_repository.md @@ -0,0 +1,25 @@ +## FunctionDef add_conversation_to_db(session, chat_type, name, conversation_id) +**add_conversation_to_db**: 此函数的功能是向数据库中新增一条聊天记录。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `chat_type`: 字符串,表示聊天的类型(例如普通聊天、客服聊天等)。 +- `name`: 字符串,聊天记录的名称,默认为空字符串。 +- `conversation_id`: 字符串,聊天记录的唯一标识符,默认为None,若未提供,则会自动生成。 + +**代码描述**: +此函数首先检查是否提供了`conversation_id`参数。如果没有提供,函数将使用`uuid.uuid4().hex`生成一个唯一的标识符。接着,函数创建一个`ConversationModel`实例,其中包含了聊天记录的ID、聊天类型、名称等信息。然后,通过`session.add(c)`将此实例添加到数据库会话中,准备将其保存到数据库。最后,函数返回新创建的聊天记录的ID。 + +此函数与`ConversationModel`类紧密相关,`ConversationModel`类定义了聊天记录的数据模型,包括聊天记录的ID、名称、聊天类型和创建时间等字段。`add_conversation_to_db`函数通过创建`ConversationModel`的实例并将其添加到数据库中,实现了聊天记录的新增功能。这体现了`ConversationModel`在项目中用于处理聊天记录数据的重要作用。 + +**注意**: +- 在调用此函数时,需要确保`session`参数是一个有效的数据库会话实例,以便能够正确执行数据库操作。 +- `chat_type`参数是必需的,因为它定义了聊天记录的类型,这对于后续的数据处理和查询是非常重要的。 +- 如果在调用函数时没有提供`conversation_id`,则会自动生成一个。这意味着每条聊天记录都将拥有一个唯一的标识符,即使在未显式指定ID的情况下也是如此。 + +**输出示例**: +假设调用`add_conversation_to_db`函数,并传入相应的参数,函数可能会返回如下的聊天记录ID: +``` +"e4eaaaf2-d142-11e1-b3e4-080027620cdd" +``` +这个返回值表示新创建的聊天记录的唯一标识符。 diff --git a/markdown_docs/server/db/repository/knowledge_base_repository.md b/markdown_docs/server/db/repository/knowledge_base_repository.md new file mode 100644 index 000000000..6c47f157a --- /dev/null +++ b/markdown_docs/server/db/repository/knowledge_base_repository.md @@ -0,0 +1,130 @@ +## FunctionDef add_kb_to_db(session, kb_name, kb_info, vs_type, embed_model) +**add_kb_to_db**: 此函数的功能是向数据库中添加或更新知识库信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_name`: 知识库的名称,用作知识库的唯一标识。 +- `kb_info`: 知识库的简介信息,提供关于知识库的基本描述。 +- `vs_type`: 向量库类型,指定知识库使用的向量库的类型。 +- `embed_model`: 嵌入模型名称,指定用于知识库的嵌入模型。 + +**代码描述**: +此函数首先尝试查询数据库中是否存在与给定知识库名称相匹配的知识库实例。如果不存在,函数将创建一个新的`KnowledgeBaseModel`实例,并使用提供的参数填充其属性,然后将此新实例添加到数据库中。如果已存在具有相同名称的知识库,函数将更新该知识库的简介(`kb_info`)、向量库类型(`vs_type`)和嵌入模型(`embed_model`)信息。无论是添加新知识库还是更新现有知识库,此函数最终都会返回`True`,表示操作成功。 + +**注意**: +- 确保传入的`session`是一个有效的数据库会话实例,以允许函数执行数据库操作。 +- 在调用此函数之前,应确保`kb_name`是唯一的,以避免不必要的知识库信息覆盖。 +- 此函数不负责提交数据库会话,调用者需要在调用此函数后,根据自己的需求决定是否提交会话。 + +**输出示例**: +由于此函数的返回值是布尔类型,因此在成功执行添加或更新操作后,它将返回`True`。例如,无论是创建了一个新的知识库还是更新了现有的知识库信息,函数调用`add_kb_to_db(session, '技术文档库', '存储技术相关文档', 'ElasticSearch', 'BERT')`都将返回`True`。 +## FunctionDef list_kbs_from_db(session, min_file_count) +**list_kbs_from_db**: 此函数的功能是从数据库中列出满足特定条件的知识库名称列表。 + +**参数**: +- `session`: 数据库会话对象,用于执行数据库查询。 +- `min_file_count`: 文件数量的最小值,默认为-1,表示不对文件数量做限制。 + +**代码描述**: +`list_kbs_from_db` 函数通过传入的数据库会话对象 `session` 来查询 `KnowledgeBaseModel` 中的知识库名称。它使用了过滤条件,只有当知识库中的文件数量大于 `min_file_count` 参数指定的值时,该知识库才会被包含在结果列表中。查询结果首先是一个包含多个元组的列表,每个元组中的第一个元素是知识库名称。然后,通过列表推导式,将这些元组转换为仅包含知识库名称的列表。最终,函数返回这个知识库名称列表。 + +**注意**: +- 在使用此函数时,需要确保传入的 `session` 对象是有效的数据库会话对象,并且已经正确配置了数据库连接。 +- `min_file_count` 参数允许调用者根据文件数量过滤知识库,可以根据实际需求调整其值。如果不需要基于文件数量过滤知识库,可以保留其默认值。 + +**输出示例**: +假设数据库中有三个知识库,文件数量分别为0、10、20,且 `min_file_count` 参数的值为5,那么函数的返回值可能如下: +``` +['知识库B', '知识库C'] +``` +这表示只有文件数量大于5的知识库B和知识库C被包含在了结果列表中。 +## FunctionDef kb_exists(session, kb_name) +**kb_exists**: 此函数的功能是检查数据库中是否存在指定名称的知识库。 + +**参数**: +- `session`: 数据库会话对象,用于执行数据库查询。 +- `kb_name`: 要检查的知识库名称。 + +**代码描述**: +`kb_exists` 函数通过接收一个数据库会话对象和一个知识库名称作为参数,来检查数据库中是否存在具有该名称的知识库。函数内部首先使用传入的会话对象执行一个查询,该查询利用`KnowledgeBaseModel`模型对数据库中的`knowledge_base`表进行过滤,查找名称与`kb_name`参数相匹配的知识库记录。这里使用`ilike`方法进行不区分大小写的匹配,以提高查询的灵活性。如果查询结果中存在至少一个匹配的记录,则函数返回`True`,表示指定名称的知识库存在;如果没有找到匹配的记录,则返回`False`,表示知识库不存在。 + +**注意**: +- 在使用`kb_exists`函数时,需要确保传入的`session`对象是有效的数据库会话对象,并且已正确配置数据库连接。 +- 传入的`kb_name`应为字符串类型,且在调用此函数前,最好进行必要的格式化或验证,以确保查询的准确性。 +- 此函数的返回值是布尔类型,可以直接用于条件判断。 + +**输出示例**: +假设数据库中存在一个名为"技术文档库"的知识库,调用`kb_exists(session, "技术文档库")`将返回`True`。如果查询一个不存在的知识库名称,如`kb_exists(session, "不存在的库")`,则会返回`False`。 + +此函数在项目中的应用场景包括,但不限于,在添加新的知识库之前检查同名知识库是否已存在,或在执行知识库相关操作前验证知识库的存在性,以确保数据的一致性和操作的有效性。 +## FunctionDef load_kb_from_db(session, kb_name) +**load_kb_from_db**: 此函数的功能是从数据库中加载指定名称的知识库信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 要加载的知识库的名称。 + +**代码描述**: `load_kb_from_db` 函数通过接收一个数据库会话和一个知识库名称作为参数,利用这个会话来查询 `KnowledgeBaseModel` 表中名称与给定名称相匹配的第一个知识库记录。查询时忽略名称的大小写。如果找到相应的知识库记录,函数将从该记录中提取知识库的名称(`kb_name`)、向量库类型(`vs_type`)和嵌入模型名称(`embed_model`)。如果没有找到相应的记录,这三个变量将被设置为 `None`。最后,函数返回这三个值。 + +**注意**: +- 在调用此函数之前,确保传入的 `session` 是有效的数据库会话实例,并且已经正确配置。 +- 传入的知识库名称 `kb_name` 应当是一个字符串,且在数据库中有对应的记录,否则函数将返回 `None` 值。 +- 此函数对知识库名称大小写不敏感,即不区分大小写。 + +**输出示例**: +假设数据库中存在一个名为 "技术文档库" 的知识库,其向量库类型为 "ElasticSearch",嵌入模型名称为 "BERT",那么调用 `load_kb_from_db(session, "技术文档库")` 将返回: +``` +("技术文档库", "ElasticSearch", "BERT") +``` +如果数据库中不存在指定名称的知识库,调用 `load_kb_from_db(session, "不存在的库")` 将返回: +``` +(None, None, None) +``` +## FunctionDef delete_kb_from_db(session, kb_name) +**delete_kb_from_db**: 此函数的功能是从数据库中删除指定的知识库。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_name`: 要删除的知识库的名称。 + +**代码描述**: +`delete_kb_from_db` 函数首先通过传入的 `session` 参数和知识库名称 `kb_name`,使用 `query` 方法查询 `KnowledgeBaseModel` 表中是否存在指定名称的知识库。查询时,使用了 `ilike` 方法来实现不区分大小写的匹配,以提高用户体验和容错性。如果查询到了目标知识库,那么使用 `session.delete` 方法将其从数据库中删除。无论是否找到并删除了知识库,函数最终都会返回 `True`,表示操作已完成。 + +**注意**: +- 在调用此函数时,需要确保传入的 `session` 是一个有效的数据库会话实例,且已正确配置数据库连接。 +- 传入的知识库名称 `kb_name` 应当是一个字符串类型,且在数据库中唯一标识一个知识库。 +- 函数执行后并不会自动提交数据库事务,调用方需要根据实际情况决定是否提交事务。 + +**输出示例**: +由于此函数的返回值是固定的 `True`,因此不提供具体的输出示例。调用此函数后,可以根据返回值确认操作已被执行,但需要通过其他方式(如查询数据库)来验证知识库是否真的被成功删除。 + +此函数在项目中的应用场景包括,但不限于,在知识库管理服务中,当用户或管理员请求删除一个知识库时,会通过调用此函数来执行删除操作。例如,在 `KBService` 类的 `drop_kb` 方法中,就通过调用 `delete_kb_from_db` 函数来实现知识库的删除功能。这样的设计使得知识库的删除操作既可以独立使用,也可以轻松集成到更复杂的服务流程中。 +## FunctionDef get_kb_detail(session, kb_name) +**get_kb_detail**: 此函数的功能是获取指定知识库的详细信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定要查询的知识库名称。 + +**代码描述**: +`get_kb_detail` 函数通过接收一个数据库会话实例和一个知识库名称作为参数,利用这个会话实例查询 `KnowledgeBaseModel` 表中名称与给定知识库名称相匹配的记录。查询时忽略大小写,以提高查询的灵活性。如果找到匹配的知识库记录,则函数将返回一个包含知识库名称 (`kb_name`)、知识库简介 (`kb_info`)、向量库类型 (`vs_type`)、嵌入模型名称 (`embed_model`)、文件数量 (`file_count`) 和创建时间 (`create_time`) 的字典。如果没有找到匹配的记录,则返回一个空字典。 + +此函数在项目中被多个位置调用,包括但不限于加载知识库嵌入向量和获取知识库详情列表。这些调用场景表明 `get_kb_detail` 函数是连接数据库知识库信息与项目其他部分的重要桥梁。 + +**注意**: +- 确保传入的 `session` 参数是一个有效的数据库会话实例,且在调用此函数前已正确配置和连接到数据库。 +- 传入的 `kb_name` 应为字符串类型,且尽量确保其准确性,以便能够正确匹配数据库中的记录。 + +**输出示例**: +假设数据库中存在一个名为 "技术文档库" 的知识库,其详细信息如下所示: +```python +{ + "kb_name": "技术文档库", + "kb_info": "存储技术相关文档的知识库", + "vs_type": "ElasticSearch", + "embed_model": "BERT", + "file_count": 100, + "create_time": "2023-04-01T12:00:00" +} +``` +如果查询的知识库名称为 "技术文档库",则 `get_kb_detail` 函数将返回上述字典。如果没有找到匹配的知识库,则函数返回 `{}`。 diff --git a/markdown_docs/server/db/repository/knowledge_file_repository.md b/markdown_docs/server/db/repository/knowledge_file_repository.md new file mode 100644 index 000000000..ec92861cc --- /dev/null +++ b/markdown_docs/server/db/repository/knowledge_file_repository.md @@ -0,0 +1,251 @@ +## FunctionDef list_file_num_docs_id_by_kb_name_and_file_name(session, kb_name, file_name) +**list_file_num_docs_id_by_kb_name_and_file_name**: 此函数的功能是列出某知识库中某文件对应的所有文档ID。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定知识库的名称。 +- `file_name`: 字符串类型,指定文件的名称。 + +**代码描述**: +`list_file_num_docs_id_by_kb_name_and_file_name`函数通过接收数据库会话、知识库名称以及文件名称作为参数,利用这些参数对数据库中的`FileDocModel`表进行查询。查询的目的是找出所有与给定知识库名称和文件名称相匹配的文档ID。这些文档ID随后被转换为整数列表返回。此过程涉及到对`FileDocModel`模型的`doc_id`字段进行筛选,确保只有符合条件的记录被选中。最终,函数返回一个整数列表,包含了所有匹配文档的ID。 + +**注意**: +- 确保传入的`session`是一个有效的数据库会话实例,且已正确配置以连接到目标数据库。 +- `kb_name`和`file_name`参数应准确无误,以匹配数据库中的记录。大小写敏感性取决于数据库配置。 +- 返回的文档ID列表是基于数据库中实际存在的记录,如果没有找到匹配的记录,则返回空列表。 + +**输出示例**: +假设存在两个文档,它们的ID分别为1和2,且这两个文档都属于知识库"知识库A"中的"文件B.pdf",那么调用此函数并传入相应的知识库名称和文件名称后,将返回列表`[1, 2]`。 + +通过此函数,可以方便地根据知识库名称和文件名称获取相关文档的ID,进而支持进行进一步的文档管理或操作,如在`MilvusKBService`的`do_delete_doc`方法中,使用此函数获取到的文档ID列表用于指定删除向量库中相应的文档记录。 +## FunctionDef list_docs_from_db(session, kb_name, file_name, metadata) +**list_docs_from_db**: 此函数的功能是列出某知识库某文件对应的所有文档。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定要查询的知识库名称。 +- `file_name`: 字符串类型,可选参数,默认为None,指定要查询的文件名称。 +- `metadata`: 字典类型,可选参数,默认为空字典,用于根据文档的元数据进行过滤查询。 + +**代码描述**: +该函数首先根据知识库名称`kb_name`对`FileDocModel`进行查询,如果提供了`file_name`参数,则进一步根据文件名称进行过滤。随后,遍历`metadata`字典中的每一项,根据元数据的键和值对查询结果进行过滤。最终,函数返回一个列表,列表中的每个元素都是一个字典,包含文档的ID(`id`)和元数据(`metadata`)。 + +在实现上,`list_docs_from_db`函数通过ORM模型`FileDocModel`与数据库交互,利用SQLAlchemy的查询接口进行数据检索。`FileDocModel.kb_name.ilike(kb_name)`和`FileDocModel.file_name.ilike(file_name)`使用了`ilike`方法进行不区分大小写的模糊匹配,增强了查询的灵活性。对于元数据的查询,通过`FileDocModel.meta_data[k].as_string() == str(v)`实现了对JSON类型字段的条件过滤。 + +**注意**: +- 在使用此函数时,应确保传入的`session`是一个有效的数据库会话实例。 +- 由于`metadata`参数默认为一个空字典,修改此默认值可能会影响到函数的预期行为。建议在调用函数时显式传入所需的`metadata`参数,避免直接修改函数定义中的默认值。 +- 在处理大量数据时,应考虑查询性能和优化,避免执行过多的过滤操作导致查询速度缓慢。 + +**输出示例**: +假设数据库中存在两条记录,其字段值分别为: +- id: 1, kb_name: "知识库A", file_name: "文件A.pdf", doc_id: "docA", metadata: {"author": "张三", "year": "2021"} +- id: 2, kb_name: "知识库A", file_name: "文件B.pdf", doc_id: "docB", metadata: {"author": "李四", "year": "2022"} + +调用`list_docs_from_db(session, "知识库A")`将返回以下列表: +```python +[ + {"id": "docA", "metadata": {"author": "张三", "year": "2021"}}, + {"id": "docB", "metadata": {"author": "李四", "year": "2022"}} +] +``` +此输出示例展示了函数如何根据指定的知识库名称返回该知识库下所有文档的ID和元数据。 +## FunctionDef delete_docs_from_db(session, kb_name, file_name) +**delete_docs_from_db**: 此函数的功能是删除某知识库某文件对应的所有文档,并返回被删除的文档信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_name`: 字符串类型,指定要删除文档的知识库名称。 +- `file_name`: 字符串类型,可选参数,默认为None,指定要删除文档的文件名称。 + +**代码描述**: +`delete_docs_from_db`函数首先调用`list_docs_from_db`函数,根据知识库名称`kb_name`和文件名称`file_name`(如果提供)列出所有对应的文档。然后,构造一个查询对象,通过`session.query(FileDocModel)`获取`FileDocModel`的查询接口,并使用`filter`方法根据知识库名称进行过滤。如果提供了`file_name`参数,则进一步根据文件名称进行过滤。接下来,使用`query.delete(synchronize_session=False)`方法删除满足条件的所有文档记录,并通过`session.commit()`提交事务,确保更改被保存到数据库中。最后,函数返回之前通过`list_docs_from_db`获取的被删除文档的列表。 + +**注意**: +- 在调用此函数之前,应确保传入的`session`是一个有效的数据库会话实例,并且已经正确配置。 +- 删除操作是不可逆的,因此在执行此函数之前,请确保确实需要删除这些文档。 +- 由于此函数返回被删除的文档信息,可以用于记录日志或进行后续处理。 + +**输出示例**: +假设数据库中存在两条文档记录,其知识库名称为"知识库A",文件名称分别为"文件A.pdf"和"文件B.pdf",调用`delete_docs_from_db(session, "知识库A", "文件A.pdf")`后,函数可能返回以下列表: +```python +[ + {"id": "docA", "metadata": {"author": "张三", "year": "2021"}} +] +``` +此输出示例展示了函数如何返回被删除的文档的ID和元数据信息。 +## FunctionDef add_docs_to_db(session, kb_name, file_name, doc_infos) +**add_docs_to_db**: 此函数的功能是将某知识库某文件对应的所有Document信息添加到数据库中。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_name`: 字符串类型,指定要添加文档信息的知识库名称。 +- `file_name`: 字符串类型,指定要添加文档信息的文件名称。 +- `doc_infos`: 文档信息列表,每个元素是一个字典,包含文档的ID和元数据。 + +**代码描述**: +`add_docs_to_db`函数主要用于将文档信息批量添加到数据库中。它接收一个数据库会话、知识库名称、文件名称以及文档信息列表作为参数。文档信息列表`doc_infos`的格式为`[{"id": str, "metadata": dict}, ...]`,其中每个字典代表一个文档的信息,包括文档的ID和元数据。 + +函数首先检查`doc_infos`是否为`None`,如果是,则打印一条错误信息,并返回`False`表示添加失败。这是为了处理可能的错误情况,确保函数的健壮性。 + +接下来,函数遍历`doc_infos`列表,对于列表中的每个文档信息,创建一个`FileDocModel`实例。`FileDocModel`是一个ORM模型,用于映射数据库中的`file_doc`表,它包含了文档的基本信息字段,如知识库名称、文件名称、文档ID以及元数据。创建`FileDocModel`实例时,会将当前遍历到的文档信息填充到相应的字段中。 + +然后,使用`session.add(obj)`将`FileDocModel`实例添加到数据库会话中,这样就可以将文档信息保存到数据库中。遍历完成后,函数返回`True`表示所有文档信息已成功添加到数据库。 + +**注意**: +- 确保传入的`session`是有效的数据库会话实例,且已正确配置数据库连接。 +- `doc_infos`参数不能为空,且其内部的字典需要包含`id`和`metadata`键。 +- 在实际应用中,可能需要处理`session.add(obj)`操作可能引发的异常,例如数据库约束违反等。 + +**输出示例**: +此函数没有直接的输出示例,因为它的主要作用是影响数据库状态。但在成功执行后,可以预期数据库中的`file_doc`表将新增相应的记录,记录的字段值将反映函数调用时提供的参数值。 +## FunctionDef count_files_from_db(session, kb_name) +**count_files_from_db**: 此函数的功能是统计指定知识库中的文件数量。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定要统计文件数量的知识库名称。 + +**代码描述**: +`count_files_from_db`函数通过接收一个数据库会话实例和一个知识库名称作为参数,利用ORM模型`KnowledgeFileModel`来查询指定知识库中的文件数量。在这个过程中,函数首先构造一个查询,该查询针对`KnowledgeFileModel`模型,使用`filter`方法根据知识库名称(`kb_name`)进行筛选,这里使用`ilike`方法实现不区分大小写的匹配,以增强查询的灵活性。最后,使用`count`方法计算并返回符合条件的记录数,即指定知识库中的文件数量。 + +**注意**: +- 在调用此函数时,确保传入的`session`参数是一个有效的数据库会话实例,且`kb_name`参数正确指定了目标知识库的名称。 +- 由于使用了`ilike`方法进行模糊匹配,可以灵活匹配知识库名称,但在使用时应注意名称的准确性,以避免错误的统计结果。 + +**输出示例**: +如果指定知识库名称为"DefaultKB",并且该知识库中有10个文件,调用`count_files_from_db(session, "DefaultKB")`将返回整数`10`,表示"DefaultKB"知识库中的文件数量为10。 + +此函数在项目中的应用场景包括,但不限于,知识库服务(如`KBService`类中的`count_files`方法)调用此函数来获取特定知识库中的文件总数,以支持知识库管理和数据分析等功能。 +## FunctionDef list_files_from_db(session, kb_name) +**list_files_from_db**: 此函数的功能是从数据库中列出属于特定知识库的所有文件名。 + +**参数**: +- `session`: 数据库会话对象,用于执行数据库查询。 +- `kb_name`: 知识库的名称,用于筛选特定知识库的文件。 + +**代码描述**: +`list_files_from_db`函数通过接收一个数据库会话对象和一个知识库名称作为参数,利用这个会话对象执行一个查询操作。这个查询是基于`KnowledgeFileModel`模型,筛选出`kb_name`字段与传入的知识库名称相匹配的所有记录。这里使用了`ilike`方法,它允许在比较时不区分大小写,增加了查询的灵活性。查询结果是`KnowledgeFileModel`的实例列表,代表找到的所有文件。然后,函数遍历这个列表,提取每个实例的`file_name`属性,即文件名,将这些文件名收集到一个列表中。最后,返回这个列表,包含了所有符合条件的文件名。 + +**注意**: +- 确保传入的`session`对象是有效的数据库会话实例,且已正确配置与数据库的连接。 +- 传入的知识库名称`kb_name`应确保其准确性,因为查询结果直接依赖于此参数。 +- 查询使用了`ilike`方法,对大小写不敏感,但这可能会影响查询性能,特别是在大型数据库中。 + +**输出示例**: +如果数据库中存在属于名为"GeneralKB"的知识库的文件,且这些文件名分别为"document1.pdf"、"report2.docx",那么调用`list_files_from_db(session, "GeneralKB")`将返回以下列表: +``` +["document1.pdf", "report2.docx"] +``` +## FunctionDef add_file_to_db(session, kb_file, docs_count, custom_docs, doc_infos) +**add_file_to_db**: 此函数的功能是将文件信息添加到数据库中,如果文件已存在,则更新该文件的信息和版本号。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_file`: `KnowledgeFile` 类型,表示要添加到数据库的知识文件。 +- `docs_count`: 整型,默认为0,表示文件中包含的文档数量。 +- `custom_docs`: 布尔型,默认为False,表示文件中的文档是否为自定义文档。 +- `doc_infos`: 文档信息列表,每个元素是一个字典,格式为`[{"id": str, "metadata": dict}, ...]`,包含文档的ID和元数据。 + +**代码描述**: +`add_file_to_db` 函数首先查询数据库中是否存在指定的知识库,如果存在,则继续检查该知识库中是否已有同名文件。如果文件已存在,函数将更新该文件的最后修改时间、文件大小、文档数量、是否为自定义文档标志以及文件版本号。如果文件不存在,则创建一个新的 `KnowledgeFileModel` 实例,并设置相应的文件信息,包括文件名、文件扩展名、所属知识库名称、文档加载器名称、文本分割器名称、文件修改时间、文件大小、文档数量和自定义文档标志。然后,将新文件实例添加到数据库会话中,并增加知识库的文件计数。无论文件是否已存在,都会调用 `add_docs_to_db` 函数,将文件对应的所有文档信息添加到数据库中。 + +**注意**: +- 确保传入的 `session` 是有效的数据库会话实例。 +- `kb_file` 参数必须是 `KnowledgeFile` 类型的实例,且其属性应正确设置以反映文件的实际信息。 +- `doc_infos` 参数中的每个字典必须包含 `id` 和 `metadata` 键。 +- 在实际应用中,可能需要处理数据库操作可能引发的异常,例如违反唯一性约束等。 + +**输出示例**: +此函数没有直接的输出示例,因为它的主要作用是影响数据库状态。但在成功执行后,可以预期数据库中的 `knowledge_file` 表将新增或更新相应的记录,记录的字段值将反映函数调用时提供的参数值。 +## FunctionDef delete_file_from_db(session, kb_file) +**delete_file_from_db**: 此函数的功能是从数据库中删除指定的知识文件,并更新相关知识库的文件计数。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_file`: `KnowledgeFile`类型的对象,表示需要从数据库中删除的知识文件。 + +**代码描述**: +`delete_file_from_db`函数首先通过传入的`session`和`kb_file`对象构造查询条件,查询目标知识文件是否存在于`KnowledgeFileModel`表中。如果存在,函数将执行以下操作: +1. 使用`session.delete(existing_file)`方法从数据库中删除找到的文件记录。 +2. 调用`delete_docs_from_db`函数,根据知识文件的名称和所属知识库名称删除该文件对应的所有文档记录。 +3. 提交数据库事务,确保上述删除操作被保存到数据库中。 +4. 查询`KnowledgeBaseModel`表,找到该知识文件所属的知识库记录,并将该知识库的`file_count`(文件计数)减1,再次提交数据库事务以保存更改。 + +**注意**: +- 在执行删除操作前,请确保传入的`session`是一个有效的数据库会话实例,并且已经正确配置。 +- 删除操作是不可逆的,因此在执行此函数之前,请确保确实需要删除指定的知识文件及其相关文档。 +- 函数在成功删除文件和相关文档后,会更新知识库的文件计数。这一步骤对于维护知识库的准确性非常重要。 + +**输出示例**: +该函数没有直接的输出示例,因为它主要执行数据库的删除操作。函数执行成功后,会返回`True`,表示知识文件及其相关文档已被成功删除,并且相关知识库的文件计数已更新。如果需要验证操作结果,可以通过查询数据库来确认指定的知识文件和文档是否已被删除,以及相应知识库的文件计数是否已减少。 +## FunctionDef delete_files_from_db(session, knowledge_base_name) +**delete_files_from_db**: 该函数的功能是从数据库中删除指定知识库的所有文件记录。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `knowledge_base_name`: 字符串类型,指定要删除文件的知识库名称。 + +**代码描述**: +`delete_files_from_db` 函数首先查询 `KnowledgeFileModel` 表,删除与指定知识库名称匹配的所有文件记录。接着,该函数查询 `FileDocModel` 表,同样删除与指定知识库名称匹配的所有文档记录。这两个操作都使用了 `ilike` 方法来进行不区分大小写的匹配,确保能够匹配到所有相关记录。之后,函数查询 `KnowledgeBaseModel` 表,找到对应的知识库实例,如果找到了,就将该知识库的文件计数设置为0,表示知识库中不再包含任何文件。最后,函数提交所有更改到数据库,并返回 `True`,表示操作成功完成。 + +**注意**: +- 在调用此函数之前,确保传入的 `session` 是有效的数据库会话实例,并且已经正确配置。 +- 该函数会永久删除指定知识库中的所有文件记录,此操作不可逆,请谨慎使用。 +- 在删除文件记录之后,相关联的知识库的文件计数会被重置为0,这意味着知识库将不再包含任何文件。 + +**输出示例**: +由于该函数的返回值是布尔类型,所以在成功执行删除操作后,它会返回 `True`。例如: +``` +操作成功完成后返回值: True +``` +## FunctionDef file_exists_in_db(session, kb_file) +**file_exists_in_db**: 该函数用于检查指定的文件是否已存在于数据库中。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_file`: `KnowledgeFile` 类型的对象,表示要检查的知识库文件。 + +**代码描述**: +`file_exists_in_db` 函数通过接收一个数据库会话 (`session`) 和一个 `KnowledgeFile` 对象 (`kb_file`) 作为参数,来检查指定的文件是否已经存在于数据库中。它首先使用 `session.query` 方法构造一个查询,该查询针对 `KnowledgeFileModel` 表进行,通过 `filter` 方法筛选出文件名 (`file_name`) 和知识库名称 (`kb_name`) 与传入的 `kb_file` 对象相匹配的记录。这里使用了 `ilike` 方法来进行不区分大小写的匹配。如果查询的结果中存在至少一条记录,即 `first()` 方法返回非空值,则认为文件已存在于数据库中,函数返回 `True`;否则,返回 `False`。 + +**注意**: +- 确保传入的 `session` 参数是一个有效的数据库会话实例,且已正确配置数据库连接。 +- 传入的 `kb_file` 对象应包含有效的 `filename` 和 `kb_name` 属性,这两个属性将用于数据库查询中的匹配条件。 +- 该函数不对数据库进行任何修改操作,仅用于检查文件的存在性。 + +**输出示例**: +假设数据库中已存在文件名为 "example.pdf",知识库名称为 "DefaultKB" 的记录,当传入一个 `kb_file` 对象,其 `filename` 属性值为 "example.pdf",`kb_name` 属性值为 "DefaultKB" 时,函数将返回 `True`。如果数据库中不存在满足条件的记录,函数将返回 `False`。 +## FunctionDef get_file_detail(session, kb_name, filename) +**get_file_detail**: 此函数用于获取指定知识库中特定文件的详细信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定要查询的知识库名称。 +- `filename`: 字符串类型,指定要查询的文件名。 + +**代码描述**: +`get_file_detail`函数首先通过传入的`session`参数,使用SQLAlchemy的查询接口,根据`kb_name`(知识库名称)和`filename`(文件名)作为过滤条件,查询`KnowledgeFileModel`模型。查询条件使用了`ilike`方法,这意味着查询是大小写不敏感的,提高了查询的灵活性。如果查询到了指定的文件,函数将从查询结果中提取文件的详细信息,并以字典形式返回。这些信息包括知识库名称、文件名、文件扩展名、文件版本、文档加载器名称、文本分割器名称、创建时间、文件的最后修改时间、文件大小、是否为自定义文档、文档数量等。如果没有查询到指定的文件,函数将返回一个空字典。 + +**注意**: +- 在使用此函数时,需要确保传入的`session`是一个有效的数据库会话实例。 +- 查询条件`kb_name`和`filename`是大小写不敏感的,这意味着无论传入的是大写还是小写,都可以正确查询到结果。 +- 返回的字典中包含了文件的多个属性,这些属性的值直接来源于数据库中的记录,因此在使用这些值时应注意它们的数据类型和含义。 + +**输出示例**: +```json +{ + "kb_name": "SampleKB", + "file_name": "example.pdf", + "file_ext": ".pdf", + "file_version": 1, + "document_loader": "PDFLoader", + "text_splitter": "SpacyTextSplitter", + "create_time": "2023-04-01 12:00:00", + "file_mtime": 1617184000, + "file_size": 1024, + "custom_docs": false, + "docs_count": 10 +} +``` +此示例展示了当查询到文件时,`get_file_detail`函数返回的信息字典。包含了文件所属的知识库名称、文件名、文件扩展名、文件版本、文档加载器名称、文本分割器名称、文件的创建时间、最后修改时间、文件大小、是否为自定义文档以及文档数量等信息。 diff --git a/markdown_docs/server/db/repository/knowledge_metadata_repository.md b/markdown_docs/server/db/repository/knowledge_metadata_repository.md new file mode 100644 index 000000000..0f74f0aca --- /dev/null +++ b/markdown_docs/server/db/repository/knowledge_metadata_repository.md @@ -0,0 +1,108 @@ +## FunctionDef list_summary_from_db(session, kb_name, metadata) +**list_summary_from_db**: 该函数的功能是列出某知识库中的chunk summary信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定要查询的知识库名称。 +- `metadata`: 字典类型,默认为空字典,用于过滤具有特定元数据的summary。 + +**代码描述**: +`list_summary_from_db` 函数通过接收一个数据库会话、知识库名称以及可选的元数据字典作为参数,来查询特定知识库中的summary信息。首先,函数使用传入的知识库名称对`SummaryChunkModel`模型进行过滤查询,以获取该知识库下的所有summary信息。如果提供了元数据字典,函数将进一步根据元数据的键值对过滤这些summary信息。最终,函数将查询结果格式化为一个列表,每个元素是一个字典,包含summary的id、summary_context、summary_id、doc_ids以及metadata,然后返回这个列表。 + +**注意**: +- 在使用`list_summary_from_db`函数时,确保传入的`session`是一个有效的数据库会话实例。 +- `kb_name`参数应确保与数据库中存储的知识库名称匹配,该参数支持大小写不敏感的匹配。 +- 当使用`metadata`参数进行过滤查询时,确保字典中的键和值与`SummaryChunkModel`中的`meta_data`字段中存储的键值对相匹配。 + +**输出示例**: +调用`list_summary_from_db`函数可能返回如下格式的列表: +``` +[ + { + "id": "1", + "summary_context": "这是一个关于AI技术的摘要", + "summary_id": "summary123", + "doc_ids": "['doc1', 'doc2']", + "metadata": {} + }, + { + "id": "2", + "summary_context": "这是第二个摘要的示例文本", + "summary_id": "summary456", + "doc_ids": "['doc3', 'doc4']", + "metadata": {"page": "1-2"} + } +] +``` +这个示例展示了两个summary的信息,每个summary包含id、摘要内容(summary_context)、摘要ID(summary_id)、关联的文档ID列表(doc_ids)以及额外的元数据信息(metadata)。 +## FunctionDef delete_summary_from_db(session, kb_name) +**delete_summary_from_db**: 该函数的功能是删除指定知识库的chunk summary,并返回被删除的chunk summary信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_name`: 字符串类型,指定要删除summary的知识库名称。 + +**代码描述**: +`delete_summary_from_db` 函数首先调用 `list_summary_from_db` 函数,根据传入的知识库名称 `kb_name` 列出该知识库中所有的chunk summary信息。接着,函数构造一个查询,通过 `session.query` 方法和 `SummaryChunkModel` 模型,使用 `filter` 方法对知识库名称进行过滤,匹配大小写不敏感的知识库名称。然后,使用 `query.delete` 方法删除匹配的所有记录,并通过 `session.commit` 方法提交更改到数据库。最后,函数返回之前通过 `list_summary_from_db` 函数获取的被删除的chunk summary信息列表。 + +**注意**: +- 在调用此函数之前,确保传入的 `session` 是一个有效的数据库会话实例,并且已经正确配置。 +- `kb_name` 参数应确保与数据库中存储的知识库名称匹配,且该参数支持大小写不敏感的匹配,以确保能正确找到目标知识库。 +- 函数执行删除操作后会立即提交更改,因此请谨慎使用,以避免误删除重要数据。 + +**输出示例**: +调用 `delete_summary_from_db` 函数可能返回如下格式的列表: +``` +[ + { + "id": "1", + "summary_context": "这是一个关于AI技术的摘要", + "doc_ids": "['doc1', 'doc2']" + }, + { + "id": "2", + "summary_context": "这是第二个摘要的示例文本", + "doc_ids": "['doc3', 'doc4']" + } +] +``` +这个示例展示了两个被删除的summary的信息,每个summary包含id、摘要内容(summary_context)以及关联的文档ID列表(doc_ids)。 +## FunctionDef add_summary_to_db(session, kb_name, summary_infos) +**add_summary_to_db**: 此函数的功能是将总结信息添加到数据库中。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `kb_name`: 字符串类型,指定要添加摘要信息的知识库名称。 +- `summary_infos`: 字典列表,每个字典包含一个总结信息,包括总结文本、文档标识符等信息。 + +**代码描述**: +`add_summary_to_db` 函数接收一个数据库会话、知识库名称以及一个包含多个总结信息的列表。每个总结信息是一个字典,包含了总结文本(`summary_context`)、总结ID(`summary_id`)、文档ID列表(`doc_ids`)以及额外的元数据(`metadata`)。函数遍历这个列表,为每个总结信息创建一个`SummaryChunkModel`实例,并将其添加到数据库会话中。完成所有总结信息的添加后,函数提交会话以保存更改,并返回`True`表示操作成功。 + +在这个过程中,`SummaryChunkModel`是用于映射数据库中的摘要信息表的模型,它定义了如何存储知识库名称、总结文本、总结ID、文档ID列表和元数据等信息。 + +**注意**: +- 确保传入的`session`是一个有效的数据库会话实例,且在调用此函数之前已经正确配置。 +- `summary_infos`列表中的每个字典都必须包含`summary_context`、`summary_id`、`doc_ids`和`metadata`键。 +- `metadata`字段应以正确的JSON格式传入,以避免在序列化或反序列化时出现错误。 +- 函数执行后,需要检查返回值确保总结信息已成功添加到数据库。 + +**输出示例**: +调用`add_summary_to_db`函数通常不直接返回具体的数据实例,而是返回一个布尔值`True`,表示所有总结信息已成功添加到数据库。 +## FunctionDef count_summary_from_db(session, kb_name) +**count_summary_from_db**: 此函数的功能是统计指定知识库名称下的摘要信息数量。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `kb_name`: 字符串类型,指定要查询摘要数量的知识库名称。 + +**代码描述**: +`count_summary_from_db` 函数通过接收一个数据库会话实例和一个知识库名称作为参数,利用这个会话实例来查询 `SummaryChunkModel` 表中与给定知识库名称相匹配的摘要信息数量。在查询过程中,使用了 `ilike` 方法来实现不区分大小写的匹配,这意味着无论传入的知识库名称的大小写如何,都能正确地匹配到相应的记录。此函数返回一个整数,表示匹配到的摘要信息数量。 + +在项目的层次结构中,`count_summary_from_db` 函数属于 `knowledge_metadata_repository.py` 文件,该文件作为数据库仓库层的一部分,主要负责处理与知识库元数据相关的数据操作。`count_summary_from_db` 函数通过查询 `SummaryChunkModel`,与之关联的 `knowledge_metadata_model.py` 中定义的 `SummaryChunkModel` 类直接交互。`SummaryChunkModel` 类定义了摘要信息的数据模型,包括知识库名称、摘要文本等字段,是数据库中存储摘要信息的表结构映射。 + +**注意**: +- 在调用此函数时,确保传入的 `session` 参数是一个有效的数据库会话实例,且 `kb_name` 参数是一个非空字符串。 +- 由于使用了 `ilike` 方法进行模糊匹配,调用此函数时应考虑性能影响,特别是在处理大量数据时。 + +**输出示例**: +假设数据库中有3条属于“技术文档”知识库的摘要信息,调用 `count_summary_from_db(session, "技术文档")` 将返回整数 `3`。 diff --git a/markdown_docs/server/db/repository/message_repository.md b/markdown_docs/server/db/repository/message_repository.md new file mode 100644 index 000000000..e327b0e1a --- /dev/null +++ b/markdown_docs/server/db/repository/message_repository.md @@ -0,0 +1,126 @@ +## FunctionDef add_message_to_db(session, conversation_id, chat_type, query, response, message_id, metadata) +**add_message_to_db**: 此函数的功能是向数据库中添加一条新的聊天记录。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `conversation_id`: 字符串类型,表示对话的唯一标识。 +- `chat_type`: 聊天类型,如普通聊天、客服聊天等。 +- `query`: 用户的提问或输入。 +- `response`: 系统或模型的回答,默认为空字符串。 +- `message_id`: 聊天记录的唯一标识ID,如果未提供,则会自动生成。 +- `metadata`: 字典类型,用于存储额外的信息,默认为空字典。 + +**代码描述**: +此函数首先检查是否提供了`message_id`,如果没有,则使用`uuid.uuid4().hex`生成一个唯一的ID。接着,创建一个`MessageModel`实例,其中包含聊天记录的所有相关信息,如聊天类型、用户问题、模型回答、会话ID和元数据。然后,使用提供的数据库会话(`session`)将此实例添加到数据库中,并提交更改。最后,函数返回新添加的聊天记录的ID。 + +**注意**: +- 在调用此函数时,确保传入的`session`是一个有效的数据库会话实例。 +- `metadata`参数应为字典类型,可以包含任意结构的数据,但需注意保持数据结构的一致性,以便于后续处理。 +- 自动生成的`message_id`是基于UUID的,确保了每条聊天记录的唯一性。 +- 函数执行成功后,会提交数据库事务,因此调用此函数前应确保其他相关数据库操作已正确执行,以避免事务冲突。 + +**输出示例**: +调用`add_message_to_db`函数可能会返回如下的聊天记录ID: +``` +'4f5e8a7b9d314f5a8e7b9d2f4b8a9e2f' +``` + +此函数在项目中的应用场景包括但不限于在用户与系统进行交互时记录聊天内容,以及在自动化测试或数据分析中记录和回溯聊天历史。通过将聊天记录持久化存储,项目可以提供更丰富的用户体验和更深入的数据洞察。 +## FunctionDef update_message(session, message_id, response, metadata) +**update_message**: 此函数的功能是更新已有的聊天记录。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `message_id`: 想要更新的聊天记录的唯一标识ID。 +- `response`: (可选)新的回复内容,字符串类型。 +- `metadata`: (可选)新的元数据,字典类型。 + +**代码描述**: +`update_message`函数首先通过调用`get_message_by_id`函数根据`message_id`查询对应的聊天记录。如果找到了对应的记录,函数将根据传入的参数更新聊天记录的回复内容(`response`)和元数据(`metadata`)。如果`response`参数非空,则更新记录的回复内容;如果`metadata`参数是字典类型,则更新记录的元数据。更新完成后,该记录会被添加到数据库会话中,并提交更改。如果更新成功,函数返回更新记录的ID。 + +**注意**: +- 确保传入的`session`是一个有效的数据库会话实例,并且已经正确配置以连接到目标数据库。 +- `message_id`应确保为有效的ID,且该ID在数据库中存在,以便能够找到对应的聊天记录进行更新。 +- 在更新元数据(`metadata`)时,传入的参数必须是字典类型,否则不会进行更新。 +- 函数执行成功后,会返回更新记录的ID;如果未找到对应的聊天记录,则不会执行更新操作,也不会返回ID。 + +**输出示例**: +假设有一条消息ID为`123`的聊天记录,调用`update_message(session, '123', response='新的回复内容', metadata={'key': 'value'})`后,如果更新成功,函数将返回`123`。这意味着ID为`123`的聊天记录的回复内容和元数据已被成功更新。 + +在项目中,`update_message`函数被`on_llm_end`方法调用,用于在语言模型处理结束后更新聊天记录的回复内容。这显示了`update_message`在实际应用场景中的一个重要用途,即在获取到新的回复或信息后,及时更新数据库中的聊天记录,以保持数据的最新状态。 +## FunctionDef get_message_by_id(session, message_id) +**get_message_by_id**: 此函数的功能是根据消息ID查询聊天记录。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `message_id`: 想要查询的聊天记录的唯一标识ID。 + +**代码描述**: +`get_message_by_id`函数通过接收一个数据库会话(`session`)和一个消息ID(`message_id`)作为参数,使用这个会话来查询`MessageModel`模型中的记录。它首先构造一个查询,该查询通过`filter_by`方法指定了消息ID作为过滤条件,然后调用`first()`方法尝试获取第一条匹配的记录。如果存在符合条件的记录,该记录将被返回;否则,返回`None`。这个过程允许调用者根据特定的消息ID快速检索聊天记录。 + +**注意**: +- 确保传入的`session`是一个有效的数据库会话实例,且已正确配置以连接到目标数据库。 +- `message_id`应确保为有效的ID,且该ID在数据库中存在,以便查询能够成功返回结果。 +- 此函数返回的是一个`MessageModel`实例,或者在未找到匹配记录时返回`None`。因此,调用此函数后应检查返回值,以确定是否成功检索到记录。 + +**输出示例**: +假设数据库中存在一条消息ID为`123`的聊天记录,调用`get_message_by_id(session, '123')`可能会返回如下的`MessageModel`实例: +``` + +``` +如果指定的`message_id`在数据库中不存在,函数将返回`None`。 +## FunctionDef feedback_message_to_db(session, message_id, feedback_score, feedback_reason) +**feedback_message_to_db**: 此函数的功能是更新聊天记录的用户反馈信息。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库操作。 +- `message_id`: 聊天记录的唯一标识ID,用于定位需要更新反馈的聊天记录。 +- `feedback_score`: 用户对聊天回答的评分,满分为100。 +- `feedback_reason`: 用户评分的理由。 + +**代码描述**: +`feedback_message_to_db`函数首先通过`session.query(MessageModel).filter_by(id=message_id).first()`查询到指定ID的聊天记录实例。如果该记录存在,函数将更新该记录的`feedback_score`和`feedback_reason`字段为传入的参数值。之后,通过`session.commit()`提交更改到数据库。如果更新成功,函数返回更新记录的ID。 + +此函数是与用户反馈相关的核心功能之一,它允许用户对聊天记录进行评分和反馈,进而可以用于改进聊天系统的回答质量或进行其他相关分析。 + +**注意**: +- 在调用此函数之前,确保`session`已正确初始化并且可以进行数据库操作。 +- 传入的`message_id`应确保在数据库中存在,否则无法进行更新操作。 +- `feedback_score`应在0到100之间,代表用户满意度的百分比。 +- 在实际应用中,可能需要对用户的反馈理由`feedback_reason`进行长度或内容的校验,以避免存储无效或不恰当的信息。 + +**输出示例**: +如果更新操作成功,函数将返回聊天记录的ID,例如: +``` +'1234567890abcdef1234567890abcdef' +``` +此ID可用于后续操作或日志记录,以便跟踪反馈操作的结果。 +## FunctionDef filter_message(session, conversation_id, limit) +**filter_message**: 此函数的功能是根据对话框ID过滤聊天记录,并返回最近的几条记录。 + +**参数**: +- `session`: 数据库会话实例,用于执行数据库查询。 +- `conversation_id`: 字符串类型,指定要查询的对话框ID。 +- `limit`: 整型,可选参数,默认值为10,指定返回记录的最大数量。 + +**代码描述**: +`filter_message`函数首先通过传入的`session`和`conversation_id`参数,使用SQLAlchemy的查询接口从`MessageModel`模型中筛选出与指定对话框ID匹配的聊天记录。在查询过程中,它还应用了两个过滤条件: +1. 忽略响应为空的记录,即只选择那些系统或模型已经给出回答的聊天记录。 +2. 按照创建时间降序排列结果,并通过`limit`参数限制返回的记录数量。 + +查询完成后,函数不直接返回`MessageModel`对象列表,而是构建了一个新的列表`data`,其中每个元素都是一个字典,包含`query`和`response`两个键值对,分别对应每条记录的用户查询和系统回答。 + +**注意**: +- 在使用此函数时,需要确保传入的`session`是一个有效的数据库会话实例,且`conversation_id`参数应为正确的对话框ID格式。 +- 函数返回的数据结构是为了简化记录的内容,仅包含查询和回答信息,如果需要更多的聊天记录信息,可能需要对函数进行相应的修改。 + +**输出示例**: +调用`filter_message`函数可能会返回如下格式的数据列表: +``` +[ + {"query": "用户的问题1", "response": "系统的回答1"}, + {"query": "用户的问题2", "response": "系统的回答2"}, + ... +] +``` +此列表包含了最多`limit`条记录,每条记录都是一个包含用户查询和系统回答的字典。 diff --git a/markdown_docs/server/db/session.md b/markdown_docs/server/db/session.md new file mode 100644 index 000000000..b11027b06 --- /dev/null +++ b/markdown_docs/server/db/session.md @@ -0,0 +1,63 @@ +## FunctionDef session_scope +**session_scope**: 该函数的功能是作为上下文管理器,用于自动管理数据库会话的生命周期,包括获取会话、提交事务、回滚事务以及关闭会话。 + +**参数**: 该函数不接受任何参数。 + +**代码描述**: `session_scope` 函数定义了一个上下文管理器,用于简化数据库会话(Session)的使用。它首先创建一个本地会话实例 `SessionLocal()`。当进入上下文管理器时,它会尝试执行用户代码块,并在执行结束后自动提交事务。如果在执行用户代码块期间发生任何异常,它会自动回滚事务,以确保数据库状态的一致性,然后重新抛出异常以便调用者可以处理。无论操作成功还是发生异常,最终都会确保会话被正确关闭,释放资源。 + +在项目中,`session_scope` 被多个地方调用,体现了其重要性和通用性。例如,在 `server/db/session.py/with_session/wrapper` 中,它被用于确保数据库操作在一个安全的会话中执行,自动处理事务的提交和回滚。在 `server/knowledge_base/migrate.py/import_from_db` 中,它被用于导入数据时管理数据库会话,确保数据的一致性和完整性。 + +**注意**: 使用 `session_scope` 可以大大简化数据库会话的管理,但开发者需要注意,任何在 `yield` 之后的代码块中对数据库进行的修改操作,都应该在没有异常的情况下自动提交。在异常情况下,会自动回滚,因此开发者不需要在每次数据库操作后手动提交或回滚事务,但仍需注意异常处理的逻辑,确保应用的健壮性。 +## FunctionDef with_session(f) +**with_session**: 该函数的功能是为被装饰的函数自动管理数据库会话。 + +**参数**: +- `f`: 被装饰的函数,该函数需要接受一个数据库会话对象作为第一个参数,后续可以接受任意数量的位置参数和关键字参数。 + +**代码描述**: +`with_session` 是一个装饰器函数,旨在简化数据库操作中会话的管理。它通过自动处理会话的创建、提交和回滚来减少重复代码,并确保数据库操作的安全性。当装饰的函数被调用时,`with_session` 首先创建一个数据库会话,并将这个会话作为第一个参数传递给被装饰的函数。在被装饰的函数执行过程中,如果操作成功完成,则会话会被提交,以保存更改。如果在执行过程中遇到任何异常,则会话会被回滚,以撤销所有未提交的更改,然后异常会被重新抛出。这样,使用`with_session`装饰的函数可以专注于业务逻辑,而不必担心数据库会话的管理。 + +在项目中,`with_session` 被用于装饰多个数据库仓库层的函数,例如 `conversation_repository.py`、`knowledge_base_repository.py` 等文件中的函数。这表明项目中的数据库操作广泛采用了`with_session`装饰器来确保数据库会话的正确管理。这种做法有助于保持代码的干净和一致性,同时减少了错误处理和会话管理的重复代码。 + +**注意**: +- 使用`with_session`装饰的函数必须接受一个数据库会话对象作为其第一个参数。 +- 被装饰的函数中的数据库操作应该在这个会话的上下文中执行。 +- 如果被装饰的函数中发生异常,会话将自动回滚,因此开发者需要确保任何调用这些函数的代码适当地处理这些异常。 + +**输出示例**: +由于`with_session`是一个装饰器,它本身不直接产生输出。它的作用是修改被装饰的函数的行为。因此,输出示例将取决于被装饰函数的具体实现。例如,如果它被用于装饰一个查询数据库并返回查询结果的函数,那么该函数的输出可能是数据库查询结果的列表。 +### FunctionDef wrapper +**wrapper**: 此函数的功能是在数据库会话中执行传入的函数,并自动处理事务的提交和回滚。 + +**参数**: +- `*args`: 传递给内部函数 `f` 的位置参数。 +- `**kwargs`: 传递给内部函数 `f` 的关键字参数。 + +**代码描述**: `wrapper` 函数是一个装饰器内部使用的函数,它利用了 `session_scope` 上下文管理器来确保数据库操作的安全性和一致性。当调用 `wrapper` 函数时,首先会通过 `session_scope()` 创建一个数据库会话的上下文环境。在这个上下文环境中,`wrapper` 尝试执行传入的函数 `f`,并将创建的会话对象 `session` 作为第一个参数传递给 `f`,同时传递任何额外的位置参数和关键字参数。 + +如果函数 `f` 成功执行,会话会通过 `session.commit()` 方法提交事务,确保所有的数据库操作被正确保存。如果在执行 `f` 或提交事务过程中发生任何异常,会话会通过 `session.rollback()` 方法回滚事务,撤销所有未提交的数据库操作,以保持数据库状态的一致性。无论操作成功还是发生异常,`session_scope` 上下文管理器都会确保数据库会话被正确关闭。 + +这种模式允许开发者在执行数据库操作时不必直接管理事务的提交和回滚,从而简化了代码并减少了错误的可能性。 + +**注意**: 使用 `wrapper` 函数时,需要确保传入的函数 `f` 接受一个 `session` 参数,并且能够正确处理任何传递给它的位置参数和关键字参数。此外,开发者应当注意异常处理,确保在发生异常时能够正确响应,避免数据不一致的问题。 + +**输出示例**: 由于 `wrapper` 函数的输出取决于传入的函数 `f` 的返回值,因此没有固定的输出格式。如果 `f` 函数设计为查询数据库并返回查询结果,那么 `wrapper` 函数的输出将是这些查询结果;如果 `f` 函数执行数据库更新操作且不返回特定值,则 `wrapper` 函数可能没有输出或返回一个表示操作成功的标志。 +*** +## FunctionDef get_db +**get_db**: 此函数的功能是创建并返回一个数据库会话实例,并确保其在使用后正确关闭。 + +**参数**: 此函数没有参数。 + +**代码描述**: `get_db` 函数首先创建一个 `SessionLocal` 类的实例,这是通过 SQLAlchemy ORM 实现的会话管理。函数体内部使用了 Python 的 `try` 语句来确保无论操作成功还是遇到异常,数据库会话都能被正确关闭。通过 `yield` 关键字,函数暂时返回数据库会话给调用者,允许调用者执行数据库操作。当调用者完成数据库操作后,控制权返回到 `get_db` 函数,执行 `finally` 块中的代码,即调用 `db.close()` 方法来关闭数据库会话。这种模式确保了数据库资源的有效管理和释放,避免了资源泄露。 + +**注意**: 使用此函数时,应当在依赖注入(Dependency Injection)的上下文中使用,特别是在使用 FastAPI 或类似框架时。这样可以确保每个请求都能获得一个独立的数据库会话,并且在请求处理完成后自动关闭会话。此外,由于使用了 `yield` 关键字,调用此函数时需要注意它返回的是一个生成器(Generator),而不是直接的 `SessionLocal` 实例。在实际使用中,通常会配合框架提供的依赖注入机制来使用此函数,以自动处理会话的创建和关闭。 +## FunctionDef get_db0 +**get_db0函数功能**: 创建并返回一个SessionLocal实例。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `get_db0`函数的主要作用是初始化并返回一个数据库会话实例。在函数内部,首先通过调用`SessionLocal()`创建了一个SessionLocal实例,该实例代表了与数据库的会话。这个会话可以用于数据库的增删改查操作。函数最后将这个会话实例返回。这种设计模式通常用于依赖注入,确保在处理请求时能够有效地管理数据库会话的生命周期。 + +**注意**: 使用`get_db0`函数时,需要确保`SessionLocal`已经被正确配置,包括数据库的连接参数等。此外,使用完毕后应确保会话被正确关闭,以避免资源泄露。 + +**输出示例**: 由于`get_db0`函数返回的是一个SessionLocal实例,其具体的输出取决于`SessionLocal`类的实现。通常,这个实例将允许执行数据库操作,但不会直接显示为具体的数据或值。例如,可以使用返回的会话实例执行查询操作,如`db.query(Model).filter(...)`,但函数本身的返回值不会直接显示查询结果。 diff --git a/markdown_docs/server/embeddings_api.md b/markdown_docs/server/embeddings_api.md new file mode 100644 index 000000000..8429ad6ac --- /dev/null +++ b/markdown_docs/server/embeddings_api.md @@ -0,0 +1,97 @@ +## FunctionDef embed_texts(texts, embed_model, to_query) +**embed_texts**: 该函数的功能是对文本进行向量化处理,并返回向量化结果。 + +**参数**: +- `texts`: 需要进行向量化处理的文本列表。 +- `embed_model`: 使用的嵌入模型名称,默认为配置中指定的嵌入模型。 +- `to_query`: 布尔值,指示向量化的文本是否用于查询,默认为False。 + +**代码描述**: +`embed_texts`函数首先检查指定的嵌入模型是否在本地嵌入模型列表中。如果是,它将使用`load_local_embeddings`函数加载本地嵌入模型,并对文本进行向量化处理,然后返回包含向量化结果的`BaseResponse`对象。如果指定的嵌入模型不在本地模型列表中,函数将检查模型是否在支持嵌入功能的在线模型列表中。对于在线模型,函数将根据模型配置创建相应的工作类实例,并调用其嵌入方法进行文本向量化,同样返回`BaseResponse`对象。如果指定的嵌入模型既不在本地模型列表中也不在在线模型列表中,函数将返回一个错误信息,指出指定的模型不支持嵌入功能。在整个过程中,如果遇到任何异常,函数将捕获异常并返回包含错误信息的`BaseResponse`对象。 + +**注意**: +- 在使用`embed_texts`函数时,需要确保传入的`texts`参数是有效的文本列表。 +- `embed_model`参数应正确指定,以便函数能够找到并使用正确的嵌入模型进行文本向量化处理。 +- `to_query`参数应根据实际需求设置,以优化向量化结果的使用场景。 +- 函数的执行结果依赖于指定嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。 + +**输出示例**: +调用`embed_texts(texts=["你好", "世界"], embed_model="example_model", to_query=False)`可能会返回如下`BaseResponse`对象: +```python +BaseResponse(code=200, msg="success", data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) +``` +这表示两个文本"你好"和"世界"被成功向量化,向量化结果分别为`[0.1, 0.2, 0.3]`和`[0.4, 0.5, 0.6]`。 +## FunctionDef aembed_texts(texts, embed_model, to_query) +**aembed_texts**: 此函数的功能是对文本列表进行异步向量化处理,并返回一个包含向量化结果的BaseResponse对象。 + +**参数**: +- `texts`: 需要进行向量化处理的文本列表,类型为List[str]。 +- `embed_model`: 使用的嵌入模型名称,默认值为配置中指定的嵌入模型,类型为str。 +- `to_query`: 布尔值,指示向量化的文本是否用于查询,默认为False。 + +**代码描述**: +`aembed_texts`函数首先检查`embed_model`是否在本地嵌入模型列表中。如果是,则使用`load_local_embeddings`函数加载本地嵌入模型,并异步调用`aembed_documents`方法进行文本向量化处理,最后返回包含向量化结果的`BaseResponse`对象。如果`embed_model`在支持嵌入功能的在线模型列表中,则通过`run_in_threadpool`函数异步调用`embed_texts`函数进行文本向量化处理,并返回相应的`BaseResponse`对象。如果在向量化过程中出现异常,函数将捕获异常并返回一个包含错误信息的`BaseResponse`对象,状态码设为500。 + +**注意**: +- 在调用此函数时,需要确保传入的`texts`参数是有效的文本列表。 +- `embed_model`参数应正确指定,以便函数能够找到并使用正确的嵌入模型进行文本向量化处理。如果未指定,将使用默认配置的嵌入模型。 +- `to_query`参数应根据实际需求设置。如果向量化的文本用于查询,应将此参数设置为True,以优化向量化结果的使用场景。 +- 函数的执行结果依赖于指定嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。 + +**输出示例**: +调用`await aembed_texts(texts=["你好", "世界"], embed_model="example_model", to_query=False)`可能会返回如下`BaseResponse`对象: +```python +BaseResponse(code=200, msg="success", data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) +``` +这表示两个文本"你好"和"世界"被成功向量化,向量化结果分别为`[0.1, 0.2, 0.3]`和`[0.4, 0.5, 0.6]`。 + +在项目中,`aembed_texts`函数被用于处理需要异步进行文本向量化的场景,如在知识库服务中对文本进行异步向量化以支持快速的文本查询和相似度计算。此外,它也支持通过在线API进行文本向量化,为项目提供了灵活的向量化解决方案。 +## FunctionDef embed_texts_endpoint(texts, embed_model, to_query) +**embed_texts_endpoint**: 该函数的功能是对文本列表进行向量化处理,并返回处理结果。 + +**参数**: +- `texts`: 要嵌入的文本列表,是一个字符串列表。该参数是必需的。 +- `embed_model`: 使用的嵌入模型。这可以是本地部署的Embedding模型,也可以是在线API提供的嵌入服务。默认值为配置中指定的嵌入模型。 +- `to_query`: 布尔值,指示向量是否用于查询。有些模型如Minimax对存储/查询的向量进行了区分优化。默认值为False。 + +**代码描述**: +`embed_texts_endpoint`函数首先接收一个文本列表、一个嵌入模型名称以及一个布尔值参数。它调用`embed_texts`函数,将这些参数传递给该函数进行处理。`embed_texts`函数根据指定的嵌入模型对文本进行向量化处理,并返回一个`BaseResponse`对象,其中包含了向量化的结果。如果在向量化过程中遇到任何异常,`embed_texts`函数会捕获这些异常并返回一个包含错误信息的`BaseResponse`对象。`embed_texts_endpoint`函数最终返回`embed_texts`函数的输出,即向量化处理的结果。 + +**注意**: +- 在调用`embed_texts_endpoint`函数时,必须提供有效的文本列表。 +- `embed_model`参数应该准确指定,以确保函数能够找到并使用正确的嵌入模型进行处理。 +- 根据实际需求设置`to_query`参数,以优化向量化结果的使用场景。 +- 函数的执行结果依赖于指定嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。 + +**输出示例**: +调用`embed_texts_endpoint(texts=["hello", "world"], embed_model="example_model", to_query=False)`可能会返回如下`BaseResponse`对象: +```python +BaseResponse(code=200, msg="success", data=[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) +``` +这表示两个文本"hello"和"world"被成功向量化,向量化结果分别为`[0.1, 0.2, 0.3]`和`[0.4, 0.5, 0.6]`。 +## FunctionDef embed_documents(docs, embed_model, to_query) +**embed_documents**: 该函数的功能是将文档列表向量化,转化为向量存储系统可以接受的参数格式。 + +**参数**: +- `docs`: 文档对象的列表,每个文档包含页面内容和元数据。 +- `embed_model`: 字符串类型,指定用于文档向量化的嵌入模型,默认使用预设的嵌入模型。 +- `to_query`: 布尔类型,指示向量化的结果是否用于查询,默认为False。 + +**代码描述**: +`embed_documents`函数首先从文档列表中提取页面内容和元数据,分别存储在`texts`和`metadatas`列表中。接着,调用`embed_texts`函数对`texts`列表中的文本进行向量化处理,其中`embed_model`参数指定使用的嵌入模型,`to_query`参数指示向量化的目的。`embed_texts`函数返回一个包含向量化结果的数据结构。如果向量化成功,`embed_documents`函数将返回一个字典,包含原始文本列表`texts`、向量化结果`embeddings`和元数据列表`metadatas`。 + +**注意**: +- 在调用`embed_documents`函数时,确保传入的`docs`参数是有效的文档对象列表。 +- `embed_model`参数应指向有效的嵌入模型,以确保文本能被正确向量化。 +- 根据使用场景选择`to_query`参数的值,以优化向量化结果的应用。 + +**输出示例**: +假设调用`embed_documents(docs=[Document1, Document2], embed_model="example_model", to_query=False)`,可能会返回如下字典: +```python +{ + "texts": ["文档1的内容", "文档2的内容"], + "embeddings": [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]], + "metadatas": [{"title": "文档1标题"}, {"title": "文档2标题"}] +} +``` +这表示两个文档被成功向量化,其中`texts`包含了文档的原始内容,`embeddings`包含了对应的向量化结果,`metadatas`包含了文档的元数据信息。 diff --git a/markdown_docs/server/knowledge_base/kb_api.md b/markdown_docs/server/knowledge_base/kb_api.md new file mode 100644 index 000000000..f7ac55736 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_api.md @@ -0,0 +1,95 @@ +## FunctionDef list_kbs +**list_kbs**: 此函数的功能是获取知识库列表。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `list_kbs` 函数是一个无参数函数,用于从数据库中获取知识库的列表。它通过调用 `list_kbs_from_db` 函数来实现这一功能。`list_kbs_from_db` 函数从数据库中查询满足特定条件的知识库名称列表,并返回这些名称。然后,`list_kbs` 函数将这些名称封装在 `ListResponse` 类的实例中返回。`ListResponse` 类是专门用于封装列表数据响应的类,它继承自 `BaseResponse` 类,能够提供状态码、状态消息以及数据列表。这样的设计使得 API 的响应格式保持一致,便于前端开发者理解和使用。 + +**注意**: +- `list_kbs` 函数依赖于 `list_kbs_from_db` 函数正确地从数据库中获取知识库名称列表。因此,确保数据库连接和查询逻辑正确是使用此函数的前提。 +- 返回的 `ListResponse` 实例中包含的数据列表应正确反映数据库中的知识库情况。这要求 `list_kbs_from_db` 函数能准确地执行其查询逻辑。 +- 在实际部署和使用时,应注意数据库的性能和响应时间,尤其是在知识库数量较多的情况下,以保证良好的用户体验。 + +**输出示例**: +假设数据库中存在三个知识库,名称分别为 "知识库A", "知识库B", "知识库C",则函数可能返回的 `ListResponse` 实例如下所示: +``` +{ + "code": 200, + "msg": "success", + "data": ["知识库A", "知识库B", "知识库C"] +} +``` +这表示 API 调用成功,且返回了包含三个知识库名称的列表。 +## FunctionDef create_kb(knowledge_base_name, vector_store_type, embed_model) +**create_kb**: 此函数用于创建一个新的知识库。 + +**参数**: +- `knowledge_base_name`: 知识库的名称,类型为字符串。通过示例参数可以提供默认示例值。 +- `vector_store_type`: 向量存储类型,类型为字符串,默认值为"faiss"。 +- `embed_model`: 嵌入模型的名称,类型为字符串,默认使用项目配置的嵌入模型。 + +**代码描述**: +此函数首先通过调用`validate_kb_name`函数验证知识库名称的合法性。如果名称不合法或为空,则分别返回403和404状态码的`BaseResponse`对象,提示错误信息。接下来,使用`KBServiceFactory.get_service_by_name`方法检查是否已存在同名的知识库,如果存在,则返回404状态码的`BaseResponse`对象,提示知识库已存在。如果验证通过,函数将通过`KBServiceFactory.get_service`方法获取对应的知识库服务实例,并调用该实例的`create_kb`方法创建知识库。如果在创建过程中发生异常,将记录错误信息并返回500状态码的`BaseResponse`对象。成功创建知识库后,返回200状态码的`BaseResponse`对象,提示已新增知识库。 + +**注意**: +- 在调用此函数创建知识库之前,需要确保知识库名称不为空且不包含非法字符,以避免安全风险。 +- 向量存储类型和嵌入模型应根据项目需求和配置进行选择,以确保知识库的正确创建和后续操作的有效性。 +- 在处理异常时,应注意记录详细的错误信息,以便于问题的定位和解决。 + +**输出示例**: +如果成功创建名为"技术文档库"的知识库,函数将返回以下`BaseResponse`对象: +``` +{ + "code": 200, + "msg": "已新增知识库 技术文档库" +} +``` +如果尝试创建一个已存在的知识库,例如名为"技术文档库",函数将返回: +``` +{ + "code": 404, + "msg": "已存在同名知识库 技术文档库" +} +``` +如果知识库名称不合法,将返回: +``` +{ + "code": 403, + "msg": "Don't attack me" +} +``` +## FunctionDef delete_kb(knowledge_base_name) +**delete_kb**: 此函数的功能是删除指定的知识库。 + +**参数**: +- `knowledge_base_name`: 字符串类型,表示要删除的知识库的名称。此参数通过请求体传入,且提供了示例值 "samples"。 + +**代码描述**: +`delete_kb` 函数首先验证知识库名称的合法性。如果名称不合法,即不通过 `validate_kb_name` 函数的验证,将返回一个状态码为403的 `BaseResponse` 对象,消息内容为 "Don't attack me",表示请求被拒绝。接着,函数对知识库名称进行URL解码,以确保名称的正确性。 + +通过 `KBServiceFactory.get_service_by_name` 方法,根据知识库名称获取对应的知识库服务实例。如果实例为 `None`,即知识库不存在,将返回一个状态码为404的 `BaseResponse` 对象,消息内容为 "未找到知识库 {knowledge_base_name}"。 + +若知识库服务实例获取成功,函数尝试调用知识库服务实例的 `clear_vs` 方法来清除知识库中的向量数据,然后调用 `drop_kb` 方法删除知识库。如果删除操作成功,将返回一个状态码为200的 `BaseResponse` 对象,消息内容为 "成功删除知识库 {knowledge_base_name}"。 + +如果在删除过程中发生异常,将捕获异常并记录错误日志,然后返回一个状态码为500的 `BaseResponse` 对象,消息内容为 "删除知识库时出现意外: {e}",其中 `{e}` 是异常信息。 + +**注意**: +- 在调用此函数之前,确保传入的知识库名称是经过URL编码的。 +- 此函数依赖于 `validate_kb_name` 函数来验证知识库名称的合法性,以防止潜在的安全风险。 +- 删除知识库是一个不可逆的操作,一旦执行,知识库中的所有数据将被永久删除。 + +**输出示例**: +如果尝试删除一个不存在的知识库 "unknown_kb",函数可能返回的 `BaseResponse` 对象如下: +``` +{ + "code": 404, + "msg": "未找到知识库 unknown_kb" +} +``` +如果成功删除名为 "samples" 的知识库,函数可能返回的 `BaseResponse` 对象如下: +``` +{ + "code": 200, + "msg": "成功删除知识库 samples" +} +``` diff --git a/markdown_docs/server/knowledge_base/kb_cache/base.md b/markdown_docs/server/knowledge_base/kb_cache/base.md new file mode 100644 index 000000000..22d4f5563 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_cache/base.md @@ -0,0 +1,374 @@ +## ClassDef ThreadSafeObject +**ThreadSafeObject**: ThreadSafeObject 类的功能是提供一个线程安全的对象封装,用于在多线程环境中安全地访问和修改对象。 + +**属性**: +- `_obj`: 存储实际对象的属性,可以是任何类型。 +- `_key`: 对象的键,用于标识对象,可以是字符串或元组。 +- `_pool`: 对象所属的缓存池,类型为 `CachePool`,默认为 None。 +- `_lock`: 一个重入锁(`threading.RLock`),用于确保线程安全。 +- `_loaded`: 一个事件(`threading.Event`),用于控制对象加载状态。 + +**代码描述**: +ThreadSafeObject 类通过封装对象、键、所属缓存池以及同步机制(重入锁和事件),提供了一个线程安全的方式来访问和修改对象。通过 `acquire` 方法,可以安全地获取对象的引用,进行操作,并在操作完成后自动释放锁。此外,`start_loading` 和 `finish_loading` 方法允许控制对象的加载状态,而 `wait_for_loading` 方法可以阻塞当前线程,直到对象加载完成。 + +在项目中,ThreadSafeObject 类与 CachePool 类紧密相关,后者负责管理缓存中的 ThreadSafeObject 实例。例如,CachePool 的 `get` 方法在返回缓存对象之前会调用 `wait_for_loading` 方法,确保对象已经加载完成。`set` 和 `pop` 方法则用于向缓存中添加或移除 ThreadSafeObject 实例。此外,`acquire` 方法提供了一种机制,允许在执行操作前安全地获取对象的引用。 + +ThreadSafeObject 类还被用作其他特定类型对象的基类,例如 ThreadSafeFaiss 类,后者在 ThreadSafeObject 的基础上增加了与 FAISS 相关的功能,如文档计数和保存到磁盘等。 + +**注意**: +- 在多线程环境中操作共享资源时,使用 ThreadSafeObject 可以避免数据竞争和其他并发问题。 +- 使用 `acquire` 方法时,应确保使用 `with` 语句或手动释放锁,以避免死锁。 +- 修改 `_obj` 属性时,应通过 `obj` 属性的 setter 方法,以确保线程安全。 + +**输出示例**: +假设有一个 ThreadSafeObject 实例,其 `_key` 为 "example_key",`_obj` 为某个自定义对象。调用 `__repr__` 方法可能会返回如下字符串: +`">"` +### FunctionDef __init__(self, key, obj, pool) +**__init__**: 该函数用于初始化ThreadSafeObject对象。 + +**参数**: +- `key`: 可以是字符串或元组,用于标识对象。 +- `obj`: 初始化时分配给ThreadSafeObject的对象,默认为None。 +- `pool`: 一个CachePool实例,用于存储缓存对象,默认为None。 + +**代码描述**: +这个`__init__`方法是`ThreadSafeObject`类的构造函数,负责初始化一个线程安全的对象。它接收三个参数:`key`、`obj`和`pool`。`key`是一个标识符,可以是字符串或元组,用于唯一标识这个对象。`obj`参数是任意类型,代表需要被线程安全访问的数据对象,默认值为None。`pool`参数是一个`CachePool`类型的实例,它是一个可选参数,默认值为None,用于指定这个对象所属的缓存池。 + +在对象初始化过程中,首先将传入的`obj`、`key`和`pool`参数分别赋值给内部变量`_obj`、`_key`和`_pool`。接着,使用`threading.RLock()`创建一个可重入锁(Reentrant Lock),并将其赋值给`_lock`属性,这样可以确保对象的线程安全访问。最后,创建一个`threading.Event()`实例赋值给`_loaded`属性,这个事件对象用于控制对象加载状态的同步。 + +**注意**: +- 在多线程环境下操作同一个`ThreadSafeObject`实例时,应确保正确使用`_lock`来避免数据竞争。 +- `key`参数是必须的,因为它用于唯一标识一个`ThreadSafeObject`实例。 +- 如果提供了`pool`参数,那么这个`ThreadSafeObject`实例将与指定的缓存池相关联,这在管理多个缓存对象时非常有用。 +*** +### FunctionDef __repr__(self) +**__repr__**: 此函数的功能是返回对象的官方字符串表示。 + +**参数**: 此函数没有参数。 + +**代码描述**: `__repr__` 方法是一个特殊的方法,用于定义对象的“官方”字符串表示。在这个实现中,首先通过 `type(self).__name__` 获取对象的类名,然后结合对象的 `key` 属性和 `_obj` 属性构造并返回一个格式化的字符串。这个字符串以 `<类名: key: 键值, obj: 对象值>` 的格式展示,其中 `键值` 是通过调用对象的 `key` 方法获取的,而 `对象值` 直接访问的是对象的 `_obj` 属性。这种表示方式不仅提供了对象的基本信息,还包括了对象的关键数据,使得调试和日志记录更为方便。 + +从项目的结构来看,`__repr__` 方法与 `key` 方法有直接的调用关系。`key` 方法用于获取对象的键值,这是对象在缓存或其他数据结构中的唯一标识符。在 `__repr__` 方法中,通过调用 `key` 方法可以获取到这个键值,并将其包含在对象的字符串表示中。这样做有助于在日志记录或调试时快速识别对象。 + +**注意**: 在使用 `__repr__` 方法时,需要确保对象的 `_key` 和 `_obj` 属性已经被正确初始化,否则可能会导致错误。此外,考虑到 `__repr__` 方法的输出可能会被用于日志记录,应确保包含的信息既有用又不过于冗长。 + +**输出示例**: 假设对象的类名为 `ThreadSafeObject`,`_key` 属性的值为 `"example_key"`,`_obj` 属性的值为 `"example_object"`,那么调用 `__repr__` 方法将返回: +``` + +``` +*** +### FunctionDef key(self) +**key**: 此函数的功能是获取对象的键值。 + +**参数**: 此函数没有参数。 + +**代码描述**: `key` 函数是一个简单但关键的部分,用于访问和返回对象的 `_key` 属性。这个属性通常代表了对象在缓存或其他数据结构中的唯一标识符。在多线程环境下,访问和管理这些键值是确保数据一致性和线程安全的重要机制。 + +从项目中的调用情况来看,`key` 函数被多个地方调用,显示其在对象表示(`__repr__` 方法)、资源获取(`acquire` 方法)、以及特定操作如保存和清空缓存(`save` 和 `clear` 方法)中的重要性。例如,在 `__repr__` 方法中,通过调用 `key` 函数来获取对象的键值,以构建并返回对象的字符串表示,这有助于调试和日志记录。在 `acquire` 方法中,`key` 函数的返回值用于日志记录,帮助追踪哪个线程正在操作哪个资源。在 `save` 和 `clear` 方法中,`key` 同样用于日志记录,提供操作的上下文信息。 + +**注意**: 使用此函数时,需要确保 `_key` 属性已经被正确初始化,否则可能会引发错误。此外,考虑到线程安全,访问 `_key` 属性时应当小心处理同步问题,尽管在此函数的实现中看似简单,但在多线程环境下使用时应当保持警惕。 + +**输出示例**: 假设 `_key` 属性的值为 `"example_key"`,那么调用 `key` 函数将返回: +``` +"example_key" +``` +*** +### FunctionDef acquire(self, owner, msg) +**acquire**: 此函数的功能是安全地获取并操作对象资源。 + +**参数**: +- `owner`: 字符串类型,默认为空字符串,表示资源的拥有者。如果未提供,则默认使用当前线程的ID。 +- `msg`: 字符串类型,默认为空字符串,用于附加额外的日志信息。 + +**代码描述**: +`acquire` 函数是一个上下文管理器,用于在多线程环境中安全地获取和释放资源。它首先尝试获取一个锁,以确保在操作对象资源时的线程安全。如果提供了`owner`参数,则使用该参数值作为资源的拥有者;如果未提供,则默认使用当前线程的ID作为拥有者。此外,如果存在`_pool`属性且不为`None`,则会调用`_pool._cache.move_to_end(self.key)`方法,将当前对象的键值移动到缓存的末尾,这通常用于维护缓存的LRU(最近最少使用)策略。 + +在成功获取锁并进行资源操作的前后,如果`log_verbose`为真,则会记录日志信息,包括操作的开始和结束,以及提供的`msg`信息。这有助于追踪资源的使用情况和调试。 + +在`finally`块中,无论资源操作是否成功,都会释放之前获取的锁,确保资源的安全释放,避免死锁的发生。 + +**注意**: +- 使用`acquire`函数时,需要确保`_lock`属性已经被正确初始化为一个锁对象,否则在尝试获取锁时会引发异常。 +- 在多线程环境下操作共享资源时,正确使用锁是非常重要的,以避免数据竞争和不一致的问题。 +- `acquire`函数设计为一个上下文管理器,推荐使用`with`语句进行调用,以确保资源的正确获取和释放。 +*** +### FunctionDef start_loading(self) +**start_loading**: 此函数的功能是清除加载状态。 + +**参数**: 此函数没有参数。 + +**代码描述**: `start_loading` 函数是 `ThreadSafeObject` 类的一个方法,用于重置对象的加载状态。在这个方法中,通过调用 `self._loaded.clear()` 实现了这一功能。`_loaded` 是一个标志,用于指示对象的数据是否已经被加载。调用 `clear` 方法将这个标志重置,意味着对象的加载状态被清除,对象被视为未加载状态。这通常是为了在数据需要重新加载时准备对象,确保数据的最新状态可以被重新加载和使用。 + +**注意**: 使用 `start_loading` 方法时,需要确保任何依赖于对象加载状态的操作都能正确处理对象的未加载状态。此外,考虑到这是一个线程安全的对象,`start_loading` 方法的调用应该在适当的同步机制下进行,以避免并发访问导致的问题。 +*** +### FunctionDef finish_loading(self) +**finish_loading**: 此函数的功能是标记对象加载完成。 + +**参数**: 此函数没有参数。 + +**代码描述**: `finish_loading` 函数是`ThreadSafeObject`类的一个方法,用于在对象的加载或初始化过程完成后,通过设置一个内部的线程安全标志(例如,使用`threading.Event`的`set`方法),来通知其他可能在等待此对象加载完成的线程。在本项目中,`finish_loading`方法被多个地方调用,主要用于标记嵌入模型(Embeddings)或向量存储(Vector Store)加载完成的状态。 + +在`load_embeddings`方法中,`finish_loading`被调用来标记一个嵌入模型对象加载完成。这个过程包括选择合适的嵌入模型,加载模型,并将模型对象赋值给`ThreadSafeObject`实例的`obj`属性,最后通过调用`finish_loading`方法来标记加载过程完成。 + +在`load_vector_store`方法中,无论是在`KBFaissPool`还是`MemoFaissPool`类中,`finish_loading`同样被用于标记向量存储加载完成。加载向量存储的过程可能包括从磁盘加载现有的向量存储,或者创建一个新的空向量存储,然后将这个向量存储对象赋值给`ThreadSafeFaiss`实例的`obj`属性,并通过`finish_loading`方法来标记加载完成。 + +**注意**: 使用`finish_loading`方法时,需要确保在对象的加载或初始化逻辑正确完成后调用此方法。此外,调用此方法前,通常会有线程锁的操作,以确保线程安全。在调用`finish_loading`之后,其他线程可以通过检查相应的线程安全标志来确定对象是否已经加载完成,从而进行后续操作。 +*** +### FunctionDef wait_for_loading(self) +**wait_for_loading**: 此函数的功能是等待直到对象加载完成。 + +**参数**: 此函数没有参数。 + +**代码描述**: `wait_for_loading` 函数是 `ThreadSafeObject` 类的一个方法,用于在多线程环境中确保对象安全地完成加载。该方法通过调用 `_loaded` 属性(一个线程安全的事件对象)的 `wait` 方法来实现。当 `_loaded` 事件被设置时,表示对象已经完成加载,此时 `wait` 方法将停止阻塞,允许执行后续代码。如果 `_loaded` 事件尚未被设置,调用此方法的线程将被阻塞,直到事件被设置。这种机制确保了在对象未完全加载前,任何依赖于对象状态的操作都将被暂停,从而避免了潜在的数据不一致或竞态条件问题。 + +**注意**: 使用 `wait_for_loading` 方法时,需要确保 `_loaded` 事件在对象加载完成后被正确设置,否则调用此方法的线程可能会无限期地阻塞。此外,考虑到多线程编程的复杂性,开发者应当仔细管理线程间的同步和通信,以避免死锁或资源竞争等问题。 +*** +### FunctionDef obj(self) +**obj**: 此函数的功能是获取ThreadSafeObject对象中的_obj属性。 + +**参数**: 此函数没有参数。 + +**代码描述**: `obj`函数是一个简单的访问器(accessor),用于返回ThreadSafeObject实例中的`_obj`属性。在多线程环境下,ThreadSafeObject对象提供了线程安全的访问方式,确保在并发访问时,对象的状态保持一致性。在项目中,`obj`函数被用于多个场景,主要是在加载嵌入向量(embeddings)和向量存储(vector store)时,获取已经加载或创建的对象实例。 + +例如,在`load_embeddings`方法中,首先检查是否已经加载了指定模型和设备的嵌入向量,如果没有,则创建一个新的ThreadSafeObject实例,并通过`obj`函数设置嵌入向量对象。在`load_vector_store`方法中,同样的逻辑被应用于加载或创建向量存储实例。这种使用方式确保了在并发环境下,对嵌入向量和向量存储的访问是线程安全的。 + +**注意**: 在使用`obj`函数时,需要确保ThreadSafeObject实例的`_obj`属性已经被正确初始化。否则,返回的将是`None`或者是初始状态的对象,这可能会导致后续操作中出现错误。 + +**输出示例**: 假设ThreadSafeObject实例的`_obj`属性被设置为了一个嵌入向量对象,那么调用`obj`函数将返回这个嵌入向量对象。例如: + +```python +embeddings = thread_safe_object_instance.obj() +``` + +这里,`embeddings`将是之前存储在ThreadSafeObject实例中的嵌入向量对象。 +*** +### FunctionDef obj(self, val) +**obj**: obj函数用于设置ThreadSafeObject实例的内部对象。 + +**参数**: +- `val`: 任意类型,表示要设置的值。 + +**代码描述**: +obj函数是ThreadSafeObject类的一个成员方法,其主要功能是将传入的参数`val`赋值给实例的`_obj`属性。这个方法是线程安全对象操作的基础,允许在多线程环境中安全地修改对象的状态。 + +在项目中,obj函数被用于不同的上下文中,主要涉及到加载和设置嵌入式对象或向量存储。例如,在`EmbeddingsPool`的`load_embeddings`方法中,obj函数用于将加载的嵌入式模型对象赋值给ThreadSafeObject实例。这样做可以确保在并发访问时,嵌入式模型对象的加载和访问是线程安全的。 + +同样,在`KBFaissPool`和`MemoFaissPool`的`load_vector_store`方法中,obj函数被用于设置加载或创建的向量存储对象。这些方法首先检查缓存中是否已存在所需的向量存储,如果不存在,则创建一个新的ThreadSafeFaiss实例,并通过obj函数将向量存储对象赋值给它。这确保了向量存储的加载和初始化过程是线程安全的。 + +**注意**: +- 使用obj函数时,需要确保传入的`val`参数是正确的类型,因为函数内部不进行类型检查。 +- 在多线程环境中使用obj函数修改对象状态时,应注意同步和并发控制,以避免数据竞争和不一致性问题。虽然obj函数本身的操作是简单的赋值,但它在项目中的应用场景通常涉及到线程安全的上下文,因此正确的使用方式对于保持程序的稳定性和正确性至关重要。 +*** +## ClassDef CachePool +**CachePool**: CachePool 类的功能是提供一个线程安全的缓存池,用于存储和管理缓存对象。 + +**属性**: +- `_cache_num`: 缓存池中允许存储的最大缓存对象数量。如果设置为-1,则不限制数量。 +- `_cache`: 一个有序字典,用于存储缓存对象。 +- `atomic`: 一个线程锁,确保缓存操作的线程安全。 + +**代码描述**: +CachePool 类提供了一个线程安全的缓存池实现,允许用户存储、获取和管理缓存对象。它使用了一个有序字典 `_cache` 来存储缓存对象,其中键是缓存对象的标识符,值是缓存对象本身。通过 `atomic` 线程锁确保了对缓存操作的线程安全性。 + +- `__init__` 方法初始化缓存池,可以指定缓存池中允许的最大缓存对象数量。 +- `keys` 方法返回当前缓存中所有键的列表。 +- `_check_count` 方法检查当前缓存的数量,如果超过了设定的最大值,则移除最早添加的缓存对象。 +- `get` 方法根据键获取缓存对象。如果对象存在,则等待对象加载完成后返回。 +- `set` 方法将一个对象添加到缓存中,并根据需要移除最早的缓存对象以保持在最大数量限制内。 +- `pop` 方法可以移除并返回指定键的缓存对象。如果没有指定键,则移除并返回最早添加的缓存对象。 +- `acquire` 方法尝试获取指定键的缓存对象,并对其进行加锁处理,确保在并发环境下的数据一致性。 +- `load_kb_embeddings` 方法用于加载知识库嵌入向量,它根据知识库名称、嵌入设备和默认嵌入模型加载嵌入向量。 + +CachePool 类在项目中被其他对象如 `EmbeddingsPool` 和 `_FaissPool` 调用,用于管理嵌入向量和向量存储的缓存。这些调用情况表明 CachePool 类在知识库嵌入向量和向量存储管理中起到了核心作用,为上层提供了缓存管理和线程安全的支持。 + +**注意**: +- 在多线程环境下操作缓存时,应确保正确使用 `atomic` 锁来避免数据竞争。 +- 当设置 `_cache_num` 限制缓存数量时,需要注意缓存淘汰策略可能会影响到缓存对象的可用性。 + +**输出示例**: +由于 CachePool 主要提供缓存管理功能,其输出依赖于存储在缓存中的对象类型。例如,如果缓存中存储的是嵌入向量对象,那么 `get` 方法可能返回一个嵌入向量对象的实例。 +### FunctionDef __init__(self, cache_num) +**__init__**: 此函数的功能是初始化CachePool对象。 + +**参数**: +- `cache_num`: 整型,表示缓存中允许的最大元素数量,默认值为-1,表示不限制数量。 +- `self._cache`: 使用`OrderedDict`初始化,用于存储缓存数据,保持插入顺序。 +- `self.atomic`: 使用`threading.RLock`初始化,提供一个基于线程的锁,用于控制对缓存数据的并发访问,确保线程安全。 + +**代码描述**: +此函数是`CachePool`类的构造函数,用于初始化一个缓存池对象。它接受一个参数`cache_num`,该参数指定了缓存中可以存储的最大元素数量。如果`cache_num`的值为-1,则表示缓存大小不受限制。函数内部首先将`cache_num`参数的值赋给对象的`_cache_num`属性,用于后续控制缓存大小。接着,使用`OrderedDict`初始化`_cache`属性,`OrderedDict`是一种特殊的字典,它可以记住元素被插入的顺序,这对于某些缓存淘汰策略(如最近最少使用LRU)是非常有用的。最后,通过`threading.RLock`创建一个可重入锁`atomic`,赋给对象的`atomic`属性。这个锁用于同步对缓存的访问,确保在多线程环境下对缓存的操作是线程安全的。 + +**注意**: +- 在多线程环境下操作缓存时,应确保正确使用`self.atomic`锁,以避免数据竞争和不一致的问题。 +- `cache_num`的默认值为-1,意味着如果不特别指定,缓存大小不会受到限制。在实际应用中,根据需要合理设置此参数,以避免因缓存过大而消耗过多内存资源。 +- `OrderedDict`虽然可以保持元素的插入顺序,但在处理大量数据时可能会比普通字典有更高的性能开销,因此在设计缓存策略时应考虑到这一点。 +*** +### FunctionDef keys(self) +**keys**: 此函数的作用是获取缓存中所有键的列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `keys` 函数是 `CachePool` 类的一个方法,它的主要作用是从缓存中检索所有的键,并将这些键作为字符串列表返回。在这个函数中,`self._cache.keys()` 调用会获取 `_cache` 字典中所有的键,然后通过 `list()` 函数将这些键转换成列表形式。这是一个非常基础但重要的功能,因为它允许其他部分的代码了解缓存中目前存储了哪些数据的键。 + +在项目中,这个函数被 `file_chat` 函数调用,以检查传入的 `knowledge_id` 是否存在于 `memo_faiss_pool` 缓存中。如果 `knowledge_id` 不在缓存的键中,`file_chat` 函数将返回一个错误响应,指出需要的临时知识库未找到。这表明 `keys` 函数在项目中用于验证和检索操作,确保在进行进一步处理之前,所需的数据已经被正确地存储在缓存中。 + +**注意**: 使用此函数时,需要确保 `_cache` 已经被正确初始化并且包含了所需的数据。此外,返回的键列表仅代表了函数被调用时刻缓存中的状态,缓存内容的后续更新不会反映在已返回的列表中。 + +**输出示例**: 假设缓存中存储了三个键,分别为 `"key1"`, `"key2"`, `"key3"`,那么调用 `keys` 函数将返回以下列表: +```python +["key1", "key2", "key3"] +``` +*** +### FunctionDef _check_count(self) +**_check_count**: 此函数的功能是检查缓存中的项目数量,并确保其不超过设定的最大值。 + +**参数**: 此函数没有参数。 + +**代码描述**: `_check_count` 函数是 `CachePool` 类的一个私有方法,用于维护缓存池中的项目数量不超过一个预设的最大值。这个函数首先检查成员变量 `_cache_num` 是否为整数且大于0。如果是,函数进入一个循环,循环的条件是缓存池 `_cache` 的长度大于 `_cache_num`。在循环内部,使用 `_cache.popitem(last=False)` 从缓存中移除最早添加的项目,直到缓存的大小不超过 `_cache_num`。这种机制确保了缓存池不会无限增长,从而有效管理内存使用。 + +在项目中,`_check_count` 被 `set` 方法调用。`set` 方法用于向缓存中添加一个新的项目,并在添加后立即调用 `_check_count` 来确保缓存池的大小不会超过预设的限制。这表明 `_check_count` 在缓存管理策略中起到了关键的作用,它通过限制缓存大小来防止内存溢出,确保了缓存系统的健壮性和稳定性。 + +**注意**: `_check_count` 是一个私有方法,意味着它仅在 `CachePool` 类内部使用,不应该被类外部直接调用。这种设计封装了缓存管理的细节,使得 `CachePool` 类的使用更加安全和方便。在使用 `CachePool` 类时,开发者无需直接管理缓存大小,而是通过设置 `_cache_num` 并使用 `set` 方法来间接控制。 +*** +### FunctionDef get(self, key) +**get**: 此函数的功能是从缓存池中获取与给定键关联的线程安全对象。 + +**参数**: +- `key`: 字符串类型,用于从缓存中检索对象的键。 + +**代码描述**: +`get` 函数首先尝试从缓存池 `_cache` 中使用给定的键 `key` 来获取一个对象。如果找到了对应的对象,该函数会调用该对象的 `wait_for_loading` 方法。这个方法的作用是阻塞当前线程,直到对象的加载状态被设置为完成。这确保了在返回对象之前,对象已经处于可用状态。如果缓存中没有找到对应的键,函数将不会返回任何值。 + +在项目中,`get` 函数被多个地方调用,包括但不限于加载嵌入向量、保存和卸载向量存储、以及在工作线程中操作向量存储。这些调用场景表明,`get` 函数是处理缓存对象的关键组件,特别是在需要确保对象加载完成后再进行操作的情况下。 + +**注意**: +- 使用 `get` 函数时,应确保提供的键 `key` 在缓存中确实存在,否则函数将返回 `None`。 +- 在多线程环境下,`get` 函数通过 `wait_for_loading` 方法确保了线程安全,避免了在对象加载完成前的竞态条件。 + +**输出示例**: +假设缓存中存在一个键为 `"example_key"` 的 `ThreadSafeObject` 实例,且该实例已完成加载。调用 `get("example_key")` 将返回该 `ThreadSafeObject` 实例。如果 `"example_key"` 不存在于缓存中,函数将返回 `None`。 +*** +### FunctionDef set(self, key, obj) +**set**: 此函数的功能是将一个线程安全的对象添加到缓存池中,并返回该对象。 + +**参数**: +- `key`: 字符串类型,用于标识缓存中的对象。 +- `obj`: `ThreadSafeObject` 类型,表示要添加到缓存中的线程安全对象。 + +**代码描述**: `set` 函数首先将传入的线程安全对象 `obj` 与其对应的键 `key` 存储在缓存池的内部字典 `_cache` 中。这一操作确保了对象可以通过键值快速检索。随后,函数调用 `_check_count` 方法来检查缓存池中的对象数量是否超过了预设的最大值,如果超过了,将自动移除最早添加的对象以保持缓存池的大小在限制之内。最后,函数返回刚刚添加的线程安全对象 `obj`。 + +在项目中,`set` 函数被用于多个场景,包括但不限于加载嵌入向量(`load_embeddings`)、加载向量存储(`load_vector_store`)等。这些场景中,`set` 函数负责将新创建或加载的资源(如嵌入向量、向量存储)以线程安全的方式添加到缓存池中,确保后续可以高效、安全地访问这些资源。 + +**注意**: +- 使用 `set` 函数时,需要确保传入的键 `key` 在缓存池中唯一,以避免覆盖已有的缓存项。 +- 由于 `set` 函数会检查缓存池的大小并在必要时移除最早的缓存项,开发者应当合理设置缓存池的最大容量 `_cache_num`,以平衡内存使用和性能需求。 +- 在多线程环境下,`set` 函数保证了添加缓存项的线程安全性,但在使用缓存项时,仍需注意线程安全的访问和操作。 + +**输出示例**: 假设调用 `set` 函数添加了一个键为 `"example_key"`,对象为某个 `ThreadSafeObject` 实例的缓存项,函数将返回这个 `ThreadSafeObject` 实例。 +*** +### FunctionDef pop(self, key) +**pop**: 该函数用于从缓存池中移除并返回指定键的对象或最早添加的对象。 + +**参数**: +- `key`: 字符串类型,指定要移除对象的键。默认为 None,表示移除并返回最早添加的对象。 + +**代码描述**: +`pop` 函数是 `CachePool` 类的一个方法,用于根据给定的键从缓存中移除并返回相应的对象。如果调用时没有提供键(即 `key=None`),则函数会移除并返回缓存中最早被添加的对象。这是通过调用 `_cache` 字典的 `popitem` 方法实现的,其中 `last=False` 参数确保返回最早添加的项。如果提供了键,则通过 `_cache` 字典的 `pop` 方法尝试移除并返回与该键关联的对象。如果键不存在,则返回 `None`。 + +在项目中,`pop` 方法被多个场景调用,例如在 `upload_temp_docs` 函数中,用于移除之前的临时文档;在 `unload_vector_store` 方法中,用于释放向量库;在 `do_clear_vs` 方法中,用于清除特定的向量存储;以及在 `drop_kb_summary` 方法中,用于删除知识库摘要。这些调用场景表明 `pop` 方法在管理缓存资源、维护缓存状态和释放不再需要的资源方面起着关键作用。 + +**注意**: +- 在使用 `pop` 方法时,应确保键的正确性和存在性,特别是在期望移除特定对象时。如果键不存在,方法将返回 `None`,而不是抛出异常。 +- 当不需要指定键移除对象时,应注意 `pop` 方法将移除并返回最早添加的对象,这可能会影响缓存的使用逻辑。 + +**输出示例**: +假设缓存中存在键为 "example_key" 的 `ThreadSafeObject` 对象,调用 `pop("example_key")` 将返回该对象,并从缓存中移除。如果缓存为空或键不存在,调用 `pop("nonexistent_key")` 将返回 `None`。 +*** +### FunctionDef acquire(self, key, owner, msg) +**acquire**: 此函数的功能是从缓存池中安全地获取与给定键关联的对象。 + +**参数**: +- `key`: 字符串或元组类型,用于从缓存中检索对象的键。 +- `owner`: 字符串类型,默认为空字符串,表示请求对象的所有者。 +- `msg`: 字符串类型,默认为空字符串,用于附加消息或说明。 + +**代码描述**: +`acquire` 函数首先通过调用 `get` 方法尝试从缓存池中获取与给定键 `key` 关联的对象。如果缓存中不存在该键对应的对象,函数将抛出 `RuntimeError` 异常,提示请求的资源不存在。如果成功获取到对象,并且该对象是 `ThreadSafeObject` 类型的实例,则会调用该对象的 `acquire` 方法来安全地获取对象的引用,并将其返回。这一过程涉及到线程安全的处理,确保在多线程环境下对对象的访问是安全的。如果获取到的对象不是 `ThreadSafeObject` 类型的实例,则直接返回该对象。 + +在项目中,`acquire` 函数被用于安全地获取缓存中的对象,以进行后续操作。例如,在 `knowledge_base_chat_iterator` 函数中,通过调用 `acquire` 方法来获取知识库中的向量存储对象,以执行相似度搜索等操作。 + +**注意**: +- 在使用 `acquire` 函数时,应确保提供的键 `key` 在缓存中确实存在,否则会抛出异常。 +- 当获取到的对象是 `ThreadSafeObject` 类型的实例时,应通过 `with` 语句或其他方式确保在操作完成后释放锁,以避免潜在的死锁问题。 +- `acquire` 方法的使用场景主要集中在需要线程安全访问和操作缓存对象的情况。 + +**输出示例**: +由于 `acquire` 函数的返回值取决于缓存中对象的类型,因此可能有不同的返回形式。如果缓存中的对象是 `ThreadSafeObject` 类型的实例,则返回值将是该对象的引用;如果是其他类型的对象,则直接返回该对象。例如,如果缓存中存在键为 `"example_key"` 的 `ThreadSafeObject` 实例,调用 `acquire("example_key")` 将返回该实例的引用。如果 `"example_key"` 对应的是非 `ThreadSafeObject` 类型的对象,则直接返回该对象。 +*** +### FunctionDef load_kb_embeddings(self, kb_name, embed_device, default_embed_model) +**load_kb_embeddings**: 此函数的功能是加载指定知识库名称的嵌入向量。 + +**参数**: +- `kb_name`: 字符串类型,指定要加载嵌入向量的知识库名称。 +- `embed_device`: 字符串类型,默认值由`embedding_device`函数确定,用于指定计算设备。 +- `default_embed_model`: 字符串类型,默认值为`EMBEDDING_MODEL`,用于指定默认的嵌入模型。 + +**代码描述**: +此函数首先从`knowledge_base_repository`中调用`get_kb_detail`函数,根据`kb_name`获取知识库的详细信息,包括嵌入模型名称。如果知识库详情中包含嵌入模型名称,则使用该名称;否则,使用传入的`default_embed_model`作为嵌入模型名称。接着,函数检查该嵌入模型是否在在线模型列表中,该列表由`list_online_embed_models`函数提供。如果嵌入模型存在于在线模型列表中,则通过`EmbeddingsFunAdapter`类创建一个嵌入向量适配器实例并返回。如果嵌入模型不在在线模型列表中,则调用`embeddings_pool`的`load_embeddings`方法,根据模型名称和设备类型加载嵌入向量,并返回加载的嵌入向量实例。 + +**注意**: +- 在调用此函数时,需要确保传入的`kb_name`是存在的知识库名称,且知识库中有对应的嵌入模型信息。 +- `embed_device`参数应根据实际计算环境选择合适的设备类型,如`"cuda"`、`"mps"`或`"cpu"`。 +- 此函数依赖于`EmbeddingsFunAdapter`类和`embeddings_pool`的`load_embeddings`方法,因此在使用前应确保相关依赖正确配置。 + +**输出示例**: +假设知识库名称为"技术文档库",且该知识库使用的嵌入模型在在线模型列表中,则可能返回一个`EmbeddingsFunAdapter`实例。如果嵌入模型不在在线模型列表中,则可能返回由`load_embeddings`方法加载的嵌入向量实例,具体类型取决于加载的嵌入模型。 +*** +## ClassDef EmbeddingsPool +**EmbeddingsPool**: EmbeddingsPool 类的功能是管理和加载不同模型的嵌入向量。 + +**属性**: +- 无特定公开属性,继承自 CachePool 类的属性。 + +**代码描述**: +EmbeddingsPool 类继承自 CachePool 类,专门用于加载和管理嵌入向量。它提供了一个 `load_embeddings` 方法,该方法负责根据指定的模型和设备加载嵌入向量。方法首先尝试从缓存中获取嵌入向量,如果缓存中不存在,则根据模型类型创建相应的嵌入向量对象,并将其添加到缓存中。 + +在加载嵌入向量时,根据模型的不同,EmbeddingsPool 类会调用不同的嵌入向量类。例如,对于 OpenAI 的 "text-embedding-ada-002" 模型,它会使用 `OpenAIEmbeddings` 类;对于包含 "bge-" 的模型,它会根据模型语言选择 `HuggingFaceBgeEmbeddings` 类,并设置相应的查询指令;对于其他模型,它默认使用 `HuggingFaceEmbeddings` 类。 + +此外,`load_embeddings` 方法在加载嵌入向量之前会通过 `atomic` 锁确保线程安全,避免在并发环境下的数据竞争问题。加载完成后,嵌入向量对象会被存储在缓存中,以便后续快速获取。 + +**注意**: +- 使用 `load_embeddings` 方法时,需要确保传入的模型和设备参数正确,否则可能无法加载正确的嵌入向量。 +- 在多线程环境下使用此类时,其内部的线程安全机制可以保护嵌入向量的加载过程,但调用者仍需注意线程安全的其他方面。 +- 由于嵌入向量可能占用大量内存,应合理管理缓存大小,避免内存溢出。 + +**输出示例**: +调用 `load_embeddings` 方法可能返回的嵌入向量对象示例: +```python +embeddings = embeddings_pool.load_embeddings(model="text-embedding-ada-002", device="cuda") +``` +此代码行将返回一个针对 "text-embedding-ada-002" 模型的 `OpenAIEmbeddings` 对象,该对象已配置好与 OpenAI API 交互所需的所有参数,并准备好在指定的设备上进行嵌入向量的计算。 +### FunctionDef load_embeddings(self, model, device) +**load_embeddings**: 此函数的功能是加载并返回指定模型和设备上的嵌入向量对象。 + +**参数**: +- `model`: 字符串类型,指定要加载的嵌入模型名称。如果未提供,则使用默认的嵌入模型。 +- `device`: 字符串类型,指定计算设备。如果未提供,则通过`embedding_device`函数自动检测并选择合适的设备。 + +**代码描述**: +函数首先尝试获取一个线程安全的锁,以确保在多线程环境下的操作安全。然后,根据提供的模型名称和设备类型构造一个键值对`key`,用于检索或存储嵌入向量对象。如果缓存中不存在对应的嵌入向量对象,函数将创建一个新的`ThreadSafeObject`实例,并根据模型名称加载相应的嵌入向量。 + +如果模型名称为`"text-embedding-ada-002"`,则加载OpenAI提供的嵌入模型。如果模型名称包含`"bge-"`,则根据模型名称中的语言标识(如`"zh"`或`"en"`)加载对应语言的HuggingFace Bge嵌入模型,并设置相应的查询指令。对于其他模型名称,将加载HuggingFace提供的嵌入模型。 + +加载完成后,将嵌入向量对象赋值给`ThreadSafeObject`实例的`obj`属性,并标记加载完成。如果缓存中已存在对应的嵌入向量对象,则直接返回该对象。 + +**注意**: +- 在使用此函数时,应确保提供的模型名称和计算设备类型正确,以便正确加载嵌入向量。 +- 函数内部使用了多线程安全机制,包括锁和`ThreadSafeObject`,以确保在并发环境下的操作安全。 +- 加载嵌入向量可能需要一定的时间,特别是首次加载时,因此在设计应用逻辑时应考虑到可能的延迟。 + +**输出示例**: +调用`load_embeddings(model="text-embedding-ada-002", device="cuda")`可能会返回一个`OpenAIEmbeddings`的实例,该实例已经加载了指定的OpenAI嵌入模型,并准备好在CUDA设备上进行嵌入向量的计算。 + +在项目中,`load_embeddings`函数被`load_kb_embeddings`和`load_local_embeddings`等函数调用,用于加载知识库嵌入向量或本地嵌入向量,以支持不同的应用场景,如文本相似度计算、文本检索等。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_cache/faiss_cache.md b/markdown_docs/server/knowledge_base/kb_cache/faiss_cache.md new file mode 100644 index 000000000..63d4862d0 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_cache/faiss_cache.md @@ -0,0 +1,302 @@ +## FunctionDef _new_ds_search(self, search) +**_new_ds_search**: 此函数的功能是根据提供的搜索字符串查找并返回相应的文档或未找到的信息。 + +**参数**: +- `search`: 需要搜索的字符串,用于在内部字典中查找对应的文档。 + +**代码描述**: +此函数接收一个名为`search`的参数,该参数是一个字符串,用于在内部维护的字典`_dict`中查找对应的条目。函数首先检查`search`是否存在于`_dict`中。如果不存在,函数将返回一个格式化的字符串,指出给定的ID未找到。如果找到了对应的条目,函数将进一步检查这个条目是否是一个`Document`类型的实例。如果是,函数将在该文档的元数据中添加一个`id`字段,其值为`search`参数的值。最后,无论条目是否为`Document`实例,函数都将返回这个条目。 + +**注意**: +- 函数返回值的类型依赖于查找结果。如果未找到对应的条目,将返回一个字符串;如果找到了条目,返回值将是该条目本身,可能是`Document`类型或其他类型。 +- 在使用此函数时,需要确保`_dict`已经被正确初始化并填充了相应的数据。 +- 当返回的是`Document`类型的实例时,其`metadata`将包含一个额外的`id`字段,其值对应于搜索字符串。 + +**输出示例**: +- 如果搜索的ID未在`_dict`中找到,可能的返回值为:"ID 12345 not found." +- 如果搜索的ID在`_dict`中找到,并且对应的条目是一个`Document`实例,返回的将是这个被更新了`metadata`的`Document`实例。 +## ClassDef ThreadSafeFaiss +**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 可以有效避免数据竞争和其他并发问题。 + +**输出示例**: +假设有一个 ThreadSafeFaiss 实例,其 `key` 为 "example_key",`_obj` 为某个 FAISS 向量库对象,且向量库中有 100 个文档。调用 `__repr__` 方法可能会返回如下字符串: +`", docs_count: 100>"` + +通过这个类,开发者可以在多线程环境中安全高效地管理和操作 FAISS 向量库,无需担心线程安全问题。 +### FunctionDef __repr__(self) +**__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__` 方法可能返回如下字符串: +``` +", docs_count: 3>" +``` +*** +### FunctionDef docs_count(self) +**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`。 +*** +### FunctionDef save(self, path, create_path) +**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`的向量库已成功保存到磁盘。 +*** +### FunctionDef clear(self) +**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, ...] +``` +如果向量库原本为空,或者在删除过程中没有实际删除任何文档,则返回一个空列表: +``` +[] +``` +*** +## ClassDef _FaissPool +**_FaissPool**: _FaissPool 类的功能是管理和操作基于FAISS库的向量存储。 + +**属性**: +- 该类继承自 `CachePool`,因此拥有 `CachePool` 的所有属性和方法。 + +**代码描述**: +_FaissPool 类提供了三个主要方法来管理向量存储:`new_vector_store`、`save_vector_store` 和 `unload_vector_store`。 + +1. `new_vector_store` 方法用于创建一个新的向量存储。它接受嵌入模型名称和嵌入设备作为参数,使用 `EmbeddingsFunAdapter` 来适配不同的嵌入模型,并创建一个文档对象 `doc` 作为初始化数据。然后,它使用 `FAISS.from_documents` 方法根据这个文档对象和嵌入模型创建一个新的FAISS向量存储,同时设置L2归一化和距离策略。创建后,它会删除这个初始化文档对象,以便返回一个空的向量存储。 + +2. `save_vector_store` 方法用于保存指定名称的向量存储到磁盘。如果在缓存中找到了对应名称的向量存储,它会调用向量存储的 `save` 方法将其保存到指定路径。 + +3. `unload_vector_store` 方法用于从缓存中卸载并释放指定名称的向量存储。如果在缓存中找到了对应名称的向量存储,它会先从缓存中移除该向量存储,然后记录一条日志信息表示向量库已成功释放。 + +**注意**: +- 在使用 `new_vector_store` 方法创建向量存储时,需要确保传入的嵌入模型名称和嵌入设备是有效的,因为这将影响向量存储的创建和后续的向量检索性能。 +- 使用 `save_vector_store` 方法保存向量存储时,如果没有提供保存路径,则需要确保向量存储对象已经配置了默认的保存路径。 +- 在调用 `unload_vector_store` 方法卸载向量存储之前,应确保没有其他操作正在使用该向量存储,以避免数据丢失或访问冲突。 + +**输出示例**: +由于这些方法主要进行向量存储的管理操作,它们的输出通常不直接返回数据给用户。例如,`new_vector_store` 方法返回一个初始化后的空的FAISS向量存储对象,而 `save_vector_store` 和 `unload_vector_store` 方法则没有返回值,它们的执行结果主要通过日志信息和向量存储的状态变化来体现。 +### FunctionDef new_vector_store(self, embed_model, embed_device) +**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对象,准备好接收和管理文档向量数据。 +*** +### FunctionDef save_vector_store(self, kb_name, path) +**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`。 +*** +### FunctionDef unload_vector_store(self, kb_name) +**unload_vector_store**: 此函数的功能是从缓存池中卸载并释放指定的向量库。 + +**参数**: +- `kb_name`: 字符串类型,指定要卸载并释放的向量库的名称。 + +**代码描述**: +`unload_vector_store` 函数是 `_FaissPool` 类的一个方法,用于卸载并释放指定名称的向量库。该函数首先调用 `get` 方法尝试从缓存池中获取与给定名称 `kb_name` 关联的向量库对象。如果成功获取到对象,`get` 方法会确保该对象的加载状态已完成,这是通过对象的 `wait_for_loading` 方法实现的,从而确保在进行后续操作前,对象已经处于可用状态。 + +获取到对象后,函数接着调用 `pop` 方法,根据提供的向量库名称 `kb_name` 从缓存池中移除该对象。移除操作成功后,会通过日志记录一条信息,表明指定的向量库已成功释放。 + +在整个过程中,`get` 方法确保了只有在向量库对象确实存在且加载完成的情况下,才会进行卸载操作。而 `pop` 方法则负责实际的移除操作,并处理缓存池中对象的移除逻辑。 + +**注意**: +- 使用此函数时,应确保提供的向量库名称 `kb_name` 在缓存池中确实存在。如果不存在,函数将不执行任何操作。 +- 此函数通过日志记录操作结果,有助于监控和调试向量库的卸载过程。 +- 在多线程环境下,`get` 方法的线程安全机制确保了在进行卸载操作前,对象的加载状态已经完成,避免了潜在的竞态条件。 +*** +## ClassDef KBFaissPool +**KBFaissPool**: KBFaissPool 类的功能是管理和加载基于FAISS库的向量存储池。 + +**属性**: +- 继承自 `_FaissPool` 类,因此拥有 `_FaissPool` 的所有属性和方法。 + +**代码描述**: +KBFaissPool 类主要提供了 `load_vector_store` 方法,用于加载或创建向量存储。该方法接受知识库名称(`kb_name`)、向量名称(`vector_name`)、是否创建新的向量存储(`create`)、嵌入模型名称(`embed_model`)和嵌入设备(`embed_device`)作为参数。 + +1. 方法首先尝试从内部缓存中获取指定的向量存储。如果未找到,它将初始化一个新的 `ThreadSafeFaiss` 对象,并尝试从磁盘加载向量存储或根据参数创建一个新的向量存储。 + +2. 如果指定路径下存在 `index.faiss` 文件,则从磁盘加载向量存储,并使用指定的嵌入模型和设备加载知识库嵌入。加载过程中,会对向量进行L2归一化,并设置距离策略为内积。 + +3. 如果指定路径下不存在 `index.faiss` 文件且 `create` 参数为真,则会创建一个新的空向量存储,并保存到磁盘。 + +4. 如果既不存在 `index.faiss` 文件,`create` 参数也为假,则抛出异常,表示指定的知识库不存在。 + +在加载或创建向量存储后,方法会将 `ThreadSafeFaiss` 对象存入内部缓存,并返回该对象。 + +**注意**: +- 在调用 `load_vector_store` 方法时,需要确保传入的知识库名称和向量名称是有效的,以便正确地加载或创建向量存储。 +- 如果指定的向量存储已存在于内部缓存中,则方法会直接返回该缓存对象,而不会重复加载或创建。 +- 在创建新的向量存储时,需要确保嵌入模型和设备参数正确配置,以保证向量存储的性能和兼容性。 + +**输出示例**: +调用 `load_vector_store` 方法可能返回的示例输出为一个 `ThreadSafeFaiss` 对象,该对象封装了FAISS向量存储的操作和管理,允许线程安全地访问和修改向量存储。 +### FunctionDef load_vector_store(self, kb_name, vector_name, create, embed_model, embed_device) +**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`对象,准备好接收和管理文档向量数据。 +*** +## ClassDef MemoFaissPool +**MemoFaissPool**: MemoFaissPool 类的功能是在内存中加载和管理基于FAISS库的向量存储池。 + +**属性**: +- 继承自 `_FaissPool` 类,因此拥有 `_FaissPool` 的所有属性和方法。 + +**代码描述**: +`MemoFaissPool` 类通过继承 `_FaissPool` 类,提供了一种高效管理FAISS向量存储的方式。它主要通过 `load_vector_store` 方法来加载或初始化向量存储。 + +1. `load_vector_store` 方法接受三个参数:`kb_name`(知识库名称),`embed_model`(嵌入模型,默认为 `EMBEDDING_MODEL`),和 `embed_device`(嵌入设备,默认由 `embedding_device()` 函数确定)。该方法首先尝试从缓存中获取指定名称的向量存储。如果未找到,它将创建一个新的 `ThreadSafeFaiss` 对象,并将其添加到缓存中。在这个过程中,它使用了线程安全的锁机制来确保操作的原子性。 + +2. 在初始化 `ThreadSafeFaiss` 对象时,会调用 `_FaissPool` 类的 `new_vector_store` 方法来创建一个空的向量存储。这个过程涉及到使用指定的嵌入模型和设备来创建向量存储,确保了向量存储的创建与配置的灵活性和可定制性。 + +3. 完成向量存储的加载后,`load_vector_store` 方法会通过调用 `finish_loading` 方法来标记向量存储的加载状态,确保向量存储已经准备好被使用。 + +**注意**: +- 在使用 `load_vector_store` 方法时,需要确保传入的知识库名称、嵌入模型和嵌入设备参数正确无误,因为这些参数直接影响向量存储的创建和性能。 +- 该类使用了线程安全的锁机制来保护向量存储的加载过程,避免了并发访问和修改时可能出现的数据不一致问题。 +- 由于 `MemoFaissPool` 类继承自 `_FaissPool`,在使用该类之前,需要对 `_FaissPool` 类及其方法有一定的了解。 + +**输出示例**: +由于 `load_vector_store` 方法的主要作用是加载或初始化向量存储,其直接的返回值是一个 `ThreadSafeFaiss` 对象。这个对象代表了一个已加载或新创建的向量存储,可以被进一步用于向量的检索或管理操作。例如,如果成功加载了名为 "knowledge_base" 的向量存储,那么返回的 `ThreadSafeFaiss` 对象将包含这个向量存储的所有相关信息和操作接口。 +### FunctionDef load_vector_store(self, kb_name, embed_model, embed_device) +**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`函数调用,用于在上传文件并进行向量化处理时,加载或初始化临时向量库。这确保了上传的文档能够被正确地添加到向量库中,以支持后续的搜索和检索操作。 +*** +## FunctionDef worker(vs_name, name) +**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`方法获取的上下文管理器确保了操作的线程安全。 diff --git a/markdown_docs/server/knowledge_base/kb_doc_api.md b/markdown_docs/server/knowledge_base/kb_doc_api.md new file mode 100644 index 000000000..df77327c5 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_doc_api.md @@ -0,0 +1,417 @@ +## FunctionDef search_docs(query, knowledge_base_name, top_k, score_threshold, file_name, metadata) +**search_docs**: 此函数的功能是根据用户输入的查询条件,在指定的知识库中搜索相关文档。 + +**参数**: +- `query`: 字符串类型,默认为空字符串,表示用户的查询输入。 +- `knowledge_base_name`: 字符串类型,必填,表示要搜索的知识库名称。 +- `top_k`: 整型,表示返回的匹配向量数目。 +- `score_threshold`: 浮点型,取值范围在0-1之间,表示知识库匹配相关度阈值。SCORE越小,相关度越高,取到1相当于不筛选。 +- `file_name`: 字符串类型,默认为空字符串,表示文件名称,支持sql通配符。 +- `metadata`: 字典类型,默认为空字典,表示根据metadata进行过滤,仅支持一级键。 + +**代码描述**: +函数首先通过`KBServiceFactory.get_service_by_name`方法获取指定知识库的服务实例。如果知识库服务实例存在,函数将根据是否提供了`query`参数来决定搜索逻辑。如果提供了`query`参数,函数将调用知识库服务实例的`search_docs`方法进行搜索,并将搜索结果转换为`DocumentWithVSId`对象列表返回。如果没有提供`query`但提供了`file_name`或`metadata`参数,函数将调用知识库服务实例的`list_docs`方法列出文档。最终,函数返回一个包含`DocumentWithVSId`对象的列表。 + +**注意**: +- 在使用此函数时,确保传入的知识库名称在系统中已存在,否则将无法获取知识库服务实例,导致搜索失败。 +- `score_threshold`参数用于过滤搜索结果,较低的值意味着更高的相关性要求,可根据实际需求调整。 +- 当`query`参数为空时,可以通过`file_name`或`metadata`参数来列出知识库中的文档,这在需要根据特定条件获取文档列表时非常有用。 + +**输出示例**: +假设在知识库中搜索"技术文档",并且设置`top_k=2`,`score_threshold=0.5`,可能得到如下输出: +```python +[ + DocumentWithVSId(id="doc1", score=0.45, metadata={"title": "技术文档介绍", "author": "张三"}), + DocumentWithVSId(id="doc2", score=0.48, metadata={"title": "技术文档使用手册", "author": "李四"}) +] +``` +此输出示例展示了根据查询条件返回的前两个最相关的文档对象列表,每个对象包含文档的唯一标识符、匹配得分以及元数据信息。 +## FunctionDef update_docs_by_id(knowledge_base_name, docs) +**update_docs_by_id**: 按照文档 ID 更新文档内容。 + +**参数**: +- `knowledge_base_name`: 知识库名称,类型为字符串。此参数用于指定要更新文档的知识库。 +- `docs`: 要更新的文档内容,类型为字典,形如 `{id: Document, ...}`。字典的键为文档的 ID,值为 `Document` 对象。 + +**代码描述**: +`update_docs_by_id` 函数首先通过 `KBServiceFactory.get_service_by_name` 方法,根据传入的知识库名称 `knowledge_base_name` 获取对应的知识库服务实例。如果指定的知识库不存在,函数将返回一个 `BaseResponse` 对象,其 `code` 属性设置为500,`msg` 属性表示指定的知识库不存在的错误信息。如果知识库存在,函数将调用知识库服务实例的 `update_doc_by_ids` 方法,尝试更新传入的文档。如果更新成功,函数返回一个 `BaseResponse` 对象,其 `msg` 属性表示文档更新成功的信息;如果更新失败,返回的 `BaseResponse` 对象的 `msg` 属性将表示文档更新失败的信息。 + +**注意**: +- 在调用此函数之前,确保传入的 `knowledge_base_name` 在系统中存在,否则将无法找到对应的知识库进行操作。 +- `docs` 参数中的 `Document` 对象应包含要更新的文档内容。确保文档 ID 与知识库中现有文档的 ID 匹配,以便正确更新。 +- 此函数的执行结果(成功或失败)将通过返回的 `BaseResponse` 对象的 `msg` 属性反馈。因此,调用此函数后应检查返回值,以确认操作结果。 + +**输出示例**: +如果指定的知识库名称不存在,函数可能返回如下的 `BaseResponse` 对象: +```python +BaseResponse(code=500, msg="指定的知识库 不存在") +``` +如果文档更新成功,函数将返回: +```python +BaseResponse(msg="文档更新成功") +``` +如果文档更新失败,函数将返回: +```python +BaseResponse(msg="文档更新失败") +``` + +此函数是项目中知识库管理功能的一部分,允许通过 API 直接根据文档 ID 更新知识库中的文档内容。它在 `server/api.py` 文件中通过 `mount_knowledge_routes` 函数注册为 API 路由,使得前端或其他服务可以通过发送 HTTP 请求来调用此功能,实现知识库文档的更新操作。 +## FunctionDef list_files(knowledge_base_name) +**list_files**: 此函数用于列出指定知识库中的所有文件名。 + +**参数**: +- `knowledge_base_name`: 字符串类型,表示要查询文件列表的知识库名称。 + +**代码描述**: `list_files` 函数首先验证传入的知识库名称的合法性,如果名称不合法(例如包含潜在的安全风险字符),则返回一个403状态码和错误信息。之后,函数对知识库名称进行URL解码处理,以确保能够正确处理经过URL编码的知识库名称。接着,通过 `KBServiceFactory.get_service_by_name` 方法获取对应知识库的服务实例。如果该知识库不存在,则返回一个404状态码和错误信息。如果知识库存在,函数将调用知识库服务实例的 `list_files` 方法获取所有文件名,并将这些文件名作为数据返回给客户端。 + +**注意**: +- 在调用此函数之前,需要确保传入的知识库名称是经过URL编码的,以避免潜在的URL解析错误。 +- 此函数依赖于 `KBServiceFactory.get_service_by_name` 方法来获取知识库服务实例,因此需要确保知识库名称在系统中是存在的。 +- 返回的文件名列表是通过 `ListResponse` 类封装的,这意味着除了文件名列表数据外,还会包含响应的状态码和状态消息。 + +**输出示例**: +假设存在一个名为 "技术文档库" 的知识库,其中包含三个文件 "doc1.docx", "doc2.pdf", "doc3.txt",调用 `list_files("技术文档库")` 将返回如下响应体: +``` +{ + "code": 200, + "msg": "success", + "data": ["doc1.docx", "doc2.pdf", "doc3.txt"] +} +``` +如果传入的知识库名称不合法或知识库不存在,将返回相应的错误状态码和消息,例如: +``` +{ + "code": 403, + "msg": "Don't attack me", + "data": [] +} +``` +或 +``` +{ + "code": 404, + "msg": "未找到知识库 技术文档库", + "data": [] +} +``` +## FunctionDef _save_files_in_thread(files, knowledge_base_name, override) +**_save_files_in_thread**: 该函数的功能是通过多线程将上传的文件保存到对应知识库目录内。 + +**参数**: +- `files`: 一个`UploadFile`对象列表,表示需要保存的文件。 +- `knowledge_base_name`: 字符串,指定要保存文件的知识库名称。 +- `override`: 布尔值,指示如果文件已存在是否覆盖原文件。 + +**代码描述**: +`_save_files_in_thread`函数主要通过内部定义的`save_file`函数来处理单个文件的保存逻辑。对于每个上传的文件,它会首先检查目标路径是否存在同名文件,如果存在且不允许覆盖,或者文件大小相同,则记录一条警告日志并返回一个包含错误代码404的字典。如果文件不存在或允许覆盖,函数会创建必要的目录结构,并将文件内容写入目标路径。在写入文件的过程中,如果遇到异常,则记录一条错误日志并返回一个包含错误代码500的字典。 + +此函数使用`run_in_thread_pool`来并发执行`save_file`函数,以提高文件保存的效率。`run_in_thread_pool`接受一个函数和一个参数列表,其中每个参数都是一个字典,包含了`save_file`所需的参数。这样,`_save_files_in_thread`可以同时处理多个文件的保存操作,每个文件的保存操作在一个独立的线程中执行。 + +**注意**: +- 在使用此函数时,需要确保`knowledge_base_name`是有效的,且对应的知识库目录具有写入权限。 +- 由于使用了多线程,需要注意线程安全问题,尤其是在写文件和创建目录时。 +- 函数返回一个生成器,每次迭代返回一个文件的保存结果,因此调用此函数时需要适当处理这些结果。 + +**输出示例**: +```python +{ + "code": 200, + "msg": "成功上传文件 example.txt", + "data": { + "knowledge_base_name": "sample_kb", + "file_name": "example.txt" + } +} +``` +此示例展示了一个成功保存文件的返回值,其中包含了状态码、消息以及文件的相关信息。 +### FunctionDef save_file(file, knowledge_base_name, override) +**save_file**: 此函数的功能是保存上传的单个文件到指定的知识库中。 + +**参数**: +- file: UploadFile类型,表示需要上传的文件。 +- knowledge_base_name: 字符串类型,表示目标知识库的名称。 +- override: 布尔类型,指示如果文件已存在是否覆盖原文件。 + +**代码描述**: +`save_file` 函数首先从上传的文件中提取文件名,并使用 `get_file_path` 函数构造目标文件的存储路径。此路径是基于知识库名称和文件名动态生成的,确保文件能够被正确地保存在对应的知识库目录下。 + +函数接着读取上传文件的内容。在尝试保存文件之前,会检查目标路径上的文件是否已存在,以及是否设置了不覆盖已存在文件的选项(`override` 参数)。如果文件已存在且不允许覆盖,函数将记录一条警告日志,并返回一个包含错误代码和消息的字典。 + +如果目标文件夹不存在,函数会创建必要的目录结构。然后,以二进制写入模式打开目标文件路径,将上传的文件内容写入其中。 + +在文件成功保存后,函数返回一个包含成功代码和消息的字典。如果在文件保存过程中发生异常,函数会捕获异常,记录一条错误日志,并返回一个包含错误代码和消息的字典。 + +**注意**: +- 在使用此函数之前,确保传入的 `file` 参数是一个有效的 `UploadFile` 对象,且 `knowledge_base_name` 参数正确指向一个存在的知识库。 +- 如果设置 `override` 参数为 `False`,而目标文件已存在且文件大小与上传文件相同,则不会进行文件覆盖,而是返回文件已存在的消息。 +- 异常处理是此函数的重要组成部分,确保了文件操作过程中的稳定性和可靠性。 + +**输出示例**: +成功上传文件时,可能的返回值为: +``` +{ + "code": 200, + "msg": "成功上传文件 example.docx", + "data": { + "knowledge_base_name": "my_knowledge_base", + "file_name": "example.docx" + } +} +``` +如果文件已存在且不覆盖,返回值可能为: +``` +{ + "code": 404, + "msg": "文件 example.docx 已存在。", + "data": { + "knowledge_base_name": "my_knowledge_base", + "file_name": "example.docx" + } +} +``` +在文件上传失败时,返回值可能为: +``` +{ + "code": 500, + "msg": "example.docx 文件上传失败,报错信息为: [具体错误信息]", + "data": { + "knowledge_base_name": "my_knowledge_base", + "file_name": "example.docx" + } +} +``` +*** +## FunctionDef upload_docs(files, knowledge_base_name, override, to_vector_store, chunk_size, chunk_overlap, zh_title_enhance, docs, not_refresh_vs_cache) +**upload_docs**: 此函数用于上传文件到知识库,并可选择进行文件的向量化处理。 + +**参数**: +- `files`: 上传的文件列表,支持多文件上传。 +- `knowledge_base_name`: 知识库名称,指定要上传文件的目标知识库。 +- `override`: 布尔值,指示是否覆盖已有文件。 +- `to_vector_store`: 布尔值,指示上传文件后是否进行向量化处理。 +- `chunk_size`: 知识库中单段文本的最大长度。 +- `chunk_overlap`: 知识库中相邻文本的重合长度。 +- `zh_title_enhance`: 布尔值,指示是否开启中文标题加强功能。 +- `docs`: 自定义的docs,需转为json字符串格式。 +- `not_refresh_vs_cache`: 布尔值,指示是否暂不保存向量库(用于FAISS)。 + +**代码描述**: +函数首先验证知识库名称的合法性,如果不合法,则返回403状态码并提示错误信息。接着,根据知识库名称获取对应的知识库服务实例。如果实例获取失败,则返回404状态码并提示未找到知识库。 + +函数继续执行,将上传的文件保存到磁盘,并记录保存失败的文件。对于需要进行向量化处理的文件,函数将调用`update_docs`函数进行处理,并更新失败文件列表。如果`not_refresh_vs_cache`为`False`,则会保存向量库。 + +最后,函数返回包含操作结果的响应,其中包括失败文件列表。 + +**注意**: +- 确保传入的知识库名称在系统中已存在。 +- 上传的文件将被保存到指定的知识库目录中,如果`override`参数为`False`,则不会覆盖已存在的同名文件。 +- 如果选择进行向量化处理,需要考虑服务器的性能和资源限制。 +- 自定义的docs需要正确格式化为json字符串,以确保能够被正确解析和处理。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "文件上传与向量化完成", + "data": { + "failed_files": { + "error_file.txt": "文件保存失败的错误信息" + } + } +} +``` +此示例展示了函数执行成功的情况,其中`failed_files`字段列出了处理失败的文件及其错误信息。 +## FunctionDef delete_docs(knowledge_base_name, file_names, delete_content, not_refresh_vs_cache) +**delete_docs**: 此函数用于从知识库中删除指定的文件。 + +**参数**: +- `knowledge_base_name`: 知识库的名称,类型为字符串,示例值为["samples"]。 +- `file_names`: 需要删除的文件名称列表,类型为字符串列表,示例值为[["file_name.md", "test.txt"]]。 +- `delete_content`: 布尔值,指定是否从磁盘中删除文件内容,默认为`False`。 +- `not_refresh_vs_cache`: 布尔值,指定是否暂不保存向量库(用于FAISS),默认为`False`,描述为"暂不保存向量库(用于FAISS)"。 + +**代码描述**: +函数首先验证知识库名称的合法性,如果不合法,则返回403状态码和错误消息"Don't attack me"。之后,对知识库名称进行URL解码,并尝试获取对应的知识库服务实例。如果知识库服务实例不存在,则返回404状态码和错误消息,指出未找到知识库。 + +对于每个指定的文件名,函数检查文件是否存在于知识库中。如果文件不存在,将其添加到失败文件列表中。对于存在的文件,尝试删除文件,包括从知识库中删除记录和可选的从磁盘中删除文件内容。如果删除过程中发生异常,将异常信息记录到失败文件列表中,并记录错误日志。 + +如果`not_refresh_vs_cache`为`False`,则调用`save_vector_store`方法保存向量库。最后,函数返回200状态码和包含失败文件列表的响应。 + +**注意**: +- 在调用此函数之前,确保传入的知识库名称和文件名列表正确,且知识库存在。 +- `delete_content`参数应谨慎使用,因为一旦从磁盘删除文件内容,该操作是不可逆的。 +- `not_refresh_vs_cache`参数用于控制是否立即保存向量库的状态,这在批量删除文件时可以用来优化性能。 + +**输出示例**: +如果所有指定的文件都成功删除,且没有需要刷新的向量库,函数可能返回如下响应: +```json +{ + "code": 200, + "msg": "文件删除完成", + "data": { + "failed_files": {} + } +} +``` +如果存在未找到或删除失败的文件,响应中的`failed_files`将包含这些文件的名称和相关错误信息。 +## FunctionDef update_info(knowledge_base_name, kb_info) +**update_info**: 此函数用于更新知识库的介绍信息。 + +**参数**: +- `knowledge_base_name`: 知识库的名称,类型为字符串。此参数是必需的,用于指定要更新介绍信息的知识库。 +- `kb_info`: 知识库的介绍信息,类型为字符串。此参数是必需的,用于提供新的知识库介绍。 + +**代码描述**: +首先,`update_info` 函数通过调用 `validate_kb_name` 函数验证传入的知识库名称是否合法。如果知识库名称不合法(例如包含潜在的安全风险字符),函数将返回一个状态码为403的 `BaseResponse` 对象,消息为"Don't attack me",表示请求被拒绝。 + +如果知识库名称验证通过,函数接着尝试通过 `KBServiceFactory.get_service_by_name` 方法获取对应知识库的服务实例。如果指定的知识库不存在(即服务实例为None),函数将返回一个状态码为404的 `BaseResponse` 对象,消息为"未找到知识库 {knowledge_base_name}",表示未找到指定的知识库。 + +当知识库服务实例成功获取后,函数调用该实例的 `update_info` 方法,传入新的知识库介绍信息 `kb_info` 进行更新。 + +最后,函数返回一个状态码为200的 `BaseResponse` 对象,消息为"知识库介绍修改完成",并在数据字段中返回更新后的知识库介绍信息,表示知识库介绍信息更新成功。 + +**注意**: +- 在调用此函数之前,确保传入的知识库名称在系统中已存在且合法,否则可能会导致更新失败。 +- 更新知识库介绍信息的操作可能会受到知识库服务实例类型的限制,确保知识库服务支持信息更新操作。 + +**输出示例**: +如果更新操作成功,函数可能返回如下的 `BaseResponse` 对象示例: +``` +{ + "code": 200, + "msg": "知识库介绍修改完成", + "data": { + "kb_info": "这是一个更新后的知识库介绍" + } +} +``` +如果知识库名称不合法,返回的 `BaseResponse` 对象示例可能如下: +``` +{ + "code": 403, + "msg": "Don't attack me", + "data": null +} +``` +如果未找到指定的知识库,返回的 `BaseResponse` 对象示例可能如下: +``` +{ + "code": 404, + "msg": "未找到知识库 {knowledge_base_name}", + "data": null +} +``` +## FunctionDef update_docs(knowledge_base_name, file_names, chunk_size, chunk_overlap, zh_title_enhance, override_custom_docs, docs, not_refresh_vs_cache) +**update_docs**: 此函数用于更新知识库中的文档。 + +**参数**: +- `knowledge_base_name`: 知识库名称,字符串类型,必填参数。 +- `file_names`: 文件名称列表,支持多文件,列表中每个元素为字符串类型。 +- `chunk_size`: 知识库中单段文本最大长度,整数类型。 +- `chunk_overlap`: 知识库中相邻文本重合长度,整数类型。 +- `zh_title_enhance`: 是否开启中文标题加强,布尔类型。 +- `override_custom_docs`: 是否覆盖之前自定义的docs,布尔类型,默认为False。 +- `docs`: 自定义的docs,需要转为json字符串,字典类型。 +- `not_refresh_vs_cache`: 暂不保存向量库(用于FAISS),布尔类型,默认为False。 + +**代码描述**: +此函数首先验证传入的知识库名称是否合法,如果不合法,则返回403状态码和错误信息。接着,通过知识库名称获取对应的知识库服务实例。如果实例获取失败,则返回404状态码和错误信息。 + +函数继续执行,生成需要加载docs的文件列表。对于每个文件,首先检查该文件是否使用了自定义docs,如果是且不覆盖自定义docs,则跳过该文件。否则,尝试将文件添加到待处理列表中。如果在此过程中出现异常,则记录错误信息。 + +接下来,函数将文件列表中的文件转换为docs,并进行向量化处理。这一步骤利用多线程在后台执行,以提高处理效率。处理完成后,如果指定了不刷新向量库缓存,则不立即保存向量库;否则,调用知识库服务的`save_vector_store`方法保存向量库。 + +最后,函数返回200状态码和处理结果,包括处理失败的文件列表。 + +**注意**: +- 在使用此函数时,确保传入的知识库名称在系统中已存在。 +- 如果需要对文件进行自定义docs处理,确保`docs`参数格式正确,并且文件名与`file_names`中的文件名匹配。 +- 此函数支持批量处理文件,但需要注意服务器资源和性能限制。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "更新文档完成", + "data": { + "failed_files": { + "error_file.txt": "加载文档时出错" + } + } +} +``` +此示例展示了函数执行成功的情况,其中`failed_files`字段列出了处理失败的文件及其错误信息。 +## FunctionDef download_doc(knowledge_base_name, file_name, preview) +**download_doc**: 此函数用于下载知识库中的文档。 + +**参数**: +- `knowledge_base_name`: 知识库名称,用于指定从哪个知识库下载文档。 +- `file_name`: 文件名称,指定要下载的文件名。 +- `preview`: 是否预览,布尔值,指示用户是希望在浏览器中预览文件还是直接下载文件。 + +**代码描述**: +`download_doc` 函数首先通过调用 `validate_kb_name` 函数验证传入的知识库名称是否合法。如果知识库名称不合法,函数将返回一个带有403状态码的 `BaseResponse` 对象,提示用户不要进行攻击。接着,函数尝试通过 `KBServiceFactory.get_service_by_name` 方法获取对应知识库的服务实例。如果找不到对应的知识库服务实例,将返回一个带有404状态码的 `BaseResponse` 对象,提示未找到指定的知识库。 + +根据 `preview` 参数的值,函数设置 `content_disposition_type`。如果 `preview` 为 `True`,则设置为 `"inline"`,允许在浏览器中预览文件;否则,`content_disposition_type` 为 `None`,表示文件将被下载。 + +然后,函数创建一个 `KnowledgeFile` 实例,用于表示和处理知识库中的文件。如果文件存在于磁盘上,函数将返回一个 `FileResponse` 对象,允许用户下载或预览文件。如果在尝试读取文件时发生异常,函数将记录错误信息并返回一个带有500状态码的 `BaseResponse` 对象,提示读取文件失败。 + +**注意**: +- 在调用此函数之前,确保传入的知识库名称和文件名称是正确的。 +- 如果知识库名称不合法或文件不存在,函数将返回错误响应。 +- 此函数支持文件预览和下载功能,通过 `preview` 参数控制。 + +**输出示例**: +假设存在一个名为 "samples" 的知识库,其中包含一个名为 "test.txt" 的文件。如果调用 `download_doc(knowledge_base_name="samples", file_name="test.txt", preview=False)`,函数将返回一个 `FileResponse` 对象,允许用户下载 "test.txt" 文件。如果指定的文件不存在,将返回一个带有404状态码的 `BaseResponse` 对象,提示未找到文件。 +## FunctionDef recreate_vector_store(knowledge_base_name, allow_empty_kb, vs_type, embed_model, chunk_size, chunk_overlap, zh_title_enhance, not_refresh_vs_cache) +**recreate_vector_store**: 该函数用于根据内容文件夹中的文档重建向量库。 + +**参数**: +- `knowledge_base_name`: 知识库名称,类型为字符串,默认示例为“samples”。 +- `allow_empty_kb`: 是否允许空的知识库,布尔类型,默认为True。 +- `vs_type`: 向量库类型,字符串类型,默认值为`DEFAULT_VS_TYPE`。 +- `embed_model`: 嵌入模型名称,字符串类型,默认值为`EMBEDDING_MODEL`。 +- `chunk_size`: 知识库中单段文本的最大长度,整数类型,默认值为`CHUNK_SIZE`。 +- `chunk_overlap`: 知识库中相邻文本的重合长度,整数类型,默认值为`OVERLAP_SIZE`。 +- `zh_title_enhance`: 是否开启中文标题加强功能,布尔类型,默认值为`ZH_TITLE_ENHANCE`。 +- `not_refresh_vs_cache`: 是否暂不保存向量库(用于FAISS),布尔类型,默认为False。 + +**代码描述**: +`recreate_vector_store`函数主要用于在用户直接将文件复制到内容文件夹而不是通过网络上传输的情况下,从这些内容文件中重建向量库。默认情况下,只有在`info.db`中存在且包含文档文件的知识库才会被返回。通过将`allow_empty_kb`设置为True,可以使该函数也适用于那些在`info.db`中不存在或没有文档的空知识库。函数内部首先尝试获取指定的知识库服务,如果知识库不存在且不允许空的知识库,则返回404错误。如果知识库存在,则清除现有的向量库并重新创建。随后,函数遍历内容文件夹中的所有文件,并将它们转换为文档,同时考虑文本的分块大小、重合长度以及是否开启中文标题加强功能。每处理完一个文件,就会生成一个包含处理状态的JSON对象,并通过生成器返回。如果在添加文件到知识库时出现错误,则记录错误并跳过该文件。最后,如果不是设置为不刷新向量库缓存,则保存向量库。 + +在项目中,`recreate_vector_store`函数通过`server/api.py/mount_knowledge_routes`被注册为FastAPI的一个POST路由。这意味着该函数可以通过HTTP POST请求被调用,用于在用户通过其他方式将文件直接放入内容文件夹后,重新构建知识库的向量库。这在管理知识库时特别有用,尤其是在需要批量更新文档内容而不想逐个上传时。 + +**注意**: +- 确保在调用此函数之前,内容文件夹中的文件格式和内容符合知识库的要求。 +- 函数的执行时间可能会根据内容文件夹中的文件数量和大小而有很大差异。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "(1 / 10): example.docx", + "total": 10, + "finished": 1, + "doc": "example.docx" +} +``` +此JSON对象表示第一个文件处理成功,总共有10个文件需要处理,当前已完成1个。 +### FunctionDef output +**output**: 此函数的功能是重建知识库的向量存储,并输出处理过程中的状态信息。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: +`output` 函数首先通过 `KBServiceFactory.get_service` 方法获取对应知识库的服务实例,该实例根据知识库名称、向量存储类型和嵌入模型来确定。如果指定的知识库不存在且不允许创建空的知识库,则函数会生成并返回一个包含错误代码404和相应错误信息的JSON对象。如果知识库存在,函数会先清除知识库中的向量存储,然后重新创建知识库。 + +接下来,函数通过 `list_files_from_folder` 方法列出知识库文件夹中的所有文件,并为每个文件创建一个 `KnowledgeFile` 实例。这些文件实例随后被批量处理,通过 `files2docs_in_thread` 方法将文件内容转换为文档,并添加到知识库中。在文件转换过程中,函数会逐个生成并返回包含处理状态的JSON对象,这些对象包含了处理进度、文件名等信息。 + +如果在文件转换过程中遇到错误,函数会记录错误信息并生成包含错误代码500和相应错误信息的JSON对象。所有文件处理完成后,如果不需要刷新向量存储缓存,则会调用 `save_vector_store` 方法保存向量库。 + +**注意**: +- 在调用此函数之前,需要确保 `KBServiceFactory.get_service` 能够根据提供的参数正确返回知识库服务实例。 +- `list_files_from_folder` 方法用于列出知识库文件夹中的所有文件,确保知识库文件夹路径正确。 +- `files2docs_in_thread` 方法负责将文件内容转换为文档并添加到知识库中,该过程是多线程执行的,需要注意线程安全问题。 +- `save_vector_store` 方法用于保存向量库,确保在调用此方法之前,所有需要保存的数据已经正确处理完毕。 +- 此函数通过生成器返回处理状态信息,调用方需要适当处理这些生成的JSON对象,以实现状态监控或错误处理。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/base.md b/markdown_docs/server/knowledge_base/kb_service/base.md new file mode 100644 index 000000000..b5ae103ef --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/base.md @@ -0,0 +1,940 @@ +## FunctionDef normalize(embeddings) +**normalize**: 此函数的功能是对输入的嵌入向量进行L2范数归一化处理。 + +**参数**: +- **embeddings**: 一个列表的列表,其中每个内部列表包含浮点数,代表一个嵌入向量。 + +**代码描述**: +`normalize`函数接受一个嵌入向量列表作为输入,这些嵌入向量可以是文档或查询的表示。它首先计算每个嵌入向量的L2范数,然后将每个向量的元素分别除以其L2范数,以实现归一化。这个过程确保了所有的嵌入向量都被规范化到单位球上,这在很多向量空间模型中是一个常见的预处理步骤,有助于提高后续处理的效果和稳定性。 + +在项目中,`normalize`函数被`EmbeddingsFunAdapter`类中的`embed_documents`、`embed_query`、`aembed_documents`和`aembed_query`方法调用。这些方法分别负责同步和异步地嵌入文档和查询,然后使用`normalize`函数对嵌入结果进行归一化处理。这表明归一化步骤是嵌入过程的一个重要组成部分,无论是处理文档还是查询,都需要进行归一化以确保嵌入向量的质量。 + +**注意**: +- 输入的嵌入向量列表需要确保每个向量的维度相同,因为归一化过程涉及到按元素的运算。 +- 该函数依赖于`numpy`库进行矩阵运算,因此在使用前需要确保已经安装了`numpy`。 + +**输出示例**: +假设输入的嵌入向量列表为`[[1.0, 2.0], [2.0, 3.0]]`,则函数的返回值可能如下所示: +``` +[[0.4472136 0.89442719] + [0.5547002 0.83205029]] +``` +这个输出展示了两个经过L2范数归一化的二维向量。 +## ClassDef SupportedVSType +**SupportedVSType**: SupportedVSType的功能是定义支持的向量存储类型。 + +**属性**: +- FAISS: 代表使用FAISS作为向量存储服务。 +- MILVUS: 代表使用MILVUS作为向量存储服务。 +- DEFAULT: 代表使用默认的向量存储服务。 +- ZILLIZ: 代表使用ZILLIZ作为向量存储服务。 +- PG: 代表使用PostgreSQL (PG) 作为向量存储服务。 +- ES: 代表使用Elasticsearch (ES) 作为向量存储服务。 +- CHROMADB: 代表使用ChromaDB作为向量存储服务。 + +**代码描述**: +SupportedVSType类是一个枚举类,它定义了在知识库服务中支持的各种向量存储类型。这些类型包括FAISS、MILVUS、ZILLIZ、PostgreSQL、Elasticsearch和ChromaDB等,以及一个默认选项。这个类在项目中的主要作用是在知识库服务工厂(KBServiceFactory)中,根据传入的向量存储类型字符串,动态选择并实例化对应的知识库服务实现。例如,如果指定了FAISS作为向量存储类型,那么KBServiceFactory将实例化并返回一个FaissKBService对象。 + +在项目中,SupportedVSType类通过KBServiceFactory的get_service方法被调用,以确定并实例化相应的知识库服务。此外,各个具体的知识库服务类(如FaissKBService、MilvusKBService等)也通过实现vs_type方法,返回其对应的SupportedVSType值,以标识它们支持的向量存储类型。 + +**注意**: +- 在使用SupportedVSType时,应确保传入的向量存储类型字符串与SupportedVSType中定义的属性名称一致,以避免在动态解析时发生错误。 +- DEFAULT类型通常用于指定一个默认的向量存储服务,具体实现可能会根据项目配置或环境而变化。 +- 在扩展项目以支持新的向量存储服务时,应在SupportedVSType中添加相应的属性,并在KBServiceFactory中实现相应的逻辑以支持新的服务类型。 +## ClassDef KBService +**KBService**: KBService 类是用于管理和操作知识库的抽象基类,提供了一系列对知识库进行操作的方法。 + +**属性**: +- `kb_name`: 知识库名称。 +- `kb_info`: 知识库信息,如果在`KB_INFO`中找不到对应的知识库名称,则显示为"关于xxx的知识库"。 +- `embed_model`: 嵌入模型名称,默认为`EMBEDDING_MODEL`。 +- `kb_path`: 知识库路径。 +- `doc_path`: 文档路径。 + +**代码描述**: +KBService 类定义了一系列方法用于管理知识库,包括创建知识库、删除知识库、向知识库添加文档、从知识库删除文档、更新知识库信息、文档搜索等。它是一个抽象基类(ABC),意味着它不能直接实例化,而是需要通过继承它的子类来实现具体的功能。这样的设计允许不同类型的知识库服务(如Faiss、Milvus、Elasticsearch等)实现相同的接口,从而提供一致的操作方式。 + +KBService 类在项目中被多个子类继承,每个子类代表一种特定类型的知识库服务,例如`FaissKBService`、`MilvusKBService`等。这些子类实现了KBService类中定义的抽象方法,以适应不同知识库的具体操作需求。 + +此外,KBService 类还与`KBServiceFactory`类相关联,`KBServiceFactory`类提供了`get_service`和`get_service_by_name`方法,用于根据知识库名称和向量存储类型动态创建相应的知识库服务实例。这种工厂模式的设计使得在不同知识库服务之间切换变得更加灵活和方便。 + +**注意**: +- 由于KBService是一个抽象基类,直接实例化KBService会引发错误。应该通过继承KBService并实现其抽象方法的方式来创建子类。 +- 在使用KBService的子类时,需要确保已经正确配置了知识库的相关信息,如知识库名称、嵌入模型名称等。 +- 在进行知识库操作(如添加文档、搜索文档等)时,需要注意操作的具体实现可能会依赖于所使用的知识库服务类型。 + +**输出示例**: +由于KBService是一个抽象基类,它本身不直接产生输出。具体的输出将取决于继承KBService的子类以及实现的方法。例如,一个可能的搜索文档的输出示例为: +```python +[ + {"id": "doc1", "text": "文档1的内容", "score": 0.95}, + {"id": "doc2", "text": "文档2的内容", "score": 0.90} +] +``` +这表示在执行搜索操作时,返回了两个文档及其相关性得分。 +### FunctionDef __init__(self, knowledge_base_name, embed_model) +**__init__**: 此函数的功能是初始化KBService类的实例。 + +**参数**: +- knowledge_base_name: 字符串类型,指定知识库的名称。 +- embed_model: 字符串类型,默认值为EMBEDDING_MODEL,指定嵌入模型的名称。 + +**代码描述**: +`__init__` 方法是 `KBService` 类的构造函数,负责初始化该类的实例。在这个方法中,首先将传入的知识库名称(`knowledge_base_name`)赋值给实例变量 `self.kb_name`。然后,使用 `KB_INFO.get` 方法尝试从一个预定义的字典 `KB_INFO` 中获取与 `knowledge_base_name` 对应的知识库信息,如果未找到,则使用默认信息(`"关于{knowledge_base_name}的知识库"`)。接下来,将传入的嵌入模型名称(`embed_model`)赋值给实例变量 `self.embed_model`。 + +此外,`__init__` 方法调用了 `get_kb_path` 和 `get_doc_path` 函数,分别用于获取知识库的存储路径和文档存储路径,并将这些路径分别赋值给实例变量 `self.kb_path` 和 `self.doc_path`。这两个函数分别位于 `server/knowledge_base/utils.py` 文件中,`get_kb_path` 函数负责构造并返回知识库的文件路径,而 `get_doc_path` 函数则负责获取知识库文档的存储路径。 + +最后,`__init__` 方法调用了 `do_init` 方法,这是一个在 `KBService` 类中定义的方法,用于执行进一步的初始化操作。当前,`do_init` 方法的实现可能为空(使用 `pass` 关键字),但它的存在表明在初始化 `KBService` 实例时可能需要执行的额外步骤或特定的初始化逻辑。 + +**注意**: +- 在使用 `KBService` 类之前,确保 `KB_INFO` 字典已经被正确定义,且包含了所有可能的知识库名称及其对应的信息。 +- `EMBEDDING_MODEL` 应为一个有效的嵌入模型名称,默认值应在类或模块的其他部分被定义。 +- `do_init` 方法的具体实现应根据实际需求进行添加,以完成知识库服务的特定初始化需求。 +*** +### FunctionDef __repr__(self) +**__repr__**: 此函数的功能是生成对象的官方字符串表示。 + +**参数**: 此函数没有参数。 + +**代码描述**: `__repr__` 方法是一个特殊方法,用于定义对象的“官方”字符串表示。在 Python 中,当我们尝试使用 `repr()` 函数或者在解释器中直接查询对象时,会调用此方法。在本例中,`__repr__` 方法返回一个格式化的字符串,该字符串包含了两个对象属性:`kb_name` 和 `embed_model`。这意味着当此方法被调用时,它会返回一个包含知识库名称 (`kb_name`) 和嵌入模型 (`embed_model`) 的字符串,两者通过 "@" 符号连接。这种表示方式有助于快速识别对象的关键信息,特别是在调试和日志记录中非常有用。 + +**注意**: 使用 `__repr__` 方法时,应确保返回的字符串尽可能明确地反映对象的关键信息。此外,返回的字符串应该尽量遵循 Python 对象表示的惯例,即可能的话,应该能够通过执行这个字符串来重新创建该对象的一个相似实例。 + +**输出示例**: 假设一个 `KBService` 对象的 `kb_name` 属性值为 `"KnowledgeBase1"`,`embed_model` 属性值为 `"ModelX"`,那么调用此对象的 `__repr__` 方法将返回字符串 `"KnowledgeBase1 @ ModelX"`。这提供了一个直观的方式来理解对象的主要属性。 +*** +### FunctionDef save_vector_store(self) +**save_vector_store**: 此函数的功能是保存向量库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `save_vector_store` 函数是`KBService`类的一个方法,它的主要作用是将向量库的数据持久化保存。在具体实现中,此函数根据不同的向量库类型(如FAISS、Milvus等)采取不同的保存策略。例如,对于FAISS类型的向量库,数据可能会被保存到磁盘上的文件中;而对于Milvus类型的向量库,数据则会被保存到数据库中。需要注意的是,当前代码示例中此函数的实现为空,这意味着具体的保存逻辑需要根据实际的向量库类型和需求来完成。 + +在项目中,`save_vector_store`函数被多个地方调用,以确保在进行文档的上传、删除、更新或向量库重建等操作后,向量库的状态能够被正确地保存。这些调用场景包括: + +- 文档上传(`upload_docs`):在上传文档并进行向量化处理后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。 +- 文档删除(`delete_docs`):在删除指定的文档后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。 +- 文档更新(`update_docs`):在更新文档内容并进行向量化处理后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。 +- 向量库重建(`recreate_vector_store`的`output`方法):在重建向量库的过程中,完成所有文档的向量化处理后,根据`not_refresh_vs_cache`参数的值决定是否立即保存向量库。 +- 数据库文档清理(`prune_db_docs`):在从数据库中删除不存在于本地文件夹中的文档后,保存向量库以确保向量库与数据库的一致性。 + +**注意**: 在使用`save_vector_store`函数时,需要根据实际使用的向量库类型(如FAISS、Milvus等)来实现具体的保存逻辑。此外,考虑到向量库可能包含大量数据,保存操作可能会涉及到较大的I/O开销,因此在设计调用此函数的策略时应当考虑到性能影响,合理安排保存向量库的时机。 +*** +### FunctionDef create_kb(self) +**create_kb**: 此函数的功能是创建知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `create_kb` 方法是 `KBService` 类的一个核心方法,负责知识库的创建流程。该方法首先检查指定的文档路径是否存在,如果不存在,则创建该路径。接着,调用 `do_create_kb` 方法,这是一个预留给开发者的扩展点,允许在知识库创建的基础流程中插入自定义逻辑。之后,该方法会调用 `add_kb_to_db` 函数,将知识库的名称、简介、向量库类型和嵌入模型等信息添加到数据库中。`add_kb_to_db` 函数的执行结果(状态)会被返回,表示知识库创建操作的成功与否。 + +在整个创建流程中,`do_create_kb` 方法提供了一个扩展点,允许开发者根据具体需求实现特定的知识库创建逻辑,而 `add_kb_to_db` 函数则负责将知识库信息持久化到数据库中。这种设计模式不仅提高了代码的可扩展性,也确保了知识库创建过程的灵活性和可维护性。 + +**注意**: +- 在调用 `create_kb` 方法之前,确保已经正确设置了 `KBService` 类的 `doc_path`、`kb_name`、`kb_info`、`vs_type()` 和 `embed_model` 属性,因为这些属性会在知识库创建过程中被使用。 +- `do_create_kb` 方法默认不执行任何操作,需要在继承 `KBService` 类的子类中根据具体需求重写此方法。 +- `add_kb_to_db` 函数的调用需要确保传入的知识库名称是唯一的,以避免不必要的信息覆盖。 + +**输出示例**: 该方法返回一个布尔值,表示知识库创建操作的成功与否。例如,如果知识库成功创建并添加到数据库中,方法将返回 `True`。 +*** +### FunctionDef clear_vs(self) +**clear_vs**: 此函数的功能是删除向量库中所有内容。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `clear_vs` 方法是 `KBService` 类的一个成员方法,主要负责清除知识库中的向量数据。该方法首先调用 `do_clear_vs` 方法,执行删除向量数据之前的预处理操作,尽管在当前的实现中,`do_clear_vs` 方法的具体实现为空,但它为未来可能的逻辑扩展提供了接口。接下来,`clear_vs` 方法通过调用 `delete_files_from_db` 函数,传入知识库名称(`self.kb_name`),从数据库中删除与该知识库相关的所有文件记录。`delete_files_from_db` 函数的执行结果(布尔值)将作为 `clear_vs` 方法的返回值,指示操作是否成功完成。 + +**注意**: +- 在调用 `clear_vs` 方法之前,确保知识库名称已正确设置在 `KBService` 实例的 `kb_name` 属性中。 +- 该方法会永久删除知识库中的所有文件记录,此操作不可逆,请谨慎使用。 +- 虽然当前 `do_clear_vs` 方法的实现为空,但开发者在未来的开发中可以在此方法中添加删除向量数据之前需要执行的特定逻辑(如日志记录、数据备份、权限检查等)。 + +**输出示例**: +如果操作成功完成,`clear_vs` 方法将返回 `True`。例如,在成功删除知识库中所有内容后,方法返回值为: +``` +True +``` + +此方法在项目中的调用场景包括但不限于知识库的删除操作(`delete_kb` 函数)、知识库向量存储的重建操作(`recreate_vector_store` 函数的 `output` 方法)、以及知识库迁移操作中的向量库重建(`folder2db` 函数)。这些场景均涉及到需要先清除知识库中现有的向量数据,再进行后续的操作,确保知识库的数据状态是最新的。 +*** +### FunctionDef drop_kb(self) +**drop_kb**: 此函数的功能是删除知识库。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `drop_kb` 方法是 `KBService` 类的一个成员方法,负责实现知识库的删除操作。该方法首先调用 `do_drop_kb` 方法来执行删除知识库的具体逻辑。`do_drop_kb` 方法是一个可由子类实现的方法,用于在删除知识库之前执行特定的逻辑,比如清理相关资源等。接着,`drop_kb` 方法调用 `delete_kb_from_db` 函数,该函数从数据库中删除指定名称的知识库。`delete_kb_from_db` 函数接受一个知识库名称作为参数,并返回一个布尔值,表示操作是否成功。最后,`drop_kb` 方法返回 `delete_kb_from_db` 函数的返回值,作为删除操作的最终状态。 + +**注意**: +- 在调用 `drop_kb` 方法之前,应确保知识库名称已正确设置在 `KBService` 实例的 `kb_name` 属性中。 +- `do_drop_kb` 方法在 `KBService` 类中默认不执行任何操作,具体的删除逻辑需要在子类中根据实际需求实现。 +- 删除知识库的操作不会自动提交数据库事务。调用 `drop_kb` 方法的代码需要根据实际情况决定是否提交事务。 + +**输出示例**: 由于 `drop_kb` 方法返回的是 `delete_kb_from_db` 函数的返回值,而该函数始终返回 `True`,因此在成功执行删除操作后,`drop_kb` 方法的返回值将为 `True`。 + +在项目中,`drop_kb` 方法的调用场景包括但不限于通过 API 删除知识库、在自动化测试中验证知识库删除功能等。例如,在 `delete_kb` API 方法中,会根据提供的知识库名称创建 `KBService` 实例,并调用其 `drop_kb` 方法来删除知识库。此外,自动化测试 `test_delete_db` 和 `test_drop_kb` 也通过调用 `drop_kb` 方法来测试知识库的删除功能是否正常工作。这些调用示例说明了 `drop_kb` 方法在知识库管理功能中的重要作用,以及如何在不同场景下使用该方法来实现知识库的删除。 +*** +### FunctionDef _docs_to_embeddings(self, docs) +**_docs_to_embeddings**: 该函数的功能是将文档对象列表转化为向量存储系统可以接受的参数格式。 + +**参数**: +- `docs`: 需要转化为向量的文档对象列表,类型为`List[Document]`。 + +**代码描述**: +`_docs_to_embeddings`函数是`KBService`类的一个私有方法,用于将文档对象列表转化为向量形式,以便后续存储或查询操作。该函数内部调用了`embed_documents`函数,传入文档对象列表`docs`、嵌入模型`embed_model`以及一个标志位`to_query`。`embed_model`是`KBService`类的一个属性,指定了用于文档向量化的模型。`to_query`参数在此处被设置为`False`,意味着向量化的结果不是用于查询操作。`embed_documents`函数负责实际的文档向量化过程,包括文本提取、向量化以及元数据处理,最终返回一个包含向量化结果的字典。 + +**注意**: +- 确保传入的`docs`参数是有效的文档对象列表,且每个文档对象都应包含必要的内容和元数据。 +- `_docs_to_embeddings`函数依赖于`embed_model`属性指定的嵌入模型,因此在使用前应确保嵌入模型已正确设置。 +- 该函数设计为KBService类的内部方法,不建议直接从类外部调用。 + +**输出示例**: +调用`_docs_to_embeddings(docs=[Document1, Document2])`可能会返回如下字典: +```python +{ + "texts": ["文档1的内容", "文档2的内容"], + "embeddings": [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]], + "metadatas": [{"title": "文档1标题"}, {"title": "文档2标题"}] +} +``` +这个字典包含了文档的原始内容(`texts`)、向量化结果(`embeddings`)以及文档的元数据信息(`metadatas`),为后续的文档存储或查询操作提供了必要的数据结构。 +*** +### FunctionDef add_doc(self, kb_file, docs) +**add_doc**: 此函数用于向知识库添加文件。 + +**参数**: +- `kb_file`: `KnowledgeFile`类型的对象,表示要添加到知识库的文件。 +- `docs`: `Document`类型的列表,默认为空列表。这些是要添加到知识库的文档。 +- `**kwargs`: 接收额外的关键字参数,这些参数将传递给内部方法。 + +**代码描述**: +`add_doc`函数首先检查`docs`参数是否已提供。如果提供了`docs`,则将`custom_docs`标志设置为`True`,并为每个文档的元数据中添加`source`字段,其值为`kb_file`的文件名。如果没有提供`docs`,则调用`kb_file`的`file2text`方法将文件内容转换为文档列表,并将`custom_docs`标志设置为`False`。 + +接下来,如果`docs`列表不为空,函数会尝试将每个文档的`source`字段中的绝对路径转换为相对于`self.doc_path`的相对路径。然后,调用`delete_doc`方法删除知识库中与`kb_file`相对应的旧文档。 + +随后,调用`do_add_doc`方法将文档添加到知识库中,该方法需要在子类中具体实现。`do_add_doc`方法的执行结果(`doc_infos`)将用于调用`add_file_to_db`函数,将文件信息添加到数据库中。此过程中,会根据`custom_docs`标志和文档数量更新数据库中的文件条目。 + +最后,函数根据操作结果返回一个状态值,如果文档列表为空,则直接返回`False`。 + +**注意**: +- 在使用`add_doc`函数时,需要确保传入的`kb_file`对象正确实例化,并且其代表的文件确实存在。 +- 如果提供了`docs`参数,则这些文档将直接添加到知识库中,不会对文件内容进行向量化处理。 +- `**kwargs`参数提供了额外的灵活性,允许在不修改`add_doc`函数签名的情况下,传递额外的参数给内部方法。 + +**输出示例**: +由于`add_doc`函数的主要作用是执行添加操作,其返回值主要用于指示操作是否成功。例如,如果文件成功添加到知识库并更新数据库,函数可能返回`True`。如果在添加过程中遇到任何问题,可能返回`False`。 +*** +### FunctionDef delete_doc(self, kb_file, delete_content) +**delete_doc**: 此函数的功能是从知识库中删除指定的文件。 + +**参数**: +- `kb_file`: `KnowledgeFile`类型的对象,表示需要从知识库中删除的文件。 +- `delete_content`: 布尔值,指定是否从磁盘中删除文件内容。默认为`False`,即不删除文件内容。 +- `**kwargs`: 接收额外的关键字参数,这些参数将传递给`do_delete_doc`方法。 + +**代码描述**: +`delete_doc`函数首先调用`do_delete_doc`方法,该方法需要在子类中根据具体逻辑进行实现,用于执行删除文件的自定义操作。随后,函数调用`delete_file_from_db`函数,从数据库中删除指定的知识文件,并更新相关知识库的文件计数。如果`delete_content`参数为`True`,且文件在磁盘上存在,则使用`os.remove`方法从磁盘中删除该文件。最后,函数返回删除操作的状态,该状态由`delete_file_from_db`函数的返回值决定。 + +**注意**: +- 在调用`delete_doc`函数之前,需要确保传入的`kb_file`对象正确实例化,且其代表的文件确实存在于知识库中。 +- `delete_content`参数应谨慎使用,因为一旦从磁盘删除文件内容,该操作是不可逆的。 +- `**kwargs`参数提供了额外的灵活性,允许在不修改`delete_doc`函数签名的情况下,传递额外的参数给`do_delete_doc`方法。 + +**输出示例**: +由于`delete_doc`函数的主要作用是执行删除操作,其返回值主要用于指示操作是否成功。例如,如果文件成功从数据库和(可选的)磁盘中删除,函数可能返回`True`。如果在删除过程中遇到任何问题,根据`delete_file_from_db`函数的实现,可能返回`False`或抛出异常。 +*** +### FunctionDef update_info(self, kb_info) +**update_info**: 此函数的功能是更新知识库的介绍信息。 + +**参数**: +- `kb_info`: 字符串类型,表示要更新的知识库介绍信息。 + +**代码描述**: +`update_info`函数主要用于更新知识库的介绍信息。它接收一个字符串参数`kb_info`,该参数包含了知识库的新介绍信息。函数首先将这个新的介绍信息赋值给`self.kb_info`,以更新当前知识库服务实例的介绍信息。随后,函数调用`add_kb_to_db`方法,将更新后的知识库信息(包括知识库名称`self.kb_name`、介绍信息`self.kb_info`、向量库类型`self.vs_type()`和嵌入模型`self.embed_model`)添加到数据库中。这里的`self.vs_type()`是通过调用`vs_type`方法获取的,该方法需要在`KBService`类的子类中具体实现,以返回正确的向量库类型。 + +`add_kb_to_db`函数负责将知识库信息添加或更新到数据库中。如果数据库中不存在具有相同名称的知识库,则会创建一个新的知识库记录;如果已存在,则更新该知识库的介绍信息、向量库类型和嵌入模型信息。`add_kb_to_db`函数最终返回一个布尔值,表示操作是否成功。 + +**注意**: +- 在调用`update_info`函数之前,确保知识库名称`self.kb_name`已经正确设置,因为它是更新数据库记录的关键标识。 +- `vs_type`方法需要在`KBService`类的子类中实现,以确保能够提供正确的向量库类型信息。 +- 调用`update_info`函数后,需要根据`add_kb_to_db`函数的返回值来判断更新操作是否成功。 + +**输出示例**: +由于`update_info`函数的返回值是由`add_kb_to_db`函数决定的,因此在成功更新知识库信息后,`update_info`函数将返回`True`。例如,如果更新操作成功完成,函数调用将返回`True`。 +*** +### FunctionDef update_doc(self, kb_file, docs) +**update_doc**: 此函数用于使用指定的文件更新知识库中的文档。 + +**参数**: +- `kb_file`: `KnowledgeFile`类型的对象,表示要更新的知识库文件。 +- `docs`: `Document`类型的列表,表示自定义的文档列表。默认为空列表。 +- `**kwargs`: 接收额外的关键字参数,这些参数将传递给内部的`delete_doc`和`add_doc`方法。 + +**代码描述**: +`update_doc`函数首先检查`kb_file`指定的文件路径是否存在。如果文件存在,则调用`delete_doc`方法删除知识库中与该文件对应的旧文档。随后,调用`add_doc`方法将新的文档添加到知识库中。如果在调用过程中指定了`docs`参数,则这些自定义文档将被添加到知识库中,并且数据库中对应的条目会被标记为`custom_docs=True`,表示这些文档是自定义的。如果没有指定`docs`,则`add_doc`方法会根据`kb_file`中的文件内容生成文档并添加到知识库中。 + +**注意**: +- 在使用`update_doc`函数时,需要确保传入的`kb_file`对象已正确初始化,并且其代表的文件确实存在于磁盘上。 +- 如果提供了`docs`参数,则这些文档将直接添加到知识库中,而不会对`kb_file`中的文件内容进行再次处理或向量化。 +- `**kwargs`参数提供了额外的灵活性,允许在不修改`update_doc`函数签名的情况下,传递额外的参数给`delete_doc`和`add_doc`方法。 + +**输出示例**: +由于`update_doc`函数的主要作用是更新知识库中的文档,其没有直接的返回值。但是,通过调用`delete_doc`和`add_doc`方法,可以间接获得关于删除和添加操作的状态。例如,如果文档成功删除并添加到知识库,则这两个方法可能会返回操作成功的状态值。如果在更新过程中遇到任何问题,根据这两个方法的实现,可能会返回错误信息或抛出异常。 + +在项目中,`update_doc`函数被`update_docs`方法调用,用于处理来自API请求的知识库文档更新操作。这包括从文件生成文档、处理自定义文档以及更新知识库中的文档向量等任务。通过这种方式,`update_doc`函数在知识库管理系统中扮演了重要的角色,确保知识库内容的准确性和最新性。 +*** +### FunctionDef exist_doc(self, file_name) +**exist_doc**: 此函数用于检查指定的文件是否已存在于知识库中。 + +**参数**: +- `file_name`: 字符串类型,表示要检查是否存在的文件名。 + +**代码描述**: +`exist_doc` 函数通过接收一个文件名 (`file_name`) 作为参数,来检查该文件是否已经存在于知识库中。函数内部首先创建了一个 `KnowledgeFile` 对象,该对象包含了知识库的名称 (`kb_name`) 和文件名 (`file_name`)。然后,调用 `file_exists_in_db` 函数,将这个 `KnowledgeFile` 对象传递给它,以检查数据库中是否存在与之对应的文件记录。如果 `file_exists_in_db` 函数返回 `True`,表示文件已存在于数据库中;如果返回 `False`,则表示文件不存在。 + +**注意**: +- 确保传入的 `file_name` 是正确的文件名,并且该文件名不应包含路径信息,只有文件名本身。 +- `exist_doc` 函数依赖于 `KnowledgeFile` 类和 `file_exists_in_db` 函数,因此在使用前需要确保这些依赖项正确实现且可用。 +- 此函数不会对数据库进行任何修改操作,仅用于检查文件的存在性。 + +**输出示例**: +假设知识库中已存在名为 "example.pdf" 的文件,当调用 `exist_doc("example.pdf")` 时,函数将返回 `True`。如果文件 "new_document.txt" 不存在于知识库中,调用 `exist_doc("new_document.txt")` 将返回 `False`。 +*** +### FunctionDef list_files(self) +**list_files**: 此函数的功能是列出属于特定知识库的所有文件名。 + +**参数**: 此函数不接受任何外部参数,但依赖于类实例中的`kb_name`属性。 + +**代码描述**: `list_files`函数是`KBService`类的一个方法,它的主要作用是调用`list_files_from_db`函数,以获取属于特定知识库的所有文件名。在调用`list_files_from_db`时,它传递了`self.kb_name`作为参数,这意味着它将列出与当前实例的`kb_name`属性相匹配的所有文件名。`list_files_from_db`函数进一步通过数据库会话查询`KnowledgeFileModel`模型,筛选出`kb_name`字段与给定知识库名称相匹配的记录,并返回这些记录的文件名列表。 + +**注意**: +- 确保在调用`list_files`方法之前,`KBService`类的实例已正确初始化,并且`kb_name`属性已经被赋予了一个有效的知识库名称。 +- 此方法的执行结果直接依赖于数据库中的数据,因此确保数据库已正确填充了相关知识库的文件信息。 +- 由于`list_files_from_db`函数使用了`ilike`方法进行查询,查询对大小写不敏感,但这可能会在某些情况下影响性能。 + +**输出示例**: 假设当前实例的`kb_name`属性值为"GeneralKB",并且数据库中存在属于"GeneralKB"的文件名为"document1.pdf"和"report2.docx"的文件,那么调用`list_files`方法将返回以下列表: +``` +["document1.pdf", "report2.docx"] +``` + +此方法在项目中的使用场景包括但不限于获取知识库文件列表以供进一步处理,如在`get_kb_file_details`方法中获取文件列表以合并文件夹和数据库中的文件信息,在`folder2db`方法中用于确定需要更新或增量添加到数据库的文件列表,以及在测试用例中验证迁移、增量更新或数据库清理操作的正确性。 +*** +### FunctionDef count_files(self) +**count_files**: 此函数的功能是统计指定知识库中的文件数量。 + +**参数**: 此函数不直接接受任何参数,但它依赖于`KBService`类的实例属性。 + +**代码描述**: `count_files`方法是`KBService`类的一个成员方法,它的主要作用是调用`count_files_from_db`函数来统计特定知识库中的文件数量。在调用`count_files_from_db`时,它传递了`self.kb_name`作为参数,其中`self.kb_name`是`KBService`类实例化时指定的知识库名称。这意味着`count_files`方法将返回该知识库中的文件总数。`count_files_from_db`函数通过数据库查询来实现此功能,具体地,它使用ORM模型`KnowledgeFileModel`来过滤特定知识库的文件,并计算满足条件的文件数量。 + +**注意**: 在使用`count_files`方法时,需要确保`KBService`类的实例已正确初始化,且`kb_name`属性已经被赋予了正确的知识库名称。此外,由于`count_files_from_db`函数使用了不区分大小写的匹配来查找知识库名称,因此在指定知识库名称时应注意其准确性,以避免统计结果的偏差。 + +**输出示例**: 假设存在一个名为"DefaultKB"的知识库,且其中包含10个文件。如果`KBService`类的实例的`kb_name`属性被设置为"DefaultKB",那么调用其`count_files`方法将返回整数`10`,表示"DefaultKB"知识库中的文件数量为10。 + +通过`count_files`方法,可以方便地获取特定知识库中的文件总数,这对于知识库管理和数据分析等功能是非常有用的。此方法的设计充分考虑了模块化和代码重用,通过与`count_files_from_db`函数的交互,实现了功能的高效执行。 +*** +### FunctionDef search_docs(self, query, top_k, score_threshold) +**search_docs**: 此函数的功能是在知识库中搜索与查询字符串最相关的文档。 + +**参数**: +- `query`: 字符串类型,用户的搜索查询。 +- `top_k`: 整型,默认值为`VECTOR_SEARCH_TOP_K`,表示返回的最相关文档的最大数量。 +- `score_threshold`: 浮点型,默认值为`SCORE_THRESHOLD`,表示只有得分高于此阈值的文档才会被返回。 + +**代码描述**: +`search_docs`方法是`KBService`类中的一个方法,旨在提供一个高层次的接口,用于执行知识库的搜索操作。该方法首先调用`do_search`方法,根据用户提供的查询字符串`query`,返回的最大文档数量`top_k`,以及得分阈值`score_threshold`,执行搜索操作。`do_search`方法负责具体的搜索逻辑,包括查询处理、文档检索和得分计算等。`search_docs`方法通过调用`do_search`,获取搜索结果后,直接将这些结果返回给调用者。这样的设计使得`search_docs`方法可以专注于处理搜索操作的高层次逻辑,如参数的默认值设置,而具体的搜索逻辑则由`do_search`方法负责。 + +**注意**: +- 在使用`search_docs`方法时,需要注意`query`参数不能为空,且`top_k`和`score_threshold`参数应根据实际需求合理设置,以确保搜索结果的相关性和精确度。 +- 该方法返回的是一个文档列表,每个文档都是搜索结果中与查询字符串相关性较高的文档。调用方需要根据自己的需求处理这些文档,例如展示给用户。 + +**输出示例**: +```python +[ + Document(id="1", title="文档标题1", content="文档内容1"), + Document(id="2", title="文档标题2", content="文档内容2"), + ... +] +``` +在项目中,`search_docs`方法被多个测试用例调用,包括`test_faiss_kb.py`、`test_milvus_db.py`和`test_pg_db.py`中的`test_search_db`函数。这些测试用例通过调用`search_docs`方法,验证不同知识库实现下的搜索功能是否正常工作,确保搜索结果的数量大于0。这表明`search_docs`方法是项目中用于执行知识库搜索操作的关键接口之一,其正确性和性能对于整个知识库服务的质量至关重要。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 此函数的功能是根据提供的文档ID列表检索对应的文档对象列表。 + +**参数**: +- ids: 一个字符串列表,包含需要检索的文档的ID。 + +**代码描述**: +`get_doc_by_ids` 函数是 `KBService` 类的一个方法,旨在根据给定的文档ID列表检索相应的文档对象。当前实现中,此函数返回一个空列表,这意味着它需要进一步的实现来完成其功能。在项目中,此函数被其他对象调用,以实现特定的业务逻辑。 + +例如,在 `list_docs` 方法中,通过文件名或元数据检索文档信息后,会使用 `get_doc_by_ids` 方法根据检索到的文档ID获取具体的文档对象。这一过程表明,`get_doc_by_ids` 方法是连接数据库检索与文档对象处理流程的关键一环。 + +另一个调用示例是在 `summary_doc_ids_to_vector_store` 函数中,该函数根据文档ID列表,使用 `get_doc_by_ids` 方法获取文档对象,进而进行文档摘要和向量存储的相关处理。这显示了 `get_doc_by_ids` 在文档处理和分析流程中的重要作用。 + +**注意**: +- 当前函数实现返回一个空列表,这表明需要根据实际的数据库或存储结构来完成此函数的具体实现。 +- 在使用此函数时,需要确保传入的ID列表中的每个ID都是有效的,并且能够在数据库或存储系统中找到对应的文档。 + +**输出示例**: +假设函数已经实现,并且数据库中存在对应的文档,那么对于输入 `["doc1", "doc2"]`,一个可能的返回值示例为: +```python +[ + Document(id="doc1", title="文档1标题", content="文档1内容"), + Document(id="doc2", title="文档2标题", content="文档2内容") +] +``` +这个示例展示了函数在成功检索到文档后可能返回的文档对象列表的结构。 +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 该函数的功能是根据提供的文档ID列表删除对应的文档。 + +**参数**: +- ids: 一个字符串列表,包含需要删除的文档的ID。 + +**代码描述**: +`del_doc_by_ids` 函数接受一个字符串列表作为参数,这个列表包含了需要被删除的文档的ID。函数的主体抛出了一个`NotImplementedError`异常,这表明该函数是一个抽象方法,需要在子类中被具体实现。在当前的上下文中,这个设计模式通常用于定义一个接口,强制继承该类的子类实现这个方法。 + +在项目中,`del_doc_by_ids` 函数被`update_doc_by_ids` 方法调用。`update_doc_by_ids` 方法的功能是更新给定ID的文档。如果传入的文档ID对应的文档不存在或者文档的`page_content`为空,则会调用`del_doc_by_ids`方法来删除这些文档。这种设计体现了一种先清理再更新的策略,确保在添加或更新文档之前,移除所有无效或不再需要的文档。 + +**注意**: +- `del_doc_by_ids` 方法是一个抽象方法,调用时需要注意在具体的子类中实现其功能。 +- 在使用`del_doc_by_ids`方法之前,确保已经正确处理和筛选了需要删除的文档ID列表,避免误删除重要文档。 +- 考虑到该方法可能会影响数据库或存储中的数据持久性,实现时应当谨慎处理异常和错误,确保数据的一致性和完整性。 +*** +### FunctionDef update_doc_by_ids(self, docs) +**update_doc_by_ids**: 此函数的功能是根据文档ID更新或删除文档。 + +**参数**: +- `docs`: 一个字典,键为文档ID,值为`Document`对象。 + +**代码描述**: +`update_doc_by_ids` 方法接收一个包含文档ID和对应`Document`对象的字典作为参数。此方法首先调用`del_doc_by_ids`方法,尝试删除所有传入的文档ID对应的文档。随后,方法初始化一个空列表用于存储有效的文档对象和对应的ID。接着,遍历传入的字典,检查每个`Document`对象的有效性:如果`Document`对象为`None`或其`page_content`属性为空(或仅包含空白字符),则该文档被视为无效,不会被添加到有效文档列表中。对于有效的文档,其ID和对象分别被添加到之前初始化的列表中。最后,调用`do_add_doc`方法,将有效的文档重新添加到知识库中。此过程实现了对指定ID的文档进行更新或删除的功能。 + +**注意**: +- 在调用此方法之前,确保传入的`docs`参数格式正确,即键为文档ID,值为对应的`Document`对象。 +- 此方法假设`del_doc_by_ids`和`do_add_doc`方法已在子类中具体实现。因此,在使用`update_doc_by_ids`方法之前,需要确保这两个方法能够正常工作。 +- 由于此方法内部调用了删除和添加文档的操作,可能会对知识库的数据产生重大影响。因此,在生产环境中使用时,应确保充分测试,并考虑实施适当的错误处理和日志记录机制,以便追踪操作结果。 + +**输出示例**: +调用`update_doc_by_ids`方法总是返回`True`,表示更新操作已被执行。然而,实际上是否成功更新或删除文档,需要依赖于`del_doc_by_ids`和`do_add_doc`方法的具体实现及其返回值。 +*** +### FunctionDef list_docs(self, file_name, metadata) +**list_docs**: 此函数的功能是通过文件名或元数据检索文档。 + +**参数**: +- `file_name`: 字符串类型,可选参数,默认为None,指定要查询的文件名称。 +- `metadata`: 字典类型,可选参数,默认为空字典,用于根据文档的元数据进行过滤查询。 + +**代码描述**: `list_docs` 函数首先调用 `list_docs_from_db` 函数,根据提供的知识库名称、文件名和元数据参数从数据库中检索文档信息。检索到的文档信息是一个包含文档ID和元数据的字典列表。随后,函数遍历这个列表,对每个文档ID调用 `get_doc_by_ids` 方法获取具体的文档对象。如果文档对象非空,则创建一个 `DocumentWithVSId` 实例,并将其添加到结果列表中。这个过程允许函数根据文件名或元数据过滤条件,返回一组经过向量化处理的文档对象。 + +**注意**: +- 在调用此函数时,应确保提供的知识库名称是有效的,以便正确检索文档。 +- 默认情况下,`metadata` 参数为空字典,如果需要根据特定元数据过滤文档,应显式传入相应的键值对。 +- 函数处理空文档对象的情况,即如果 `get_doc_by_ids` 方法返回空,则当前迭代会跳过,不会向结果列表中添加任何对象。 + +**输出示例**: +假设数据库中存在两条记录,其字段值分别为: +- id: "docA", metadata: {"author": "张三", "year": "2021"} +- id: "docB", metadata: {"author": "李四", "year": "2022"} + +调用 `list_docs(file_name="文件A.pdf")` 可能返回以下列表: +```python +[ + DocumentWithVSId(id="docA", metadata={"author": "张三", "year": "2021"}, score=3.0), + DocumentWithVSId(id="docB", metadata={"author": "李四", "year": "2022"}, score=3.0) +] +``` +此输出示例展示了函数如何根据指定的文件名返回该文件下所有文档的向量化处理对象列表。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是创建知识库的子类实现逻辑。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_create_kb` 函数是 `KBService` 类中的一个方法,设计用于被子类重写,以实现特定的知识库创建逻辑。在 `KBService` 类的上下文中,`do_create_kb` 方法提供了一个扩展点,允许开发者在不修改 `create_kb` 方法逻辑的情况下,添加或修改知识库创建时的行为。具体来说,当 `create_kb` 方法被调用时,它首先检查指定的文档路径是否存在,如果不存在则创建该路径。之后,`create_kb` 方法会调用 `do_create_kb`,这一步骤是预留给开发者的扩展点,允许在创建知识库的基础流程中插入自定义逻辑。完成这些步骤后,`create_kb` 方法会继续执行,将知识库信息添加到数据库中,并返回操作的状态。 + +在实际使用中,开发者应该通过继承 `KBService` 类并重写 `do_create_kb` 方法来实现特定的知识库创建逻辑。这种设计模式提高了代码的可扩展性和可维护性,允许不同的知识库实现具有不同的创建逻辑,而不必修改公共的 `create_kb` 方法。 + +**注意**: `do_create_kb` 方法默认不执行任何操作,因为它是设计给子类用于重写的。如果在不重写此方法的情况下直接使用,它将不会对知识库的创建过程产生任何影响。因此,开发者在使用 `KBService` 类时,需要根据具体需求重写 `do_create_kb` 方法,以实现所需的知识库创建逻辑。 +*** +### FunctionDef list_kbs_type +**list_kbs_type**: 此函数的功能是列出所有知识库类型。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `list_kbs_type` 函数的主要作用是从一个名为 `kbs_config` 的字典中获取所有的键,并将这些键作为一个列表返回。这里的 `kbs_config` 字典预期包含了不同知识库类型的配置信息,其中字典的键代表了各个知识库的类型。通过调用 `keys()` 方法,我们可以获取到一个包含所有键的视图,然后通过 `list()` 函数将这个视图转换成列表。这样,最终返回的就是一个包含所有知识库类型名称的列表。 + +**注意**: 使用此函数时,需要确保 `kbs_config` 字典已经被正确初始化并且包含了至少一个知识库类型的配置信息。如果 `kbs_config` 是空的,那么此函数将返回一个空列表。 + +**输出示例**: +假设 `kbs_config` 字典如下所示: +```python +kbs_config = { + "type1": {...}, + "type2": {...}, + "type3": {...} +} +``` +调用 `list_kbs_type()` 函数将返回: +```python +["type1", "type2", "type3"] +``` +这表示当前配置中存在三种类型的知识库。 +*** +### FunctionDef list_kbs(cls) +**list_kbs**: 此函数的功能是从数据库中列出满足特定条件的知识库名称列表。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `list_kbs` 函数是 `KBService` 类的一个方法,它通过调用 `list_kbs_from_db` 函数来实现其功能。`list_kbs_from_db` 函数负责从数据库中检索并返回满足特定条件(如文件数量大于某个最小值)的知识库名称列表。`list_kbs` 函数作为一个接口,简化了从数据库获取知识库名称列表的过程,使得其他函数或服务可以轻松地获取这些信息而无需直接与数据库交互。 + +**注意**: +- `list_kbs` 函数的实现依赖于 `list_kbs_from_db` 函数,因此在使用 `list_kbs` 函数之前,需要确保 `list_kbs_from_db` 函数已正确实现并能够成功从数据库中检索信息。 +- 此函数不接受任何参数,因此调用时不需要提供额外信息。它将返回数据库中所有符合条件的知识库名称列表,具体的筛选条件(如文件数量的最小值)是在 `list_kbs_from_db` 函数内部定义的。 + +**输出示例**: 假设数据库中存在多个知识库,且根据 `list_kbs_from_db` 函数的筛选条件,有两个知识库满足条件。那么 `list_kbs` 函数的返回值可能如下: +``` +['知识库A', '知识库B'] +``` +这表示在满足特定条件下,数据库中的知识库A和知识库B被成功检索并返回。 + +通过 `list_kbs` 函数,`KBService` 类为其他服务或函数提供了一个简洁的接口来获取数据库中的知识库名称列表,进一步促进了项目中不同组件之间的解耦和协作。 +*** +### FunctionDef exists(self, kb_name) +**exists**: 此函数的功能是检查指定名称的知识库是否存在。 + +**参数**: +- `kb_name`: 可选参数,字符串类型,表示要检查的知识库名称。如果未提供,则使用对象自身的`kb_name`属性。 + +**代码描述**: +`exists`函数用于判断给定名称的知识库是否存在于数据库中。函数首先检查是否提供了`kb_name`参数,如果没有提供,则使用对象自身的`kb_name`属性作为要检查的知识库名称。然后,函数调用`kb_exists`函数,传入知识库名称作为参数,`kb_exists`函数会查询数据库,检查是否存在具有该名称的知识库。如果存在,则`kb_exists`函数返回`True`,否则返回`False`。最终,`exists`函数返回`kb_exists`的返回值,即表示知识库是否存在的布尔值。 + +**注意**: +- 在调用`exists`函数时,如果已知知识库名称,可以通过`kb_name`参数直接提供。如果不提供`kb_name`参数,则默认使用对象自身的`kb_name`属性。 +- 确保在调用此函数之前,对象的`kb_name`属性已正确设置,以避免查询错误的知识库名称。 +- 此函数的返回值是布尔类型,可以直接用于条件判断,例如在决定是否创建新知识库或执行其他依赖于知识库存在性的操作时。 + +**输出示例**: +假设数据库中存在名为"技术文档库"的知识库,调用`exists(kb_name="技术文档库")`将返回`True`。如果查询一个不存在的知识库名称,如`exists(kb_name="不存在的库")`,则会返回`False`。 + +在项目中,`exists`函数被多个场景调用,包括在重建向量存储、生成知识库摘要向量存储、向知识库添加文档前的存在性检查等。这些调用场景表明,`exists`函数是知识库管理流程中的一个重要环节,用于确保操作的目标知识库确实存在,从而保证数据的一致性和操作的有效性。 +*** +### FunctionDef vs_type(self) +**vs_type**: 此函数的功能是获取知识库的类型。 + +**参数**: 此函数没有参数。 + +**代码描述**: `vs_type` 函数设计用于返回一个字符串,该字符串代表知识库的类型。在当前的代码实现中,函数体是空的,这意味着需要由继承`KBService`类的子类来具体实现`vs_type`方法,以返回正确的知识库类型。在项目中,`vs_type`函数被`create_kb`和`update_info`两个方法调用。这两个方法分别用于创建和更新知识库,它们通过调用`vs_type`来获取知识库的类型,并将这个类型信息作为参数之一传递给`add_kb_to_db`函数,以便将知识库的相关信息添加到数据库中。这表明`vs_type`函数在知识库创建和更新流程中扮演着关键的角色,确保了知识库类型的信息能够正确地存储和管理。 + +**注意**: 虽然当前`vs_type`函数的实现为空,但在实际使用时,开发者需要在继承`KBService`类的子类中重写此方法,以返回具体的知识库类型。这是因为不同类型的知识库可能需要不同的处理逻辑和存储方式,因此正确地识别和返回知识库的类型对于知识库的管理至关重要。 +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化知识库服务。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_init` 函数是 `KBService` 类的一个方法,目前其内部实现为空(即使用 `pass` 关键字),这意味着它是一个待实现的功能或者是一个占位符。在 `KBService` 类的构造函数 `__init__` 中,`do_init` 被调用,这表明在创建 `KBService` 对象的过程中,`do_init` 函数被设计为完成知识库服务的初始化工作。具体来说,`__init__` 函数首先设置了知识库的名称、知识库信息、嵌入模型、知识库路径和文档路径等属性,然后调用 `do_init` 来进行进一步的初始化操作。虽然当前 `do_init` 函数的实现为空,但它的存在暗示了在知识库服务初始化过程中可能需要执行的额外步骤或者特定的初始化逻辑,这些逻辑在未来可以在 `do_init` 函数中实现。 + +**注意**: 虽然当前 `do_init` 函数内部为空,但开发者在未来可能会在此函数中添加具体的初始化逻辑。因此,在修改或扩展 `KBService` 类的功能时,应当考虑到 `do_init` 函数的潜在作用和可能的实现内容。此外,调用 `do_init` 的方式表明它是类初始化过程的一部分,因此任何对 `do_init` 的修改都应当谨慎进行,以避免影响 `KBService` 类对象的正常创建和初始化。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是执行删除知识库的具体逻辑。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `do_drop_kb` 函数是 `KBService` 类中定义的一个方法,用于实现删除知识库的具体逻辑。在该方法的当前实现中,它仅包含一个 `pass` 语句,这意味着它是一个空方法,需要由继承 `KBService` 类的子类来具体实现删除知识库的逻辑。此方法的设计初衷是允许不同的知识库子类根据自己的需求实现具体的删除逻辑,从而提供了一种灵活的方式来扩展知识库服务的功能。 + +在项目中,`do_drop_kb` 方法被 `drop_kb` 方法调用。`drop_kb` 方法的主要职责是删除知识库,它首先调用 `do_drop_kb` 方法来执行特定的删除逻辑,然后调用 `delete_kb_from_db` 函数来从数据库中删除知识库,最后返回操作的状态。这种设计模式允许在删除知识库的过程中插入额外的逻辑,而不仅仅是从数据库中删除记录,从而提供了更大的灵活性和可扩展性。 + +**注意**: 由于 `do_drop_kb` 方法在 `KBService` 类中默认不执行任何操作,因此在使用 `KBService` 类或其子类进行知识库删除操作时,需要确保根据具体需求重写 `do_drop_kb` 方法,以实现所需的删除逻辑。此外,开发者在扩展或继承 `KBService` 类时,应当注意保持 `do_drop_kb` 方法与知识库删除流程的一致性和完整性。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 此函数的功能是执行知识库的搜索操作。 + +**参数**: +- `query`: 字符串类型,表示搜索查询的内容。 +- `top_k`: 整型,指定返回的最相关文档的最大数量。 +- `score_threshold`: 浮点型,设定的分数阈值,只有得分高于此阈值的文档才会被返回。 + +**代码描述**: +`do_search`函数是`KBService`类的一个方法,旨在根据给定的查询参数,在知识库中搜索并返回最相关的文档。该方法接受三个参数:`query`为用户的查询字符串,`top_k`限定了返回结果的数量,而`score_threshold`则是过滤结果的得分阈值,只有当文档的相关性得分超过这个阈值时,该文档才会被考虑为搜索结果的一部分。函数返回一个列表,列表中的每个元素是一个元组,包含一个文档和该文档的得分。 + +在项目中,`do_search`方法被`search_docs`方法调用。`search_docs`方法同样位于`KBService`类中,它提供了一个更高层次的接口,用于执行搜索操作。`search_docs`方法通过调用`do_search`,利用其提供的底层搜索逻辑,然后返回搜索结果。这种设计允许`do_search`方法专注于执行搜索逻辑,而`search_docs`方法则处理与搜索相关的其他逻辑,如参数的默认值设置等。 + +**注意**: +- `do_search`方法是一个抽象方法,意味着它需要在子类中被具体实现。在不同的知识库实现中,根据具体的搜索需求和知识库的结构,`do_search`方法的实现可能会有所不同。 +- 调用此方法时,需要确保传入的参数类型和值是正确的,特别是`top_k`和`score_threshold`,这两个参数直接影响搜索结果的质量和数量。 +- 由于`do_search`方法返回的是包含文档和得分的元组列表,因此调用方需要根据自己的需求处理这些结果,例如展示给用户等。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 此函数的功能是向知识库添加文档。 + +**参数**: +- `docs`: 需要添加到知识库中的文档列表,类型为`List[Document]`。 +- `**kwargs`: 接受可变数量的关键字参数,用于扩展或自定义功能。 + +**代码描述**: +`do_add_doc`函数是`KBService`类的一个方法,设计用于将文档添加到知识库中。该方法接受一个文档列表`docs`作为参数,每个文档都是`Document`类型的实例,此外还可以接受多个关键字参数`**kwargs`,以提供更多的灵活性和扩展性。函数体内的具体实现逻辑需要由子类根据具体需求来完成,因为在基类中,此方法仅以`pass`占位,暗示这是一个待子类实现的抽象方法。 + +在项目中,`do_add_doc`方法被`add_doc`和`update_doc_by_ids`两个方法调用。`add_doc`方法用于向知识库添加文件,如果指定了`docs`参数,则直接调用`do_add_doc`方法添加这些文档,而不再进行文本向量化处理;`update_doc_by_ids`方法则是用于根据文档ID更新知识库中的文档,如果文档内容有效,则会调用`do_add_doc`方法重新添加这些文档。这两种调用方式都体现了`do_add_doc`方法在知识库文档管理中的核心作用,即作为一个接口,允许不同的上层逻辑向知识库中添加或更新文档。 + +**注意**: +- 由于`do_add_doc`方法在基类中没有具体实现,因此在使用时需要确保其子类已经根据具体的业务逻辑重写了这个方法。 +- 调用此方法时,需要确保传入的`docs`参数是一个`Document`类型的实例列表,且每个实例都应该包含了要添加到知识库的文档信息。 +- 通过`**kwargs`参数,可以灵活地为方法传入额外的参数,但使用时应注意检查子类实现中对这些参数的处理逻辑,以避免出现意外的行为。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数的功能是从知识库中删除指定的文档。 + +**参数**: +- `kb_file`: 表示要删除的知识库文件的KnowledgeFile对象。 + +**代码描述**: `do_delete_doc`函数是KBService类中用于删除知识库中文档的方法。它接收一个KnowledgeFile类型的参数`kb_file`,该参数封装了需要删除的文件的相关信息。此函数的实现需要子类根据具体逻辑进行重写。在当前的实现中,函数体内部仅包含一个`pass`语句,意味着默认情况下此函数不执行任何操作。实际的删除逻辑应由继承KBService类的子类根据具体需求实现。 + +**注意**: +- 在使用`do_delete_doc`函数时,需要确保传入的`kb_file`参数正确实例化,且其代表的文件确实存在于知识库中。否则,可能无法正确执行删除操作。 +- 由于`do_delete_doc`函数默认不执行任何操作,开发者需要在子类中重写此方法,添加具体的删除逻辑。 +- 此函数通常与`delete_doc`方法配合使用。`delete_doc`方法调用`do_delete_doc`进行文件的删除操作,并根据参数决定是否从磁盘和数据库中删除文件内容。这意味着`do_delete_doc`负责执行删除操作的自定义部分,而`delete_doc`则处理更广泛的删除流程,包括可选的从磁盘删除文件和更新数据库状态。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是从知识库删除全部向量子类实自己逻辑。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `do_clear_vs` 函数是 `KBService` 类中的一个方法,其主要作用是在知识库服务中执行删除所有向量数据的前置逻辑。具体来说,该函数被设计为在删除向量库中所有内容之前,执行必要的清理或准备工作。然而,根据提供的代码片段,`do_clear_vs` 方法的实现目前为空(使用了 `pass` 语句),这意味着它没有执行任何操作。这可能表明该方法是为了未来可能的扩展而保留的,或者是等待进一步的实现。 + +在项目中,`do_clear_vs` 方法被 `clear_vs` 方法调用。`clear_vs` 方法的文档说明了其功能是“删除向量库中所有内容”。在执行具体的删除操作之前,`clear_vs` 首先调用 `do_clear_vs` 方法。这表明 `do_clear_vs` 方法的设计初衷是作为执行实际删除操作前的一个预处理步骤。在 `do_clear_vs` 方法调用之后,`clear_vs` 方法继续调用 `delete_files_from_db` 函数,传入知识库名称作为参数,来完成向量库中所有内容的删除操作,并返回操作的状态。 + +**注意**: 虽然当前 `do_clear_vs` 方法的实现为空,但在未来的开发中,如果需要在删除向量数据之前执行特定的逻辑(如日志记录、数据备份、权限检查等),可以在此方法中添加相应的代码。因此,开发者在使用或修改此方法时,应考虑到其在整个删除流程中的定位和作用,避免破坏已有的调用关系和逻辑顺序。 +*** +## ClassDef KBServiceFactory +**KBServiceFactory**: KBServiceFactory 类的功能是提供一个静态方法工厂,用于根据不同的参数创建并返回不同类型的知识库服务实例。 + +**属性**:该类没有定义属性,所有功能都通过静态方法实现。 + +**代码描述**: +KBServiceFactory 类提供了三个静态方法,分别用于根据不同的条件获取知识库服务实例。 + +1. `get_service` 方法接受知识库名称(kb_name)、向量存储类型(vector_store_type)、嵌入模型名称(embed_model)作为参数。该方法首先会检查向量存储类型是否为字符串,如果是,则将其转换为 `SupportedVSType` 枚举类型。根据向量存储类型的不同,方法会动态导入并返回对应的知识库服务实例,如 FaissKBService、PGKBService、MilvusKBService 等。这些服务实例都继承自 KBService 基类,但具体实现根据向量存储的不同而有所差异。 + +2. `get_service_by_name` 方法接受知识库名称(kb_name)作为参数,通过调用数据库加载函数 `load_kb_from_db` 来获取知识库的向量存储类型和嵌入模型名称,然后调用 `get_service` 方法来获取对应的知识库服务实例。如果数据库中不存在该知识库,则返回 None。 + +3. `get_default` 方法不接受任何参数,直接返回一个默认向量存储类型为 `SupportedVSType.DEFAULT` 的知识库服务实例。 + +在项目中,KBServiceFactory 被多个模块调用,用于创建、删除、更新、搜索知识库中的文档,以及上传和下载文档等操作。例如,在 `knowledge_base_chat.py` 中,通过 KBServiceFactory 获取知识库服务实例来搜索知识库中的文档;在 `kb_api.py` 中,通过 KBServiceFactory 创建新的知识库或删除现有知识库。 + +**注意**: +- 在使用 `get_service` 方法时,需要确保传入的向量存储类型是支持的类型之一,否则可能会抛出异常。 +- `get_service_by_name` 方法依赖于数据库中的知识库配置信息,如果数据库中不存在指定的知识库名称,将返回 None。 +- 默认情况下,`get_default` 方法返回的知识库服务实例使用的向量存储类型为 `SupportedVSType.DEFAULT`,具体实现可能会根据项目需求进行调整。 + +**输出示例**: +由于 KBServiceFactory 类主要提供静态方法来获取知识库服务实例,而不直接产生输出,因此没有具体的输出示例。返回的知识库服务实例根据不同的向量存储类型,将具有不同的方法和属性,用于执行知识库的相关操作。 +### FunctionDef get_service(kb_name, vector_store_type, embed_model) +**get_service**: `get_service` 函数用于根据知识库名称、向量存储类型和嵌入模型名称动态获取对应的知识库服务实例。 + +**参数**: +- `kb_name`: 知识库名称,类型为 `str`。 +- `vector_store_type`: 向量存储类型,可以是 `str` 类型的向量存储类型名称或 `SupportedVSType` 枚举类型。 +- `embed_model`: 嵌入模型名称,默认值为 `EMBEDDING_MODEL`,类型为 `str`。 + +**代码描述**: +此函数首先判断 `vector_store_type` 参数的类型,如果是字符串,则将其转换为 `SupportedVSType` 枚举类型。接着,根据向量存储类型的不同,动态导入并返回对应的知识库服务类的实例。支持的向量存储类型包括 FAISS、Milvus、Zilliz、PostgreSQL、Elasticsearch、ChromaDB 等,以及一个默认的向量存储类型。如果指定的向量存储类型为默认类型,则会根据 `model_config.kbs_config` 中的配置返回 MilvusKBService 实例。每种向量存储类型对应的知识库服务类都继承自 `KBService` 基类,并实现了相应的方法以支持知识库的操作。 + +**注意**: +- 在使用 `get_service` 函数时,需要确保传入的向量存储类型名称与 `SupportedVSType` 中定义的类型名称一致,否则可能会引发错误。 +- 如果项目中新增了向量存储类型,需要在 `SupportedVSType` 枚举类中添加相应的类型,并在 `get_service` 函数中添加相应的逻辑以支持新的向量存储类型。 +- 在调用此函数获取知识库服务实例后,可以使用该实例执行创建知识库、添加文档、搜索文档等操作。 + +**输出示例**: +由于 `get_service` 函数返回的是知识库服务实例,而不是具体的数据,因此没有直接的输出示例。返回的实例类型取决于传入的向量存储类型参数。例如,如果传入的向量存储类型为 `FAISS`,则函数将返回一个 `FaissKBService` 类的实例。 +*** +### FunctionDef get_service_by_name(kb_name) +**get_service_by_name**: 此函数的功能是根据知识库名称获取对应的知识库服务实例。 + +**参数**: +- `kb_name`: 知识库的名称,类型为字符串。 + +**代码描述**: `get_service_by_name` 函数首先调用 `load_kb_from_db` 函数,根据传入的知识库名称 `kb_name` 从数据库中加载知识库的信息,包括知识库的名称、向量库类型和嵌入模型名称。如果数据库中不存在指定名称的知识库,`load_kb_from_db` 将返回三个 `None` 值,此时 `get_service_by_name` 函数也将返回 `None`。如果成功从数据库中加载到知识库信息,`get_service_by_name` 函数将使用加载到的知识库名称、向量库类型和嵌入模型名称作为参数,调用 `KBServiceFactory.get_service` 方法,动态获取并返回对应的知识库服务实例。 + +**注意**: +- 在调用此函数之前,确保传入的知识库名称在数据库中存在,否则函数将返回 `None`。 +- 此函数依赖于 `load_kb_from_db` 函数从数据库中加载知识库信息,因此需要确保数据库连接正常且知识库信息已正确录入数据库。 +- 返回的知识库服务实例类型取决于知识库的向量库类型,例如,如果向量库类型为 `FAISS`,则返回的实例将是 `FaissKBService` 类的实例。 + +**输出示例**: +假设数据库中存在一个名为 "技术文档库" 的知识库,其向量库类型为 "FAISS",嵌入模型名称为 "BERT",调用 `get_service_by_name("技术文档库")` 将返回一个 `FaissKBService` 类的实例,该实例用于管理和操作名为 "技术文档库" 的知识库。如果数据库中不存在名为 "不存在的库" 的知识库,调用 `get_service_by_name("不存在的库")` 将返回 `None`。 +*** +### FunctionDef get_default +**get_default**: `get_default` 函数的功能是获取默认的知识库服务实例。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `get_default` 函数通过调用 `KBServiceFactory.get_service` 方法,传入 `"default"` 作为知识库名称和 `SupportedVSType.DEFAULT` 作为向量存储类型,来获取默认的知识库服务实例。在这个过程中,`SupportedVSType.DEFAULT` 指代默认的向量存储服务类型,其具体实现可能会根据项目配置或环境而变化。根据 `KBServiceFactory.get_service` 的实现逻辑,如果向量存储类型为 `SupportedVSType.DEFAULT`,则会返回一个 `MilvusKBService` 实例,除非项目配置指定了不同的默认服务。这意味着,如果没有特别指定,默认的知识库服务将使用 Milvus 作为向量存储后端。 + +**注意**: +- 使用 `get_default` 函数时,不需要传递任何参数,这使得它非常适合于需要快速获取默认知识库服务实例的场景。 +- 返回的知识库服务实例类型可能会根据项目的配置或环境设置而有所不同。默认情况下,它返回的是 `MilvusKBService` 实例,但这一行为是可配置的。 +- 在实际应用中,应确保项目配置正确,以便 `get_default` 能够返回预期的知识库服务实例。 + +**输出示例**: 由于 `get_default` 函数的返回值取决于项目配置,因此没有固定的输出示例。但在大多数情况下,如果项目使用 Milvus 作为默认的向量存储服务,那么该函数可能返回类似于以下的实例表示: + +```python + +``` + +这表示 `get_default` 成功返回了一个 `MilvusKBService` 的实例,可以用于执行知识库相关的操作,如创建知识库、添加文档、搜索文档等。 +*** +## FunctionDef get_kb_details +**get_kb_details**: 此函数的功能是获取所有知识库的详细信息列表。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `get_kb_details` 函数首先调用 `list_kbs_from_folder` 函数来获取文件夹中的知识库列表,然后调用 `KBService.list_kbs` 方法获取数据库中的知识库列表。对于文件夹中的每个知识库,函数初始化一个包含基本信息的字典,并将其添加到结果字典中。接下来,对于数据库中的每个知识库,函数通过调用 `get_kb_detail` 函数获取其详细信息,并更新结果字典中相应知识库的信息。如果数据库中的知识库在结果字典中不存在,则将其添加到结果字典中,并标记为不在文件夹中。最后,函数将结果字典中的值转换为列表,并为每个知识库分配一个序号,然后返回这个列表。 + +**注意**: +- 确保 `list_kbs_from_folder` 和 `KBService.list_kbs` 方法能够正确执行,且数据库连接正常,以便能够获取完整的知识库列表。 +- `get_kb_detail` 函数需要能够正确返回知识库的详细信息,包括知识库名称、简介、向量库类型、嵌入模型名称、文件数量和创建时间等。 + +**输出示例**: +假设文件夹和数据库中各有两个知识库,函数可能返回如下列表: +```python +[ + { + "No": 1, + "kb_name": "知识库1", + "vs_type": "ElasticSearch", + "kb_info": "知识库1的简介", + "embed_model": "BERT", + "file_count": 100, + "create_time": "2023-04-01T12:00:00", + "in_folder": True, + "in_db": True + }, + { + "No": 2, + "kb_name": "知识库2", + "vs_type": "Faiss", + "kb_info": "知识库2的简介", + "embed_model": "RoBERTa", + "file_count": 50, + "create_time": "2023-04-02T12:00:00", + "in_folder": False, + "in_db": True + } +] +``` +这个列表包含了两个知识库的详细信息,每个知识库都有一个序号、名称、向量库类型、简介、嵌入模型名称、文件数量、创建时间以及它们是否存在于文件夹和数据库中的标记。 +## FunctionDef get_kb_file_details(kb_name) +**get_kb_file_details**: 此函数用于获取指定知识库中的文件详细信息列表。 + +**参数**: +- `kb_name`: 字符串类型,指定要查询的知识库名称。 + +**代码描述**: `get_kb_file_details` 函数首先通过 `KBServiceFactory.get_service_by_name` 方法根据知识库名称获取对应的知识库服务实例。如果该实例不存在,则直接返回空列表。接着,函数调用 `list_files_from_folder` 函数列出知识库文件夹中的所有文件,并通过知识库服务实例的 `list_files` 方法获取数据库中记录的所有文件名。然后,函数遍历文件夹中的文件,为每个文件构建一个包含文件基本信息的字典,并将其添加到结果字典中。对于数据库中存在的文件,函数通过调用 `get_file_detail` 函数获取其详细信息,并更新到结果字典中。最后,函数将结果字典中的值转换为列表,并为每个元素添加一个序号字段,然后返回这个列表。 + +**注意**: +- 确保传入的 `kb_name` 在系统中是存在的,否则函数将返回空列表。 +- 此函数整合了文件夹和数据库中的文件信息,如果文件同时存在于文件夹和数据库中,数据库中的文件信息将覆盖文件夹中的同名文件信息。 +- 返回的列表中的每个字典都包含了文件的多个属性,如文件名、扩展名、版本等,这些信息有助于进一步处理和管理知识库中的文件。 + +**输出示例**: +```json +[ + { + "No": 1, + "kb_name": "技术文档库", + "file_name": "document1.pdf", + "file_ext": ".pdf", + "file_version": 0, + "document_loader": "", + "docs_count": 0, + "text_splitter": "", + "create_time": null, + "in_folder": true, + "in_db": false + }, + { + "No": 2, + "kb_name": "技术文档库", + "file_name": "report2.docx", + "file_ext": ".docx", + "file_version": 1, + "document_loader": "WordLoader", + "docs_count": 10, + "text_splitter": "SpacyTextSplitter", + "create_time": "2023-04-01 12:00:00", + "in_folder": false, + "in_db": true + } +] +``` +此示例展示了当查询到文件时,`get_kb_file_details` 函数返回的信息列表。列表中的每个元素都是一个字典,包含了文件所属的知识库名称、文件名、文件扩展名、文件版本、文档加载器名称、文本分割器名称、文件的创建时间、是否存在于文件夹中、是否存在于数据库中等信息。 +## ClassDef EmbeddingsFunAdapter +**EmbeddingsFunAdapter**: EmbeddingsFunAdapter类的功能是对文本进行嵌入表示的转换,支持同步和异步两种方式。 + +**属性**: +- `embed_model`: 嵌入模型的名称,用于指定使用哪个预训练模型进行文本嵌入。 + +**代码描述**: +EmbeddingsFunAdapter类继承自Embeddings类,主要提供了文本嵌入表示的功能。它包含以下几个关键方法: +- `__init__`: 构造函数,接收一个嵌入模型名称作为参数,默认使用预定义的EMBEDDING_MODEL。 +- `embed_documents`: 接收一个文本列表,返回这些文本的嵌入表示。该方法首先使用指定的嵌入模型将文本转换为嵌入向量,然后对这些向量进行归一化处理。 +- `embed_query`: 接收单个文本字符串,返回该文本的嵌入表示。与`embed_documents`方法类似,但是专门针对单个查询文本进行处理,并将结果转换为一维数组返回。 +- `aembed_documents`: 异步版本的`embed_documents`方法,功能相同但适用于异步调用场景。 +- `aembed_query`: 异步版本的`embed_query`方法,功能相同但适用于异步调用场景。 + +在项目中,EmbeddingsFunAdapter类被多个模块调用,用于处理不同场景下的文本嵌入需求。例如,在知识库聊天迭代器、知识库缓存加载、以及各种知识库服务中,都可以看到EmbeddingsFunAdapter的身影。这些调用场景表明,EmbeddingsFunAdapter是处理文本嵌入表示的核心组件,支持多种知识库服务的文本相似度查询功能。 + +**注意**: +- 在使用EmbeddingsFunAdapter进行文本嵌入转换时,需要确保传入的嵌入模型名称是有效且已经预训练好的。 +- 异步方法`aembed_documents`和`aembed_query`需要在异步环境下调用,以避免阻塞主线程。 + +**输出示例**: +```python +# 使用embed_query方法的输出示例 +embeddings = embed_func.embed_query("这是一个示例文本") +# 输出: [0.01, -0.02, 0.03, ..., 0.05] # 假设的嵌入向量列表 + +# 使用aembed_documents方法的输出示例 +embeddings = await embed_func.aembed_documents(["文本1", "文本2"]) +# 输出: [[0.01, -0.02, 0.03, ..., 0.05], [0.02, -0.03, 0.04, ..., 0.06]] # 假设的嵌入向量列表 +``` +在实际应用中,嵌入向量的维度和具体数值将取决于所使用的嵌入模型。 +### FunctionDef __init__(self, embed_model) +**__init__**: 该函数用于初始化EmbeddingsFunAdapter类的实例。 + +**参数**: +- **embed_model**: 字符串类型,默认值为EMBEDDING_MODEL。该参数用于指定嵌入模型。 + +**代码描述**: +`__init__`方法是`EmbeddingsFunAdapter`类的构造函数,负责初始化类的实例。在这个方法中,接收一个名为`embed_model`的参数,该参数用于指定将要使用的嵌入模型。如果调用时没有指定`embed_model`参数,则会使用`EMBEDDING_MODEL`作为默认值。这里的`EMBEDDING_MODEL`是在类外部定义的一个常量,代表默认的嵌入模型名称。 + +在方法体内,将传入的`embed_model`参数值赋给实例变量`self.embed_model`。这样,每个`EmbeddingsFunAdapter`类的实例都会拥有一个`embed_model`实例变量,用于存储该实例所使用的嵌入模型名称。 + +**注意**: +- 在使用`EmbeddingsFunAdapter`类创建实例时,可以根据需要传入不同的`embed_model`参数值,以指定不同的嵌入模型。如果不指定,将使用默认的嵌入模型。 +- 确保传入的`embed_model`参数值是有效的,且对应的嵌入模型已经正确安装和配置,以避免在后续使用过程中出现错误。 +*** +### FunctionDef embed_documents(self, texts) +**embed_documents**: 该函数的功能是将文本列表转换为归一化的嵌入向量列表。 + +**参数**: +- `texts`: 需要转换为嵌入向量的文本字符串列表。 + +**代码描述**: +`embed_documents`函数首先调用`embed_texts`函数,将文本列表`texts`和嵌入模型`self.embed_model`作为参数传递,以获取文本的嵌入向量。`embed_texts`函数负责将文本向量化,可以处理本地或在线的嵌入模型,并返回一个包含向量化结果的`BaseResponse`对象。接着,`embed_documents`函数使用`normalize`函数对嵌入向量进行L2范数归一化处理,以确保所有向量都规范化到单位球上。这一步骤对于后续的向量空间模型处理非常重要,有助于提高模型的效果和稳定性。最后,函数将归一化的嵌入向量转换为列表格式并返回。 + +在整个过程中,`embed_documents`函数依赖于`embed_texts`函数进行文本的向量化处理,并依赖于`normalize`函数进行向量的归一化处理,这两个函数是实现文本嵌入和归一化的关键步骤。 + +**注意**: +- 确保传入的`texts`参数是有效的文本列表,且`self.embed_model`已正确指定,以便函数能够找到并使用正确的嵌入模型进行文本向量化处理。 +- 归一化步骤是必要的,它确保了嵌入向量的质量,对于后续的处理非常重要。 + +**输出示例**: +假设调用`embed_documents`函数,传入文本列表`["你好", "世界"]`,可能会返回如下归一化的嵌入向量列表: +``` +[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]] +``` +这表示两个文本"你好"和"世界"被成功转换为嵌入向量,并且这些向量已经过归一化处理。 +*** +### FunctionDef embed_query(self, text) +**embed_query**: 该函数的功能是对输入的文本进行向量化处理,并返回归一化后的向量列表。 + +**参数**: +- `text`: 需要进行向量化处理的文本,数据类型为字符串。 + +**代码描述**: +`embed_query`函数首先调用`embed_texts`函数,将输入的文本`text`转换为向量化表示。在这个过程中,`embed_texts`函数接收一个文本列表(本例中为单个文本构成的列表)、嵌入模型名称以及一个标志位`to_query`,后者指示该文本是作为查询使用。得到的向量化结果是一个包含单个向量的列表,该向量代表输入文本的嵌入表示。 + +接下来,函数将这个向量转换为二维数组,以满足后续处理的需求。这是通过`np.reshape`实现的,其中`query_embed`是原始的一维向量,`query_embed_2d`是转换后的二维数组。 + +然后,使用`normalize`函数对二维数组进行L2范数归一化处理。归一化是向量空间模型中的一个常见预处理步骤,有助于提高模型的效果和稳定性。归一化后的结果是一个二维数组,其中包含了归一化后的嵌入向量。 + +最后,函数将归一化后的二维数组转换回一维数组,并将其转换为列表格式返回。这样,返回的结果便是输入文本的归一化嵌入表示,可以直接用于后续的查询或其他处理。 + +**注意**: +- 输入文本`text`应为有效的字符串,不应为空或非文本类型。 +- 该函数依赖于`embed_texts`和`normalize`两个函数,因此在使用前需要确保这些依赖函数正确实现且可用。 +- 归一化处理依赖于`numpy`库,使用前需确保已安装`numpy`。 + +**输出示例**: +假设输入文本为"你好世界",且嵌入模型将该文本向量化为`[0.1, 0.2, 0.3]`,则归一化后的输出可能如下所示: +``` +[0.26726124, 0.53452248, 0.80178373] +``` +这表示输入文本"你好世界"的归一化嵌入向量为上述列表。 +*** +### FunctionDef aembed_documents(self, texts) +**aembed_documents**: 此函数的功能是异步地将一系列文本向量化,并返回归一化后的向量列表。 + +**参数**: +- `texts`: 需要进行向量化处理的文本列表,类型为List[str]。 + +**代码描述**: +`aembed_documents`函数是`EmbeddingsFunAdapter`类的一个方法,它接受一个文本列表作为输入,使用`aembed_texts`函数异步地将这些文本转换为嵌入向量。这一过程涉及到调用`aembed_texts`函数,该函数根据指定的嵌入模型(`embed_model`)对文本进行向量化处理,并返回一个包含向量化结果的`BaseResponse`对象。在获得向量化结果后,`aembed_documents`方法进一步调用`normalize`函数对嵌入向量进行L2范数归一化处理,以确保向量在同一规范化空间内,这对于后续的向量相似度计算等操作是非常重要的。最后,该方法将归一化后的嵌入向量转换为列表格式并返回。 + +从功能角度看,`aembed_documents`方法与其调用的`aembed_texts`函数和`normalize`函数共同构成了文本向量化和归一化处理的完整流程。其中,`aembed_texts`负责文本的异步向量化处理,而`normalize`负责对向量化结果进行归一化,以优化向量的表示和后续使用。 + +**注意**: +- 在调用此方法时,需要确保传入的`texts`参数是有效的文本列表。 +- 该方法的执行效率和效果依赖于`embed_model`的选择和配置,以及`aembed_texts`函数和`normalize`函数的实现。 +- 由于该方法涉及到异步调用,因此在使用时需要配合`await`关键字或在异步环境中调用。 + +**输出示例**: +假设调用`await aembed_documents(texts=["你好", "世界"])`,可能会返回如下归一化后的向量列表: +``` +[[0.4472136, 0.89442719], [0.5547002, 0.83205029]] +``` +这表示两个文本"你好"和"世界"被成功向量化并归一化,向量化结果分别为`[0.4472136, 0.89442719]`和`[0.5547002, 0.83205029]`。 +*** +### FunctionDef aembed_query(self, text) +**aembed_query**: 此函数的功能是对给定文本进行异步向量化处理,并返回归一化后的向量列表。 + +**参数**: +- `text`: 需要进行向量化处理的文本,类型为str。 + +**代码描述**: +`aembed_query`函数首先调用`aembed_texts`函数,对输入的文本`text`进行异步向量化处理。该过程涉及将文本封装成列表,并指定使用的嵌入模型`embed_model`以及将`to_query`参数设置为True,以优化向量化结果的使用场景。向量化处理后,返回的结果是一个包含向量化结果的`BaseResponse`对象。 + +接下来,函数从`BaseResponse`对象中提取出第一个(也是唯一一个,因为输入文本为单个字符串)向量化结果,并将其从一维数组转换为二维数组。这一步骤是为了满足后续归一化处理的需求。 + +随后,函数调用`normalize`函数对二维数组进行L2范数归一化处理。归一化是向量空间模型中的一个常见预处理步骤,有助于提高后续处理的效果和稳定性。归一化处理后,函数将归一化后的二维数组转换回一维数组,并将其作为最终结果返回。 + +**注意**: +- 在调用此函数时,需要确保传入的`text`参数是有效的文本字符串。 +- 函数的执行结果依赖于`embed_model`指定的嵌入模型的有效性和可用性,因此在使用前应确认模型配置正确且模型可用。 +- 归一化处理是基于`numpy`库实现的,因此在使用此函数前需要确保已经安装了`numpy`库。 + +**输出示例**: +假设调用`await aembed_query(text="你好")`,可能会返回如下归一化后的向量列表: +```python +[0.1, 0.2, 0.3, 0.4] +``` +这表示文本"你好"被成功向量化并归一化,向量化结果为一个一维数组。 + +在项目中,`aembed_query`函数被用于处理需要异步进行文本向量化的场景,如在聊天文件中对用户查询进行异步向量化以支持快速的文本查询和相似度计算。此外,它也支持通过在线API进行文本向量化,为项目提供了灵活的向量化解决方案。 +*** +## FunctionDef score_threshold_process(score_threshold, k, docs) +**score_threshold_process**: 此函数的功能是根据给定的分数阈值和文档相似度,筛选出符合条件的文档,并返回前k个文档。 + +**参数**: +- score_threshold: 分数阈值,用于筛选相似度高于此阈值的文档。 +- k: 返回的文档数量上限。 +- docs: 包含文档及其相似度分数的列表。 + +**代码描述**: +`score_threshold_process` 函数接收三个参数:`score_threshold`(分数阈值),`k`(返回的文档数量上限),以及`docs`(包含文档及其相似度分数的列表)。如果`score_threshold`不为`None`,则函数会使用`operator.le`(小于等于比较操作符)来筛选出相似度分数小于等于`score_threshold`的文档。之后,函数返回筛选后的文档列表中的前`k`个文档。 + +在项目中,`score_threshold_process`函数被多个知识库服务(如`MilvusKBService`、`PGKBService`和`ZillizKBService`)中的`do_search`方法调用。这些服务通过不同的后端(如Milvus、PostgreSQL、Zilliz等)执行相似度搜索,并使用`score_threshold_process`函数来根据分数阈值筛选和限制返回的结果数量。这样,无论底层使用哪种搜索技术,都能通过统一的方式控制搜索结果的质量和数量。 + +**注意**: +- 如果`score_threshold`为`None`,则不会进行分数阈值筛选,直接返回前`k`个文档。 +- 函数的返回值依赖于输入的`docs`列表和`k`值,因此在调用此函数前,确保`docs`列表已按相似度分数排序。 + +**输出示例**: +假设有以下输入: +- score_threshold = 0.5 +- k = 3 +- docs = [("doc1", 0.6), ("doc2", 0.4), ("doc3", 0.7), ("doc4", 0.5)] + +调用`score_threshold_process(score_threshold, k, docs)`后,返回值可能为: +- [("doc1", 0.6), ("doc3", 0.7), ("doc4", 0.5)] + +这表示在给定的文档中,有三个文档的相似度分数满足小于等于分数阈值的条件,并且根据要求返回了前3个文档。 diff --git a/markdown_docs/server/knowledge_base/kb_service/chromadb_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/chromadb_kb_service.md new file mode 100644 index 000000000..6f2b48923 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/chromadb_kb_service.md @@ -0,0 +1,306 @@ +## FunctionDef _get_result_to_documents(get_result) +**_get_result_to_documents**: 该函数的功能是将`GetResult`类型的查询结果转换为`Document`对象列表。 + +**参数**: +- `get_result`: `GetResult`类型,表示从数据库查询得到的结果。 + +**代码描述**: +`_get_result_to_documents`函数主要用于处理从数据库查询得到的结果,并将这些结果转换为`Document`对象列表。首先,函数检查`get_result`中的`documents`字段是否为空,如果为空,则直接返回空列表。如果不为空,则继续处理。 + +接下来,函数检查`get_result`中的`metadatas`字段。如果`metadatas`字段存在且不为空,则使用该字段的值;如果不存在或为空,则创建一个与`documents`字段长度相同的空字典列表。这一步确保了每个文档都有对应的元数据,即使某些文档没有元数据也会分配一个空字典。 + +然后,函数遍历`documents`和`metadatas`列表,将它们的元素打包成`Document`对象,并添加到一个新的列表`document_list`中。这里,`Document`对象是通过关键字参数`page_content`和`metadata`构造的,分别对应每个文档的内容和元数据。 + +最后,函数返回构造好的`Document`对象列表。 + +在项目中,`_get_result_to_documents`函数被`ChromaKBService`类的`get_doc_by_ids`方法调用。`get_doc_by_ids`方法负责根据给定的ID列表从数据库中查询文档,并使用`_get_result_to_documents`函数将查询结果转换为`Document`对象列表,以便进一步处理或响应客户端请求。 + +**注意**: +- 确保传入的`get_result`参数格式正确,特别是`documents`和`metadatas`字段,以避免运行时错误。 +- 该函数不直接与数据库交互,而是处理已经查询得到的结果。 + +**输出示例**: +```python +[ + Document(page_content="文档内容1", metadata={"作者": "张三"}), + Document(page_content="文档内容2", metadata={"作者": "李四"}) +] +``` +此示例展示了当`_get_result_to_documents`函数处理包含两个文档内容和对应元数据的查询结果时,返回的`Document`对象列表的可能形态。 +## FunctionDef _results_to_docs_and_scores(results) +**_results_to_docs_and_scores**: 该函数的功能是将搜索结果转换为文档和分数的列表。 + +**参数**: +- `results`: 任意类型,预期为包含文档内容、元数据和距离的搜索结果。 + +**代码描述**: +`_results_to_docs_and_scores` 函数接收一个包含搜索结果的参数 `results`,这个参数预期是一个字典,其中包含三个键:`"documents"`、`"metadatas"` 和 `"distances"`。每个键对应的值都是一个列表,列表中的每个元素分别代表搜索到的文档内容、文档的元数据和文档与查询之间的距离(通常用于表示相似度或相关性的分数)。 + +函数通过对这三个列表进行并行迭代(使用 `zip` 函数),为每个搜索结果创建一个元组,其中包含一个 `Document` 对象和一个浮点数。`Document` 对象由文档内容和元数据构成,而浮点数则是该文档与查询之间的距离。这个过程生成了一个元组列表,每个元组代表一个搜索结果及其相关性分数。 + +在项目中,`_results_to_docs_and_scores` 函数被 `ChromaKBService` 类的 `do_search` 方法调用。`do_search` 方法负责执行搜索查询,并使用 `_results_to_docs_and_scores` 函数处理查询结果,将其转换为更易于处理和展示的格式。这种设计模式允许将搜索逻辑与结果处理逻辑分离,提高了代码的可读性和可维护性。 + +**注意**: +- 确保传入的 `results` 参数格式正确,即包含 `"documents"`、`"metadatas"` 和 `"distances"` 三个键,且每个键对应的值都是列表格式。 +- 该函数依赖于 `Document` 类的正确实现。`Document` 类需要能够接受页面内容和元数据作为参数,并将它们封装为一个对象。 + +**输出示例**: +```python +[ + (Document(page_content="文档内容1", metadata={"作者": "张三"}), 0.95), + (Document(page_content="文档内容2", metadata={"作者": "李四"}), 0.89) +] +``` +此输出示例展示了函数返回值的可能形式,其中包含了两个元组,每个元组都包含一个 `Document` 对象和一个表示与查询相似度的分数。 +## ClassDef ChromaKBService +**ChromaKBService**: ChromaKBService 类是用于操作和管理基于 ChromaDB 的知识库服务。 + +**属性**: +- `vs_path`: 向量存储路径。 +- `kb_path`: 知识库路径。 +- `client`: ChromaDB 客户端实例。 +- `collection`: 当前知识库的集合。 + +**代码描述**: +ChromaKBService 类继承自 KBService 类,专门用于处理基于 ChromaDB 的知识库操作。它提供了一系列方法来初始化服务、创建知识库、删除知识库、添加文档、删除文档、清空向量存储、以及执行文档搜索等操作。 + +- `vs_type` 方法返回当前知识库服务使用的向量存储类型,即 ChromaDB。 +- `get_vs_path` 和 `get_kb_path` 方法分别用于获取向量存储和知识库的路径。 +- `do_init` 方法初始化 ChromaDB 客户端和集合。 +- `do_create_kb` 方法创建一个新的知识库,实际上是在 ChromaDB 中创建一个新的集合。 +- `do_drop_kb` 方法删除知识库,即删除 ChromaDB 中的集合。 +- `do_search` 方法执行文档搜索,返回与查询最相关的文档列表和它们的得分。 +- `do_add_doc` 方法向知识库添加文档,包括文档的文本、嵌入向量和元数据。 +- `get_doc_by_ids` 和 `del_doc_by_ids` 方法分别根据文档 ID 获取文档和删除文档。 +- `do_clear_vs` 方法清空向量存储,通过删除并重新创建集合来实现。 +- `do_delete_doc` 方法根据提供的知识文件删除文档。 + +**注意**: +- 在使用 ChromaKBService 之前,需要确保 ChromaDB 环境已经正确设置并可用。 +- 在调用 `do_add_doc` 方法添加文档时,需要确保文档数据包含有效的文本、嵌入向量和元数据。 +- 删除操作(`do_drop_kb`、`del_doc_by_ids`、`do_delete_doc`)应谨慎使用,以避免意外丢失数据。 + +**输出示例**: +```python +# 搜索文档的示例输出 +[ + (Document(text="文档内容示例", metadata={"author": "作者示例"}), 0.95), + (Document(text="另一个文档内容示例", metadata={"author": "另一个作者示例"}), 0.90) +] +``` +这个示例展示了执行文档搜索操作后,可能返回的文档列表和它们的相关性得分。每个元组包含一个 Document 实例和一个得分,Document 实例包含文档的文本和元数据。 +### FunctionDef vs_type(self) +**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。 + +**参数**: 该函数没有参数。 + +**代码描述**: vs_type函数是ChromaKBService类的一个方法,它的作用是指明该知识库服务实例支持的向量存储类型。在这个具体实现中,vs_type方法通过返回SupportedVSType枚举类中的CHROMADB值,明确表示ChromaKBService支持ChromaDB作为其向量存储服务。SupportedVSType枚举类定义了一系列项目中支持的向量存储类型,包括但不限于FAISS、MILVUS、ZILLIZ、PostgreSQL、Elasticsearch等,其中CHROMADB代表使用ChromaDB作为向量存储服务。这种设计允许知识库服务在项目中以一种灵活的方式来指定和使用不同的向量存储解决方案,同时也便于在KBServiceFactory中根据需要动态选择和实例化相应的知识库服务实现。 + +**注意**: +- 在使用vs_type方法时,开发者不需要传递任何参数,该方法将自动返回ChromaKBService所支持的向量存储类型。 +- 返回的向量存储类型应与SupportedVSType枚举类中定义的类型一致,以确保知识库服务的正确实例化和使用。 +- 当扩展项目以支持新的向量存储服务时,应在SupportedVSType枚举类中添加新的类型,并确保知识库服务类正确实现vs_type方法以反映这一变化。 + +**输出示例**: +```python +'chromadb' +``` +在这个示例中,vs_type方法将返回一个字符串'chromadb',表示ChromaKBService类支持使用ChromaDB作为其向量存储服务。 +*** +### FunctionDef get_vs_path(self) +**get_vs_path**: 此函数的功能是获取向量空间的路径。 + +**参数**: 此函数没有显式参数,但依赖于对象的`kb_name`和`embed_model`属性。 + +**代码描述**: `get_vs_path`函数是`ChromaKBService`类的一个方法,用于返回知识库的向量空间路径。它通过调用全局函数`get_vs_path`实现,该全局函数接受两个参数:知识库名称(`kb_name`)和嵌入模型(`embed_model`)。这两个参数是`ChromaKBService`对象的属性,分别代表当前知识库的名称和使用的嵌入模型。此方法的返回值是一个字符串,表示向量空间的文件路径。 + +在项目中,`get_vs_path`方法被`do_init`方法调用。在`do_init`方法中,首先通过调用`get_kb_path`获取知识库的路径,然后调用`get_vs_path`获取向量空间的路径,并使用此路径初始化`PersistentClient`对象。这表明`get_vs_path`方法在知识库初始化过程中起到了关键作用,它确保了向量空间的路径可以被正确获取并用于后续的数据库客户端和集合的创建。 + +**注意**: 使用`get_vs_path`方法时,需要确保`ChromaKBService`对象的`kb_name`和`embed_model`属性已经被正确设置,因为这两个属性直接影响向量空间路径的生成。 + +**输出示例**: 假设知识库名称为`example_kb`,嵌入模型为`model_v1`,则`get_vs_path`可能返回的路径示例为`/path/to/vector_space/example_kb_model_v1.vs`。 +*** +### FunctionDef get_kb_path(self) +**get_kb_path**: 此函数的功能是获取知识库的路径。 + +**参数**: 此函数没有参数。 + +**代码描述**: `get_kb_path` 函数是 `ChromaKBService` 类的一个方法,它的主要作用是返回知识库的路径。这个方法通过调用 `get_kb_path` 函数,并传递 `self.kb_name` 作为参数,来实现这一功能。在这里,`self.kb_name` 是 `ChromaKBService` 类的一个属性,它存储了当前知识库的名称。通过这种方式,`get_kb_path` 方法能够根据知识库的名称动态地获取其路径。 + +在项目中,`get_kb_path` 方法被 `do_init` 方法调用。在 `do_init` 方法中,首先通过调用 `get_kb_path` 方法来获取知识库路径,并将其存储在 `self.kb_path` 属性中。这一步骤是初始化过程的一部分,确保了后续操作能够基于正确的知识库路径进行。此外,`do_init` 方法还涉及到获取视图存储路径和初始化持久化客户端等操作,这些都是基于知识库服务正常运行所必需的步骤。 + +**注意**: 在使用 `get_kb_path` 方法时,需要确保 `self.kb_name` 已经被正确赋值,因为这将直接影响到获取路径的结果。 + +**输出示例**: 假设当前知识库的名称为 "example_kb",那么 `get_kb_path` 方法的返回值可能看起来像这样: +``` +"/path/to/knowledge_bases/example_kb" +``` +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化ChromaKBService对象。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_init`方法是`ChromaKBService`类的一个关键方法,负责初始化知识库服务的核心组件。这个方法首先调用`get_kb_path`方法来获取知识库的路径,并将这个路径存储在`self.kb_path`属性中。接着,它调用`get_vs_path`方法来获取向量空间的路径,并将这个路径用于初始化`PersistentClient`对象,该对象存储在`self.client`属性中。最后,通过`self.client`的`get_or_create_collection`方法,使用`self.kb_name`属性(即知识库的名称)来获取或创建一个集合,并将这个集合对象存储在`self.collection`属性中。 + +从功能上看,`do_init`方法通过组合`get_kb_path`和`get_vs_path`方法的功能,确保了知识库服务可以正确地访问知识库路径和向量空间路径。这两个路径对于后续的知识库操作至关重要,因为它们分别确定了知识库数据的存储位置和向量空间数据的存储位置。通过`PersistentClient`对象,`do_init`方法进一步确保了知识库服务能够进行持久化操作,如数据的存储和检索。此外,`self.collection`的初始化为知识库中数据的管理提供了基础,使得数据的增删查改操作可以在此基础上进行。 + +**注意**: 在调用`do_init`方法之前,需要确保`ChromaKBService`对象的`kb_name`和`embed_model`属性已经被正确设置,因为这些属性会影响到`get_vs_path`方法的执行结果,进而影响到整个知识库服务的初始化过程。此外,`do_init`方法的成功执行是后续所有知识库操作能够正常进行的前提,因此在知识库服务的启动流程中,这个方法的调用是不可或缺的一步。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是在ChromaDB中创建一个知识库(KB)。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `do_create_kb`函数是`ChromaKBService`类的一个方法,用于在ChromaDB中创建一个新的知识库。在ChromaDB中,知识库的概念与集合(collection)相对应。因此,此函数的主要任务是创建或获取一个与知识库名称(`self.kb_name`)相对应的集合。这一过程通过调用`self.client.get_or_create_collection(self.kb_name)`实现,其中`self.client`是指向ChromaDB客户端的引用,而`self.kb_name`则是需要创建或获取的集合的名称。如果指定名称的集合已经存在,则此操作将返回现有集合的引用;如果不存在,则创建一个新的集合并返回其引用。操作完成后,集合的引用被存储在`self.collection`属性中,以便后续操作可以使用。 + +**注意**: 使用`do_create_kb`方法时,需要确保`self.client`已经正确初始化并且可以连接到ChromaDB服务器。此外,`self.kb_name`应该是一个有效的集合名称,遵循ChromaDB对集合名称的任何限制或规则。在调用此方法之前,最好确认这些条件已经满足,以避免运行时错误。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是删除ChromaDB中的一个集合。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_drop_kb`函数负责在ChromaDB数据库中删除一个名为`kb_name`的集合。这个过程首先尝试通过调用`self.client.delete_collection`方法来实现,其中`self.kb_name`作为参数传递,指定了要删除的集合的名称。如果在删除过程中遇到`ValueError`异常,并且异常信息不是因为集合不存在(即错误信息不是"Collection {self.kb_name} does not exist."),那么这个异常将会被重新抛出,以便调用者可以处理这个异常情况。这种设计确保了只有在遇到预期之外的错误时,才会中断程序的执行,而对于集合不存在这种可能预期的情况,则不会影响程序的继续执行。 + +在项目中,`do_drop_kb`函数被`do_clear_vs`函数调用,作为清空向量存储的一部分操作。在`do_clear_vs`函数中,调用`do_drop_kb`可以理解为在清空向量存储之前,先删除对应的集合,这可能是因为在某些情况下,直接删除集合比尝试清空其内容来得更为高效或者更符合业务逻辑。 + +**注意**: 在使用`do_drop_kb`函数时,需要确保`self.kb_name`已经正确设置为目标集合的名称,并且调用者应当准备好处理可能抛出的`ValueError`异常,特别是在集合可能不存在的情况下。此外,考虑到删除集合是一个不可逆的操作,应当谨慎使用此函数,确保其调用是在适当的上下文中,并且符合业务逻辑的需求。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 该函数的功能是执行文本查询,并返回与查询最相关的文档及其相关性分数。 + +**参数**: +- `query`: 需要进行搜索的查询文本,数据类型为字符串。 +- `top_k`: 返回的最相关文档的数量,数据类型为整数。 +- `score_threshold`: 相关性分数的阈值,默认为SCORE_THRESHOLD,只有分数高于此阈值的文档才会被返回,数据类型为浮点数。 + +**代码描述**: +`do_search`函数首先通过`EmbeddingsFunAdapter`类的实例化,使用`self.embed_model`作为嵌入模型来创建一个嵌入函数`embed_func`。然后,使用`embed_func.embed_query(query)`方法将查询文本`query`转换为嵌入向量`embeddings`。这一步骤是通过将文本转换为向量化表示,以便后续进行相似度计算。 + +接下来,函数调用`self.collection.query`方法,传入查询嵌入向量`embeddings`和结果数量`n_results`等于`top_k`,执行查询操作。此方法返回一个`QueryResult`对象,包含了查询的结果。 + +最后,函数调用`_results_to_docs_and_scores(query_result)`,将查询结果转换为文档和分数的列表。这一步骤通过解析`QueryResult`对象,提取出每个文档及其与查询文本的相似度分数,然后将这些信息封装成元组列表返回。 + +在整个过程中,`do_search`函数通过与`EmbeddingsFunAdapter`和`_results_to_docs_and_scores`等函数的交互,实现了从文本查询到获取相关文档及其分数的完整流程。 + +**注意**: +- 确保`query`参数是有效的查询文本,且`top_k`参数正确设置以返回期望数量的结果。 +- 函数的性能和准确性依赖于嵌入模型的质量和查询处理机制,因此选择合适的嵌入模型和调整查询参数对于获得有用的搜索结果至关重要。 +- 默认的`score_threshold`是SCORE_THRESHOLD,可以根据需要调整以过滤掉低相关性的结果。 + +**输出示例**: +```python +[ + (Document(page_content="文档内容1", metadata={"作者": "张三"}), 0.95), + (Document(page_content="文档内容2", metadata={"作者": "李四"}), 0.89) +] +``` +此输出示例展示了函数返回值的可能形式,其中包含了两个元组,每个元组都包含一个`Document`对象和一个表示与查询相似度的分数。这样的输出格式便于后续处理和展示搜索结果。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 该函数的功能是将文档列表添加到数据库中,并返回包含文档ID和元数据的信息列表。 + +**参数**: +- `docs`: 需要添加到数据库的文档对象列表,类型为`List[Document]`。 +- `**kwargs`: 接受可变数量的关键字参数,用于扩展或自定义功能。 + +**代码描述**: +`do_add_doc`函数首先调用`_docs_to_embeddings`私有方法,将文档对象列表转化为向量化的数据,包括文本内容、向量化结果和元数据。这一步是为了准备将文档存储到向量数据库中,便于后续的检索和分析操作。 + +接下来,函数为每个文档生成一个唯一的ID(使用`uuid.uuid1()`方法),并通过遍历每个文档的向量化数据,调用`collection.add`方法将文档的ID、向量化结果、元数据和文本内容添加到数据库的集合中。每次添加操作后,函数会将文档的ID和元数据收集到`doc_infos`列表中。 + +最后,函数返回`doc_infos`列表,其中包含了每个添加到数据库中的文档的ID和元数据信息,为后续的文档管理和检索提供了便利。 + +**注意**: +- 确保传入的`docs`参数是有效的文档对象列表,且每个文档对象都应包含必要的内容和元数据。 +- `_docs_to_embeddings`方法依赖于特定的文档向量化模型,因此在使用`do_add_doc`函数之前,应确保相关的向量化模型已经被正确设置和初始化。 +- 生成的文档ID是基于时间戳的UUID,保证了每个文档的唯一性。 + +**输出示例**: +调用`do_add_doc(docs=[Document1, Document2])`可能会返回如下列表: +```python +[ + {"id": "文档1的UUID", "metadata": {"title": "文档1标题"}}, + {"id": "文档2的UUID", "metadata": {"title": "文档2标题"}} +] +``` +这个列表包含了每个添加到数据库中的文档的唯一ID和元数据信息,便于后续的文档管理和检索操作。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 该函数的功能是根据一组ID从数据库中查询并返回对应的文档对象列表。 + +**参数**: +- `ids`: `List[str]`类型,表示需要查询的文档ID列表。 + +**代码描述**: +`get_doc_by_ids`方法是`ChromaKBService`类的一部分,负责根据给定的ID列表从数据库中检索文档。该方法首先调用集合的`get`方法,传入ID列表作为参数,以从数据库中获取对应的文档数据。获取的结果是`GetResult`类型,随后该方法调用`_get_result_to_documents`函数,将`GetResult`类型的查询结果转换为`Document`对象列表。 + +`_get_result_to_documents`函数详细处理了如何从`GetResult`类型的查询结果中提取文档内容和元数据,并将它们封装成`Document`对象。这一过程包括检查查询结果中的`documents`和`metadatas`字段,确保每个文档都能正确地与其元数据对应,并最终生成一个包含所有查询到的文档的`Document`对象列表。 + +通过这种方式,`get_doc_by_ids`方法能够提供一个高效且方便的接口,用于根据文档ID查询并获取文档内容及其元数据,进而支持后续的文档处理或响应客户端请求。 + +**注意**: +- 传入的ID列表应确保有效,以避免查询不到文档或产生异常。 +- 该方法依赖于`_get_result_to_documents`函数正确处理查询结果,因此需要保证`GetResult`类型的数据结构与预期匹配。 + +**输出示例**: +```python +[ + Document(page_content="文档内容1", metadata={"作者": "张三"}), + Document(page_content="文档内容2", metadata={"作者": "李四"}) +] +``` +此示例展示了当根据给定的ID列表查询数据库并处理结果时,`get_doc_by_ids`方法可能返回的`Document`对象列表的形态。每个`Document`对象包含了文档的内容(`page_content`)和元数据(`metadata`)。 +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 此函数的功能是根据提供的ID列表删除数据库中的文档。 + +**参数**: +- ids: 一个字符串列表,包含要删除的文档的ID。 + +**代码描述**: +`del_doc_by_ids`函数接受一个参数`ids`,这是一个字符串列表,每个字符串代表一个需要从数据库中删除的文档的ID。函数内部调用`self.collection.delete`方法,将`ids`作为参数传递给该方法,以便删除对应的文档。完成删除操作后,函数返回`True`,表示文档已成功删除。 + +**注意**: +- 确保传递给`del_doc_by_ids`函数的`ids`列表中的每个ID都是有效且存在于数据库中的,否则可能会导致删除操作失败或不完全。 +- 此函数总是返回`True`,即使某些ID可能因为不存在而没有被实际删除。因此,调用者可能需要额外的逻辑来验证删除操作的实际效果。 + +**输出示例**: +由于此函数返回的是一个布尔值,因此调用`del_doc_by_ids(['123', '456'])`后,预期的返回值为: +``` +True +``` +这表示指定的文档已被成功删除。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是清空向量存储。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_clear_vs`函数是ChromaKBService类中的一个方法,其主要作用是清空向量存储。在实现上,它通过调用`do_drop_kb`方法来达到清空向量存储的目的。根据`do_drop_kb`方法的文档描述,我们知道`do_drop_kb`的功能是删除ChromaDB中的一个集合。因此,`do_clear_vs`通过删除集合的方式来清空向量存储,这可能是因为直接删除集合比尝试清空其内容来得更为高效或者更符合业务逻辑。在调用`do_drop_kb`时,会尝试删除一个名为`kb_name`的集合,如果在删除过程中遇到`ValueError`异常,并且异常信息不是因为集合不存在,则这个异常将会被重新抛出。这种设计确保了只有在遇到预期之外的错误时,才会中断程序的执行。 + +**注意**: 在使用`do_clear_vs`函数时,需要确保`self.kb_name`已经正确设置为目标集合的名称。此外,考虑到删除集合是一个不可逆的操作,应当谨慎使用此函数,确保其调用是在适当的上下文中,并且符合业务逻辑的需求。由于`do_clear_vs`函数的实现依赖于`do_drop_kb`,因此在使用`do_clear_vs`时也应当准备好处理可能由`do_drop_kb`抛出的`ValueError`异常,特别是在集合可能不存在的情况下。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数用于删除知识库中的指定文件。 + +**参数**: +- `kb_file`: KnowledgeFile对象,代表要删除的知识库文件。 +- `**kwargs`: 接收额外的关键字参数,可用于扩展功能或传递额外信息。 + +**代码描述**: +`do_delete_doc`函数是`ChromaKBService`类的一个方法,负责从知识库中删除指定的文件。该方法接收一个`KnowledgeFile`对象作为参数,该对象包含了要删除文件的详细信息,包括文件的路径等。函数内部通过调用`self.collection.delete`方法来执行删除操作,其中`where`参数用于指定删除条件,本例中以文件的路径(`kb_file.filepath`)作为删除的依据。 + +在项目的层次结构中,`KnowledgeFile`对象由`server/knowledge_base/utils.py`中定义,它封装了与知识库文件相关的信息和操作。`do_delete_doc`方法通过使用这个对象,可以精确地定位并操作知识库中的特定文件,实现了文件的删除功能。 + +此方法的实现依赖于`collection`对象的`delete`方法,该方法是对数据库操作的抽象,允许通过指定条件来删除记录。在本项目中,`collection`很可能代表了一个封装了数据库操作的类实例,用于管理知识库中的数据记录。 + +**注意**: +- 在调用`do_delete_doc`方法时,需要确保传入的`kb_file`对象有效,并且其`filepath`属性正确指向了要删除的文件路径。 +- 该方法的执行结果依赖于`collection.delete`方法的实现,因此在不同的数据库或数据存储方案中,其具体行为可能会有所不同。 +- 删除操作是不可逆的,因此在执行前应确保文件确实不再需要,以避免数据丢失。 + +**输出示例**: +由于`do_delete_doc`方法的主要作用是从数据库中删除记录,其返回值取决于`collection.delete`方法的实现。通常,该方法可能会返回一个表示删除操作结果的对象或布尔值。例如,如果删除成功,可能会返回`True`或者一个包含删除成功信息的对象;如果删除失败,可能会返回`False`或者一个包含错误信息的对象。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/default_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/default_kb_service.md new file mode 100644 index 000000000..35a4e9602 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/default_kb_service.md @@ -0,0 +1,138 @@ +## ClassDef DefaultKBService +**DefaultKBService**: DefaultKBService 类是用于提供默认的知识库服务实现。 + +**属性**: +此类继承自KBService,因此继承了KBService的所有属性,包括知识库名称(kb_name)、知识库信息(kb_info)、嵌入模型名称(embed_model)、知识库路径(kb_path)和文档路径(doc_path)等。 + +**代码描述**: +DefaultKBService 类是KBService的一个具体实现,提供了对知识库的基本操作,包括创建知识库、删除知识库、向知识库添加文档、清空知识库、获取知识库类型、初始化知识库、搜索知识库、批量插入知识、单个插入知识和删除文档等方法。这些方法在DefaultKBService中大多以空方法(pass)的形式存在,意味着需要由继承DefaultKBService的子类来具体实现这些方法的功能。 + +DefaultKBService通过继承KBService类,确保了与其他知识库服务实现相同的接口,这样做的目的是为了提供一种默认的知识库服务实现,方便在没有指定具体知识库服务类型时使用。 + +**注意**: +- DefaultKBService类本身大多数方法未具体实现(使用pass),需要通过继承此类并重写这些方法来提供具体的功能。 +- 在使用DefaultKBService或其子类时,需要确保已经正确配置了知识库的相关信息,如知识库名称、嵌入模型名称等。 +- DefaultKBService类的实例化通常由KBServiceFactory类的get_service方法根据配置动态完成,而不是直接在代码中实例化。 + +**输出示例**: +由于DefaultKBService类的方法大多未具体实现,因此没有直接的输出示例。具体的输出将取决于继承DefaultKBService的子类以及这些子类实现的方法。例如,如果子类实现了do_search方法,那么搜索文档的输出示例可能如下: +```python +[ + {"id": "doc1", "text": "文档1的内容", "score": 0.95}, + {"id": "doc2", "text": "文档2的内容", "score": 0.90} +] +``` +这表示在执行搜索操作时,返回了两个文档及其相关性得分。 +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是创建知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_create_kb` 函数是 `DefaultKBService` 类的一个方法,旨在创建一个知识库。在当前的代码实现中,此函数体为空,这意味着它尚未实现具体的功能。在实际应用中,开发者需要在此函数中添加创建知识库的逻辑,例如初始化知识库的结构,存储知识库的数据,或者配置知识库的相关设置等。此函数作为一个框架或者占位符存在,供将来扩展和具体实现使用。 + +**注意**: 使用此函数时,需要注意以下几点: +- 由于当前函数体为空,直接调用此函数不会有任何效果。开发者需要根据具体需求,实现知识库的创建逻辑。 +- 在实现函数逻辑时,应考虑知识库的安全性、可扩展性和性能等因素,确保知识库的稳定和高效运行。 +- 如果项目中已经有现成的知识库服务或框架,开发者应评估是否直接使用或扩展现有服务,以避免重复工作和提高开发效率。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是删除知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_drop_kb` 函数是 `DefaultKBService` 类的一个方法,用于实现知识库的删除操作。在当前的代码实现中,此函数体为空(使用了 `pass` 语句),这意味着它没有执行任何操作。在实际应用中,开发者需要在此函数中添加逻辑来实现知识库的具体删除操作,例如从数据库中删除知识库相关的数据或清理知识库使用的资源等。 + +**注意**: 虽然当前的实现为空,但开发者在使用此函数时应当注意,删除知识库是一个重要操作,可能会对系统中存储的数据产生不可逆的影响。因此,在实现和调用此函数时,应确保有充分的权限检查和必要的数据备份机制,以防止数据丢失或错误删除。此外,考虑到操作的敏感性,可能还需要实现相应的日志记录功能,以便于问题的追踪和审计。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 此函数的功能是向知识库中添加文档。 + +**参数**: +- `docs`: 需要添加到知识库中的文档列表,类型为`List[Document]`。 + +**代码描述**: +`do_add_doc`函数是`DefaultKBService`类的一个方法,旨在实现将一系列文档(`docs`)添加到知识库中的功能。该方法接受一个参数`docs`,这是一个`Document`对象的列表。每个`Document`对象代表了一个需要被添加到知识库的文档。 + +在当前的代码实现中,`do_add_doc`方法的具体逻辑尚未实现,仅提供了方法的定义和参数接收的框架。这意味着,如果你需要使用这个方法来向知识库添加文档,你需要在此基础上实现具体的添加文档到知识库的逻辑。 + +**注意**: +- 在实际使用`do_add_doc`方法之前,需要确保每个`Document`对象都已经正确构造,并包含了所有必要的信息,以便能够被成功添加到知识库中。 +- 由于当前的实现是空的,调用此方法不会有任何实际效果,直到你实现了添加文档到知识库的具体逻辑。 +- 在实现具体逻辑时,需要考虑如何处理文档添加过程中可能出现的异常情况,例如文档格式不正确或添加到知识库失败等。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是清除视图状态。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_clear_vs`函数是`DefaultKBService`类的一个成员方法,目前其内部实现为空,即该方法被调用时不会执行任何操作。在`DefaultKBService`类中,此方法可能被设计为用于清除或重置与知识库服务相关的某些视图状态,但具体的实现细节尚未提供。这种设计通常用于在需要时重置服务的状态,或者在某些操作完成后清理资源。 + +**注意**: 虽然当前`do_clear_vs`方法的实现为空,但开发者在使用此方法时应注意其未来可能的更新或实现。在调用此方法之前,建议检查相关的文档或更新日志,以了解其最新的功能和使用方式。此外,由于该方法目前不执行任何操作,开发者应避免在生产环境中不必要地调用它,以免在未来的版本中引入潜在的副作用或性能问题。 +*** +### FunctionDef vs_type(self) +**vs_type函数功能**: 返回当前知识库服务的类型。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `vs_type`函数是`DefaultKBService`类的一个方法,用于标识当前使用的知识库服务类型。在这个上下文中,它被设计为返回一个字符串值`"default"`,意味着如果没有特别指定,将使用默认的知识库服务类型。这个设计允许在系统中可能存在多种知识库服务类型时,能够灵活地指定和使用不同的服务类型。通过返回一个明确的字符串标识符,系统的其他部分可以根据这个标识符来决定如何与知识库服务交互。 + +**注意**: 在使用`vs_type`方法时,需要注意它是如何与系统中其他部分的逻辑配合工作的。因为它返回一个固定的字符串值,如果系统扩展了更多的知识库服务类型,可能需要更新此方法以反映新的服务类型。 + +**输出示例**: +```python +"default" +``` +这个输出示例展示了调用`vs_type`方法时会收到的返回值。在当前的实现中,每次调用此方法都会返回字符串`"default"`,表示使用默认的知识库服务类型。 +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化DefaultKBService类的实例。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_init`函数是`DefaultKBService`类中的一个方法,目前其内部实现为空,即没有执行任何操作。这通常意味着该方法是为了将来的扩展而预留的,或者作为一个接口的一部分,具体的实现将在子类中完成。在面向对象编程中,这样的设计允许开发者在不修改现有代码的情况下,通过继承和重写方法来扩展功能。 + +**注意**: 虽然当前`do_init`方法没有执行任何操作,但在将来的开发中,如果需要对`DefaultKBService`类的实例进行初始化设置,比如配置参数的加载、资源的分配等,都可以在此方法中实现。因此,开发者在使用`DefaultKBService`类时,应当注意到`do_init`方法可能会在未来包含重要的初始化逻辑,应当在创建实例后调用它,以确保对象正确地被初始化。 +*** +### FunctionDef do_search(self) +**do_search**: 此函数的功能是执行搜索操作。 + +**参数**: 此函数目前没有定义任何参数。 + +**代码描述**: `do_search` 函数是 `DefaultKBService` 类的一个成员方法,旨在实现搜索功能。根据函数体的实现,当前此函数体为空,即它未执行任何操作。这通常意味着该函数是一个待实现的功能桩,预留给开发者后续根据具体需求实现搜索逻辑。在实际应用中,开发者可能需要根据特定的搜索需求,如关键词搜索、模糊搜索或其他高级搜索功能,来填充此函数体。例如,可以通过查询数据库、调用外部搜索服务或应用搜索算法来实现具体的搜索逻辑。 + +**注意**: 虽然当前 `do_search` 函数未具体实现任何逻辑,但在将来的开发中,开发者应确保为其添加适当的参数和返回值,以满足搜索功能的需求。此外,考虑到性能和准确性是搜索功能的关键,开发时应注意优化搜索算法和处理大量数据的能力。在实现具体逻辑之前,建议先定义好函数的输入输出规范,以及可能涉及的错误处理机制。 +*** +### FunctionDef do_insert_multi_knowledge(self) +**do_insert_multi_knowledge**: 此函数的功能是批量插入多条知识数据。 + +**参数**: 此函数目前不接受任何参数。 + +**代码描述**: `do_insert_multi_knowledge` 函数是 `DefaultKBService` 类的一个方法,设计用于处理批量插入知识数据的操作。当前,该函数的实现为空(使用了 `pass` 语句),这意味着它尚未实现具体的功能。在未来的开发中,此函数可能会被扩展以接受参数,如知识数据列表,并将这些数据批量插入到知识库中。这种批量插入操作通常比单条插入更高效,特别是当需要向知识库中添加大量数据时。 + +**注意**: +- 由于当前 `do_insert_multi_knowledge` 函数的实现为空,调用此函数不会产生任何效果。开发者在使用此函数之前需要实现具体的插入逻辑。 +- 在实现批量插入逻辑时,需要考虑到数据的一致性和事务管理,确保数据的准确性和完整性。 +- 开发者在扩展此函数以实现具体功能时,应考虑到性能优化,例如,使用批处理技术减少数据库访问次数,提高数据插入效率。 +- 此函数在未来可能会更新以接受参数和返回值,开发者在使用时应关注相关文档的更新,以便正确使用。 +*** +### FunctionDef do_insert_one_knowledge(self) +**do_insert_one_knowledge**: 此函数的功能是插入单条知识记录。 + +**参数**: 此函数目前不接受任何参数。 + +**代码描述**: `do_insert_one_knowledge` 函数是 `DefaultKBService` 类的一个成员方法,旨在向知识库中插入一条新的知识记录。当前版本的函数体为空,这意味着它尚未实现具体的插入逻辑。在未来的版本中,此函数可能会被扩展以包含与数据库交互的代码,用于实际将知识记录插入到后端存储系统中。这可能涉及到构造数据库查询、处理数据模型以及管理数据库连接和事务等操作。 + +**注意**: +- 由于当前函数体为空,调用此函数不会产生任何效果。开发者在使用此函数时需要注意其实现状态,避免在生产环境中直接使用尚未完成的功能。 +- 在未来的实现中,开发者可能需要关注函数参数的设计,以便能够灵活地传递要插入的知识记录数据。 +- 此外,考虑到数据的一致性和完整性,实现此功能时可能需要处理错误和异常情况,确保知识记录的正确插入。 +*** +### FunctionDef do_delete_doc(self) +**do_delete_doc**: 此函数的功能是删除文档。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_delete_doc` 函数是 `DefaultKBService` 类的一个方法,目前其内部实现为空,即函数体中没有任何执行代码。这通常意味着该方法是一个待实现的功能占位符,或者在当前版本的代码中,删除文档的具体逻辑尚未被定义。在面向对象编程中,这种做法常用于定义接口或抽象类,预留方法供子类实现具体功能。然而,根据此函数所在的上下文——位于`default_kb_service.py`文件中的`DefaultKBService`类,我们可以推断`do_delete_doc`方法旨在提供一个删除知识库中特定文档的功能。在未来的版本中,开发者可能会在此方法中添加代码来实现从数据库或存储系统中删除特定文档的逻辑。 + +**注意**: 虽然当前`do_delete_doc`方法的实现为空,但在使用此方法之前,开发者应确保理解其预期的功能和实现逻辑。如果你是负责扩展或维护`DefaultKBService`类的开发者,那么在实现`do_delete_doc`方法时,需要考虑如何安全有效地从你的知识库服务中删除数据,包括处理可能的依赖关系和确保数据一致性等问题。此外,考虑到数据的重要性,实现删除功能时应提供充分的错误处理和日志记录,以便跟踪和恢复意外删除的数据。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/es_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/es_kb_service.md new file mode 100644 index 000000000..a8c59d70d --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/es_kb_service.md @@ -0,0 +1,282 @@ +## ClassDef ESKBService +**ESKBService**: ESKBService 类用于实现基于 Elasticsearch 的知识库服务。 + +**属性**: +- `kb_path`: 知识库路径。 +- `index_name`: Elasticsearch 索引名称。 +- `IP`: Elasticsearch 服务的 IP 地址。 +- `PORT`: Elasticsearch 服务的端口号。 +- `user`: 连接 Elasticsearch 服务的用户名。 +- `password`: 连接 Elasticsearch 服务的密码。 +- `dims_length`: 向量的维度。 +- `embeddings_model`: 本地加载的嵌入模型。 +- `es_client_python`: Elasticsearch 的 Python 客户端实例。 +- `db_init`: 用于初始化和创建索引的 ElasticsearchStore 实例。 + +**代码描述**: +ESKBService 类继承自 KBService 类,专门用于操作和管理基于 Elasticsearch 的知识库。它提供了一系列方法来初始化服务、创建知识库、添加文档、删除文档、搜索文档等。 + +- `do_init` 方法用于初始化 Elasticsearch 客户端,包括连接到 Elasticsearch 服务、创建索引等。 +- `get_kb_path` 和 `get_vs_path` 静态方法用于获取知识库路径和向量存储路径。 +- `do_create_kb` 方法用于创建知识库,如果知识库路径不存在,则创建之。 +- `vs_type` 方法返回支持的向量存储类型,即 Elasticsearch。 +- `_load_es` 方法用于将文档加载到 Elasticsearch 中。 +- `do_search` 方法用于执行文本相似性搜索。 +- `get_doc_by_ids` 方法根据文档 ID 获取文档。 +- `del_doc_by_ids` 方法根据文档 ID 删除文档。 +- `do_delete_doc` 方法用于从知识库中删除指定的文档。 +- `do_add_doc` 方法用于向知识库添加文档。 +- `do_clear_vs` 方法用于从知识库中删除所有向量。 +- `do_drop_kb` 方法用于删除整个知识库。 + +**注意**: +- 在使用 ESKBService 类之前,需要确保 Elasticsearch 服务已经启动并可访问。 +- 用户名和密码是可选的,如果 Elasticsearch 服务没有设置认证,可以不提供。 +- 创建索引时,需要指定向量的维度,这对于后续的向量搜索非常重要。 + +**输出示例**: +由于 ESKBService 类主要与 Elasticsearch 交互,它的方法通常不直接返回具体的输出,而是影响 Elasticsearch 中的数据。例如,`do_add_doc` 方法成功执行后,将在 Elasticsearch 中创建或更新文档,但不会返回具体的输出。搜索方法 `do_search` 可能会返回如下格式的文档列表: +```python +[ + {"id": "doc1", "text": "文档1的内容", "score": 0.95}, + {"id": "doc2", "text": "文档2的内容", "score": 0.90} +] +``` +这表示在执行搜索操作时,返回了两个文档及其相关性得分。 +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化ESKBService类的实例,包括配置知识库路径、索引名称、连接Elasticsearch服务的参数以及加载本地嵌入模型。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `do_init` 方法首先通过调用 `get_kb_path` 方法获取知识库的完整路径,并从该路径中提取索引名称。然后,它根据 `vs_type` 方法返回的向量存储类型,从配置文件中获取Elasticsearch服务的主机地址、端口、用户、密码和向量维度长度。接着,`do_init` 方法使用 `load_local_embeddings` 函数加载本地嵌入模型,以支持后续的向量搜索功能。 + +此外,`do_init` 方法尝试建立与Elasticsearch服务的连接。如果提供了用户名和密码,则使用基本认证;否则,发出警告并尝试无认证连接。连接成功后,尝试创建Elasticsearch索引,如果遇到BadRequestError异常,则记录错误信息。 + +最后,`do_init` 方法尝试通过 `ElasticsearchStore` 类的实例 `db_init` 初始化Elasticsearch连接和索引,这一步骤同样考虑了认证信息。如果在任何连接尝试中遇到 `ConnectionError` 或其他异常,将记录错误信息并抛出异常。 + +**注意**: +- 在调用 `do_init` 方法之前,确保已经正确配置了Elasticsearch服务的相关参数,包括主机地址、端口、用户、密码等。 +- `do_init` 方法在ESKBService类的实例化过程中自动调用,用于准备Elasticsearch服务的连接和配置,因此在使用ESKBService类之前不需要手动调用此方法。 +- 如果在连接Elasticsearch服务或创建索引时遇到问题,`do_init` 方法将记录错误信息并抛出异常,调用方应捕获并处理这些异常。 +- `do_init` 方法依赖于 `load_local_embeddings` 函数加载的本地嵌入模型,确保嵌入模型与Elasticsearch服务的向量搜索功能兼容。 +*** +### FunctionDef get_kb_path(knowledge_base_name) +**get_kb_path**: 此函数的功能是获取知识库的完整路径。 + +**参数**: +- knowledge_base_name: 字符串类型,代表知识库的名称。 + +**代码描述**: +`get_kb_path` 函数接受一个参数 `knowledge_base_name`,这是一个字符串,代表知识库的名称。函数使用 `os.path.join` 方法将 `KB_ROOT_PATH`(一个在代码中预定义的常量,代表知识库根目录的路径)与 `knowledge_base_name` 拼接,从而构造出该知识库的完整路径。这个函数在项目中被用于构建知识库路径,以便于其他操作(如初始化、索引创建等)能够在正确的位置进行。 + +在项目中,`get_kb_path` 函数被 `do_init` 方法调用,用于确定知识库的存储路径,并据此设置索引名称和其他与 Elasticsearch 服务相关的配置。此外,它还被 `get_vs_path` 方法调用,后者进一步在知识库路径的基础上添加 "vector_store" 子目录,用于特定的向量存储操作。这表明 `get_kb_path` 函数是连接知识库基础设施与 Elasticsearch 服务操作的关键环节。 + +**注意**: +- 确保 `KB_ROOT_PATH` 已经正确设置,且指向一个有效的文件系统路径,否则构建的知识库路径可能无效。 +- 在调用此函数之前,应确保传入的 `knowledge_base_name` 是唯一的,以避免路径冲突。 + +**输出示例**: +如果 `KB_ROOT_PATH` 设置为 "/data/knowledge_bases",且传入的 `knowledge_base_name` 为 "my_kb",则函数返回的路径将会是 "/data/knowledge_bases/my_kb"。 +*** +### FunctionDef get_vs_path(knowledge_base_name) +**get_vs_path**: 此函数的功能是获取知识库中向量存储的完整路径。 + +**参数**: +- knowledge_base_name: 字符串类型,代表知识库的名称。 + +**代码描述**: +`get_vs_path` 函数是用于构建知识库中向量存储位置的路径。它接受一个参数 `knowledge_base_name`,这是一个字符串,指定了知识库的名称。函数首先调用 `get_kb_path` 方法,该方法根据传入的知识库名称构建出知识库的根路径。然后,`get_vs_path` 函数使用 `os.path.join` 方法将这个根路径与 "vector_store" 字符串拼接,从而生成并返回向量存储的完整路径。 + +从功能角度来看,`get_vs_path` 函数与其调用的 `get_kb_path` 函数紧密相关。`get_kb_path` 提供了知识库的基础路径,而 `get_vs_path` 在此基础上进一步定位到知识库中用于存储向量数据的特定子目录。这种设计使得知识库的结构更加清晰,同时也便于管理和访问知识库中的向量数据。 + +**注意**: +- 在使用 `get_vs_path` 函数之前,应确保传入的知识库名称 `knowledge_base_name` 是准确且存在的,因为这将直接影响到向量存储路径的正确性。 +- 由于 `get_vs_path` 函数依赖于 `get_kb_path` 函数来获取知识库的根路径,因此需要保证 `get_kb_path` 函数能够正常工作,包括确保知识库根目录的路径(`KB_ROOT_PATH`)已经被正确设置。 + +**输出示例**: +假设知识库的根目录路径为 "/data/knowledge_bases",且传入的知识库名称为 "my_kb",那么 `get_vs_path` 函数将返回的路径将会是 "/data/knowledge_bases/my_kb/vector_store"。这个路径指向了 "my_kb" 知识库中用于存储向量数据的子目录。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是创建知识库所需的向量存储目录。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_create_kb` 函数首先检查文档路径(`self.doc_path`)是否存在。如果该路径存在,函数将继续检查知识库路径(`self.kb_path`)下是否存在名为 "vector_store" 的目录。如果 "vector_store" 目录不存在,则函数会在 `self.kb_path` 下创建该目录。如果 "vector_store" 目录已经存在,则会记录一条警告日志,提示目录已经存在。这个过程确保了知识库的向量存储目录被正确创建,以便后续操作可以在其中存储和管理知识库的向量数据。 + +**注意**: +- 确保在调用此函数之前,`self.doc_path` 和 `self.kb_path` 已经被正确设置,并且指向有效的文件系统路径。 +- 如果在创建 "vector_store" 目录时遇到文件系统权限问题,可能会导致目录创建失败。因此,确保应用程序具有足够的权限来创建和写入指定的路径。 +- 记录的警告信息可以帮助开发者了解知识库的当前状态,特别是在调试或者排查问题时。 +*** +### FunctionDef vs_type(self) +**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。 + +**参数**: 该函数不接受任何参数。 + +**代码描述**: vs_type函数是ESKBService类的一个方法,它的主要作用是指明Elasticsearch (ES) 作为向量存储服务。该函数通过返回SupportedVSType枚举类中的ES属性值来实现这一点。在ESKBService类中,vs_type方法的返回值被用于配置和初始化Elasticsearch客户端,包括连接信息、索引名称、认证信息等。此外,vs_type方法的返回值还决定了向量维度长度、嵌入模型等配置的获取。这意味着,通过vs_type方法,ESKBService类能够明确其向量存储服务的类型,并据此进行相应的初始化和配置。 + +**注意**: +- 在使用vs_type方法时,需要确保SupportedVSType枚举类中已定义了返回的向量存储类型,否则可能会影响知识库服务的初始化和配置。 +- vs_type方法的返回值直接影响到Elasticsearch客户端的配置,因此在修改该方法时应谨慎,以避免对知识库服务的正常操作产生不利影响。 + +**输出示例**: "es" +*** +### FunctionDef _load_es(self, docs, embed_model) +**_load_es**: 该函数的功能是将文档(docs)写入到Elasticsearch中。 + +**参数**: +- docs: 需要写入Elasticsearch的文档列表。 +- embed_model: 用于生成文档嵌入向量的模型。 + +**代码描述**: +`_load_es` 函数主要负责将一组文档(docs)通过嵌入模型(embed_model)处理后,写入到Elasticsearch数据库中。该函数首先检查是否提供了用户认证信息(用户名和密码),如果提供了,则使用这些信息来建立与Elasticsearch的安全连接。接着,根据是否提供了用户信息,选择相应的方式来初始化`ElasticsearchStore`对象,该对象负责将文档和它们的嵌入向量存储到指定的Elasticsearch索引中。在存储过程中,会设置一些参数,如索引名(`index_name`)、距离策略(`distance_strategy`)、查询字段(`query_field`)和向量查询字段(`vector_query_field`)等。 + +在存储文档到Elasticsearch的过程中,如果遇到连接错误(`ConnectionError`),会打印错误信息并记录日志。对于其他类型的异常,也会记录错误日志并打印异常信息。 + +该函数被`do_add_doc`方法调用,用于在向知识库添加文档的过程中,将文档写入Elasticsearch。`do_add_doc`方法首先打印待写入文档的数量,然后调用`_load_es`函数进行文档的写入操作。文档写入成功后,`do_add_doc`方法会继续执行一系列的操作,包括验证写入的文档是否能够被成功检索等。 + +**注意**: +- 确保在调用`_load_es`函数之前,`docs`参数中的文档已经准备好,并且`embed_model`模型能够正确生成文档的嵌入向量。 +- 在使用`_load_es`函数时,需要确保Elasticsearch服务是可用的,并且提供的用户认证信息(如果有的话)是正确的。 +- 该函数中捕获并处理了连接错误,但在实际使用中,还需要注意处理其他可能的异常情况,以确保系统的稳定性。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 此函数用于执行基于文本相似性的搜索。 + +**参数**: +- `query`: 字符串类型,表示搜索查询的文本。 +- `top_k`: 整型,指定返回的最相似文档数量。 +- `score_threshold`: 浮点型,设定的相似度分数阈值,用于过滤结果。 + +**代码描述**: +`do_search` 函数通过接收一个查询字符串 `query`、一个整数 `top_k` 和一个浮点数 `score_threshold` 作为参数,执行文本相似性搜索。它首先调用 `db_init` 对象的 `similarity_search_with_score` 方法,该方法根据提供的查询 `query` 和指定的返回文档数量 `k=top_k` 来检索最相似的文档。此方法返回一个包含文档的列表,这些文档根据与查询的相似度得分进行排序。 + +**注意**: +- 确保 `db_init` 已正确初始化并且可以访问相应的数据库或索引,以便执行相似性搜索。 +- `top_k` 应为正整数,表示需要返回的文档数量。 +- `score_threshold` 参数在此代码段中未直接使用,但可能在 `similarity_search_with_score` 方法内部用于过滤相似度得分低于某一阈值的文档。 + +**输出示例**: +```python +[ + {'doc_id': '123', 'score': 0.95}, + {'doc_id': '456', 'score': 0.93}, + ... +] +``` +此输出示例展示了一个可能的返回值,其中包含了文档的ID和与查询的相似度得分。返回的文档数量和具体得分取决于查询内容、`top_k` 的值以及数据库中存储的文档。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 此函数的功能是根据提供的文档ID列表从Elasticsearch中检索文档。 + +**参数**: +- `ids`: 一个字符串列表,包含需要检索的文档的ID。 + +**代码描述**: +`get_doc_by_ids` 函数接收一个文档ID列表作为输入参数,返回一个包含检索到的文档的列表。函数内部,通过遍历ID列表,使用Elasticsearch客户端的`get`方法根据每个ID检索文档。检索到的文档信息存储在变量`response`中,其中包含文档的源数据(`_source`)。函数假设每个文档包含`context`和`metadata`字段,分别用于存储文档的文本内容和元数据。如果检索成功,函数将创建一个`Document`对象,其中包含文档的文本内容和元数据,并将此对象添加到结果列表中。如果在检索过程中遇到异常,会通过日志记录错误信息,但不会中断整个检索过程。 + +**注意**: +- 函数假设Elasticsearch中的文档具有`context`和`metadata`字段。如果文档结构不同,需要相应地调整源代码中的字段名称。 +- 在检索文档时遇到的任何异常都会被捕获并记录日志,但不会导致函数终止执行。这意味着即使某些文档ID可能因为错误而未能检索到文档,函数仍会继续尝试检索其余的文档ID。 +- 函数返回的是一个`Document`对象列表,每个对象包含一个文档的文本内容和元数据。如果某个文档ID检索失败,该ID对应的文档将不会出现在返回的列表中。 + +**输出示例**: +假设有两个文档ID分别为"doc1"和"doc2",且这两个文档在Elasticsearch中成功检索到,函数可能返回如下列表: +```python +[ + Document(page_content="文档1的文本内容", metadata={"作者": "张三", "发布日期": "2023-01-01"}), + Document(page_content="文档2的文本内容", metadata={"作者": "李四", "发布日期": "2023-02-01"}) +] +``` +如果"doc2"的检索失败,那么返回的列表将只包含"doc1"对应的`Document`对象。 +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 此函数的功能是根据提供的文档ID列表删除Elasticsearch中的相应文档。 + +**参数**: +- `ids`: 一个字符串列表,包含要从Elasticsearch中删除的文档的ID。 + +**代码描述**: +`del_doc_by_ids`函数接收一个字符串列表`ids`作为参数,这个列表包含了需要从Elasticsearch索引中删除的文档的ID。函数遍历这个ID列表,对于列表中的每一个ID,它尝试使用`es_client_python.delete`方法从指定的索引`self.index_name`中删除对应的文档,并且设置`refresh=True`以确保删除操作立即生效。 + +如果在删除操作过程中遇到任何异常,函数会捕获这些异常并通过`logger.error`记录错误信息,包括异常的详细信息。这样做可以帮助开发者在出现问题时迅速定位和解决问题。 + +**注意**: +- 确保在调用此函数之前,`self.es_client_python`已经被正确初始化,并且已经设置了正确的索引名称`self.index_name`。 +- 删除操作会立即影响Elasticsearch索引的状态,因此请谨慎使用此函数,确保不会误删除重要文档。 +- 如果提供的ID列表中包含不存在于索引中的ID,对应的删除操作将会被忽略,不会影响其他有效删除操作的执行。 +- 异常处理机制确保了函数的健壮性,但开发者应注意检查日志文件以了解是否有删除操作失败的情况,并根据需要采取相应措施。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数的功能是从Elasticsearch索引中删除与给定知识库文件相关的文档。 + +**参数**: +- `kb_file`: 需要删除的知识库文件对象,此对象应包含一个`filepath`属性,该属性用于在Elasticsearch中定位相关文档。 +- `**kwargs`: 关键字参数,用于提供额外的配置选项,虽然在当前实现中未直接使用,但保留了扩展性。 + +**代码描述**: +此函数首先检查Elasticsearch中是否存在指定的索引。如果索引存在,它将构造一个查询,该查询使用`kb_file.filepath`作为关键字,查找所有与给定知识库文件路径匹配的文档。查询时,注意设置查询返回的文档数量`size`为50,这是为了确保能够找到所有相关的文档,而不是默认的前10个。 + +接下来,函数会从查询结果中提取文档的ID,并将这些ID存储在`delete_list`列表中。如果`delete_list`为空,即没有找到任何匹配的文档,函数将返回`None`。如果找到了匹配的文档,函数将遍历`delete_list`中的每个文档ID,并使用Elasticsearch的`delete`方法逐一删除这些文档。在删除过程中,如果遇到任何异常,将通过日志记录错误信息。 + +**注意**: +- 确保`kb_file`对象有一个有效的`filepath`属性,因为它是定位和删除Elasticsearch中文档的关键。 +- 删除操作会即时刷新索引(通过`refresh=True`参数),这可能会对性能有一定影响,特别是在处理大量文档时。请根据实际情况评估是否需要即时刷新。 +- 异常处理部分仅记录错误信息,不会中断程序执行。开发者需要关注日志输出,以便了解删除操作是否遇到问题。 + +**输出示例**: +此函数没有明确的返回值(在成功删除文档或没有找到匹配文档时返回`None`)。因此,函数的主要作用是执行操作,而不是返回数据。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 该函数的功能是向知识库添加文档。 + +**参数**: +- docs: 文档列表,每个文档都是一个Document对象。 +- **kwargs: 接收可变数量的关键字参数。 + +**代码描述**: +`do_add_doc` 函数首先打印输入的文档(docs)数量,然后调用 `_load_es` 方法将这些文档写入Elasticsearch。在文档写入过程中,会使用到`embeddings_model`模型来处理文档数据。文档成功写入后,函数会检查Elasticsearch索引是否存在,如果存在,则根据文档的`source`路径构造一个查询,以检索与该路径相匹配的文档。此查询默认返回最多50个结果。如果没有检索到任何文档,函数会抛出一个`ValueError`异常。最后,函数会从检索结果中提取文档的ID和元数据(metadata),并将这些信息以列表的形式返回。 + +该函数与 `_load_es` 方法的关系是,`do_add_doc` 调用 `_load_es` 方法来实现文档的写入操作。`_load_es` 方法负责将文档通过嵌入模型处理后,写入到Elasticsearch数据库中。这一步是`do_add_doc`实现其功能的关键部分。 + +**注意**: +- 在调用`do_add_doc`函数之前,确保传入的`docs`参数中的文档已经准备好。 +- 该函数依赖于Elasticsearch的索引设置和查询功能,因此在使用前需要确保Elasticsearch服务是可用的,并且相关索引已经正确设置。 +- 函数中的错误处理包括检查召回元素个数是否为0,这是为了确保写入的文档能够被成功检索。在实际应用中,可能还需要考虑其他的异常情况。 + +**输出示例**: +```python +[ + {"id": "文档ID1", "metadata": {"source": "文档源路径1", "其他元数据": "值"}}, + {"id": "文档ID2", "metadata": {"source": "文档源路径2", "其他元数据": "值"}}, + ... +] +``` +此输出示例展示了函数返回值的可能形式,即一个包含多个字典的列表,每个字典代表一个文档的ID和元数据信息。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 该函数的功能是从知识库删除全部向量。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `do_clear_vs` 函数是 `ESKBService` 类的一个方法,用于从Elasticsearch知识库中删除所有的向量数据。首先,该函数通过调用 `self.es_client_python.indices.exists` 方法检查指定的索引(即知识库名称,存储在 `self.kb_name` 中)是否存在。如果索引存在,那么通过调用 `self.es_client_python.indices.delete` 方法删除该索引及其包含的所有数据。这一操作将清空知识库中存储的全部向量数据,实现知识库的初始化或清理。 + +**注意**: +- 在执行此函数之前,确保已经正确设置了 `self.es_client_python` 和 `self.kb_name` 属性。`self.es_client_python` 应为一个有效的Elasticsearch客户端实例,而 `self.kb_name` 应为一个字符串,表示要操作的Elasticsearch索引名称。 +- 删除索引是一个不可逆的操作,一旦执行,索引中的所有数据将被永久删除。因此,在调用此函数之前,请确保已经做好了相应的数据备份或确认不再需要索引中的数据。 +- 由于这个操作会影响到整个知识库的数据,建议在执行此操作前进行充分的测试和评估,确保其对系统的影响是可接受的。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数用于删除知识库。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `do_drop_kb` 函数是 `ESKBService` 类的一个方法,旨在删除指定的知识库目录。该函数首先检查 `self.kb_path`(知识库路径)是否存在。如果该路径存在,则使用 `shutil.rmtree` 方法删除该路径及其下的所有内容。这里的 `self.kb_path` 是一个类属性,代表了知识库文件存储的路径。 + +具体步骤如下: +1. 通过 `self.kb_path` 获取知识库的存储路径。 +2. 使用 `os.path.exists` 函数检查该路径是否存在。 +3. 如果路径存在,调用 `shutil.rmtree` 函数删除该路径及其包含的所有文件和子目录。 + +**注意**: 在使用此函数删除知识库之前,确保已经做好了相应的数据备份,以防不小心删除重要数据。此外,此操作不可逆,请谨慎操作。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/faiss_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/faiss_kb_service.md new file mode 100644 index 000000000..b7f6fe1eb --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/faiss_kb_service.md @@ -0,0 +1,327 @@ +## ClassDef FaissKBService +**FaissKBService**: FaissKBService 类是用于通过 FAISS 实现知识库服务的具体类。 + +**属性**: +- `vs_path`: 向量存储路径。 +- `kb_path`: 知识库路径。 +- `vector_name`: 向量名称,默认为 None。 + +**代码描述**: +FaissKBService 类继承自 KBService 类,专门用于处理基于 FAISS 的向量搜索服务。它提供了一系列方法来管理和操作 FAISS 知识库,包括知识库的创建、删除、文档的添加、删除以及搜索等。 + +- `vs_type` 方法返回支持的向量存储类型,即 FAISS。 +- `get_vs_path` 和 `get_kb_path` 方法分别用于获取向量存储路径和知识库路径。 +- `load_vector_store` 方法加载向量存储,返回一个线程安全的 FAISS 实例。 +- `save_vector_store` 方法将向量存储保存到指定路径。 +- `get_doc_by_ids` 方法根据文档 ID 获取文档。 +- `del_doc_by_ids` 方法根据文档 ID 删除文档。 +- `do_init` 方法在类初始化时设置向量名称、知识库路径和向量存储路径。 +- `do_create_kb` 方法创建知识库,如果向量存储路径不存在,则创建该路径。 +- `do_drop_kb` 方法删除知识库,包括清除向量存储和删除知识库路径。 +- `do_search` 方法实现了基于 FAISS 的文档搜索功能。 +- `do_add_doc` 方法向知识库添加文档,并将文档转化为向量存储。 +- `do_delete_doc` 方法从知识库中删除指定的文档。 +- `do_clear_vs` 方法清除向量存储中的所有内容。 +- `exist_doc` 方法检查指定文件名的文档是否存在。 + +**注意**: +- 使用 FaissKBService 类之前,需要确保 FAISS 环境已正确安装和配置。 +- 在调用 `do_add_doc`、`do_delete_doc` 等方法修改知识库内容时,应注意操作的原子性和线程安全性。 +- `do_search` 方法中的 `score_threshold` 参数用于过滤搜索结果,只返回得分高于此阈值的文档。 + +**输出示例**: +```python +# 假设执行搜索操作,返回两个文档及其相关性得分 +[ + (Document(id="doc1", text="文档1的内容"), 0.95), + (Document(id="doc2", text="文档2的内容"), 0.90) +] +``` +这表示在执行搜索操作时,返回了两个文档及其相关性得分。 +### FunctionDef vs_type(self) +**vs_type**: vs_type的功能是返回当前知识库服务使用的向量存储类型。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: vs_type函数是FaissKBService类的一个方法,其主要作用是标识FaissKBService类实例所使用的向量存储类型。在这个具体实现中,vs_type方法通过返回SupportedVSType.FAISS,明确指出FaissKBService使用FAISS作为其向量存储服务。SupportedVSType是一个枚举类,定义了项目支持的所有向量存储类型,包括但不限于FAISS、MILVUS、ZILLIZ、PostgreSQL、Elasticsearch和ChromaDB等。通过返回SupportedVSType.FAISS,vs_type方法使得知识库服务工厂(KBServiceFactory)能够识别并实例化FaissKBService作为向量存储服务的具体实现。这种设计允许项目动态地根据配置或需求,选择不同的向量存储服务实现,增强了项目的灵活性和可扩展性。 + +**注意**: +- 在使用vs_type方法时,无需传递任何参数,该方法将直接返回FaissKBService所支持的向量存储类型。 +- 该方法的返回值应与SupportedVSType中定义的向量存储类型一致,以确保知识库服务工厂能够正确识别并实例化相应的服务。 +- 当扩展项目以支持新的向量存储服务时,应在SupportedVSType枚举类中添加新的类型,并确保相应的知识库服务类实现了vs_type方法,返回其支持的向量存储类型。 + +**输出示例**: +```python +'faiss' +``` +在这个示例中,vs_type方法返回一个字符串'faiss',表明FaissKBService使用FAISS作为其向量存储服务。 +*** +### FunctionDef get_vs_path(self) +**get_vs_path**: 此函数的功能是获取向量存储路径。 + +**参数**: 此函数没有显式参数,它依赖于对象的内部状态。 + +**代码描述**: `get_vs_path` 函数是 `FaissKBService` 类的一个方法,用于获取向量存储(vector storage)的路径。它通过调用全局的 `get_vs_path` 函数实现,此全局函数需要两个参数:`kb_name` 和 `vector_name`。这两个参数分别代表知识库的名称和向量的名称,它们是 `FaissKBService` 对象的属性。这意味着,当 `get_vs_path` 方法被调用时,它会使用当前对象的知识库名称和向量名称作为参数来获取向量存储的路径。 + +在项目中,`get_vs_path` 方法被 `do_init` 方法调用。在 `do_init` 方法中,首先通过一系列初始化操作设置了 `vector_name` 和 `kb_path`,然后调用 `get_vs_path` 方法获取向量存储的路径,并将其存储在 `vs_path` 属性中。这表明 `get_vs_path` 方法是在对象初始化过程中,用于确定向量存储位置的关键步骤。 + +**注意**: 使用此函数时,确保 `kb_name` 和 `vector_name` 属性已经被正确设置,因为这两个属性直接影响到向量存储路径的获取结果。 + +**输出示例**: 假设知识库名称为 "my_kb",向量名称为 "my_vector",则此函数可能返回的路径示例为 "/path/to/my_kb/my_vector_storage"。 +*** +### FunctionDef get_kb_path(self) +**get_kb_path**: 此函数的功能是获取知识库的路径。 + +**参数**: 此函数没有参数。 + +**代码描述**: `get_kb_path`函数是`FaissKBService`类的一个方法,用于返回知识库文件的路径。它通过调用`get_kb_path`函数并传入`self.kb_name`作为参数来实现。这里的`self.kb_name`是在`FaissKBService`类的实例化过程中定义的,代表了知识库的名称。此方法的设计意图是为了提供一种灵活的方式来获取知识库文件的路径,这对于知识库的存储和访问至关重要。 + +在项目中,`get_kb_path`方法被`do_init`方法调用。在`do_init`方法中,首先通过`self.get_kb_path()`获取知识库路径并将其赋值给`self.kb_path`,然后继续获取向量存储路径并赋值给`self.vs_path`。这表明`get_kb_path`方法在`FaissKBService`类的初始化过程中起到了关键作用,它确保了知识库路径的正确设置,从而为后续的知识库操作提供了基础。 + +**注意**: 使用`get_kb_path`方法时,需要确保`self.kb_name`已经被正确赋值,因为这直接影响到知识库路径的获取。此外,确保调用此方法的环境中有对应的`get_kb_path`函数定义,且能正确处理传入的知识库名称参数。 + +**输出示例**: 假设`self.kb_name`的值为"example_kb",则`get_kb_path`方法可能返回的路径示例为`"/path/to/knowledge_bases/example_kb"`。这个返回值代表了知识库文件存储的具体路径。 +*** +### FunctionDef load_vector_store(self) +**load_vector_store**: 此函数的功能是加载并返回一个线程安全的FAISS向量库实例。 + +**参数**: 此函数没有显式参数,它通过`self`访问类实例的属性。 + +**代码描述**: `load_vector_store`函数通过调用`kb_faiss_pool.load_vector_store`方法来加载一个FAISS向量库。它传递了三个参数:`kb_name`、`vector_name`和`embed_model`,这些参数分别代表知识库的名称、向量的名称以及嵌入模型。这些参数都是`FaissKBService`类实例的属性,用于指定加载哪个向量库以及使用哪个嵌入模型。加载的向量库是一个`ThreadSafeFaiss`实例,这保证了在多线程环境下对FAISS向量库的操作是安全的。 + +**注意**: +- 使用此函数前,确保`kb_name`、`vector_name`和`embed_model`属性已正确设置,因为它们决定了将加载哪个向量库。 +- 返回的`ThreadSafeFaiss`实例支持线程安全的操作,包括文档的增加、删除、搜索等,适用于多线程环境。 + +**输出示例**: 假设`kb_name`为"my_kb",`vector_name`为"my_vector",`embed_model`为"bert",则此函数可能返回一个表示如下的`ThreadSafeFaiss`实例: +``` +, docs_count: 100> +``` +这表示加载了一个名为"my_kb_my_vector"的FAISS向量库,其中包含100个文档。 + +在项目中,`load_vector_store`函数被多个方法调用,包括`save_vector_store`、`get_doc_by_ids`、`del_doc_by_ids`、`do_create_kb`、`do_search`、`do_add_doc`和`do_delete_doc`。这些方法利用`load_vector_store`加载的向量库执行各种操作,如保存向量库到磁盘、通过ID获取文档、删除指定ID的文档、创建知识库、执行搜索、添加文档和删除文档等。这体现了`load_vector_store`在`FaissKBService`类中的核心作用,它为管理和操作FAISS向量库提供了基础。 +*** +### FunctionDef save_vector_store(self) +**save_vector_store**: 此函数的功能是保存当前加载的向量库到磁盘。 + +**参数**: 此函数没有显式参数。 + +**代码描述**: `save_vector_store`方法首先调用`load_vector_store`方法来加载当前的向量库,确保操作的向量库是最新的。加载的向量库是一个线程安全的FAISS向量库实例,这一点由`load_vector_store`方法保证。加载完成后,通过调用向量库实例的`save`方法,将其保存到`self.vs_path`指定的路径。这个路径是`FaissKBService`类实例化时确定的,代表向量库在磁盘上的存储位置。 + +在保存向量库的过程中,`save`方法会检查目标路径是否存在,如果不存在且其`create_path`参数为True(默认值),则会创建该路径。这一过程确保了即使目标路径在之前未创建,向量库也能被成功保存。保存操作完成后,会在日志中记录向量库保存的相关信息,包括向量库的键值和保存的目标路径。 + +**注意**: +- 在调用`save_vector_store`方法之前,确保`self.vs_path`已正确设置,因为它决定了向量库将被保存到哪个路径。 +- 由于`save_vector_store`方法依赖于`load_vector_store`来加载向量库,因此需要确保相关的属性(如`kb_name`、`vector_name`和`embed_model`)已经被正确设置,以便能够加载正确的向量库。 +- 此方法在多线程环境下安全使用,但在保存向量库时,应确保没有其他操作正在修改向量库,以避免数据不一致的问题。 +- 如果在保存向量库的过程中遇到路径不存在且无法创建路径的情况,操作可能会失败。因此,调用此方法时应确保应用程序具有足够的权限来创建目录或写入文件。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 此函数的功能是根据提供的ID列表获取对应的文档对象列表。 + +**参数**: +- `ids`: 字符串列表,表示需要获取的文档的ID。 + +**代码描述**: +`get_doc_by_ids`函数首先通过调用`load_vector_store`方法加载一个线程安全的FAISS向量库实例。加载的向量库实例提供了一个上下文管理器,确保在多线程环境下安全地访问和操作向量库。在成功加载向量库实例后,函数使用Python列表推导式遍历提供的ID列表,通过访问向量库实例的`docstore`属性(一个字典类型的存储),使用`get`方法尝试获取每个ID对应的文档对象。如果某个ID在`docstore`中不存在,则返回值为`None`。 + +此函数与`load_vector_store`方法的关系是,它依赖于`load_vector_store`方法提供的线程安全的向量库实例来安全、高效地获取文档对象。`load_vector_store`方法确保了在多线程环境下对FAISS向量库的操作是安全的,这对于`get_doc_by_ids`函数在执行文档检索时至关重要。 + +**注意**: +- 确保在调用此函数前,向量库已经被正确加载且包含了目标文档的向量数据,否则无法获取到文档对象。 +- 返回的文档对象列表中可能包含`None`值,这表示某些提供的ID在向量库的文档存储中不存在。调用方需要对此进行适当的处理。 + +**输出示例**: +假设提供了ID列表`["doc1", "doc2", "doc3"]`,并且这些ID在向量库的文档存储中都存在对应的文档对象,则此函数可能返回如下的文档对象列表: +``` +[, , ] +``` +如果某个ID(如"doc3")在文档存储中不存在,则对应位置将返回`None`: +``` +[, , None] +``` +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 此函数的功能是根据提供的ID列表删除向量库中的文档。 + +**参数**: +- `ids`: 一个字符串列表,包含要从向量库中删除的文档的ID。 + +**代码描述**: +`del_doc_by_ids`函数首先通过调用`load_vector_store`方法加载一个线程安全的FAISS向量库实例。这一步骤确保了在多线程环境下对向量库的操作是安全的。加载向量库实例后,使用`with`语句和`acquire`方法创建一个上下文管理器,这样可以安全地获取向量库资源进行操作。在这个上下文管理器内部,调用向量库实例的`delete`方法,传入参数`ids`,即可删除指定ID的文档。 + +从功能上看,`del_doc_by_ids`与其调用的`load_vector_store`和`acquire`方法紧密相关。`load_vector_store`负责加载并返回一个线程安全的向量库实例,这是进行任何向量库操作的前提。而`acquire`方法则提供了一个安全的环境,确保在执行删除操作时,不会因为多线程访问而导致数据竞争或不一致的问题。 + +**注意**: +- 在调用`del_doc_by_ids`函数之前,确保传入的ID列表中的每个ID都是向量库中实际存在的文档ID。如果尝试删除一个不存在的ID,根据FAISS库的具体实现,这可能会导致错误或者简单地忽略该操作。 +- 由于`del_doc_by_ids`涉及到对向量库的修改操作,建议在执行此操作前后对向量库进行适当的备份,以防止意外数据丢失。 +- 此函数适用于需要从向量库中批量删除文档的场景,例如在文档更新或清理过程中。 +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化FaissKBService对象。 + +**参数**: 此函数没有显式参数。 + +**代码描述**: `do_init` 方法是 `FaissKBService` 类的一个关键方法,用于完成对象的初始化工作。在这个方法中,首先会检查 `self.vector_name` 是否已经被赋值,如果没有,则将其设置为 `self.embed_model` 的值。这一步骤确保了向量名称的正确设置,是后续操作如向量存储路径的获取的基础。 + +接下来,`do_init` 方法调用 `self.get_kb_path()` 方法来获取知识库的路径,并将这个路径赋值给 `self.kb_path` 属性。这一步是为了确保知识库路径的正确设置,从而使得后续对知识库的操作能够基于正确的路径进行。 + +紧接着,`do_init` 方法调用 `self.get_vs_path()` 方法来获取向量存储的路径,并将这个路径赋值给 `self.vs_path` 属性。这一步是为了确保向量存储路径的正确设置,从而使得后续对向量的存储和访问能够基于正确的路径进行。 + +通过这些步骤,`do_init` 方法为 `FaissKBService` 对象的后续操作提供了必要的初始化设置,包括知识库路径和向量存储路径的设置,以及向量名称的确认。这些设置是后续操作正确进行的基础。 + +**注意**: 在使用 `do_init` 方法之前,确保 `self.embed_model` 已经被正确赋值,因为在向量名称未显式设置的情况下,`do_init` 方法会将 `self.embed_model` 作为向量名称。此外,`do_init` 方法的正确执行依赖于 `get_kb_path` 和 `get_vs_path` 方法的正确实现,因此在调用 `do_init` 方法之前,需要确保这两个方法能够正确返回知识库路径和向量存储路径。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是创建知识库。 + +**参数**: 此函数没有显式参数,它通过`self`访问类实例的属性。 + +**代码描述**: `do_create_kb`函数首先检查由`self.vs_path`指定的路径是否存在,如果不存在,则创建该路径。这一步骤确保了存储向量数据的目录是可用的。接着,该函数调用`load_vector_store`方法。`load_vector_store`方法的作用是加载并返回一个线程安全的FAISS向量库实例,这一过程是通过访问`FaissKBService`类实例的`kb_name`、`vector_name`和`embed_model`属性来完成的,这些属性分别指定了要加载的知识库名称、向量名称以及嵌入模型。加载的向量库是线程安全的,支持在多线程环境下安全地进行文档的增加、删除和搜索等操作。 + +从功能角度看,`do_create_kb`函数通过确保向量存储路径的存在并加载向量库,为后续的知识库操作(如添加文档、搜索文档等)准备了必要的环境。这一过程是`FaissKBService`类管理和操作FAISS向量库的基础步骤之一。 + +**注意**: +- 在调用`do_create_kb`函数之前,确保`vs_path`属性已正确设置,因为它决定了向量数据存储的位置。 +- 该函数依赖于`load_vector_store`方法来加载向量库,因此在使用前应确保`kb_name`、`vector_name`和`embed_model`属性已经被正确配置,以指定加载哪个向量库以及使用哪个嵌入模型。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是删除知识库。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `do_drop_kb` 方法是 `FaissKBService` 类的成员方法,主要负责删除整个知识库。该方法首先调用 `clear_vs` 方法来清除知识库中的向量数据。根据 `clear_vs` 方法的文档,这一步骤会删除向量库中的所有内容,并且是通过删除数据库中与知识库相关的所有文件记录来实现的。这是一个重要的预处理步骤,确保在物理删除知识库文件之前,相关的向量数据已经被清除。 + +接下来,`do_drop_kb` 方法尝试使用 `shutil.rmtree` 函数删除知识库的物理文件夹。这一步骤是通过传递 `self.kb_path` 作为参数来完成的,其中 `self.kb_path` 表示知识库文件夹的路径。如果在删除过程中遇到任何异常,该方法会捕获异常并不做进一步处理,这意味着异常情况下的具体处理逻辑可能需要在未来根据实际需求进行添加。 + +**注意**: +- 在调用 `do_drop_kb` 方法之前,请确保已经备份了重要数据。一旦执行此方法,知识库及其包含的所有数据将被永久删除,这一操作是不可逆的。 +- 请确保 `self.kb_path` 已经正确设置,指向了需要被删除的知识库的物理路径。 +- 考虑到异常处理目前尚未实现详细逻辑,开发者在使用此方法时应当注意异常情况的监控和处理,以避免潜在的问题。 + +此方法在项目中的主要应用场景包括知识库的重置或删除操作,特别是在知识库数据需要被彻底清除以释放存储空间或为新的知识库初始化时。通过先清除向量数据再删除物理文件夹的步骤,`do_drop_kb` 方法确保了知识库的彻底清除。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 此函数的功能是根据给定的查询字符串,执行相似度搜索并返回最相关的文档列表及其相应的分数。 + +**参数**: +- `query`: 需要进行搜索的查询字符串。 +- `top_k`: 返回的最相关文档的数量。 +- `score_threshold`: 分数阈值,只有当文档的相似度分数高于此阈值时,才会被包含在结果中。默认值为`SCORE_THRESHOLD`。 + +**代码描述**: +`do_search`函数首先通过`EmbeddingsFunAdapter`类的实例化,使用`self.embed_model`作为嵌入模型,对查询字符串`query`进行向量化处理,得到查询的嵌入向量。`EmbeddingsFunAdapter`类是一个专门用于将文本转换为嵌入向量的适配器,它支持同步和异步两种方式进行文本的嵌入表示转换。 + +随后,函数调用`self.load_vector_store()`方法获取一个线程安全的FAISS向量库实例。`load_vector_store`方法负责加载并返回一个`ThreadSafeFaiss`实例,该实例封装了FAISS向量库的操作,确保在多线程环境下的线程安全性。加载的向量库包含了预先索引的文档向量,用于执行相似度搜索。 + +在成功获取向量库实例后,函数使用`acquire`方法以线程安全的方式访问向量库,并调用`similarity_search_with_score_by_vector`方法执行相似度搜索。该方法接受查询的嵌入向量、`top_k`参数指定的返回文档数量以及`score_threshold`分数阈值作为输入,返回与查询最相关的`top_k`个文档及其相似度分数。 + +最后,函数返回搜索结果,即最相关的文档列表及其相应的分数。 + +**注意**: +- 在使用`do_search`函数之前,确保`self.embed_model`已正确设置,因为它决定了查询字符串如何被向量化。 +- `top_k`参数应为正整数,表示需要返回的最相关文档的数量。 +- 分数阈值`score_threshold`用于过滤相似度分数低于该阈值的文档,可以根据实际需求调整。 + +**输出示例**: +假设对于查询字符串"人工智能",`top_k`设置为3,`score_threshold`设置为0.5,函数可能返回如下结果: +``` +[ + (Document(id="doc1", title="人工智能基础", content="..."), 0.95), + (Document(id="doc2", title="人工智能应用", content="..."), 0.85), + (Document(id="doc3", title="人工智能未来", content="..."), 0.75) +] +``` +这表示找到了三个与查询"人工智能"最相关的文档,它们的相似度分数分别为0.95、0.85和0.75。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 此函数的功能是向知识库中添加文档,并返回添加的文档信息。 + +**参数**: +- `docs`: 需要添加到知识库中的文档对象列表,类型为`List[Document]`。 +- `**kwargs`: 关键字参数,可以包括`ids`和`not_refresh_vs_cache`等选项。 + +**代码描述**: +`do_add_doc`方法首先调用`_docs_to_embeddings`私有方法,将文档对象列表转化为向量和元数据的格式,这一步骤有助于减少向量库的锁定时间,提高效率。接着,通过`load_vector_store`方法加载线程安全的FAISS向量库实例,并使用`acquire`方法安全地获取向量库的操作权限。在这个上下文管理器中,使用`add_embeddings`方法将文档的文本、向量和元数据添加到向量库中,并根据`kwargs`中的`ids`参数指定的ID进行存储。如果`kwargs`中没有设置`not_refresh_vs_cache`为`True`,则会调用`save_local`方法将向量库的当前状态保存到本地路径`self.vs_path`。最后,构造并返回包含文档ID和元数据的信息列表。在方法的末尾,调用`torch_gc`函数清理PyTorch的缓存内存,以避免内存溢出或性能下降的问题。 + +**注意**: +- 确保传入的`docs`参数是有效的文档对象列表。 +- 使用`kwargs`中的`ids`参数可以指定添加文档的ID,如果不指定,则向量库会自动生成ID。 +- 如果不希望每次添加文档后都刷新向量库缓存,可以通过设置`kwargs`中的`not_refresh_vs_cache`为`True`来跳过保存向量库到本地的步骤。 +- 调用`torch_gc`函数清理缓存是为了管理内存使用,特别是在处理大量数据时。 + +**输出示例**: +调用`do_add_doc(docs=[Document1, Document2], ids=[1, 2])`可能会返回如下列表: +```python +[ + {"id": 1, "metadata": {"title": "文档1标题"}}, + {"id": 2, "metadata": {"title": "文档2标题"}} +] +``` +这个列表包含了每个添加到知识库中文档的ID和元数据信息。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数的功能是根据给定的知识库文件删除相应的文档向量。 + +**参数**: +- `kb_file`: KnowledgeFile对象,表示要删除的知识库文件。 +- `**kwargs`: 关键字参数,用于提供额外的配置选项。 + +**代码描述**: +`do_delete_doc`函数首先通过调用`load_vector_store`方法加载一个线程安全的FAISS向量库实例。接着,它遍历向量库中的文档存储(`vs.docstore._dict`),寻找其元数据中`source`字段与`kb_file.filename`相匹配(不区分大小写)的文档ID。找到后,将这些ID存储在列表`ids`中。如果`ids`列表不为空,即存在需要删除的文档,那么调用`vs.delete(ids)`方法删除这些文档。 + +此外,函数检查关键字参数`not_refresh_vs_cache`。如果该参数不存在或其值为`False`,则调用`vs.save_local(self.vs_path)`方法,将更新后的向量库保存到本地路径。这一步骤确保了向量库的状态与实际文档保持一致。 + +最后,函数返回被删除的文档ID列表`ids`。 + +**注意**: +- 在调用此函数之前,确保传入的`kb_file`对象正确表示了要删除的知识库文件,并且该文件已经存在于知识库中。 +- 删除操作会直接影响向量库的内容,因此在执行此操作前应确保已经做好相应的备份或确认操作的必要性。 +- `not_refresh_vs_cache`参数允许调用者控制是否立即更新本地向量库缓存,这在批量删除操作时可能有用,以避免频繁的磁盘写操作。 + +**输出示例**: +```python +# 假设删除操作找到并删除了两个文档,其ID分别为'123'和'456' +deleted_ids = do_delete_doc(kb_file) +print(deleted_ids) # 输出: ['123', '456'] +``` +在此示例中,`do_delete_doc`函数返回了一个包含被删除文档ID的列表。这表明两个文档已从向量库中成功删除。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是清除特定向量存储。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `do_clear_vs` 函数是 `FaissKBService` 类的一个方法,用于清除与特定知识库名称 (`kb_name`) 和向量名称 (`vector_name`) 相关联的向量存储。该函数首先通过 `kb_faiss_pool.atomic` 上下文管理器确保对 `kb_faiss_pool` 的操作是原子的,然后调用 `pop` 方法从 `kb_faiss_pool` 中移除指定的键值对。这里的键是由知识库名称和向量名称组成的元组 `(self.kb_name, self.vector_name)`。`pop` 方法的作用是从缓存池中移除并返回指定键的对象,如果键不存在,则不执行任何操作。 + +接下来,函数尝试删除向量存储的物理路径 `self.vs_path`。这是通过调用 `shutil.rmtree` 方法实现的,该方法会递归删除文件夹及其所有内容。如果在删除过程中遇到任何异常(例如路径不存在或权限问题),异常会被捕获并忽略,确保程序的稳定性。 + +最后,函数使用 `os.makedirs` 方法重新创建向量存储的路径,`exist_ok=True` 参数确保如果路径已经存在,则不会抛出异常。这一步骤是为了确保即使向量存储被清除,相关的路径结构仍然被保留,便于后续的向量存储操作。 + +**注意**: +- 在调用 `do_clear_vs` 函数之前,应确保知识库名称 (`kb_name`) 和向量名称 (`vector_name`) 已经正确设置,因为这些信息将用于定位需要清除的向量存储。 +- 由于 `do_clear_vs` 函数会删除物理路径下的所有文件和文件夹,因此在调用此函数时应谨慎,以避免意外删除重要数据。 +- 在多线程或多进程环境中使用 `do_clear_vs` 函数时,应注意同步和并发控制,以防止数据竞争或不一致的情况发生。 +*** +### FunctionDef exist_doc(self, file_name) +**exist_doc**: 此函数的功能是判断指定的文件名是否存在于知识库中。 + +**参数**: +- `file_name`: 需要查询的文件名,类型为字符串。 + +**代码描述**: +`exist_doc` 函数首先调用其父类的 `exist_doc` 方法来检查指定的文件名是否已经存在于数据库中。如果父类方法返回 `True`,表示文件已存在于数据库中,那么此函数将返回 `"in_db"` 字符串,表示文件存在于数据库。 + +如果文件不在数据库中,函数接着会检查文件是否存在于知识库的 `content` 文件夹内。这是通过拼接知识库路径 (`self.kb_path`) 和 `"content"` 子目录,然后检查拼接路径下是否有与 `file_name` 相对应的文件来实现的。如果文件确实存在于 `content` 文件夹中,函数将返回 `"in_folder"` 字符串,表示文件存在于文件夹中。 + +如果以上两种情况都不成立,即文件既不在数据库中也不在文件夹中,函数将返回 `False`,表示文件不存在于知识库中。 + +**注意**: +- 确保在调用此函数前,`self.kb_path` 已被正确设置,指向知识库的根目录。 +- 此函数的返回值有三种可能:"in_db"、"in_folder" 和 `False`,分别表示文件存在于数据库中、存在于文件夹中和不存在于知识库中。 + +**输出示例**: +- 如果文件存在于数据库中: `"in_db"` +- 如果文件存在于文件夹中: `"in_folder"` +- 如果文件不存在于知识库中: `False` +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/milvus_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/milvus_kb_service.md new file mode 100644 index 000000000..147fe851f --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/milvus_kb_service.md @@ -0,0 +1,292 @@ +## ClassDef MilvusKBService +**MilvusKBService**: MilvusKBService 类是用于在 Milvus 向量数据库中管理和操作知识库的服务。 + +**属性**: +- `milvus`: Milvus 实例,用于执行与 Milvus 数据库相关的操作。 + +**代码描述**: +MilvusKBService 类继承自 KBService 类,提供了一系列方法用于在 Milvus 向量数据库中管理和操作知识库。这包括文档的增加、删除、搜索以及知识库的创建、初始化、删除等操作。 + +- `get_collection` 静态方法用于获取 Milvus 中的集合(Collection)。 +- `get_doc_by_ids` 方法根据文档ID列表检索文档,返回包含文档内容和元数据的 Document 对象列表。 +- `del_doc_by_ids` 方法根据文档ID列表从知识库中删除文档。 +- `search` 静态方法实现了基于内容的搜索功能,返回与搜索内容最相关的文档列表。 +- `do_create_kb` 方法用于创建知识库,此方法在 MilvusKBService 类中为空实现,具体逻辑需在子类中定义。 +- `vs_type` 方法返回知识库使用的向量存储类型,对于 MilvusKBService 类,始终返回 `SupportedVSType.MILVUS`。 +- `_load_milvus` 方法负责加载 Milvus 实例,包括设置嵌入函数、集合名称、连接参数等。 +- `do_init` 方法初始化 Milvus 实例。 +- `do_drop_kb` 方法删除知识库,包括释放和删除集合。 +- `do_search` 方法实现了基于查询的搜索功能,返回与查询最相关的文档列表。 +- `do_add_doc` 方法向知识库添加文档。 +- `do_delete_doc` 方法根据 KnowledgeFile 对象从知识库中删除文档。 +- `do_clear_vs` 方法清空知识库中的所有文档。 + +**注意**: +- 使用 MilvusKBService 类之前,需要确保 Milvus 服务已经启动并可连接。 +- 在调用 `do_add_doc` 和 `do_delete_doc` 方法时,需要传入符合 Milvus 要求的文档格式。 +- `get_collection` 方法需要确保传入的集合名称在 Milvus 中已存在。 + +**输出示例**: +```python +# 假设执行搜索操作后的返回示例 +[ + {"id": "123", "content": "文档内容示例", "score": 0.95}, + {"id": "456", "content": "另一个文档内容示例", "score": 0.90} +] +``` +这表示在执行搜索操作时,返回了两个文档及其相关性得分。 +### FunctionDef get_collection(milvus_name) +**get_collection**: 此函数的功能是获取指定名称的Milvus集合。 + +**参数**: +- **milvus_name**: 需要获取的Milvus集合的名称。 + +**代码描述**: +`get_collection`函数是`MilvusKBService`类中用于获取Milvus数据库中特定名称的集合的方法。它通过`milvus_name`参数接收集合的名称,并使用`pymilvus`库中的`Collection`类来获取并返回这个集合的实例。这个函数在项目中的主要作用是为其他需要操作Milvus集合的方法提供集合实例,例如,在`search`方法中,它通过调用`get_collection`来获取集合实例,然后在这个集合上执行搜索操作。 + +在`search`方法中,`get_collection`被用来获取一个集合实例,然后使用这个实例来执行搜索操作,其中包括指定搜索参数和返回字段。这显示了`get_collection`在项目中作为获取Milvus集合实例的基础功能的重要性。 + +**注意**: +- 确保传入的`milvus_name`参数正确,且对应的Milvus集合已经存在,否则`Collection`类可能会抛出异常。 +- 使用`get_collection`函数需要先安装并正确配置`pymilvus`库。 + +**输出示例**: +调用`get_collection("example_collection")`可能会返回一个`Collection`类的实例,这个实例代表了名为`example_collection`的Milvus集合。具体的返回值依赖于Milvus数据库中该集合的状态和内容。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 此函数的功能是根据提供的ID列表从Milvus数据库中检索文档。 + +**参数**: +- `ids`: 一个字符串列表,包含要检索的文档的ID。 + +**代码描述**: +`get_doc_by_ids` 函数接受一个ID列表作为参数,返回一个包含对应ID的文档列表。首先,函数检查Milvus数据库的集合是否存在。如果集合存在,函数将继续执行以下步骤: + +1. 将输入的ID列表中的每个ID转换为整数,因为Milvus数据库中可能以整数形式存储这些ID。 +2. 使用转换后的ID列表构造一个查询表达式,用于从Milvus数据库的集合中检索具有这些ID的文档。 +3. 执行查询,检索包含所有指定字段的文档列表。这里的`output_fields=["*"]`表示检索文档的所有字段。 +4. 遍历查询结果,从每个结果中提取文本内容,并将其余部分作为元数据存储。每个文档被封装为一个`Document`对象,其中包含页面内容(`page_content`)和元数据(`metadata`)。 +5. 将所有`Document`对象收集到一个列表中,并返回这个列表。 + +**注意**: +- 确保传入的ID列表中的ID与Milvus数据库中存储的ID类型相匹配。如果数据库中的ID是整数类型,确保转换ID类型。 +- 此函数依赖于Milvus数据库的连接实例(`self.milvus`)和其集合(`self.milvus.col`)。确保在调用此函数之前已正确配置这些连接。 + +**输出示例**: +假设有两个文档的ID分别为"1"和"2",调用`get_doc_by_ids(["1", "2"])`可能返回如下列表: + +```python +[ + Document(page_content="文档1的内容", metadata={"id": 1, "title": "文档1标题", ...}), + Document(page_content="文档2的内容", metadata={"id": 2, "title": "文档2标题", ...}) +] +``` + +此示例展示了函数返回的`Document`对象列表,每个对象包含了对应文档的页面内容和元数据。 +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 此函数的功能是根据提供的ID列表删除Milvus数据库中的文档。 + +**参数**: +- `ids`: 需要删除的文档的ID列表,类型为`List[str]`。 + +**代码描述**: +`del_doc_by_ids`函数接受一个字符串列表`ids`作为参数,这个列表包含了需要从Milvus数据库中删除的文档的ID。函数内部,通过调用`self.milvus.col.delete`方法来执行删除操作。这个方法使用了一个表达式`expr=f'pk in {ids}'`,其中`pk`代表Milvus数据库中的主键字段,这个表达式的意思是选择所有主键在`ids`列表中的文档进行删除。 + +**注意**: +- 确保传入的`ids`列表中的ID是存在于Milvus数据库中的,否则删除操作不会影响任何文档。 +- 删除操作是不可逆的,一旦执行,相应的文档将从数据库中永久移除,请谨慎使用此功能。 +- 在执行删除操作前,建议先进行必要的数据备份,以防不慎删除重要数据。 +- 此函数返回一个布尔值,表示删除操作是否成功执行,但需要注意的是,即使删除操作成功,也不代表所有指定的ID都被成功删除,因为某些ID可能本来就不存在于数据库中。 +*** +### FunctionDef search(milvus_name, content, limit) +**search**: 此函数的功能是在Milvus集合中执行向量搜索操作。 + +**参数**: +- **milvus_name**: 字符串类型,指定要搜索的Milvus集合的名称。 +- **content**: 搜索内容,通常是向量或向量数组。 +- **limit**: 整型,指定返回的最大结果数量,默认为3。 + +**代码描述**: +`search`函数是`MilvusKBService`类中用于在指定的Milvus集合中执行向量搜索操作的方法。它首先定义了一个搜索参数`search_params`,其中包括度量类型("L2")和其他搜索相关参数(如"nprobe": 10)。这些参数用于控制搜索过程中的行为,例如,"L2"指定了使用L2距离(欧几里得距离)作为相似度的衡量标准。 + +接下来,函数通过调用`get_collection`方法获取指定名称(`milvus_name`)的Milvus集合的实例。`get_collection`方法是`MilvusKBService`类中的一个重要方法,它负责连接到Milvus数据库并获取集合的实例,以便进行后续的操作,如本函数中的搜索操作。 + +一旦获得集合实例,函数使用该实例的`search`方法执行搜索操作。搜索操作的参数包括搜索内容(`content`)、搜索字段("embeddings")、搜索参数(`search_params`)、结果数量限制(`limit`)和输出字段(["content"])。这允许函数在指定的集合中根据给定的向量内容进行搜索,并返回与搜索内容最相似的几个结果。 + +**注意**: +- 确保`milvus_name`参数正确,且对应的Milvus集合已经存在,否则可能无法获取集合实例,导致搜索失败。 +- 搜索参数`search_params`中的"metric_type"和"params"应根据实际搜索需求进行调整。 +- `limit`参数控制返回结果的数量,根据实际需求调整此值。 + +**输出示例**: +调用`search("example_collection", some_vector, limit=2)`可能会返回如下格式的结果: +```python +[ + {"content": "文档1的内容", "distance": 0.1}, + {"content": "文档2的内容", "distance": 0.2} +] +``` +这个示例显示了搜索操作返回的两个最相似的结果,每个结果包括了匹配内容和与搜索内容的距离(相似度的衡量)。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb函数功能**: 此函数用于创建知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_create_kb`函数是`MilvusKBService`类中的一个方法,目前其内部实现为空(使用了`pass`语句)。这意味着,函数被调用时不会执行任何操作。在实际应用中,该函数可能被设计为负责在Milvus向量数据库中创建一个新的知识库,包括但不限于初始化知识库的结构、配置知识库的存储参数等。由于当前代码中该函数的实现为空,开发者需要根据实际需求完成相应的功能实现。 + +**注意**: +- 由于`do_create_kb`函数当前未实现任何功能,直接调用它不会对系统产生任何影响。开发者在使用时需要添加具体的实现逻辑。 +- 在为`do_create_kb`函数添加实现逻辑时,应确保理解Milvus向量数据库的相关API和知识库的需求,以确保正确和高效地创建知识库。 +- 考虑到未来可能的需求变更和功能扩展,建议在实现具体逻辑时编写清晰、可维护的代码,并充分进行测试。 +*** +### FunctionDef vs_type(self) +**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。 + +**参数**: 该函数不接受任何参数。 + +**代码描述**: vs_type函数是MilvusKBService类的一个方法,它的作用是标识该服务实例支持的向量存储类型。在这个具体实现中,vs_type方法通过返回SupportedVSType.MILVUS来明确指出,当前的知识库服务使用的是MILVUS作为其向量存储解决方案。SupportedVSType是一个枚举类,其中定义了一系列支持的向量存储类型,包括但不限于FAISS、MILVUS、ZILLIZ等。通过返回SupportedVSType.MILVUS,vs_type方法为知识库服务工厂(KBServiceFactory)提供了必要的信息,以便在需要时能够正确地实例化和管理MilvusKBService对象。这种设计允许系统灵活地支持多种向量存储服务,同时保持了代码的模块化和可扩展性。 + +**注意**: +- 在使用vs_type方法时,不需要传递任何参数,它将返回一个字符串,表示支持的向量存储类型。 +- 返回的向量存储类型应与SupportedVSType枚举类中定义的类型一致,以确保系统的一致性和可靠性。 +- 当需要扩展知识库服务以支持更多的向量存储类型时,应首先在SupportedVSType枚举类中添加新的类型,然后在相应的知识库服务类中实现vs_type方法,以返回新增的类型。 + +**输出示例**: +```python +'milvus' +``` +在这个示例中,vs_type方法返回了一个字符串'milvus',表明当前的知识库服务实例使用MILVUS作为其向量存储解决方案。 +*** +### FunctionDef _load_milvus(self) +**_load_milvus**: 此函数的功能是初始化Milvus服务的连接并配置相关参数。 + +**参数**: 此函数没有显式参数,但它依赖于类属性进行操作。 + +**代码描述**: `_load_milvus`函数负责创建一个Milvus实例,并通过该实例连接到Milvus服务。它使用`EmbeddingsFunAdapter`类来适配嵌入模型,该模型将用于文本的嵌入表示转换。此外,它还配置了Milvus集合的名称、连接参数、索引参数和搜索参数。这些参数从`kbs_config`配置对象中获取,其中包括: +- `embedding_function`:使用`EmbeddingsFunAdapter`类,它根据提供的嵌入模型(`embed_model`)来生成文本的嵌入表示。 +- `collection_name`:指定Milvus中的集合名称,这里使用`self.kb_name`作为集合名称。 +- `connection_args`:包含连接Milvus服务所需的参数,这些参数从`kbs_config.get("milvus")`中获取。 +- `index_params`和`search_params`:分别用于配置Milvus索引的创建参数和搜索参数,这些参数通过`kbs_config.get("milvus_kwargs")`获取。 + +此函数是`MilvusKBService`类的私有方法,主要在类的初始化过程(`do_init`)和执行搜索操作(`do_search`)之前被调用,以确保Milvus服务的连接已经建立并配置好了相应的参数。 + +**注意**: +- 在调用`_load_milvus`之前,确保`kbs_config`配置对象中包含了正确的Milvus连接参数、索引参数和搜索参数。 +- `EmbeddingsFunAdapter`类是一个关键组件,它负责将文本转换为嵌入向量,这些嵌入向量随后将用于Milvus中的相似度搜索。因此,确保`embed_model`属性已正确设置,并且所引用的嵌入模型是有效的。 +- `_load_milvus`函数不应直接从类外部调用,而是通过类的公共方法(如`do_init`和`do_search`)间接调用。 +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化Milvus知识库服务。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_init`函数是`MilvusKBService`类的公共方法,其主要职责是调用`_load_milvus`私有方法来完成Milvus服务的初始化。在`_load_milvus`方法中,会创建一个Milvus实例,并通过该实例连接到Milvus服务,同时配置相关的参数,如嵌入模型、集合名称、连接参数、索引参数和搜索参数。这些参数的配置是基于`kbs_config`配置对象进行的。因此,`do_init`方法通过调用`_load_milvus`,间接完成了Milvus服务的连接和参数配置,为后续的知识库操作(如搜索)做好准备。 + +**注意**: +- `do_init`方法通常在`MilvusKBService`类实例化后立即调用,以确保Milvus服务的连接和配置正确完成。 +- 在调用`do_init`方法之前,应确保`kbs_config`配置对象已正确设置,包括Milvus服务的连接信息和操作参数。 +- 除了在类初始化时调用,`do_init`方法还可能在需要重新初始化Milvus服务连接时被调用,例如在`do_clear_vs`方法中,如果已存在的Milvus集合被清除,将会调用`do_init`来重新初始化服务。 +- 由于`do_init`方法依赖于`_load_milvus`私有方法,因此在修改或维护代码时应注意这两个方法之间的关系和依赖。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是释放并删除当前Milvus数据库中的集合。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_drop_kb`函数是`MilvusKBService`类的一个方法,用于处理与Milvus数据库中的集合相关的删除操作。当调用此函数时,首先会检查`self.milvus.col`(即当前操作的Milvus集合)是否存在。如果存在,该方法将执行两个步骤:首先,使用`release()`方法释放集合,这是为了确保在删除集合之前,所有的资源都被正确地释放;随后,调用`drop()`方法删除集合。这个过程确保了集合被安全且彻底地从Milvus数据库中移除。 + +在项目中,`do_drop_kb`函数被`do_clear_vs`方法调用。`do_clear_vs`方法的目的是清理视图状态,它通过调用`do_drop_kb`来删除相关的Milvus集合,然后通过调用`do_init`来重新初始化状态。这表明`do_drop_kb`在项目中扮演着重要的角色,它是处理数据清理和状态重置流程中不可或缺的一部分。 + +**注意**: 在使用`do_drop_kb`函数时,需要确保Milvus数据库的连接是正常的,并且调用此函数会永久删除集合及其所有数据,这是一个不可逆的操作。因此,在调用此函数之前,应该仔细考虑是否真的需要删除集合,以避免意外丢失重要数据。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 此函数的功能是执行文本查询,并返回与查询最相似的前k个文档及其相似度分数。 + +**参数**: +- `query`: 需要查询的文本,数据类型为字符串。 +- `top_k`: 返回的文档数量上限,数据类型为整数。 +- `score_threshold`: 分数阈值,用于筛选相似度高于此阈值的文档,数据类型为浮点数。 + +**代码描述**: +`do_search`函数首先调用`_load_milvus`方法来初始化Milvus服务的连接并配置相关参数,确保Milvus服务可以被正确访问。接着,使用`EmbeddingsFunAdapter`类的实例`embed_func`来处理输入的查询文本`query`,将其转换为嵌入向量。这一步是通过调用`embed_func.embed_query(query)`实现的,该方法返回查询文本的嵌入向量。 + +随后,函数利用`self.milvus.similarity_search_with_score_by_vector`方法,传入查询文本的嵌入向量和`top_k`参数,执行相似度搜索。该方法返回与查询最相似的前`top_k`个文档及其相似度分数。 + +最后,调用`score_threshold_process`函数,传入`score_threshold`、`top_k`和搜索结果`docs`作为参数,根据分数阈值筛选出符合条件的文档,并返回前`top_k`个文档及其相似度分数。这一步骤确保了最终返回的文档不仅与查询文本相似度高,而且其相似度分数超过了指定的阈值。 + +**注意**: +- 在调用`do_search`函数之前,确保Milvus服务已经正确配置并可以访问。 +- `top_k`参数应根据实际需求合理设置,以避免返回过多不相关的结果。 +- `score_threshold`参数用于进一步筛选相似度较高的文档,应根据实际情况调整其值。 + +**输出示例**: +假设输入查询为"最近的科技新闻",`top_k`为3,`score_threshold`为0.5,可能的返回值为: +``` +[ + ("doc1", 0.8), + ("doc2", 0.75), + ("doc3", 0.65) +] +``` +这表示在所有文档中,有三个文档的相似度分数满足大于等于0.5的条件,并且是与查询"最近的科技新闻"最相似的前3个文档。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 此函数的功能是向Milvus数据库中添加文档,并返回添加的文档信息。 + +**参数**: +- `docs`: 需要添加到Milvus数据库中的文档列表,每个文档都是一个Document对象。 +- `**kwargs`: 接受可变数量的关键字参数,这些参数可以用于扩展或自定义功能。 + +**代码描述**: +此函数首先遍历输入的文档列表`docs`。对于每个文档,它会遍历文档的元数据`metadata`,将所有元数据的值转换为字符串类型。接着,它会检查Milvus数据库的字段,确保每个文档的元数据中都包含这些字段,如果缺少,则会添加空字符串作为默认值。此外,它会从元数据中移除特定的字段,这些字段通常是用于文本和向量数据的字段,因为它们可能不适合直接存储为元数据。 + +在处理完所有文档的元数据后,函数调用`self.milvus.add_documents(docs)`方法将文档添加到Milvus数据库中。此方法返回添加的文档的ID列表。 + +最后,函数构造一个包含文档ID和更新后的元数据的字典列表,并将此列表作为结果返回。 + +**注意**: +- 确保传入的文档列表`docs`中的每个文档都是有效的Document对象,并且已经正确设置了必要的元数据。 +- 此函数不处理文本和向量字段的存储,调用此函数前请确保这些数据已经以适当的方式处理。 + +**输出示例**: +```python +[ + {"id": "123456789", "metadata": {"title": "文档标题1", "author": "作者1"}}, + {"id": "987654321", "metadata": {"title": "文档标题2", "author": "作者2"}} +] +``` +此示例展示了函数返回值的可能形式,包含了每个添加到Milvus数据库中的文档的ID和更新后的元数据。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数的功能是删除指定知识库文件中的文档记录。 + +**参数**: +- `kb_file`: KnowledgeFile类型,表示要删除文档的知识库文件。 +- `**kwargs`: 接收可变数量的关键字参数,用于扩展或自定义功能。 + +**代码描述**: +`do_delete_doc`函数主要用于删除Milvus向量数据库中,与指定知识库文件相关联的文档记录。首先,通过调用`list_file_num_docs_id_by_kb_name_and_file_name`函数,根据`kb_file`对象提供的知识库名称(`kb_name`)和文件名称(`filename`),获取该文件对应的所有文档ID列表。然后,如果Milvus的集合(`col`)存在,使用Milvus的`delete`方法,构造删除表达式`expr=f'pk in {id_list}'`,以此表达式为条件执行删除操作。这里的`pk`代表主键,即文档的唯一标识符,`id_list`是需要删除的文档ID列表。 + +此函数与`list_file_num_docs_id_by_kb_name_and_file_name`函数紧密相关,后者负责查询并返回指定文件中所有文档的ID,而`do_delete_doc`则使用这些ID来定位并删除Milvus数据库中对应的文档记录。这种设计使得文档的删除操作既准确又高效,确保了知识库的数据一致性和准确性。 + +**注意**: +- 在调用此函数之前,确保`kb_file`对象正确初始化,且其属性`kb_name`和`filename`准确无误,以匹配数据库中的记录。 +- 此函数依赖于Milvus数据库的连接和配置正确设置,确保`self.milvus.col`指向有效的Milvus集合。 +- 删除操作一旦执行,被删除的文档记录将无法恢复,请谨慎使用此功能以避免数据丢失。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是清理Milvus知识库服务的视图状态。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_clear_vs`函数是`MilvusKBService`类的一个方法,用于清理Milvus知识库服务的视图状态。该方法首先检查`self.milvus.col`,即当前操作的Milvus集合是否存在。如果存在,则执行两个操作:首先调用`do_drop_kb`方法来释放并删除当前Milvus数据库中的集合,然后调用`do_init`方法来重新初始化Milvus知识库服务。 + +具体来说,`do_drop_kb`方法负责释放并删除Milvus数据库中的集合,确保集合被安全且彻底地从数据库中移除。随后,`do_init`方法被调用来重新初始化Milvus服务的连接和配置,为后续的知识库操作(如搜索)做好准备。这一过程表明`do_clear_vs`方法在处理数据清理和状态重置流程中扮演着重要的角色,它通过组合`do_drop_kb`和`do_init`两个方法的功能,实现了对Milvus知识库服务视图状态的彻底清理和重置。 + +**注意**: +- 在调用`do_clear_vs`方法之前,应确保Milvus服务的连接是正常的。 +- 由于`do_clear_vs`方法会导致当前Milvus数据库中的集合被删除,这是一个不可逆的操作。因此,在执行此方法之前,应仔细考虑是否真的需要清理视图状态,以避免意外丢失重要数据。 +- `do_clear_vs`方法的执行依赖于`do_drop_kb`和`do_init`两个方法,因此在修改或维护这些方法时,应注意它们之间的关系和依赖,确保整个流程的正确执行。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/pg_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/pg_kb_service.md new file mode 100644 index 000000000..052395be1 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/pg_kb_service.md @@ -0,0 +1,254 @@ +## ClassDef PGKBService +**PGKBService**: PGKBService 类是用于通过 PostgreSQL 实现知识库服务的具体类。 + +**属性**: +- `engine`: 通过 SQLAlchemy 创建的连接引擎,用于与 PostgreSQL 数据库进行交互。 +- `pg_vector`: 用于存储和检索嵌入向量的 PGVector 实例。 + +**代码描述**: +PGKBService 类继承自 KBService 类,提供了与 PostgreSQL 数据库交互的具体实现。它使用 SQLAlchemy 作为 ORM 工具,通过 `engine` 属性与数据库建立连接。此类主要负责初始化向量存储、文档的增删查改、知识库的创建和删除等操作。 + +- `_load_pg_vector` 方法用于加载 PGVector 实例,该实例负责嵌入向量的存储和检索。 +- `get_doc_by_ids` 方法通过文档 ID 获取文档内容和元数据。 +- `del_doc_by_ids` 方法删除指定 ID 的文档,实际调用基类的同名方法。 +- `do_init` 方法在类初始化时被调用,用于加载 PGVector 实例。 +- `do_create_kb` 方法是创建知识库的具体实现,当前为空实现。 +- `vs_type` 方法返回支持的向量存储类型,即 PostgreSQL。 +- `do_drop_kb` 方法删除知识库,包括数据库中的相关记录和文件系统上的知识库路径。 +- `do_search` 方法实现了基于查询的文档搜索功能,返回与查询最相关的文档列表。 +- `do_add_doc` 方法向知识库添加文档,并返回添加的文档信息。 +- `do_delete_doc` 方法从知识库删除指定的文档。 +- `do_clear_vs` 方法清空向量存储中的所有内容,并重新创建集合。 + +**注意**: +- 使用 PGKBService 类之前,需要确保 PostgreSQL 数据库已经正确配置,并且 `kbs_config` 中的 `pg` 配置项包含了正确的数据库连接 URI。 +- 在调用 `do_add_doc` 和 `do_delete_doc` 等方法修改数据库内容时,需要确保传入的参数符合预期格式,以避免执行错误或数据损坏。 +- `do_drop_kb` 方法在删除知识库时会同时删除数据库中的记录和文件系统上的知识库路径,使用时需谨慎以防误删重要数据。 + +**输出示例**: +```python +# 假设调用 get_doc_by_ids 方法查询 ID 为 ['doc1', 'doc2'] 的文档 +docs = pgkb_service.get_doc_by_ids(['doc1', 'doc2']) +# 可能的返回值为 +[ + Document(page_content="文档1的内容", metadata={"author": "作者1"}), + Document(page_content="文档2的内容", metadata={"author": "作者2"}) +] +``` +此示例展示了通过文档 ID 获取文档内容和元数据的过程及其可能的返回值。 +### FunctionDef _load_pg_vector(self) +**_load_pg_vector**: 此函数的功能是加载PostgreSQL向量空间搜索引擎。 + +**参数**: 此函数没有显式参数,但它依赖于类实例的多个属性。 + +**代码描述**: `_load_pg_vector`函数负责初始化一个PGVector实例,该实例用于在PostgreSQL数据库中进行向量空间搜索。这个过程包括以下几个关键步骤: + +1. 使用`EmbeddingsFunAdapter`类创建一个嵌入函数适配器。这个适配器基于类实例的`embed_model`属性,用于将文本转换为向量表示。`EmbeddingsFunAdapter`支持同步和异步两种文本嵌入方式,适用于不同的应用场景。 + +2. 指定向量空间搜索的集合名称,这里使用类实例的`kb_name`属性作为集合名称。 + +3. 设置距离策略为欧几里得距离(`DistanceStrategy.EUCLIDEAN`),用于计算向量之间的距离。 + +4. 使用`PGKBService.engine`作为数据库连接。这是一个类属性,表示与PostgreSQL数据库的连接引擎。 + +5. 通过`kbs_config.get("pg").get("connection_uri")`获取数据库连接字符串,这个字符串包含了数据库的地址、端口、用户名、密码等信息,用于建立数据库连接。 + +通过这些步骤,`_load_pg_vector`函数配置了一个用于向量空间搜索的PGVector实例,并将其保存在类实例的`pg_vector`属性中。这使得类的其他方法可以利用这个PGVector实例来执行向量空间搜索操作,例如查找与给定文本向量最相似的文档。 + +**注意**: +- 在调用`_load_pg_vector`函数之前,需要确保类实例的`embed_model`和`kb_name`属性已经被正确设置。这些属性对于初始化PGVector实例至关重要。 +- `PGKBService.engine`需要预先配置好,确保能够成功连接到PostgreSQL数据库。 +- 数据库连接字符串应该保密处理,避免泄露数据库的敏感信息。 + +此函数是在`do_init`方法中被调用的,`do_init`方法负责执行类的初始化操作,包括加载PostgreSQL向量空间搜索引擎。这表明`_load_pg_vector`函数是类初始化过程的一个重要组成部分,确保了向量空间搜索功能的可用性。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 此函数的功能是根据提供的ID列表查询并返回相应的文档列表。 + +**参数**: +- ids: 一个字符串列表,包含需要查询的文档的ID。 + +**代码描述**: +`get_doc_by_ids` 函数接受一个字符串列表 `ids` 作为参数,这个列表包含了需要查询的文档的ID。函数内部首先使用 `Session` 上下文管理器创建一个会话,通过这个会话与数据库进行交互。接着,定义了一个SQL查询语句 `stmt`,这个语句用于从名为 `langchain_pg_embedding` 的表中选取 `document` 和 `cmetadata` 字段,条件是 `collection_id` 字段的值包含在参数 `ids` 提供的ID列表中。 + +通过执行这个查询语句并传入 `ids` 参数,函数会从数据库中检索出匹配的记录。每条记录都会被用来创建一个 `Document` 对象,这个对象包含了检索到的文档内容(`page_content`)和元数据(`metadata`)。所有这些 `Document` 对象随后被收集到一个列表中,并作为函数的返回值。 + +**注意**: +- 确保传入的ID列表 `ids` 不为空,且每个ID都是有效的,以确保查询能够正确执行。 +- 此函数依赖于数据库表 `langchain_pg_embedding` 的结构,特别是它查询的字段。如果数据库结构发生变化,可能需要相应地更新此函数。 + +**输出示例**: +假设数据库中有两条记录的 `collection_id` 匹配给定的ID列表,函数可能返回如下的列表: +```python +[ + Document(page_content="文档内容1", metadata={"作者": "张三", "发布日期": "2023-01-01"}), + Document(page_content="文档内容2", metadata={"作者": "李四", "发布日期": "2023-02-01"}) +] +``` +这个列表包含了两个 `Document` 对象,每个对象都包含了从数据库检索到的文档内容和元数据。 +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 此函数的功能是根据提供的ID列表删除文档。 + +**参数**: +- ids: 一个字符串列表,包含要删除的文档的ID。 + +**代码描述**: +`del_doc_by_ids` 函数接受一个字符串列表 `ids` 作为参数,这个列表包含了需要从数据库中删除的文档的ID。函数通过调用其父类的 `del_doc_by_ids` 方法来实现删除操作,并将 `ids` 参数传递给该方法。这表明实际的删除逻辑被封装在父类的方法中,而当前函数主要负责将删除请求转发给父类处理。 + +**注意**: +- 确保传递给此函数的 `ids` 参数包含有效的文档ID,否则可能不会有任何文档被删除。 +- 此函数返回一个布尔值,表示删除操作是否成功。但是,具体的成功与否依赖于父类方法的实现细节。 +- 在使用此函数之前,应当了解父类中 `del_doc_by_ids` 方法的具体实现,以及它对于不同情况下删除操作的处理方式。 + +**输出示例**: +调用 `del_doc_by_ids(['doc1', 'doc2'])` 可能会返回 `True`,表示指定ID的文档已成功删除。如果操作失败,可能会返回 `False`。请注意,实际的返回值取决于父类方法的具体实现。 +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化PGKBService类的实例。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_init`方法是PGKBService类的一个初始化方法,它通过调用`_load_pg_vector`方法来加载PostgreSQL向量空间搜索引擎。这个过程是类实例化过程中的一个重要步骤,确保了类的实例能够正确地进行向量空间搜索操作。 + +在`do_init`方法中,通过调用`_load_pg_vector`方法,完成了以下几个关键的初始化步骤: +1. 创建一个嵌入函数适配器`EmbeddingsFunAdapter`,该适配器基于类实例的`embed_model`属性,用于将文本转换为向量表示。 +2. 指定向量空间搜索的集合名称,使用类实例的`kb_name`属性作为集合名称。 +3. 设置距离策略为欧几里得距离,用于计算向量之间的距离。 +4. 使用类属性`PGKBService.engine`作为数据库连接,这表示与PostgreSQL数据库的连接引擎。 +5. 获取数据库连接字符串,用于建立数据库连接。 + +通过这些步骤,`_load_pg_vector`方法配置了一个用于向量空间搜索的PGVector实例,并将其保存在类实例的`pg_vector`属性中。这样,类的其他方法就可以利用这个PGVector实例来执行向量空间搜索操作,例如查找与给定文本向量最相似的文档。 + +**注意**: +- 在调用`do_init`方法之前,不需要进行特别的准备工作,因为它是类实例化过程中自动调用的初始化方法。 +- 需要确保`embed_model`和`kb_name`属性在调用`_load_pg_vector`之前已经被正确设置,因为这些属性对于初始化PGVector实例至关重要。 +- `PGKBService.engine`需要预先配置好,以确保能够成功连接到PostgreSQL数据库。 +- 数据库连接字符串应该保密处理,避免泄露数据库的敏感信息。 + +总的来说,`do_init`方法通过调用`_load_pg_vector`方法,完成了PGKBService类实例的初始化,为后续的向量空间搜索操作做好了准备。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是创建知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_create_kb` 函数是 `PGKBService` 类的一个方法,负责创建知识库的具体逻辑。目前,此函数的实现为空(使用了 `pass` 语句),这意味着它不执行任何操作。在实际应用中,开发者需要在此函数中添加创建知识库的代码逻辑,例如连接数据库、执行数据库操作等。 + +**注意**: 虽然当前 `do_create_kb` 函数的实现为空,但在将来的开发中,当添加具体的实现逻辑时,需要确保数据库连接的正确性和操作的安全性。此外,考虑到知识库可能包含大量数据,还需要注意性能优化和错误处理。 +*** +### FunctionDef vs_type(self) +**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。 + +**参数**: 该函数不接受任何参数。 + +**代码描述**: vs_type函数是PGKBService类的一个方法,它的主要作用是标识该知识库服务实例支持的向量存储类型。在这个具体实现中,vs_type方法通过返回SupportedVSType.PG,明确指出PostgreSQL(简称PG)是该服务实例使用的向量存储类型。SupportedVSType是一个枚举类,它定义了项目中支持的所有向量存储类型,包括但不限于FAISS、MILVUS、ZILLIZ、Elasticsearch(ES)、ChromaDB等,以及PG。通过返回SupportedVSType中的一个枚举值,vs_type方法为知识库服务的配置和实例化提供了必要的信息。这种设计使得知识库服务的管理和扩展更加灵活和方便,因为可以根据需要动态选择和切换不同的向量存储服务。 + +**注意**: +- 在使用PGKBService类及其vs_type方法时,应当了解SupportedVSType枚举类中定义的向量存储类型,以确保正确理解和使用该方法返回的向量存储类型信息。 +- 由于vs_type方法返回的是一个枚举成员,因此在处理返回值时,应当注意枚举类型的使用方法,例如通过枚举成员的name或value属性获取具体的信息。 + +**输出示例**: 假设调用PGKBService实例的vs_type方法,可能的返回值为: +``` +'pg' +``` +这表示当前知识库服务实例使用PostgreSQL作为其向量存储服务。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是删除与指定知识库名称相关联的数据库记录和文件系统中的知识库目录。 + +**参数**: 此函数没有显式参数,但它依赖于`self.kb_name`和`self.kb_path`这两个实例变量。 + +**代码描述**: +`do_drop_kb`函数是`PGKBService`类的一个方法,用于删除特定知识库相关的数据。该方法首先通过SQL语句删除数据库中与知识库相关联的记录,然后删除文件系统中对应的知识库目录。具体步骤如下: + +1. 使用`Session`上下文管理器创建一个数据库会话,确保数据库操作在一个会话中完成,并且在操作结束后自动关闭会话。 +2. 在会话中执行SQL删除操作。首先,删除`langchain_pg_embedding`表中所有`collection_id`与`langchain_pg_collection`表中`name`字段匹配`self.kb_name`的记录的`uuid`相匹配的记录。这意味着,所有与指定知识库名称相关联的嵌入信息将被删除。 +3. 接着,删除`langchain_pg_collection`表中`name`字段与`self.kb_name`匹配的记录。这一步骤将删除知识库的集合记录。 +4. 执行`session.commit()`提交数据库事务,确保上述删除操作被保存到数据库中。 +5. 使用`shutil.rmtree`函数删除文件系统中的知识库目录。`self.kb_path`变量指定了知识库目录的路径,该函数将递归删除该目录及其所有内容。 + +**注意**: +- 在执行此函数之前,确保`self.kb_name`和`self.kb_path`已经正确设置,分别指向要删除的知识库的名称和路径。 +- 该操作不可逆,一旦执行,相关的数据库记录和文件系统中的目录将被永久删除。因此,在调用此函数之前,请确保已经做好相应的备份或确认不再需要这些数据。 +- 由于直接操作数据库和文件系统,确保执行此操作的用户具有相应的权限。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 此函数的功能是执行文本查询,并根据给定的分数阈值和返回的文档数量上限筛选出相似度最高的文档。 + +**参数**: +- `query`: 需要查询的文本,数据类型为字符串。 +- `top_k`: 返回的文档数量上限,数据类型为整数。 +- `score_threshold`: 分数阈值,用于筛选相似度高于此阈值的文档,数据类型为浮点数。 + +**代码描述**: +`do_search`函数首先通过`EmbeddingsFunAdapter`类的实例`embed_func`,调用`embed_query`方法将查询文本`query`转换为嵌入向量。这一步骤是通过将文本转换为向量化表示,以便后续进行相似度搜索。 + +接着,函数使用`self.pg_vector`的`similarity_search_with_score_by_vector`方法,传入上一步得到的嵌入向量和`top_k`参数,执行相似度搜索。此方法返回一个包含文档及其相似度分数的列表,列表中的文档是根据与查询向量的相似度排序的。 + +最后,函数调用`score_threshold_process`方法,传入`score_threshold`、`top_k`和相似度搜索的结果,根据分数阈值筛选出符合条件的文档,并返回前`top_k`个文档。这一步骤确保了返回的文档不仅与查询文本相似度高,而且其相似度分数超过了指定的阈值。 + +**注意**: +- 确保传入的`query`是有效的字符串,`top_k`是正整数,`score_threshold`是非负浮点数。 +- `EmbeddingsFunAdapter`和`score_threshold_process`是此函数依赖的关键组件,确保它们的实现与预期一致。 +- 此函数的性能和准确性依赖于嵌入模型的质量和相似度搜索算法的效率。 + +**输出示例**: +假设调用`do_search`函数,传入查询文本"示例查询",`top_k`为3,`score_threshold`为0.5,可能的返回值为: +``` +[("文档1", 0.8), ("文档3", 0.7), ("文档5", 0.6)] +``` +这表示在所有文档中,有三个文档的相似度分数满足大于等于0.5的条件,并且是相似度最高的前三个文档。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 此函数的功能是向数据库中添加文档,并返回包含文档ID和元数据的信息列表。 + +**参数**: +- `docs`: 需要添加到数据库中的文档列表,每个文档都是一个`Document`对象。 +- `**kwargs`: 接受可变数量的关键字参数,这些参数可以根据需要传递给底层数据库操作。 + +**代码描述**: +`do_add_doc`函数首先调用`pg_vector`对象的`add_documents`方法,将`docs`列表中的文档添加到数据库中。`add_documents`方法返回一个包含每个文档ID的列表。然后,函数遍历这些ID和原始的`docs`列表,使用列表推导式创建一个新的列表`doc_infos`。这个新列表的每个元素都是一个字典,包含两个键:`id`和`metadata`。`id`键对应于文档的ID,`metadata`键对应于文档的元数据。最后,函数返回`doc_infos`列表。 + +**注意**: +- 确保传递给`do_add_doc`函数的`docs`参数是一个`Document`对象的列表,且每个`Document`对象都应该有有效的元数据。 +- 传递给`**kwargs`的关键字参数将直接影响底层数据库操作,因此请谨慎使用,确保了解这些参数的影响。 + +**输出示例**: +假设我们向`do_add_doc`函数传递了两个文档,且这两个文档成功添加到数据库中,函数可能返回如下列表: +```python +[ + {"id": "doc1_id", "metadata": {"title": "Document 1 Title", "author": "Author Name"}}, + {"id": "doc2_id", "metadata": {"title": "Document 2 Title", "author": "Another Author Name"}} +] +``` +这个列表包含了每个文档的ID和元数据,可以用于进一步的处理或显示。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数用于从数据库中删除与指定知识文件相关联的文档向量。 + +**参数**: +- `kb_file`: KnowledgeFile对象,代表需要删除其文档向量的知识库文件。 +- `**kwargs`: 接收额外的关键字参数,以便在未来的版本中扩展功能而不影响现有接口。 + +**代码描述**: +`do_delete_doc`函数首先通过`kb_file`参数获取知识库文件的完整路径。为了确保数据库查询语句中的文件路径字符串格式正确,它将路径中的所有反斜杠(`\`)替换为双反斜杠(`\\`)。这是因为在SQL查询中,反斜杠是一个特殊字符,需要进行转义。 + +接着,函数使用`Session`上下文管理器创建一个数据库会话,并执行一个SQL `DELETE`语句。这个`DELETE`语句的目的是从`langchain_pg_embedding`表中删除所有`cmetadata`字段(以JSONB格式存储)中`source`键对应的值与给定文件路径匹配的记录。这里,`cmetadata::jsonb @> '{"source": "filepath"}'::jsonb`是一个PostgreSQL的JSONB查询表达式,用于查找`cmetadata`中包含特定`source`键值对的记录。 + +在执行删除操作后,函数通过`session.commit()`提交更改,确保删除操作被保存到数据库中。 + +**注意**: +- 使用此函数时,需要确保传入的`kb_file`对象有效,且其`filepath`属性正确反映了文件在磁盘上的位置。 +- 此函数直接操作数据库,执行删除操作。因此,在调用此函数之前,应确保已经对要删除的数据进行了适当的备份或确认,以防意外数据丢失。 +- 由于此函数涉及数据库操作,其执行效率和影响范围可能会受到数据库当前状态和配置的影响。在处理大量数据或高负载情况下,建议监控数据库性能,以避免潜在的性能问题。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是清除并重新创建向量空间。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `do_clear_vs` 函数是 `PGKBService` 类的一个方法,用于管理向量空间的清除和重建过程。在这个函数中,首先调用 `self.pg_vector.delete_collection()` 方法来删除当前的向量空间集合。这一步骤是为了清除所有现有的数据,确保向量空间是空的。紧接着,通过调用 `self.pg_vector.create_collection()` 方法来重新创建一个新的向量空间集合。这样做的目的是为了在删除旧数据之后,提供一个全新的环境以便后续的数据插入和管理。 + +**注意**: 使用 `do_clear_vs` 函数时需要谨慎,因为这会导致所有现有的向量空间数据被永久删除,无法恢复。因此,在执行此操作之前,请确保已经做好了充分的数据备份或确认不再需要这些数据。此外,重新创建向量空间集合后,需要重新配置任何相关的设置或索引,以确保向量空间的正常使用和性能优化。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_service/zilliz_kb_service.md b/markdown_docs/server/knowledge_base/kb_service/zilliz_kb_service.md new file mode 100644 index 000000000..587b69e18 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_service/zilliz_kb_service.md @@ -0,0 +1,280 @@ +## ClassDef ZillizKBService +**ZillizKBService**: ZillizKBService 类是用于在 Zilliz 向量数据库中管理和操作知识库的服务。 + +**属性**: +- `zilliz`: Zilliz 实例,用于与 Zilliz 向量数据库进行交互。 + +**代码描述**: +ZillizKBService 类继承自 KBService 类,提供了一系列专门用于在 Zilliz 向量数据库中管理和操作知识库的方法。这些方法包括获取集合、通过 ID 获取文档、通过 ID 删除文档、搜索、创建知识库、初始化、删除知识库、添加文档、删除文档以及清除向量空间等。 + +- `get_collection` 静态方法用于获取指定名称的集合。 +- `get_doc_by_ids` 方法根据提供的 ID 列表查询并返回文档列表。 +- `del_doc_by_ids` 方法根据提供的 ID 列表删除文档。 +- `search` 静态方法用于在指定的集合中搜索与给定内容相似的文档。 +- `do_create_kb` 方法用于创建知识库,当前为空实现。 +- `vs_type` 方法返回支持的向量存储类型,即 Zilliz。 +- `_load_zilliz` 方法用于加载 Zilliz 实例。 +- `do_init` 方法用于初始化服务,包括加载 Zilliz 实例。 +- `do_drop_kb` 方法用于删除知识库。 +- `do_search` 方法用于搜索知识库。 +- `do_add_doc` 方法用于向知识库添加文档。 +- `do_delete_doc` 方法用于从知识库删除指定的文档。 +- `do_clear_vs` 方法用于清除向量空间。 + +**注意**: +- 在使用 ZillizKBService 之前,需要确保 Zilliz 向量数据库已正确配置并可用。 +- 由于 ZillizKBService 继承自 KBService,部分方法的具体实现可能依赖于 KBService 类中定义的抽象方法。 +- 在调用 `do_add_doc` 和 `do_delete_doc` 等方法时,需要注意传入的参数格式和类型。 + +**输出示例**: +```python +# 假设已经有一个 ZillizKBService 实例,名为 zilliz_service +# 搜索内容为 "example content" 的文档,限制返回结果为前3个 +search_results = zilliz_service.search("example_collection", "example content", limit=3) +# 输出可能为: +[ + {"content": "文档1内容", "score": 0.95}, + {"content": "文档2内容", "score": 0.90}, + {"content": "文档3内容", "score": 0.85} +] +``` +此输出示例展示了使用 `search` 方法进行内容搜索的可能结果,包括每个匹配文档的内容和相似度得分。 +### FunctionDef get_collection(zilliz_name) +**get_collection**: 此函数的功能是获取指定名称的集合。 + +**参数**: +- **zilliz_name**: 集合的名称。 + +**代码描述**: +`get_collection` 函数是`ZillizKBService`类中的一个方法,它的主要作用是通过传入的集合名称`zilliz_name`,使用`pymilvus`库中的`Collection`类来获取对应的集合对象。这个方法简洁明了,只涉及到从`pymilvus`导入`Collection`类并返回一个集合对象的过程。 + +在项目中,`get_collection`方法被`search`方法调用。在`search`方法中,首先通过`get_collection`获取到了一个指定名称的集合对象,然后使用这个集合对象执行搜索操作。这表明`get_collection`方法是搜索功能实现的基础,它确保了搜索操作能够在正确的集合上执行。 + +**注意**: +- 确保在调用此函数之前,指定的集合名称`zilliz_name`已经存在于Milvus数据库中,否则会导致获取集合失败。 +- 使用此函数需要安装并正确配置`pymilvus`库。 + +**输出示例**: +调用`get_collection("example_collection")`可能会返回一个`pymilvus`库中的`Collection`对象,这个对象代表了名为"example_collection"的集合。 +*** +### FunctionDef get_doc_by_ids(self, ids) +**get_doc_by_ids**: 此函数的功能是根据提供的ID列表从Zilliz的集合中检索文档。 + +**参数**: +- `ids`: 一个字符串列表,包含要检索的文档的ID。 + +**代码描述**: +`get_doc_by_ids`函数接受一个ID列表作为参数,返回一个文档列表。这个函数首先检查`self.zilliz.col`是否存在,这是一个对Zilliz集合的引用。如果这个集合存在,函数将继续执行查询操作。 + +查询是通过调用`self.zilliz.col.query`方法实现的,该方法的`expr`参数设置为`'pk in {ids}'`,其中`{ids}`是传入的ID列表。这意味着函数将查询主键(pk)在给定ID列表中的所有记录。`output_fields=["*"]`参数指示查询返回所有字段的数据。 + +对于查询结果中的每条数据,函数将从数据中提取`text`字段,并将其余字段作为元数据。然后,它使用这些信息创建一个`Document`对象,其中`page_content`设置为提取的文本,`metadata`设置为剩余的数据字段。这些`Document`对象被收集到一个列表中,最后返回这个列表。 + +**注意**: +- 确保传入的ID列表中的ID是存在于Zilliz集合中的有效ID,否则查询将不会返回任何结果。 +- 此函数依赖于`self.zilliz.col`的存在,这意味着在调用此函数之前,必须正确初始化并设置对应的Zilliz集合引用。 + +**输出示例**: +假设有两个文档的ID分别为"123"和"456",并且这些文档在Zilliz集合中存在。调用`get_doc_by_ids(['123', '456'])`可能会返回如下列表: + +```python +[ + Document(page_content="这是文档123的内容", metadata={'id': '123', 'title': '文档123标题', 'date': '2023-01-01'}), + Document(page_content="这是文档456的内容", metadata={'id': '456', 'title': '文档456标题', 'date': '2023-01-02'}) +] +``` + +这个列表包含两个`Document`对象,每个对象都包含了从Zilliz集合中检索到的文档的内容和元数据。 +*** +### FunctionDef del_doc_by_ids(self, ids) +**del_doc_by_ids**: 此函数的功能是根据提供的ID列表删除对应的文档。 + +**参数**: +- ids: 一个字符串列表,包含需要删除的文档的ID。 + +**代码描述**: +`del_doc_by_ids`函数是`ZillizKBService`类的一个方法,用于从Zilliz的知识库服务中删除指定ID的文档。此函数接受一个参数`ids`,这是一个字符串列表,每个字符串代表一个需要删除的文档的ID。函数内部,通过调用`self.zilliz.col.delete`方法来执行删除操作,其中`expr=f'pk in {ids}'`是一个表达式,用于指定需要删除的文档的ID条件。这里`pk`代表文档的主键,`in {ids}`表示主键在提供的ID列表中的文档将被删除。 + +**注意**: +- 确保传入的ID列表中的每个ID都是有效的,并且对应于知识库中实际存在的文档。如果列表中包含无效或不存在的ID,这些ID将被忽略,不会影响其他有效ID的删除操作。 +- 删除操作一旦执行,被删除的文档将无法恢复,请在执行删除操作前仔细确认。 +- 此函数返回一个布尔值,表示删除操作是否成功执行。然而,具体的代码实现中没有明确返回值,这可能需要根据实际的业务逻辑进行相应的调整或补充。 +*** +### FunctionDef search(zilliz_name, content, limit) +**search**: 此函数的功能是在指定的集合中执行基于内容的搜索操作。 + +**参数**: +- **zilliz_name**: 指定的集合名称。 +- **content**: 搜索的内容。 +- **limit**: 返回的结果数量上限,默认值为3。 + +**代码描述**: +`search` 函数是`ZillizKBService`类中的一个方法,它用于在指定的集合中执行基于内容的搜索操作。首先,该函数定义了搜索参数`search_params`,其中包括度量类型("IP")和其他搜索相关的参数。接着,通过调用`get_collection`方法获取到指定名称的集合对象。最后,使用集合对象的`search`方法执行搜索操作,该操作基于`content`参数进行,搜索范围限定在"embeddings"字段中,同时指定了搜索参数`search_params`和结果数量上限`limit`。此外,还通过`output_fields`参数指定了搜索结果中需要包含的字段,本例中为["content"]。 + +从功能角度看,`get_collection`方法为`search`方法提供了执行搜索所需的集合对象,确保搜索操作能够在正确的集合上进行。这种设计体现了模块化和功能分离的原则,便于代码的维护和扩展。 + +**注意**: +- 在使用`search`函数之前,确保`zilliz_name`指定的集合已经存在,并且集合中的数据已经按照需要进行了索引。 +- `limit`参数应根据实际需求调整,以平衡搜索结果的全面性和性能开销。 +- 确保`pymilvus`库已正确安装并配置,因为`search`函数的实现依赖于此库。 + +**输出示例**: +调用`search("example_collection", "some search content")`可能会返回如下格式的搜索结果: +```python +[ + {"content": "匹配的内容1"}, + {"content": "匹配的内容2"}, + {"content": "匹配的内容3"} +] +``` +这个示例展示了当搜索限制为返回最多3个结果时,可能得到的搜索结果。每个结果包含了指定的输出字段"content",其中包含了与搜索内容匹配的集合中的数据。 +*** +### FunctionDef do_create_kb(self) +**do_create_kb**: 此函数的功能是创建知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `do_create_kb` 函数是 `ZillizKBService` 类的一个方法,用于创建知识库。在当前的代码实现中,此函数体内没有具体的执行代码,仅包含一个 `pass` 语句。这意味着,此函数作为一个框架或者是占位符存在,等待后续的实现。在实际应用中,开发者需要根据具体需求,填充此函数以实现知识库的创建逻辑,比如初始化数据库连接、设置知识库的结构、数据导入等操作。 + +**注意**: 虽然当前 `do_create_kb` 函数没有实现具体的功能,但在将来的版本中,开发者可能会添加具体的实现代码。因此,在使用此函数时,需要关注其最新的实现状态和文档说明,以确保正确使用。同时,考虑到此函数的目的是创建知识库,开发者在实现时应确保有充分的权限和正确的配置信息,以避免潜在的权限问题或配置错误。 +*** +### FunctionDef vs_type(self) +**vs_type**: vs_type函数的功能是返回当前知识库服务支持的向量存储类型。 + +**参数**: 此函数没有参数。 + +**代码描述**: vs_type函数是ZillizKBService类的一个方法,它的作用是标识该知识库服务实例支持的向量存储类型。在这个具体实现中,vs_type方法通过返回SupportedVSType.ZILLIZ来明确指出,当前的知识库服务使用的是ZILLIZ作为其向量存储解决方案。SupportedVSType是一个枚举类,其中定义了项目支持的所有向量存储类型,包括但不限于FAISS、MILVUS、ZILLIZ等。ZILLIZ在这里被选定,意味着ZillizKBService专门为与ZILLIZ向量存储服务交互而设计。这种设计方式便于在知识库服务工厂(KBServiceFactory)中根据需要动态选择和实例化具体的知识库服务实现,从而提高了项目的灵活性和可扩展性。 + +**注意**: +- 在使用ZillizKBService类时,开发者应当了解其背后的向量存储类型是ZILLIZ,这对于理解如何配置和使用该服务至关重要。 +- 如果项目需要支持其他类型的向量存储服务,应在SupportedVSType枚举类中添加相应的类型,并在知识库服务工厂中实现相应的逻辑以支持新的服务类型。 + +**输出示例**: 该函数调用将返回一个字符串值:"zilliz"。 +*** +### FunctionDef _load_zilliz(self) +**_load_zilliz**: 此函数的功能是加载Zilliz服务。 + +**参数**: 此函数没有显式参数,它通过类实例访问成员变量。 + +**代码描述**: `_load_zilliz`函数首先从配置中获取名为`zilliz`的参数,这些参数用于配置Zilliz服务的连接。然后,它创建一个`Zilliz`实例,该实例负责处理嵌入向量的存储和搜索。在创建`Zilliz`实例时,它使用`EmbeddingsFunAdapter`类将当前对象的`embed_model`属性作为嵌入函数传递给`Zilliz`。`EmbeddingsFunAdapter`是一个适配器类,用于将文本转换为嵌入向量,支持同步和异步两种方式。此外,`Zilliz`实例还接收知识库的名称(`kb_name`)和连接参数(`zilliz_args`)。这意味着,每当需要初始化或执行搜索操作时,都会通过`Zilliz`实例与Zilliz服务进行交互,以便处理嵌入向量的存储和相似度搜索。 + +**注意**: +- 在调用`_load_zilliz`函数之前,需要确保`kbs_config`中已经正确配置了`zilliz`参数,包括Zilliz服务的连接信息。 +- `EmbeddingsFunAdapter`类的使用依赖于有效的嵌入模型名称(`embed_model`),该名称应指向一个预先训练好的模型,用于文本嵌入转换。 +- `_load_zilliz`函数通常在知识库服务的初始化(`do_init`)和搜索(`do_search`)过程中被调用,以确保Zilliz服务的连接和配置在进行操作前已经就绪。 + +通过这种方式,`_load_zilliz`函数为知识库服务提供了一个核心功能,即配置和初始化与Zilliz服务的连接,这对于后续的文本嵌入存储和相似度搜索操作至关重要。 +*** +### FunctionDef do_init(self) +**do_init**: 此函数的功能是初始化Zilliz知识库服务。 + +**参数**: 此函数没有显式参数。 + +**代码描述**: `do_init`函数是`ZillizKBService`类的一个方法,用于初始化Zilliz知识库服务。它通过调用`_load_zilliz`方法来加载和配置Zilliz服务。`_load_zilliz`方法负责创建一个Zilliz实例,这个实例用于处理嵌入向量的存储和搜索。这一过程包括从配置中获取Zilliz服务的连接参数,以及使用`EmbeddingsFunAdapter`类将当前对象的`embed_model`属性作为嵌入函数传递给Zilliz实例。这确保了Zilliz服务能够根据预先训练好的模型将文本转换为嵌入向量,并进行存储和相似度搜索操作。 + +**注意**: +- 在调用`do_init`方法之前,应确保已经在`kbs_config`中正确配置了Zilliz服务的连接信息。 +- `do_init`方法通常在知识库服务需要重新初始化时调用,例如在`do_clear_vs`方法中,如果检测到知识库集合已存在,则会先删除现有集合,然后通过调用`do_init`来重新初始化Zilliz服务。 +- 此方法的成功执行对于后续的知识库操作(如文本嵌入存储和相似度搜索)是必要的,因为它确保了Zilliz服务的连接和配置已经就绪。 + +通过`do_init`方法,`ZillizKBService`类能够确保Zilliz知识库服务的正确初始化和配置,为后续的操作提供了基础。 +*** +### FunctionDef do_drop_kb(self) +**do_drop_kb**: 此函数的功能是释放并删除当前的知识库集合。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `do_drop_kb` 函数是`ZillizKBService`类的一个方法,用于处理知识库集合的释放和删除操作。当`ZillizKBService`实例中的`zilliz.col`属性存在时,此方法首先调用`release`方法来释放集合,随后调用`drop`方法来删除集合。这个过程确保了知识库的集合被正确地清理,避免了资源泄露或是不必要的存储占用。 + +在项目中,`do_drop_kb`方法被`do_clear_vs`方法调用。`do_clear_vs`方法的目的是清理视图状态,在清理过程中,它首先调用`do_drop_kb`来释放并删除知识库集合,然后通过调用`do_init`方法重新初始化状态。这表明`do_drop_kb`在知识库管理流程中扮演着重要的角色,确保了知识库的集合在不再需要时能够被正确地处理。 + +**注意**: 使用`do_drop_kb`方法时,需要确保`zilliz.col`属性已经正确初始化,并且在调用此方法后,相关的集合资源将被释放和删除。因此,在调用此方法之前,应当确保不再需要对该集合进行任何操作。 +*** +### FunctionDef do_search(self, query, top_k, score_threshold) +**do_search**: 此函数的功能是执行文本查询的搜索操作,并返回符合条件的文档列表。 + +**参数**: +- `query`: 需要进行搜索的查询文本,数据类型为字符串。 +- `top_k`: 返回的文档数量上限,数据类型为整数。 +- `score_threshold`: 分数阈值,用于筛选相似度高于此阈值的文档,数据类型为浮点数。 + +**代码描述**: +`do_search`函数首先调用`_load_zilliz`方法来加载Zilliz服务,这一步骤确保了与Zilliz服务的连接已经建立,并且相关配置已经就绪。接下来,函数创建了一个`EmbeddingsFunAdapter`实例,该实例使用类中的`embed_model`属性作为嵌入模型。通过`EmbeddingsFunAdapter`的`embed_query`方法,将输入的查询文本`query`转换为嵌入向量。 + +得到嵌入向量后,函数调用`zilliz`实例的`similarity_search_with_score_by_vector`方法,执行相似度搜索操作。此方法接收嵌入向量、`top_k`参数,并返回一个包含文档及其相似度分数的列表。 + +最后,函数调用`score_threshold_process`方法,根据`score_threshold`参数筛选出相似度分数高于阈值的文档,并限制返回的文档数量不超过`top_k`。这一步骤确保了返回的文档列表既符合相似度要求,又满足数量上限的要求。 + +**注意**: +- 在调用`do_search`函数之前,需要确保`embed_model`已经正确配置,且指向一个有效的预训练嵌入模型。 +- `score_threshold`参数允许调用者根据需要筛选相似度较高的文档,如果设置为较低的值,可能会返回更多的文档;如果设置为较高的值,则可能会返回较少的文档。 +- `top_k`参数控制返回的文档数量上限,应根据实际需求合理设置。 + +**输出示例**: +假设输入查询文本为"人工智能",`top_k`为3,`score_threshold`为0.5,且相似度搜索返回的文档及其相似度分数列表为[("doc1", 0.6), ("doc2", 0.4), ("doc3", 0.7), ("doc4", 0.5)]。经过`score_threshold_process`处理后,最终返回的文档列表可能为[("doc1", 0.6), ("doc3", 0.7), ("doc4", 0.5)],表示这三个文档的相似度分数满足大于等于0.5的条件,并且数量不超过3。 +*** +### FunctionDef do_add_doc(self, docs) +**do_add_doc**: 此函数的功能是将文档添加到知识库中,并返回包含文档ID和元数据的列表。 + +**参数**: +- `docs`: 需要添加到知识库中的文档列表,每个文档都是一个Document对象。 +- `**kwargs`: 接收额外的关键字参数,用于扩展或自定义功能。 + +**代码描述**: +此函数首先遍历传入的文档列表`docs`。对于每个文档,它会遍历文档的元数据`metadata`,将所有元数据的值转换为字符串格式。接着,它会检查是否有缺失的字段,如果有,则为这些字段设置默认的空字符串值。此外,函数会从元数据中移除特定的字段,这些字段通常是用于文本和向量表示的字段,由`self.zilliz._text_field`和`self.zilliz._vector_field`指定。 + +在处理完所有文档的元数据后,函数调用`self.zilliz.add_documents(docs)`方法将文档添加到知识库中,并接收返回的文档ID列表。最后,函数构造一个包含文档ID和更新后的元数据的列表,并将其返回。 + +**注意**: +- 确保传入的文档列表中的每个文档都有`metadata`属性,且其值为字典类型。 +- 此函数不处理文本和向量字段的添加,确保在调用此函数之前已经正确设置了这些字段。 +- 传入的文档对象应该是已经准备好添加到知识库的,包括所有必要的元数据和内容。 + +**输出示例**: +```python +[ + {"id": "123", "metadata": {"title": "文档标题1", "author": "作者1"}}, + {"id": "456", "metadata": {"title": "文档标题2", "author": "作者2"}} +] +``` +此示例展示了函数返回值的可能形式,包含了每个文档的ID和更新后的元数据。 +*** +### FunctionDef do_delete_doc(self, kb_file) +**do_delete_doc**: 此函数用于从知识库中删除指定文件的文档。 + +**参数**: +- `kb_file`: KnowledgeFile对象,代表需要删除的知识库文件。 +- `**kwargs`: 接收可变数量的关键字参数,用于扩展或自定义功能。 + +**代码描述**: +`do_delete_doc`函数是`ZillizKBService`类的一个方法,负责删除知识库中与指定文件相关的文档。首先,该函数检查`zilliz`对象的`col`属性是否存在,`col`属性代表当前操作的数据库集合。如果集合存在,则继续执行删除操作。 + +函数通过`kb_file`参数接收一个`KnowledgeFile`对象,该对象包含了知识库文件的详细信息,如文件路径等。为了确保文件路径在数据库查询中正确使用,函数首先将文件路径中的反斜杠(`\`)替换为双反斜杠(`\\`),以适应数据库查询语法。 + +接着,函数使用`self.zilliz.col.query`方法查询与指定文件路径匹配的所有文档,并从查询结果中提取文档的主键(`pk`)列表。这一步是为了找出需要删除的文档的唯一标识符。 + +最后,函数通过`self.zilliz.col.delete`方法,使用提取的主键列表构造删除表达式,从数据库集合中删除这些文档。删除操作的表达式形式为`'pk in {delete_list}'`,其中`{delete_list}`是需要删除的文档主键的列表。 + +**注意**: +- 使用`do_delete_doc`函数时,需要确保传入的`kb_file`对象有效,并且该文件已经在知识库中注册。 +- 删除操作依赖于`zilliz`对象的`col`属性,该属性必须指向一个有效的数据库集合。 +- 文件路径的处理是为了适应数据库查询语法,确保查询和删除操作能够正确执行。 +- 删除操作是基于文档的主键(`pk`)执行的,因此需要确保数据库中的文档有唯一的主键标识。 + +此函数与`KnowledgeFile`对象紧密相关,因为它使用`KnowledgeFile`对象提供的文件路径信息来定位和删除知识库中的文档。通过这种方式,`do_delete_doc`函数支持高效地管理知识库内容,允许用户根据文件信息快速删除相关文档,从而维护知识库的准确性和清洁度。 +*** +### FunctionDef do_clear_vs(self) +**do_clear_vs**: 此函数的功能是清理Zilliz知识库服务的视图状态。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `do_clear_vs`函数是`ZillizKBService`类中的一个方法,用于在特定情况下清理Zilliz知识库服务的视图状态。该方法首先检查`ZillizKBService`实例的`zilliz.col`属性是否存在,这个属性代表当前的知识库集合。如果该属性存在,说明当前有一个活跃的知识库集合,那么`do_clear_vs`方法会进行两个步骤的操作:首先,调用`do_drop_kb`方法来释放并删除当前的知识库集合;其次,调用`do_init`方法来重新初始化Zilliz知识库服务。 + +`do_drop_kb`方法负责释放并删除知识库集合,确保在重新初始化之前,当前的集合资源被正确地清理。而`do_init`方法则用于重新加载和配置Zilliz服务,包括创建新的知识库集合和配置嵌入向量的处理。这一系列操作确保了Zilliz知识库服务可以在清理现有状态后,以正确的配置重新开始服务。 + +**注意**: +- 在调用`do_clear_vs`方法之前,应确保`ZillizKBService`实例已经正确初始化,特别是`zilliz.col`属性,它代表了当前的知识库集合。 +- `do_clear_vs`方法的调用场景通常是在需要重置知识库服务状态时,例如在测试过程中或者在知识库数据结构需要更新时。 +- 由于此方法会删除当前的知识库集合,因此在调用之前应确保不再需要集合中的数据,或者已经做好了数据备份。 +- 此方法的执行会影响Zilliz知识库服务的状态,因此建议在知识库服务的使用低峰时段进行,以避免对正常服务造成影响。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_summary/base.md b/markdown_docs/server/knowledge_base/kb_summary/base.md new file mode 100644 index 000000000..a0f6e7962 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_summary/base.md @@ -0,0 +1,134 @@ +## ClassDef KBSummaryService +**KBSummaryService**: KBSummaryService类的功能是管理和操作知识库摘要的生成、添加和删除。 + +**属性**: +- `kb_name`: 知识库的名称。 +- `embed_model`: 嵌入模型的名称。 +- `vs_path`: 向量存储的路径。 +- `kb_path`: 知识库的路径。 + +**代码描述**: +KBSummaryService类是一个抽象基类(ABC),用于定义操作知识库摘要的基本方法和属性。它主要负责知识库摘要的创建、添加和删除。类的初始化方法接受知识库名称和嵌入模型名称作为参数,并根据这些参数设置知识库路径和向量存储路径。如果向量存储路径不存在,则会创建该路径。 + +- `get_vs_path`方法返回向量存储的完整路径。 +- `get_kb_path`方法返回知识库的完整路径。 +- `load_vector_store`方法负责加载或创建向量存储。 +- `add_kb_summary`方法用于将文档摘要添加到向量存储和数据库中。 +- `create_kb_summary`方法用于创建知识库摘要的存储空间,如果存储空间不存在则创建。 +- `drop_kb_summary`方法用于删除知识库摘要的向量存储和数据库记录。 + +在项目中,`KBSummaryService`类被用于处理知识库摘要的生成和管理。例如,在`recreate_summary_vector_store`和`summary_file_to_vector_store`的场景中,通过`KBSummaryService`类的实例来重新创建或更新知识库的摘要信息。这涉及到从知识库中读取文档,生成摘要,然后将这些摘要添加到向量存储和数据库中。 + +**注意**: +- 在使用`KBSummaryService`类之前,确保已经正确设置了知识库的路径和嵌入模型。 +- 在调用`add_kb_summary`方法之前,应确保摘要信息已经准备好,并且向量存储已经创建。 + +**输出示例**: +由于`KBSummaryService`类的方法主要进行数据处理和存储操作,它们的输出通常不直接返回给用户,而是通过日志记录或数据库状态反映操作结果。例如,当成功添加知识库摘要时,可能会在日志中记录相应的信息,如“知识库'example_kb'的摘要添加成功”。 +### FunctionDef __init__(self, knowledge_base_name, embed_model) +**__init__**: 此函数的功能是初始化KBSummaryService类的实例。 + +**参数**: +- knowledge_base_name: 知识库的名称,类型为字符串。 +- embed_model: 嵌入模型的名称,默认值为EMBEDDING_MODEL,类型为字符串。 + +**代码描述**: `__init__` 方法是 `KBSummaryService` 类的构造函数,用于初始化类的实例。在这个方法中,首先将传入的 `knowledge_base_name` 和 `embed_model` 参数分别赋值给实例变量 `self.kb_name` 和 `self.embed_model`。这两个实例变量分别存储了知识库的名称和使用的嵌入模型名称。 + +接下来,方法调用 `self.get_kb_path()` 和 `self.get_vs_path()` 分别获取知识库的完整路径和向量存储的完整路径,并将这些路径分别赋值给实例变量 `self.kb_path` 和 `self.vs_path`。`get_kb_path` 方法返回知识库文件的完整路径,而 `get_vs_path` 方法则基于 `get_kb_path` 方法返回的路径,进一步构造出向量存储的完整路径。 + +最后,通过检查 `self.vs_path` 指定的路径是否存在,如果不存在,则使用 `os.makedirs` 方法创建该路径。这一步骤确保了向量存储的目录在使用前已经被正确创建。 + +**注意**: 在使用 `__init__` 方法初始化 `KBSummaryService` 类的实例时,需要确保传入的 `knowledge_base_name` 是有效的,且对应的知识库在文件系统中存在。此外,考虑到不同操作系统的路径表示可能有所不同,`get_kb_path` 和 `get_vs_path` 方法内部使用了 `os.path.join` 来构造路径,以确保路径的正确性和兼容性。 +*** +### FunctionDef get_vs_path(self) +**get_vs_path**: 此函数的功能是获取向量存储的完整路径。 + +**参数**: 此函数没有参数。 + +**代码描述**: `get_vs_path` 函数是 `KBSummaryService` 类的一个方法,用于构造并返回知识库摘要向量存储的完整路径。它首先调用 `get_kb_path` 方法获取知识库的完整路径,然后使用 `os.path.join` 方法将此路径与字符串 "summary_vector_store" 拼接起来,从而生成向量存储的完整路径。这个方法在 `KBSummaryService` 类的初始化方法 `__init__` 中被调用,并将生成的路径赋值给实例变量 `self.vs_path`。如果检测到该路径不存在,则会创建对应的目录。 + +**注意**: 使用此函数时,需要确保 `get_kb_path` 方法能够正确返回知识库的路径,且该路径已经存在于文件系统中。此外,考虑到不同操作系统之间的路径表示差异,使用 `os.path.join` 方法可以确保路径的正确性和兼容性。 + +**输出示例**: 假设 `get_kb_path` 方法返回的路径为 "/data/knowledge_bases/tech_docs",那么此函数的返回值将会是 "/data/knowledge_bases/tech_docs/summary_vector_store"。这意味着向量存储将位于知识库 "tech_docs" 下的 "summary_vector_store" 目录中。 +*** +### FunctionDef get_kb_path(self) +**get_kb_path**: 此函数的功能是获取知识库的完整路径。 + +**参数**: 此函数没有参数。 + +**代码描述**: `get_kb_path` 函数是 `KBSummaryService` 类的一个方法,用于返回知识库文件的完整路径。它通过将 `KB_ROOT_PATH`(一个预定义的知识库根路径常量)与 `self.kb_name`(知识库的名称,是在类的初始化时通过参数传入的)使用 `os.path.join` 方法拼接起来,从而构造出知识库的完整路径。这个方法在 `KBSummaryService` 类的初始化方法 `__init__` 中被调用,用于设置实例变量 `self.kb_path`,即知识库路径。此外,它还被 `get_vs_path` 方法调用,作为构造向量存储路径的一部分。 + +在项目中,`get_kb_path` 方法的调用确保了知识库路径的一致性和正确性,无论是直接获取知识库路径还是作为其他路径(如向量存储路径)构建的基础,都能确保路径的准确性。 + +**注意**: 使用此函数时,需要确保 `KB_ROOT_PATH` 和 `self.kb_name` 已经正确设置,且 `KB_ROOT_PATH` 指向的目录存在于文件系统中。此外,考虑到操作系统的差异,`os.path.join` 方法能够确保路径的正确性,无论是在 Windows 还是在类 Unix 系统上。 + +**输出示例**: 假设 `KB_ROOT_PATH` 为 "/data/knowledge_bases",且 `self.kb_name` 为 "tech_docs",那么此函数的返回值将会是 "/data/knowledge_bases/tech_docs"。 +*** +### FunctionDef load_vector_store(self) +**load_vector_store**: 此函数的功能是加载一个线程安全的FAISS向量库实例。 + +**参数**: 此函数没有显式参数,但它依赖于`KBSummaryService`类的实例属性。 + +**代码描述**: `load_vector_store`函数通过调用`kb_faiss_pool.load_vector_store`方法来加载一个FAISS向量库。这个方法接受几个关键参数:`kb_name`(知识库的名称),`vector_name`(向量库的名称,这里固定为"summary_vector_store"),`embed_model`(嵌入模型),以及`create`(一个布尔值,指示如果向量库不存在时是否创建)。这些参数的值来源于`KBSummaryService`类的实例属性。函数返回一个`ThreadSafeFaiss`实例,这是一个线程安全的封装,用于操作和管理FAISS向量库。 + +**注意**: 使用`load_vector_store`函数时,需要确保`KBSummaryService`类的实例属性已正确设置,因为这些属性将直接影响向量库的加载过程。此外,返回的`ThreadSafeFaiss`实例支持线程安全的操作,适用于多线程环境。 + +**输出示例**: 假设`KBSummaryService`的实例属性已正确设置,调用`load_vector_store`可能会返回如下的`ThreadSafeFaiss`实例表示: +`, docs_count: 100>` + +此函数在项目中的调用情况包括在`add_kb_summary`方法中,用于获取向量库实例以添加文档并将其保存到本地路径。这表明`load_vector_store`函数是知识库摘要服务中管理和操作FAISS向量库的关键组成部分,支持知识库摘要的添加和存储过程。 +*** +### FunctionDef add_kb_summary(self, summary_combine_docs) +**add_kb_summary**: 此函数的功能是将文档摘要添加到向量存储并更新数据库。 + +**参数**: +- `summary_combine_docs`: `List[Document]`类型,包含需要添加到向量存储和数据库中的文档摘要信息。 + +**代码描述**: +`add_kb_summary`函数首先通过调用`load_vector_store`方法加载一个线程安全的FAISS向量库实例。接着,使用`acquire`方法安全地获取向量库实例,并向其中添加文档摘要信息,这些信息来自于`summary_combine_docs`参数。添加完成后,向量库的状态会被保存到本地路径。 + +随后,函数构造一个包含摘要信息的列表`summary_infos`,每个摘要信息包括摘要内容、摘要ID、文档ID列表和元数据。这些信息是基于`summary_combine_docs`中每个文档的`page_content`、生成的ID、`metadata`中的`doc_ids`和`metadata`本身。 + +最后,`add_kb_summary`函数调用`add_summary_to_db`函数,将摘要信息添加到数据库中。此操作依赖于当前知识库服务实例的`kb_name`属性和构造的`summary_infos`列表。函数执行成功后,返回`add_summary_to_db`的执行结果,通常是一个表示操作成功的布尔值。 + +**注意**: +- 确保`summary_combine_docs`参数中的每个文档都包含必要的摘要信息和元数据。 +- 在多线程环境下操作向量库和数据库时,函数内部已采取必要的线程安全措施,请避免在外部重复加锁。 +- 函数执行成功并不直接返回摘要信息,而是通过数据库操作的结果来反映操作是否成功。 + +**输出示例**: +调用`add_kb_summary`函数通常不会直接返回具体的摘要信息,而是返回一个布尔值,例如`True`,表示所有摘要信息已成功添加到向量存储并更新到数据库中。 + +在项目中,`add_kb_summary`函数被用于处理知识库文档的摘要信息,支持知识库摘要的创建和更新流程。例如,在知识库摘要API中,通过处理文档文件生成摘要并调用此函数,将摘要信息添加到向量存储和数据库,从而实现知识库的动态更新和管理。 +*** +### FunctionDef create_kb_summary(self) +**create_kb_summary**: 此函数的功能是创建知识库摘要的存储路径。 + +**参数**: 此函数没有参数。 + +**代码描述**: `create_kb_summary` 函数是 `KBSummaryService` 类的一个方法,用于在指定的存储路径不存在时创建该路径。这个方法首先检查 `self.vs_path`(一个类属性,代表知识库摘要的存储路径)是否存在。如果该路径不存在,函数则会使用 `os.makedirs` 方法创建这个路径。这个功能在知识库摘要的生成和存储过程中非常关键,确保了存储知识库摘要的目录是存在的,从而可以顺利地保存摘要数据。 + +在项目中,`create_kb_summary` 函数被 `recreate_summary_vector_store` 和 `summary_file_to_vector_store` 两个方法调用。这两个方法分别位于 `kb_summary_api.py` 文件中,它们的共同点是都会在处理知识库摘要之前调用 `create_kb_summary` 函数来确保摘要数据的存储路径是存在的。无论是重新创建知识库摘要还是将单个文件的摘要信息保存到向量存储中,`create_kb_summary` 都是一个必要的步骤,以保证后续操作的顺利进行。 + +**注意**: 在使用 `create_kb_summary` 函数时,需要确保 `self.vs_path` 已经正确设置为期望的存储路径。此外,考虑到文件系统权限的问题,调用此函数的环境需要有相应的权限来创建目录。 + +**输出示例**: 由于 `create_kb_summary` 函数的主要作用是创建目录,它本身不返回任何值。但是,如果目录创建成功,指定的路径将会存在于文件系统中,这可以通过文件系统的检查工具(如在终端使用 `ls` 命令)来验证。如果之前路径不存在,调用此函数后,你将能够看到新创建的目录。 +*** +### FunctionDef drop_kb_summary(self) +**drop_kb_summary**: 该函数的功能是删除指定知识库的chunk summary。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `drop_kb_summary` 函数是 `KBSummaryService` 类的一个方法,用于删除特定知识库的摘要信息。该方法首先通过 `kb_faiss_pool.atomic` 确保操作的原子性,接着使用 `kb_faiss_pool.pop(self.kb_name)` 从缓存池中移除指定知识库的摘要信息。紧接着,`shutil.rmtree(self.vs_path)` 调用用于删除与知识库相关的向量存储目录。最后,调用 `delete_summary_from_db(kb_name=self.kb_name)` 方法从数据库中删除该知识库的chunk summary信息。 + +在删除过程中,首先确保通过缓存池的原子操作来维护数据一致性,然后从缓存中移除知识库摘要信息,接着删除文件系统中的相关数据,最后从数据库中彻底清除该知识库的摘要信息。这一系列操作确保了知识库摘要的完全删除,避免了数据残留问题。 + +**注意**: +- 在执行此函数之前,确保 `self.kb_name` 和 `self.vs_path` 已正确设置,分别代表了知识库的名称和向量存储的路径。 +- 由于该操作会从缓存、文件系统和数据库中删除数据,因此操作不可逆,请在调用前确保确实需要删除对应的知识库摘要信息。 +- 该函数不返回任何值,但会影响系统中的缓存、文件系统和数据库状态。 + +**输出示例**: 该函数不提供输出示例,因为它不返回任何数据,而是直接对系统状态产生影响。 + +通过对 `drop_kb_summary` 函数的分析,开发者应能理解其在知识库管理中的重要作用,特别是在需要清理或重置知识库摘要信息时。务必谨慎使用此函数,以避免不必要的数据丢失。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_summary/summary_chunk.md b/markdown_docs/server/knowledge_base/kb_summary/summary_chunk.md new file mode 100644 index 000000000..4dfcb3dc6 --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_summary/summary_chunk.md @@ -0,0 +1,190 @@ +## ClassDef SummaryAdapter +**SummaryAdapter**: SummaryAdapter类的功能是实现文档摘要的生成和处理。 + +**属性**: +- `_OVERLAP_SIZE`: 重叠大小,用于处理文档时去除重叠部分。 +- `token_max`: 最大token数量,用于限制生成摘要的最大长度。 +- `_separator`: 分隔符,默认为两个换行符,用于连接文档。 +- `chain`: MapReduceDocumentsChain对象,用于执行文档的映射、规约和摘要合并操作。 + +**代码描述**: +SummaryAdapter类提供了文档摘要的生成、处理和优化的功能。它通过`form_summary`类方法创建实例,该方法接受两个基于语言模型的参数(`llm`和`reduce_llm`),用于生成摘要和合并摘要,以及`overlap_size`和`token_max`参数,分别控制重叠部分的大小和生成摘要的最大token数量。此外,该类还提供了`summarize`和`asummarize`方法,用于同步和异步生成文档摘要,以及`_drop_overlap`和`_join_docs`私有方法,用于处理文档中的重叠部分和连接文档。 + +从功能角度看,SummaryAdapter类在项目中被用于处理和生成知识库文档的摘要。它通过调用`form_summary`方法创建实例,并使用`summarize`方法生成文档摘要。这些摘要随后被用于更新或创建知识库的摘要信息,如在`kb_summary_api.py`文件中的`recreate_summary_vector_store`和`summary_file_to_vector_store`方法中所示。 + +**注意**: +- 在使用SummaryAdapter类时,需要确保提供的语言模型(`llm`和`reduce_llm`)能够有效地生成和合并文档摘要。 +- `overlap_size`和`token_max`参数应根据实际需求和文档的特性进行调整,以优化摘要生成的效果。 +- 在处理大量文档或需要高性能的场景下,应考虑使用`asummarize`方法进行异步摘要生成,以提高处理效率。 + +**输出示例**: +```python +[Document(page_content="这是生成的文档摘要。", metadata={"file_description": "文件描述", "summary_intermediate_steps": "摘要中间步骤", "doc_ids": "文档ID列表"})] +``` +此输出示例展示了`summarize`方法返回的文档摘要列表,其中每个摘要包含了生成的摘要内容、文件描述、摘要生成的中间步骤和文档ID列表等元数据信息。 +### FunctionDef __init__(self, overlap_size, token_max, chain) +**__init__**: 此函数的功能是初始化SummaryAdapter对象。 + +**参数**: +- `overlap_size`: 整型,表示文本块之间重叠的大小。 +- `token_max`: 整型,表示处理的最大令牌数。 +- `chain`: MapReduceDocumentsChain对象,用于处理文档的链式操作。 + +**代码描述**: +此`__init__`方法是`SummaryAdapter`类的构造函数,用于初始化该类的实例。在这个方法中,首先将传入的`overlap_size`参数赋值给私有变量`_OVERLAP_SIZE`,这个变量定义了在文本摘要过程中,文本块之间应该有多大的重叠部分。这是为了确保在处理长文本时,可以平滑地过渡并保持上下文的连贯性。 + +其次,`token_max`参数被直接赋值给实例变量`token_max`,这个参数限制了在文本处理过程中,可以处理的最大令牌(例如,单词或字符)数量。这是为了控制处理的复杂度和资源消耗。 + +最后,`chain`参数是一个`MapReduceDocumentsChain`对象,它被赋值给实例变量`chain`。这个对象代表了一个处理文档的链式操作序列,允许对文档进行复杂的处理流程,如分词、摘要生成等。 + +**注意**: +- 在使用`SummaryAdapter`类时,需要确保传入的`overlap_size`和`token_max`参数是合理的,以避免处理时出现性能问题或结果不准确的情况。 +- `chain`参数需要是一个有效的`MapReduceDocumentsChain`实例,这意味着在使用之前应该正确配置链式操作。 +*** +### FunctionDef form_summary(cls, llm, reduce_llm, overlap_size, token_max) +**form_summary**: 该函数用于形成文本摘要。 + +**参数**: +- **llm**: 用于生成摘要的语言模型。 +- **reduce_llm**: 用于合并摘要的语言模型。 +- **overlap_size**: 文本重叠部分的大小。 +- **token_max**: 每个摘要块的最大token数量,默认为1300。 + +**代码描述**: +`form_summary`函数是`SummaryAdapter`类的一个方法,负责创建一个文本摘要的处理流程。该流程包括使用语言模型生成摘要、合并摘要以及处理文本块以确保每个摘要块的长度不超过指定的最大token数量。函数首先定义了文档格式化的模板,然后定义了一个处理链`llm_chain`,用于生成摘要。接着,定义了另一个处理链`reduce_llm_chain`,用于合并这些摘要。最后,通过`MapReduceDocumentsChain`将生成摘要和合并摘要的流程结合起来,返回一个配置好的摘要处理流程实例。 + +在项目中,`form_summary`函数被多个地方调用,包括重建知识库摘要向量存储、将文件摘要转换为向量存储以及根据文档ID将摘要转换为向量存储等场景。这些调用场景表明,`form_summary`函数是处理知识库文档摘要的核心功能,它能够根据不同的需求生成和合并文档摘要,为知识库的构建和更新提供支持。 + +**注意**: +- 确保传入的`llm`和`reduce_llm`参数是有效的语言模型实例。 +- `overlap_size`和`token_max`参数应根据实际需求合理设置,以优化摘要生成的效果和性能。 +- 该函数返回的是一个配置好的摘要处理流程实例,需要通过调用其`summarize`方法来执行摘要的生成和合并操作。 + +**输出示例**: +由于`form_summary`函数返回的是一个配置好的摘要处理流程实例,而非直接的摘要结果,因此没有直接的输出示例。但在使用返回的实例调用`summarize`方法后,可以得到如下格式的摘要结果: +```json +{ + "code": 200, + "msg": "摘要生成成功", + "summarize": [ + { + "doc_id": "文档ID1", + "summary": "这里是文档摘要内容..." + }, + { + "doc_id": "文档ID2", + "summary": "这里是另一个文档的摘要内容..." + } + ] +} +``` +这个示例展示了摘要处理流程实例在处理完文档后返回的摘要结果格式,其中包含了文档的ID和对应的摘要内容。 +*** +### FunctionDef summarize(self, file_description, docs) +**summarize**: 此函数的功能是同步调用异步生成文档摘要的方法。 + +**参数**: +- `file_description`: 字符串类型,描述文件的内容。 +- `docs`: `DocumentWithVSId` 类型的列表,默认为空列表。这些文档将被用来生成摘要。 + +**代码描述**: +`summarize` 函数是 `SummaryAdapter` 类的一个方法,用于同步调用异步方法 `asummarize` 生成文档的摘要。该函数首先根据 Python 版本检查来决定如何获取或创建事件循环。如果 Python 版本低于 3.10,它将使用 `asyncio.get_event_loop()` 来获取当前事件循环;对于 Python 3.10 及以上版本,它尝试使用 `asyncio.get_running_loop()` 获取正在运行的事件循环,如果失败,则创建一个新的事件循环并设置为当前事件循环。之后,函数通过事件循环的 `run_until_complete` 方法同步调用 `asummarize` 方法,并传入文件描述和文档列表作为参数,最终返回一个包含 `Document` 对象的列表。 + +**注意**: +- 该函数是一个同步包装器,用于在同步代码中调用异步方法 `asummarize`,确保异步方法能够在同步环境中正确执行。 +- 如果传入的文档列表 `docs` 为空,`asummarize` 方法将直接返回一个空的 `Document` 对象列表。 +- 在使用该函数时,需要注意 Python 版本的兼容性问题,以确保事件循环能够正确获取或创建。 + +**输出示例**: +调用 `summarize` 函数可能会返回如下格式的列表: +```python +[ + Document( + page_content="这里是合并后的摘要内容。", + metadata={ + "file_description": "文件描述信息", + "summary_intermediate_steps": "中间步骤的信息", + "doc_ids": "文档ID列表" + } + ) +] +``` +这个列表包含一个 `Document` 对象,其中 `page_content` 属性包含了生成的摘要内容,`metadata` 属性包含了文件描述、中间步骤的信息和文档ID列表。 +*** +### FunctionDef asummarize(self, file_description, docs) +**asummarize**: 此函数的功能是异步生成文档的摘要。 + +**参数**: +- `file_description`: 字符串类型,描述文件的内容。 +- `docs`: `DocumentWithVSId` 类型的列表,默认为空列表。这些文档将被用来生成摘要。 + +**代码描述**: +`asummarize` 函数是`SummaryAdapter`类的一个异步方法,用于处理文档摘要的生成。该过程分为两个主要部分:首先,对每个文档进行处理,得到每个文档的摘要;其次,将这些摘要合并成一个最终的摘要,并且可以返回中间步骤的信息。 + +在处理文档摘要时,该函数首先记录开始生成摘要的日志信息。然后,通过调用`chain.combine_docs`方法,传入文档列表和任务简介,来生成文档的摘要。这个方法会返回合并后的摘要和中间步骤的信息。函数会打印出合并后的摘要和中间步骤的信息,以便于调试和查看。 + +函数还会记录文档ID,并将文件描述、中间步骤的信息以及文档ID作为元数据,与合并后的摘要一起封装成一个`Document`对象。最后,函数返回一个包含这个`Document`对象的列表。 + +**注意**: +- 该函数是异步的,需要在异步环境中调用。 +- 如果传入的文档列表为空,函数将直接返回一个空的`Document`对象列表。 +- 函数中有一段被注释的代码,说明在某些情况下可能需要重新生成摘要,这部分逻辑在当前版本中未被启用。 + +**输出示例**: +调用`asummarize`函数可能会返回如下格式的列表: +```python +[ + Document( + page_content="这里是合并后的摘要内容。", + metadata={ + "file_description": "文件描述信息", + "summary_intermediate_steps": "中间步骤的信息", + "doc_ids": "文档ID列表" + } + ) +] +``` +这个列表包含一个`Document`对象,其中`page_content`属性包含了生成的摘要内容,`metadata`属性包含了文件描述、中间步骤的信息和文档ID列表。 +*** +### FunctionDef _drop_overlap(self, docs) +**_drop_overlap**: 此函数的功能是去除文档列表中页面内容句子重叠的部分。 + +**参数**: +- `docs`: 一个包含DocumentWithVSId实例的列表,每个实例代表一个文档,其中包含页面内容。 + +**代码描述**: +`_drop_overlap` 函数接收一个文档列表作为输入,这些文档通过DocumentWithVSId类的实例表示,每个实例包含一个页面内容属性。该函数的目的是处理文档列表,去除其中页面内容句子重叠的部分,以便于后续的文档处理或摘要生成过程中,减少冗余信息的干扰。 + +函数首先初始化一个空列表`merge_docs`,用于存储处理后的文档内容。然后,通过遍历输入的文档列表`docs`,逐个处理每个文档。对于列表中的第一个文档,其页面内容直接被添加到`merge_docs`列表中,作为处理的起始点。对于后续的文档,函数检查当前文档的页面内容开头是否与前一个文档的页面内容结尾存在重叠部分。如果存在重叠,函数则从当前文档的页面内容中去除这部分重叠的内容,只将非重叠部分添加到`merge_docs`列表中。 + +重叠检测和去除的具体实现是通过迭代减少前一个文档页面内容的长度,并与当前文档页面内容的开头进行比较,直到找到重叠的部分或达到一定的迭代条件。这里使用了`self._OVERLAP_SIZE`和`self._separator`两个属性来辅助确定重叠检测的条件和处理逻辑。 + +**注意**: +- `_drop_overlap`函数依赖于`DocumentWithVSId`类的`page_content`属性来获取文档的页面内容。因此,确保传入的文档列表中的每个实例都包含有效的页面内容。 +- 函数处理的效果和性能可能会受到`self._OVERLAP_SIZE`和`self._separator`值的影响,适当调整这些值可以优化处理结果。 + +**输出示例**: +假设有两个文档的页面内容分别为"今天天气不错,适合出去玩。适合出去玩,不要忘记带伞。"和"适合出去玩,不要忘记带伞。明天也是好天气。",经过`_drop_overlap`函数处理后,返回的`merge_docs`列表可能如下: +``` +["今天天气不错,适合出去玩。适合出去玩,不要忘记带伞。", "明天也是好天气。"] +``` +这表示第二个文档中与第一个文档重叠的部分已被成功去除。 +*** +### FunctionDef _join_docs(self, docs) +**_join_docs**: 此函数的功能是将字符串列表连接成一个字符串,并在必要时返回None。 + +**参数**: +- `docs`: 字符串列表,即要连接的文档列表。 + +**代码描述**: +`_join_docs` 函数接收一个字符串列表作为参数。它使用实例变量 `_separator` 作为分隔符,将这些字符串连接成一个新的字符串。然后,它会去除新字符串两端的空白字符。如果处理后的字符串为空(即长度为0),函数将返回 `None`;否则,返回处理后的字符串。 + +这个函数的设计考虑到了可能存在的空字符串或全空白字符的字符串列表,确保在这种情况下不会返回一个空字符串而是返回 `None`,这在很多情况下对于后续的逻辑判断是有帮助的。 + +**注意**: +- `_separator` 应该在类的其他部分被定义,它决定了如何在字符串之间插入分隔符。如果 `_separator` 没有被正确定义,这个函数可能不会按预期工作。 +- 传入的 `docs` 列表不能为空,否则函数将返回 `None`。 + +**输出示例**: +假设 `_separator` 被定义为逗号 `,`,并且 `docs` 参数为 `["Hello", "world", "!"]`,那么函数的返回值将是 `"Hello,world,!"`。如果 `docs` 为空列表,或者列表中的所有字符串都是空或者只包含空白字符,函数将返回 `None`。 +*** diff --git a/markdown_docs/server/knowledge_base/kb_summary_api.md b/markdown_docs/server/knowledge_base/kb_summary_api.md new file mode 100644 index 000000000..11bac1c3d --- /dev/null +++ b/markdown_docs/server/knowledge_base/kb_summary_api.md @@ -0,0 +1,169 @@ +## FunctionDef recreate_summary_vector_store(knowledge_base_name, allow_empty_kb, vs_type, embed_model, file_description, model_name, temperature, max_tokens) +**recreate_summary_vector_store**: 此函数的功能是重建单个知识库文件摘要。 + +**参数**: +- `knowledge_base_name`: 知识库的名称,类型为字符串。 +- `allow_empty_kb`: 是否允许空的知识库,布尔类型,默认为True。 +- `vs_type`: 向量存储类型,字符串类型,默认值由`DEFAULT_VS_TYPE`变量决定。 +- `embed_model`: 嵌入模型名称,字符串类型,默认值由`EMBEDDING_MODEL`变量决定。 +- `file_description`: 文件描述,字符串类型,默认为空字符串。 +- `model_name`: LLM模型名称,字符串类型,默认值为`LLM_MODELS`列表的第一个元素。 +- `temperature`: LLM采样温度,浮点数类型,必须在0.0到1.0之间。 +- `max_tokens`: 限制LLM生成Token的数量,整数类型或None,默认为None,代表使用模型的最大值。 + +**代码描述**: +`recreate_summary_vector_store`函数主要用于重建指定知识库的文件摘要。首先,通过`KBServiceFactory.get_service`方法获取知识库服务实例。如果指定的知识库不存在且不允许空的知识库,则返回404错误。否则,会先删除现有的知识库摘要,然后重新创建。接着,利用指定的LLM模型参数创建文本摘要适配器,并对知识库中的每个文件进行摘要处理。每处理完一个文件,就会向客户端发送一个包含处理状态的JSON消息。如果在处理某个文件时出错,则会记录错误信息并跳过该文件。 + +此函数通过`EventSourceResponse`返回一个生成器,该生成器会逐步产生处理每个文件的状态信息,使得客户端可以实时获取处理进度。 + +在项目中,`recreate_summary_vector_store`函数被`server/api.py/mount_filename_summary_routes`中的`mount_filename_summary_routes`函数调用,并注册为FastAPI的一个POST路由。这表明该函数主要用于处理HTTP POST请求,用于在Web服务中重建知识库文件摘要。 + +**注意**: +- 确保在调用此函数之前,已经正确设置了`DEFAULT_VS_TYPE`、`EMBEDDING_MODEL`、`LLM_MODELS`等全局变量。 +- 函数处理过程中可能会产生大量日志,建议监控日志以便及时发现和解决问题。 +- 调用此函数可能需要较长的处理时间,特别是当知识库文件数量较多时。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "(1 / 10): example_file.txt", + "total": 10, + "finished": 1, + "doc": "example_file.txt" +} +``` +此JSON表示第一个文件`example_file.txt`已经处理完成,总共需要处理10个文件。 +### FunctionDef output +**output**: 此函数的功能是输出知识库摘要的创建或更新过程中的状态信息。 + +**参数**: 此函数没有参数。 + +**代码描述**: `output` 函数是一个生成器,用于在知识库摘要的创建或更新过程中,逐步输出处理状态信息。首先,通过 `KBServiceFactory.get_service` 方法获取知识库服务实例。如果指定的知识库不存在且不允许空知识库,则生成并返回一个包含错误代码404和相应消息的字典。否则,会重新创建知识库摘要,包括删除旧的知识库摘要和创建新的知识库摘要。 + +接下来,函数初始化两个 `ChatOpenAI` 实例,`llm` 和 `reduce_llm`,用于生成和合并文本摘要。然后,通过 `SummaryAdapter.form_summary` 方法创建一个摘要适配器实例,用于处理文本摘要。 + +函数遍历知识库中的文件,对每个文件使用 `kb.list_docs` 方法获取文档信息,并通过摘要适配器的 `summary.summarize` 方法生成摘要。如果摘要成功添加到知识库摘要中,则输出一个包含成功状态的JSON字符串;如果在添加摘要过程中出错,则输出一个包含错误信息的JSON字符串。 + +此函数与项目中的其他组件紧密相关,特别是与知识库服务 (`KBServiceFactory`)、摘要生成 (`ChatOpenAI` 和 `SummaryAdapter`) 相关联。它通过调用这些组件的方法,实现了知识库摘要的自动化创建和更新过程,并通过生成器逐步返回处理状态,为知识库管理提供了实时反馈。 + +**注意**: +- 确保在调用此函数之前,知识库名称、嵌入模型等参数已正确配置,以确保能够正确初始化知识库服务和摘要生成器。 +- 此函数作为生成器,需要在循环或迭代器中使用,以获取所有的状态信息。 +- 在处理大量文件或大型知识库时,此函数可能需要较长时间执行,建议异步调用或在后台任务中执行。 +*** +## FunctionDef summary_file_to_vector_store(knowledge_base_name, file_name, allow_empty_kb, vs_type, embed_model, file_description, model_name, temperature, max_tokens) +**summary_file_to_vector_store**: 此函数的功能是根据文件名称对单个知识库进行摘要,并将摘要结果存储到向量存储中。 + +**参数**: +- `knowledge_base_name`: 知识库的名称,示例值为"samples"。 +- `file_name`: 需要进行摘要的文件名称,示例值为"test.pdf"。 +- `allow_empty_kb`: 是否允许空的知识库,默认为True。 +- `vs_type`: 向量存储的类型,默认值由`DEFAULT_VS_TYPE`指定。 +- `embed_model`: 嵌入模型的名称,默认值由`EMBEDDING_MODEL`指定。 +- `file_description`: 文件的描述,默认为空字符串。 +- `model_name`: LLM模型的名称,默认值为`LLM_MODELS`数组的第一个元素,用于指定使用的语言模型。 +- `temperature`: LLM采样温度,取值范围为0.0至1.0,默认值由`TEMPERATURE`指定。 +- `max_tokens`: 限制LLM生成的Token数量,若为None则代表使用模型的最大值,默认为None。 + +**代码描述**: +`summary_file_to_vector_store`函数主要负责将指定文件的内容进行摘要,并将摘要结果存储到向量存储中。首先,通过`KBServiceFactory.get_service`获取知识库服务实例。如果指定的知识库不存在且不允许空的知识库,则返回404错误。否则,使用`KBSummaryService`创建知识库摘要服务,并调用`create_kb_summary`方法重新创建知识库摘要。接着,初始化两个LLM模型实例用于生成摘要。通过`SummaryAdapter.form_summary`方法,结合LLM模型和文件描述,对文件内容进行摘要。最后,将摘要结果添加到知识库摘要中,并根据操作结果返回相应的状态码和信息。 + +在项目中,`summary_file_to_vector_store`函数被`server/api.py/mount_filename_summary_routes`对象调用,用于处理HTTP POST请求,实现根据文件名称对单个知识库进行摘要的API接口。这表明该函数是知识库管理功能中处理文件摘要的核心逻辑部分。 + +**注意**: +- 确保传入的`knowledge_base_name`和`file_name`有效,以避免处理不存在的知识库或文件。 +- `allow_empty_kb`参数在知识库为空时特别有用,可以根据实际需求调整其值。 +- 调用此函数时,需要注意`model_name`、`temperature`和`max_tokens`参数的设置,以确保摘要生成的效果符合预期。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "test.pdf 总结完成", + "doc": "test.pdf" +} +``` +或在知识库不存在时: +```json +{ + "code": 404, + "msg": "未找到知识库 ‘samples’" +} +``` +### FunctionDef output +**output**: 此函数的功能是输出知识库摘要的处理结果。 + +**参数**: 此函数没有参数。 + +**代码描述**: `output` 函数是知识库摘要API中的一个关键组成部分,主要负责输出知识库摘要的处理结果。首先,通过 `KBServiceFactory.get_service` 方法获取知识库服务实例。如果指定的知识库不存在且不允许空知识库,则返回404状态码和相应的错误信息。如果知识库存在或允许空知识库,函数将继续执行以下步骤: + +1. 使用 `KBSummaryService` 创建或更新知识库摘要。 +2. 通过 `get_ChatOpenAI` 方法初始化两个语言模型实例,用于生成和优化文本摘要。 +3. 使用 `SummaryAdapter.form_summary` 方法配置文本摘要的生成流程。 +4. 通过 `KBService.list_docs` 方法获取指定文件的文档列表。 +5. 调用 `SummaryAdapter.summarize` 方法生成文档摘要。 +6. 将生成的文档摘要添加到知识库摘要中,并检查操作是否成功。 + +如果知识库摘要添加成功,函数将记录日志信息并返回200状态码、成功信息和文件名。如果在添加知识库摘要时发生错误,函数将记录错误信息并返回500状态码和错误信息。 + +**注意**: +- 在调用 `output` 函数之前,需要确保知识库名称、向量存储类型和嵌入模型等参数已经正确配置。 +- `get_ChatOpenAI` 方法返回的语言模型实例用于生成和优化文本摘要,确保传入的模型名称、温度和最大token数量等参数符合预期。 +- `SummaryAdapter.form_summary` 方法配置的文本摘要生成流程包括文档的格式化、摘要生成和摘要合并等步骤,需要根据实际需求调整参数。 +- 在处理大量文档或执行复杂的摘要生成任务时,应注意性能和资源消耗,可能需要优化算法或调整系统资源。 + +此函数在知识库摘要API中扮演着核心角色,通过综合利用知识库服务、语言模型和文本摘要适配器等组件,实现了知识库文档摘要的自动化生成和更新。 +*** +## FunctionDef summary_doc_ids_to_vector_store(knowledge_base_name, doc_ids, vs_type, embed_model, file_description, model_name, temperature, max_tokens) +**summary_doc_ids_to_vector_store**: 此函数的功能是根据文档ID列表生成单个知识库的文档摘要,并将摘要信息存储到向量存储中。 + +**参数**: +- `knowledge_base_name`: 知识库名称,字符串类型,默认示例为"samples"。 +- `doc_ids`: 文档ID列表,列表类型,默认为空列表,示例值为["uuid"]。 +- `vs_type`: 向量存储类型,字符串类型,默认值由`DEFAULT_VS_TYPE`变量决定。 +- `embed_model`: 嵌入模型名称,字符串类型,默认值由`EMBEDDING_MODEL`变量决定。 +- `file_description`: 文件描述,字符串类型,默认为空字符串。 +- `model_name`: LLM模型名称,字符串类型,默认值为`LLM_MODELS`列表的第一个元素,用于描述使用的语言模型。 +- `temperature`: LLM采样温度,浮点数类型,用于控制生成文本的多样性,默认值由`TEMPERATURE`变量决定,取值范围为0.0至1.0。 +- `max_tokens`: 限制LLM生成Token数量,整型或None,默认为None代表模型最大值。 + +**代码描述**: +函数首先通过`KBServiceFactory.get_service`方法获取知识库服务实例。如果指定的知识库不存在,则返回404状态码和相应的错误信息。否则,函数将初始化两个`ChatOpenAI`实例,分别用于生成文档摘要和合并摘要。接着,使用`SummaryAdapter.form_summary`方法创建文本摘要适配器,并通过知识库服务实例的`get_doc_by_ids`方法获取文档信息。然后,将文档信息转换为`DocumentWithVSId`对象,并调用摘要适配器的`summarize`方法生成文档摘要。最后,将生成的文档摘要转换为字典格式并返回,状态码为200,表示操作成功。 + +**注意**: +- 确保传入的知识库名称、文档ID列表和向量存储类型等参数正确无误,以避免查询错误或操作失败。 +- 在调用此函数之前,请确保知识库服务已正确配置,包括知识库存在性、向量存储类型和嵌入模型等。 +- 函数依赖于`ChatOpenAI`实例进行文档摘要的生成和合并,因此需要确保提供的模型名称、采样温度和Token数量限制等参数适合于所使用的语言模型。 + +**输出示例**: +调用`summary_doc_ids_to_vector_store`函数可能会返回如下格式的响应: +```json +{ + "code": 200, + "msg": "总结完成", + "data": { + "summarize": [ + { + "id": "文档ID1", + "page_content": "这里是文档摘要内容...", + "metadata": { + "file_description": "文件描述信息", + "summary_intermediate_steps": "摘要中间步骤信息", + "doc_ids": "文档ID列表" + } + }, + { + "id": "文档ID2", + "page_content": "这里是另一个文档的摘要内容...", + "metadata": { + "file_description": "文件描述信息", + "summary_intermediate_steps": "摘要中间步骤信息", + "doc_ids": "文档ID列表" + } + } + ] + } +} +``` +此输出示例展示了函数在处理完文档后返回的摘要结果格式,其中包含了文档的ID、摘要内容和相关的元数据信息。 diff --git a/markdown_docs/server/knowledge_base/migrate.md b/markdown_docs/server/knowledge_base/migrate.md new file mode 100644 index 000000000..85b9d04b5 --- /dev/null +++ b/markdown_docs/server/knowledge_base/migrate.md @@ -0,0 +1,166 @@ +## FunctionDef create_tables +**create_tables**: 此函数的功能是创建数据库表。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `create_tables` 函数是在数据库迁移过程中使用的关键函数,用于创建数据库中定义的所有表。它通过调用 `Base.metadata.create_all` 方法并将 `engine` 作为绑定参数来实现。这里的 `Base` 是一个ORM声明基类,它存储了所有模型(即表)的元数据,而 `engine` 是SQLAlchemy的连接引擎,用于执行对数据库的实际操作。 + +在项目中,`create_tables` 函数被多个对象调用,显示了其在不同场景下的重要性: +- 在初始化数据库(`init_database.py`)、服务器启动(`startup.py`)时,确保所需的表结构已经创建。 +- 在重置表(`server/knowledge_base/migrate.py/reset_tables`)时,先删除所有表,然后重新调用此函数来创建表,用于测试或重置数据库环境。 +- 在各种测试场景中(如`tests/kb_vector_db/test_faiss_kb.py/test_init`、`tests/kb_vector_db/test_milvus_db.py/test_init`、`tests/kb_vector_db/test_pg_db.py/test_init`),确保测试前数据库表结构正确设置。 + +**注意**: 使用此函数时,需要确保`Base`和`engine`已经正确初始化,且所有的表模型都已经通过`Base`定义。此外,调用此函数将会创建所有未存在的表,如果表已经存在,则不会对其进行修改,这意味着它不会更新或修改现有表结构。因此,在生产环境中使用时应谨慎,以避免数据丢失。 +## FunctionDef reset_tables +**reset_tables**: 此函数的功能是重置数据库表。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `reset_tables` 函数是数据库迁移过程中的一个重要环节,用于重置数据库环境。它首先调用 `Base.metadata.drop_all` 方法删除所有现有的表结构,然后通过调用 `create_tables` 函数重新创建表结构。这个过程通常用于测试或者在需要彻底清理数据库并重新设置表结构的场景下。 + +在这个函数中,`Base.metadata.drop_all(bind=engine)` 负责删除所有表,其中 `Base` 是ORM声明基类,存储了所有模型(即表)的元数据,`engine` 是SQLAlchemy的连接引擎,用于执行对数据库的实际操作。紧接着,`create_tables()` 被调用以重新创建数据库中定义的所有表。这确保了数据库环境可以被重置到一个干净的初始状态。 + +**注意**: 在调用 `reset_tables` 函数时,需要确保 `Base` 和 `engine` 已经被正确初始化,并且所有的表模型都已经通过 `Base` 定义。此外,由于此函数会删除所有现有的表并重新创建,因此在生产环境中使用时应格外小心,以避免不必要的数据丢失。在测试或开发环境中使用此函数可以帮助快速重置数据库状态,便于进行环境的清理和重建。 +## FunctionDef import_from_db(sqlite_path) +**import_from_db**: 该函数的功能是从备份数据库中导入数据到 info.db。 + +**参数**: +- `sqlite_path`: 字符串类型,指定 SQLite 数据库的路径。默认为 None。 + +**代码描述**: +`import_from_db` 函数主要用于在知识库与向量库无变化的情况下,从备份的 SQLite 数据库中导入数据到当前的 info.db 数据库中。这种情况通常出现在版本升级时,info.db 的结构发生了变化,但数据本身不需要重新向量化处理。函数开始时,会导入必要的模块,包括 `sqlite3` 用于操作 SQLite 数据库,以及 `pprint` 用于打印数据。 + +函数内部首先获取数据库模型列表,然后尝试连接到指定的 SQLite 数据库。通过查询 SQLite 的 `sqlite_master` 表,获取并遍历所有表名。对于每一个模型对应的表,如果表存在于数据库中,则会进一步读取该表的所有数据。对于每一行数据,函数会根据模型定义的列名过滤出需要的字段,并特别处理 `create_time` 字段,将其解析为正确的时间格式。之后,使用 `session_scope` 上下文管理器自动管理数据库会话,将过滤并处理后的数据添加到会话中,最终提交到数据库。 + +如果在数据导入过程中遇到任何异常,函数会打印错误信息,并返回 False 表示导入失败。否则,在成功处理所有数据后关闭数据库连接,并返回 True 表示导入成功。 + +**注意**: +- 请确保传入的 `sqlite_path` 是正确的 SQLite 数据库文件路径。 +- 确保备份数据库中的表名和字段名与当前数据库模型一致。 +- 该函数目前仅支持 SQLite 数据库。 +- 使用该函数导入数据时,应确保没有其他操作正在访问目标数据库,以避免数据冲突。 + +**输出示例**: +- 成功导入数据时,函数返回 `True`。 +- 如果无法读取备份数据库或遇到其他错误,函数返回 `False`。 +## FunctionDef file_to_kbfile(kb_name, files) +**file_to_kbfile**: 该函数的功能是将文件列表转换为KnowledgeFile对象列表。 + +**参数**: +- `kb_name`: 字符串类型,表示知识库的名称。 +- `files`: 字符串列表,包含需要转换的文件名。 + +**代码描述**: `file_to_kbfile`函数接收知识库名称和文件名列表作为输入参数,遍历文件列表,为每个文件创建一个`KnowledgeFile`实例。在实例化`KnowledgeFile`过程中,如果遇到任何异常,该文件会被跳过,并且异常信息会被记录到日志中。函数最终返回一个`KnowledgeFile`对象的列表,这些对象包含了文件与知识库名称的关联信息以及其他由`KnowledgeFile`类提供的文件处理功能。 + +**注意**: +- 在调用此函数之前,需要确保传入的文件列表中的文件都存在于磁盘上。 +- 如果文件格式不被支持,或者在创建`KnowledgeFile`实例的过程中出现其他问题,相关文件将被跳过,错误信息会被记录。 +- 日志记录的详细程度取决于全局日志配置中`log_verbose`的设置。 + +**输出示例**: +假设有一个文件列表`["document1.md", "document2.txt"]`和知识库名称`"demo_kb"`,调用`file_to_kbfile("demo_kb", ["document1.md", "document2.txt"])`可能会返回如下`KnowledgeFile`对象列表(具体内容取决于文件内容和`KnowledgeFile`类的实现): +```python +[ + KnowledgeFile(filename="document1.md", knowledge_base_name="demo_kb"), + KnowledgeFile(filename="document2.txt", knowledge_base_name="demo_kb") +] +``` +这个列表中的每个`KnowledgeFile`对象都代表了一个与知识库`demo_kb`关联的文件,可以进一步用于知识库的文件处理、文档加载和文本分割等操作。 + +在项目中,`file_to_kbfile`函数被用于多个场景,包括但不限于将本地文件夹中的文件转换为知识库文件、更新知识库中的文件、从知识库中删除文件等。例如,在`folder2db`函数中,它被用来将指定文件夹中的文件转换为`KnowledgeFile`对象,然后这些对象可以用于向量库的创建或更新;在`prune_db_docs`函数中,它用于识别并删除那些在本地文件夹中已经不存在的知识库文件。 +## FunctionDef folder2db(kb_names, mode, vs_type, embed_model, chunk_size, chunk_overlap, zh_title_enhance) +**folder2db**: 此函数的功能是使用本地文件夹中的现有文件来填充数据库和/或向量存储。 + +**参数**: +- `kb_names`: 知识库名称列表,类型为 `List[str]`。 +- `mode`: 迁移模式,可选值为 `"recreate_vs"`, `"update_in_db"`, `"increment"`,类型为 `Literal["recreate_vs", "update_in_db", "increment"]`。 +- `vs_type`: 向量存储类型,可选值为 `"faiss"`, `"milvus"`, `"pg"`, `"chromadb"`,默认值为 `DEFAULT_VS_TYPE`,类型为 `Literal["faiss", "milvus", "pg", "chromadb"]`。 +- `embed_model`: 嵌入模型名称,默认值为 `EMBEDDING_MODEL`,类型为 `str`。 +- `chunk_size`: 分块大小,默认值为 `CHUNK_SIZE`,类型为 `int`。 +- `chunk_overlap`: 分块重叠大小,默认值为 `OVERLAP_SIZE`,类型为 `int`。 +- `zh_title_enhance`: 是否增强中文标题,默认值为 `ZH_TITLE_ENHANCE`,类型为 `bool`。 + +**代码描述**: +此函数根据提供的参数,从本地文件夹中读取文件,并根据指定的迁移模式将文件信息填充到数据库和/或向量存储中。支持的迁移模式包括: +- `recreate_vs`:重新创建所有向量存储,并使用本地文件夹中的现有文件填充数据库信息。 +- `update_in_db`:使用数据库中已存在的本地文件更新向量存储和数据库信息。 +- `increment`:为数据库中不存在的本地文件创建向量存储和数据库信息。 + +函数首先检查是否提供了知识库名称列表,如果没有,则调用 `list_kbs_from_folder` 函数获取所有知识库目录名称。然后,根据指定的向量存储类型和嵌入模型名称,通过 `KBServiceFactory.get_service` 方法获取相应的知识库服务实例。根据迁移模式的不同,函数执行相应的操作,如清除向量存储、创建知识库、更新向量存储等。 + +**注意**: +- 在使用此函数之前,确保本地文件夹中存在目标知识库的相关文件。 +- 根据迁移模式的不同,操作可能会涉及到重建向量存储或更新数据库信息,这可能会对现有数据产生影响,请谨慎操作。 +- 函数内部通过调用多个辅助函数和服务实例方法来完成具体的操作,确保这些辅助函数和方法已正确实现并可用。 + +在项目中,`folder2db` 函数被用于初始化数据库 (`init_database.py`) 和测试迁移功能 (`tests/test_migrate.py`),包括测试重新创建向量存储 (`test_recreate_vs`) 和增量更新 (`test_increment`)。这些调用情况表明,`folder2db` 函数是知识库迁移和管理流程中的关键组件,用于根据本地文件夹中的文件更新或重建数据库和向量存储。 +### FunctionDef files2vs(kb_name, kb_files) +**files2vs**: 此函数的功能是将文件批量转换并添加到向量库中。 + +**参数**: +- `kb_name`: 字符串类型,表示知识库的名称。 +- `kb_files`: `KnowledgeFile`对象的列表,表示要处理并添加到向量库的文件列表。 + +**代码描述**: +`files2vs`函数主要负责将给定的文件列表(`kb_files`)批量处理并添加到指定的知识库(`kb_name`)中。这个过程涉及以下几个步骤: + +1. 调用`files2docs_in_thread`函数,该函数使用多线程将文件列表中的每个文件转换成文档列表。这个过程中,会根据文件的内容和一系列参数(如文档分块大小`chunk_size`、分块重叠大小`chunk_overlap`、是否增强中文标题`zh_title_enhance`等)进行处理。 + +2. 对于`files2docs_in_thread`函数的每个返回结果,首先检查转换是否成功。如果成功,会获取转换后的文件名和文档列表。 + +3. 对于每个成功转换的文件,创建一个新的`KnowledgeFile`实例,并将文件名、知识库名称以及分割处理后的文档列表(`splited_docs`)设置给这个实例。 + +4. 调用`KBService`的`add_doc`方法,将上一步创建的`KnowledgeFile`实例添加到知识库中。在这个过程中,不刷新向量库缓存(`not_refresh_vs_cache=True`)。 + +5. 如果转换失败,则打印错误信息。 + +此函数通过上述步骤,实现了将文件内容批量转换并添加到知识库的向量库中,以支持后续的搜索和检索功能。 + +**注意**: +- 在使用`files2vs`函数时,需要确保传入的`kb_name`和`kb_files`参数正确且有效。`kb_files`中的每个`KnowledgeFile`对象都应该是可以被正确处理的文件。 +- `files2docs_in_thread`函数的多线程处理可以提高文件转换的效率,但在使用时也需要注意线程安全问题。 +- `add_doc`方法的调用不刷新向量库缓存,这意味着在添加大量文档后,可能需要手动刷新缓存以确保向量库的数据是最新的。 +*** +## FunctionDef prune_db_docs(kb_names) +**prune_db_docs**: 此函数的功能是删除数据库中不存在于本地文件夹中的文档。 + +**参数**: +- `kb_names`: 字符串列表,包含需要进行清理操作的知识库名称。 + +**代码描述**: `prune_db_docs` 函数通过遍历传入的知识库名称列表 `kb_names`,对每一个知识库执行以下操作: +1. 使用 `KBServiceFactory.get_service_by_name` 方法根据知识库名称获取对应的知识库服务实例。如果该实例存在,则继续执行;如果不存在,则跳过当前知识库。 +2. 调用知识库服务实例的 `list_files` 方法获取数据库中的文件列表。 +3. 调用 `list_files_from_folder` 函数获取本地文件夹中的文件列表。 +4. 计算出存在于数据库中但不在本地文件夹中的文件列表。 +5. 使用 `file_to_kbfile` 函数将步骤4中得到的文件列表转换为 `KnowledgeFile` 对象列表。 +6. 遍历 `KnowledgeFile` 对象列表,对每个对象调用知识库服务实例的 `delete_doc` 方法删除数据库中的文档,并打印成功删除的文档信息。 +7. 调用知识库服务实例的 `save_vector_store` 方法保存向量库的状态。 + +**注意**: +- 确保在调用此函数之前,传入的知识库名称列表 `kb_names` 中的每个知识库都已经在数据库中注册并正确配置。 +- 此函数用于同步本地文件夹和数据库中的文档状态,特别适用于用户在文件浏览器中删除了某些文档文件后,需要从数据库中也删除这些文档的场景。 +- 在删除数据库中的文档时,`delete_doc` 方法的 `not_refresh_vs_cache` 参数被设置为 `True`,这意味着在删除操作后不立即刷新向量库缓存。向量库的状态将在所有删除操作完成后通过 `save_vector_store` 方法统一保存。 +- 函数执行过程中,会打印每个成功删除的文档的信息,包括知识库名称和文件名,以便于跟踪操作结果。 + +通过以上步骤,`prune_db_docs` 函数能够有效地从数据库中删除那些已经不再存在于本地文件夹中的文档,从而保持数据库内容的准确性和最新性。 +## FunctionDef prune_folder_files(kb_names) +**prune_folder_files**: 此函数的功能是删除本地文件夹中不存在于数据库中的文档文件,用于通过删除未使用的文档文件释放本地磁盘空间。 + +**参数**: +- `kb_names`: 一个字符串列表,表示需要处理的知识库的名称。 + +**代码描述**: +`prune_folder_files` 函数接收一个包含知识库名称的列表作为参数。对于列表中的每一个知识库名称,函数首先使用 `KBServiceFactory.get_service_by_name` 方法尝试获取对应的知识库服务实例。如果成功获取到服务实例,则继续执行以下步骤: + +1. 调用知识库服务实例的 `list_files` 方法获取数据库中存储的文件列表。 +2. 使用 `list_files_from_folder` 函数获取本地文件夹中的文件列表。 +3. 通过集合运算找出存在于本地文件夹中但不在数据库文件列表中的文件,这些文件被认为是未使用的文件。 +4. 对于每一个未使用的文件,使用 `os.remove` 方法删除该文件,并打印删除成功的消息。 + +此过程确保了本地存储空间不会被数据库中已经不存在的文件占用,从而优化了存储资源的使用。 + +**注意**: +- 在调用此函数之前,需要确保提供的知识库名称列表中的每个名称都是有效的,并且对应的知识库服务实例可以成功获取。 +- 该函数依赖于 `KBServiceFactory.get_service_by_name`、`list_files_from_folder` 和 `get_file_path` 函数,因此需要确保这些依赖函数能够正常工作。 +- 删除文件操作是不可逆的,因此在执行此函数之前应确保已经正确备份了重要数据。 +- 函数执行过程中会打印每个被删除文件的信息,可以通过这些信息跟踪删除操作的执行情况。 diff --git a/markdown_docs/server/knowledge_base/model/kb_document_model.md b/markdown_docs/server/knowledge_base/model/kb_document_model.md new file mode 100644 index 000000000..34481e217 --- /dev/null +++ b/markdown_docs/server/knowledge_base/model/kb_document_model.md @@ -0,0 +1,18 @@ +## ClassDef DocumentWithVSId +**DocumentWithVSId**: DocumentWithVSId 类的功能是表示一个经过向量化处理的文档。 + +**属性**: +- `id`: 文档的唯一标识符,类型为字符串。 +- `score`: 文档的评分,初始默认值为3.0,类型为浮点数。 + +**代码描述**: +DocumentWithVSId 类继承自 Document 类,用于表示一个经过向量化处理的文档。这个类主要用于知识库系统中,对文档进行向量化处理后,通过这个类的实例来表示处理结果。类中定义了两个属性:`id` 和 `score`。`id` 属性用于存储文档的唯一标识符,而 `score` 属性则用于存储文档在某些操作(如搜索或排序)中的评分或相关性度量。 + +在项目中,DocumentWithVSId 类的实例主要用于以下几个场景: +1. 在搜索知识库文档时,返回的搜索结果会包含一系列 DocumentWithVSId 实例,其中每个实例代表一个搜索到的文档,其 `score` 属性表示该文档与搜索查询的匹配程度。 +2. 在列出知识库文档时,如果需要根据特定的文件名或元数据进行过滤,返回的结果也可能包含 DocumentWithVSId 实例。 +3. 在文档摘要生成过程中,DocumentWithVSId 实例用于表示需要进行摘要处理的文档,其中 `id` 属性用于标识具体的文档。 + +**注意**: +- 在使用 DocumentWithVSId 类时,需要注意 `id` 属性的唯一性,确保每个实例能够准确地对应到知识库中的一个具体文档。 +- `score` 属性的值可能会根据不同的操作或上下文环境有所变化,因此在使用时应注意其含义和计算方式。 diff --git a/markdown_docs/server/knowledge_base/utils.md b/markdown_docs/server/knowledge_base/utils.md new file mode 100644 index 000000000..3ab8e49e8 --- /dev/null +++ b/markdown_docs/server/knowledge_base/utils.md @@ -0,0 +1,529 @@ +## 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', '加载文档时出错:错误信息')) +``` +*** diff --git a/markdown_docs/server/llm_api.md b/markdown_docs/server/llm_api.md new file mode 100644 index 000000000..8b36cde69 --- /dev/null +++ b/markdown_docs/server/llm_api.md @@ -0,0 +1,202 @@ +## FunctionDef list_running_models(controller_address, placeholder) +**list_running_models**: 此函数的功能是从fastchat controller获取已加载模型列表及其配置项。 + +**参数**: +- `controller_address`: 字符串类型,Fastchat controller服务器地址。如果未提供,则会尝试从`fschat_controller_address()`函数获取默认地址。 +- `placeholder`: 字符串类型,该参数未使用,仅作为占位符。 + +**代码描述**: +`list_running_models`函数首先检查`controller_address`参数是否提供,如果未提供,则调用`fschat_controller_address()`函数获取Fastchat控制器的默认地址。随后,函数使用`get_httpx_client()`函数创建一个HTTP客户端实例,并向`controller_address`指定的地址发送POST请求,请求路径为`/list_models`。请求成功后,从响应中解析出模型列表,并对每个模型调用`get_model_config()`函数获取其配置项,最后将模型及其配置项以字典形式包装在`BaseResponse`对象中返回。 + +在异常处理方面,如果在执行过程中遇到任何异常,函数会记录错误信息,并返回一个`code`为500的`BaseResponse`对象,同时在`msg`字段中提供错误详情。 + +**注意**: +- 确保提供的`controller_address`是有效的Fastchat控制器地址,否则无法成功获取模型列表。 +- 该函数依赖于`get_httpx_client()`和`get_model_config()`函数,确保这些依赖函数能够正常工作。 +- 函数使用POST请求与Fastchat控制器通信,确保控制器支持`/list_models`路径的处理。 +- 在处理异常时,函数会记录详细的错误信息,有助于调试和问题定位。 + +**输出示例**: +```python +{ + "code": 200, + "msg": "success", + "data": { + "model1": { + "model_version": "1.0", + "language": "English", + // 其他配置项 + }, + "model2": { + "model_version": "2.0", + "language": "Chinese", + // 其他配置项 + } + // 更多模型及其配置项 + } +} +``` +此示例展示了函数调用成功时可能返回的响应格式,其中`data`字段包含了每个模型及其配置项的详细信息,而`code`和`msg`字段表示请求处理成功。 +## FunctionDef list_config_models(types, placeholder) +**list_config_models**: 此函数的功能是从本地获取configs中配置的模型列表。 + +**参数**: +- `types`: 类型为`List[str]`,默认值为`["local", "online"]`。此参数用于指定需要获取的模型配置项类别,例如`local`、`online`、`worker`等。 +- `placeholder`: 类型为`str`,默认值为`None`。此参数为占位用,调用时无实际效果,主要用于API设计的扩展性。 + +**代码描述**: +`list_config_models`函数首先定义了一个空字典`data`,用于存储最终的模型配置信息。函数通过调用`list_config_llm_models`函数获取所有配置的大型语言模型(LLM)的不同类型。然后,函数遍历这些模型类型,如果模型类型存在于`types`参数中,则通过调用`get_model_config`函数获取每个模型的详细配置信息,并将这些信息添加到`data`字典中。最后,函数返回一个`BaseResponse`对象,其中`data`字段包含了根据`types`参数筛选后的模型配置信息。 + +**注意**: +- 在使用此函数时,需要确保`types`参数中包含的模型类型已经在系统中正确配置,否则可能无法获取到预期的配置信息。 +- 此函数通过`BaseResponse`对象返回数据,确保了API响应的一致性和标准化。调用方可以通过检查`BaseResponse`对象中的`code`和`msg`字段来判断请求处理的状态和结果。 + +**输出示例**: +```python +{ + "code": 200, + "msg": "success", + "data": { + "local": { + "model1": { + "config1": "value1", + "config2": "value2" + }, + "model2": { + "config1": "value1", + "config2": "value2" + } + }, + "online": { + "model3": { + "config1": "value1", + "config2": "value2" + }, + "model4": { + "config1": "value1", + "config2": "value2" + } + } + } +} +``` +此输出示例展示了函数调用成功时可能返回的响应格式,其中`data`字段包含了根据`types`参数筛选后的模型配置信息,而`code`和`msg`字段表示请求处理成功。 +## FunctionDef get_model_config(model_name, placeholder) +**get_model_config**: 此函数的功能是获取LLM模型的配置项(合并后的)。 + +**参数**: +- `model_name`: 字符串类型,通过Body传入,描述为"配置中LLM模型的名称",用于指定需要获取配置的模型名称。 +- `placeholder`: 字符串类型,通过Body传入,描述为"占位用,无实际效果",此参数在函数内部没有被使用,仅作为API设计时的占位符。 + +**代码描述**: +`get_model_config`函数首先定义了一个空字典`config`,用于存储过滤后的模型配置项。函数通过调用`get_model_worker_config`函数,传入`model_name`参数,获取指定模型的工作配置项。然后,函数遍历这些配置项,通过一系列条件判断(排除包含"worker_class"、"key"、"secret"或以"id"结尾的键),过滤掉敏感信息或不需要公开的配置项,并将剩余的配置项添加到`config`字典中。 + +最后,函数返回一个`BaseResponse`对象,其中`data`字段包含了过滤后的模型配置项。这样,调用方可以通过标准的API响应格式,获取到所需的模型配置信息。 + +**注意**: +- 在使用此函数时,需要确保传入的`model_name`参数正确,且对应的模型配置已经在系统中正确配置,否则可能无法获取到预期的配置信息。 +- 此函数通过过滤敏感信息来保护模型配置的安全性,因此返回的配置项中不会包含可能泄露模型内部实现细节的信息。 +- 返回的`BaseResponse`对象中的`code`、`msg`字段可以用于判断请求处理的状态和结果,确保调用方可以正确处理响应数据。 + +**输出示例**: +```python +{ + "code": 200, + "msg": "success", + "data": { + "model_version": "1.0", + "language": "English", + // 其他非敏感配置项 + } +} +``` +此示例展示了函数调用成功时可能返回的响应格式,其中`data`字段包含了过滤后的模型配置项,而`code`和`msg`字段表示请求处理成功。 +## FunctionDef stop_llm_model(model_name, controller_address) +**stop_llm_model**: 此函数的功能是向fastchat controller请求停止某个LLM模型。 + +**参数**: +- `model_name`: 要停止的LLM模型的名称,此参数是必需的。 +- `controller_address`: Fastchat controller服务器的地址,此参数是可选的。如果未提供,则会使用`fschat_controller_address`函数获取默认地址。 + +**代码描述**: +`stop_llm_model`函数主要用于停止指定的LLM模型。首先,如果没有提供`controller_address`参数,函数会调用`fschat_controller_address`来获取Fastchat控制器的地址。然后,使用`get_httpx_client`函数获取一个httpx客户端实例,通过这个客户端向Fastchat控制器发送POST请求,请求的URL是由控制器地址和`/release_worker`路径组成,请求体中包含了要停止的模型名称。如果请求成功,函数将返回控制器的响应内容。在异常情况下,函数会记录错误信息并返回一个包含错误信息的`BaseResponse`对象。 + +**注意**: +- 在调用此函数时,确保提供的模型名称是正确且当前正在运行的。如果模型名称错误或模型未运行,可能会导致停止操作失败。 +- 如果未能成功连接到Fastchat控制器或控制器处理请求失败,函数会返回一个包含错误信息的`BaseResponse`对象,其中`code`为500,表示服务器内部错误。 +- 由于Fastchat的实现方式,停止LLM模型实际上是停止了模型所在的model_worker。 + +**输出示例**: +假设成功停止了名为"example_model"的LLM模型,函数可能返回如下的`BaseResponse`对象: +```python +{ + "code": 200, + "msg": "success", + "data": null +} +``` +如果尝试停止一个不存在的模型,或者与Fastchat控制器的通信失败,返回的`BaseResponse`对象可能如下: +```python +{ + "code": 500, + "msg": "failed to stop LLM model example_model from controller: http://127.0.0.1:8080。错误信息是: ConnectionError", + "data": null +} +``` +## FunctionDef change_llm_model(model_name, new_model_name, controller_address) +**change_llm_model**: 此函数的功能是向fastchat controller请求切换LLM模型。 + +**参数**: +- `model_name`: 字符串类型,表示当前运行的模型名称。 +- `new_model_name`: 字符串类型,表示要切换到的新模型名称。 +- `controller_address`: 字符串类型,表示Fastchat controller服务器的地址。如果未提供,则会使用`fschat_controller_address`函数获取默认地址。 + +**代码描述**: +`change_llm_model`函数首先检查`controller_address`参数是否提供,如果未提供,则调用`fschat_controller_address`函数获取Fastchat controller的地址。然后,使用`get_httpx_client`函数获取一个httpx客户端实例,用于发送HTTP POST请求到controller地址的`/release_worker`端点。请求的JSON体包含`model_name`和`new_model_name`字段,分别表示当前模型和要切换到的新模型。请求超时时间由`HTTPX_DEFAULT_TIMEOUT`常量定义。如果请求成功,函数将返回controller的响应JSON。在遇到异常时,函数会记录错误日志,并返回一个包含错误信息的`BaseResponse`对象。 + +**注意**: +- 确保`controller_address`正确指向Fastchat controller服务器,否则请求将失败。 +- 使用此函数时,应确保`model_name`和`new_model_name`正确且对应的模型在服务器上可用。 +- 函数中使用了`get_httpx_client`来获取httpx客户端实例,确保了代理设置和超时配置的正确应用,同时也支持了异常处理和日志记录。 + +**输出示例**: +成功切换模型时,可能的返回值示例为: +```json +{ + "code": 200, + "msg": "Model switched successfully", + "data": { + "previous_model": "old_model_name", + "current_model": "new_model_name" + } +} +``` +在遇到错误时,返回值示例为: +```json +{ + "code": 500, + "msg": "failed to switch LLM model from controller: http://127.0.0.1:8080。错误信息是:ConnectionError" +} +``` +## FunctionDef list_search_engines +**list_search_engines**: 此函数的功能是列出服务器支持的搜索引擎。 + +**参数**: 此函数没有参数。 + +**代码描述**: `list_search_engines` 函数首先从 `server.chat.search_engine_chat` 模块导入 `SEARCH_ENGINES` 变量,该变量包含了服务器支持的所有搜索引擎的列表。然后,函数使用 `BaseResponse` 类构造一个响应对象,其中 `data` 字段被设置为 `SEARCH_ENGINES` 列表的内容。`BaseResponse` 类是一个标准化的 API 响应格式,包含 `code`、`msg` 和 `data` 三个字段,分别表示 API 的状态码、状态消息和返回的数据内容。在本函数中,只需关注 `data` 字段,它被用来存放搜索引擎列表。 + +**注意**: +- `list_search_engines` 函数返回的是一个 `BaseResponse` 对象,因此在调用此函数时,应当处理这个对象,以获取其中的数据。 +- 由于 `SEARCH_ENGINES` 是从另一个模块导入的,确保该变量在导入前已正确定义和初始化。 +- 此函数没有接收任何参数,因此可以直接调用而无需提供额外的信息。 + +**输出示例**: +调用 `list_search_engines` 函数可能返回的示例响应如下: +```python +{ + "code": 200, + "msg": "success", + "data": ["Google", "Bing", "DuckDuckGo"] +} +``` +此示例中,`code` 和 `msg` 字段表示请求成功处理,而 `data` 字段包含了一个列表,列出了服务器支持的搜索引擎名称。 diff --git a/markdown_docs/server/llm_api_stale.md b/markdown_docs/server/llm_api_stale.md new file mode 100644 index 000000000..dea130331 --- /dev/null +++ b/markdown_docs/server/llm_api_stale.md @@ -0,0 +1,72 @@ +## FunctionDef string_args(args, args_list) +**string_args**: 此函数的功能是将参数对象中的键值对转换成字符串格式,以便在命令行中使用。 + +**参数**: +- args: 包含参数的对象,此对象应具备一个名为 `_get_kwargs` 的方法,该方法返回对象中所有键值对的迭代器。 +- args_list: 一个字符串列表,指定需要转换为字符串的参数键名。 + +**代码描述**: +`string_args` 函数接受两个参数:`args` 和 `args_list`。`args` 是一个对象,它通过 `_get_kwargs` 方法提供了一系列的键值对。`args_list` 是一个字符串列表,指定了需要包含在最终字符串中的参数键名。 + +函数首先初始化一个空字符串 `args_str`,用于累积最终的参数字符串。然后,它遍历 `args` 对象的键值对。对于每个键值对,函数首先将键名中的下划线 (`_`) 替换为短横线 (`-`),因为命令行参数通常使用短横线而不是下划线。接着,函数检查处理后的键名是否在 `args_list` 中指定的参数列表里。如果不在,则跳过当前键值对,不将其加入到最终的字符串中。 + +对于需要处理的键值对,如果键名是 `port` 或 `host`,则去除键名中的前缀,只保留 `port` 或 `host`。这是因为在某些上下文中,如 `fastchat`,`port` 和 `host` 参数可能不需要前缀。 + +接下来,函数根据值的类型构建参数字符串。对于布尔值 `True`,只需添加键名前缀为 `--` 的参数;对于列表、元组或集合,将值转换为以空格分隔的字符串;对于其他类型的值,直接将键值对转换为字符串格式,并加入到 `args_str` 中。 + +最后,函数返回构建好的参数字符串 `args_str`。 + +**在项目中的调用关系**: +`string_args` 函数在项目中被多个地方调用,包括 `launch_worker`、`launch_all`、`launch_api` 和 `launch_webui` 函数。这些调用点传递不同的参数对象和参数列表给 `string_args` 函数,以生成特定上下文中所需的命令行参数字符串。这表明 `string_args` 函数在项目中扮演着构建命令行参数字符串的核心角色,为启动不同的服务组件提供支持。 + +**注意**: +- 确保传递给 `string_args` 函数的 `args` 对象具有 `_get_kwargs` 方法。 +- 在使用 `string_args` 函数时,应仔细定义 `args_list`,确保只包含需要转换为命令行参数的键名。 + +**输出示例**: +假设 `args` 对象包含 `{ 'model_path': 'path/to/model', 'worker_host': 'localhost', 'worker_port': 8080, 'use_ssl': True }`,且 `args_list` 为 `['model-path', 'worker-host', 'worker-port', 'use-ssl']`,则 `string_args` 函数的输出可能为: +``` +--model path/to/model --host localhost --port 8080 --ssl +``` +## FunctionDef launch_worker(item, args, worker_args) +**launch_worker**: 此函数的功能是启动一个工作进程。 + +**参数**: +- item: 一个字符串,包含模型路径、工作进程主机和端口的组合,格式为"model-path@worker-host@worker-port"。 +- args: 一个对象,包含了启动工作进程所需的各种参数。 +- worker_args: 一个列表,指定了需要转换为字符串的工作进程参数键名。 + +**代码描述**: +`launch_worker` 函数首先通过对 `item` 参数进行分割,提取出模型路径、工作进程主机和端口,然后构建工作进程的地址。接着,函数打印一条消息,提示用户如果工作进程长时间未启动,可以查看日志文件以获取更多信息。此日志文件的名称是基于 `item` 参数生成的,其中的特殊字符会被替换以确保文件名的有效性。 + +函数随后调用 `string_args` 函数,将 `args` 和 `worker_args` 转换为字符串格式的命令行参数。这些参数将用于构建启动工作进程的 shell 命令。`base_launch_sh` 和 `base_check_sh` 是两个格式化字符串,分别用于生成启动和检查工作进程的 shell 命令。这些命令通过 `subprocess.run` 函数执行,以实际启动和检查工作进程。 + +**注意**: +- 确保 `item` 参数的格式正确,即包含模型路径、工作进程主机和端口,且以 "@" 分隔。 +- `args` 对象应包含所有必要的参数,并且应具有 `_get_kwargs` 方法,以便 `string_args` 函数能够正确处理。 +- `worker_args` 应为一个列表,包含了需要转换为命令行参数的键名。 +- 此函数依赖于外部定义的 `base_launch_sh` 和 `base_check_sh` 格式化字符串,以及 `LOG_PATH` 常量,确保这些依赖在调用函数前已正确定义和初始化。 +- 使用此函数时,应注意检查相关日志文件,以便在出现问题时能够迅速定位和解决。 +## FunctionDef launch_all(args, controller_args, worker_args, server_args) +**launch_all**: 此函数的功能是启动整个LLM服务,包括控制器、工作进程和服务器。 + +**参数**: +- args: 包含启动服务所需的各种参数的对象。 +- controller_args: 控制器启动所需的参数列表。 +- worker_args: 工作进程启动所需的参数列表。 +- server_args: 服务器启动所需的参数列表。 + +**代码描述**: +`launch_all` 函数首先打印日志路径信息,提示用户LLM服务正在启动,并且可以在指定的日志路径下监控各模块的日志。接着,函数使用 `string_args` 函数将 `args` 对象和 `controller_args` 列表转换为字符串格式的命令行参数,用于构建启动控制器的 shell 命令。这些命令通过 `subprocess.run` 函数执行,以实际启动控制器并检查其运行状态。 + +对于工作进程的启动,函数首先判断 `args.model_path_address` 是否为字符串。如果是,直接调用 `launch_worker` 函数启动单个工作进程。如果不是,说明有多个模型路径,函数将遍历这些路径,并对每个路径调用 `launch_worker` 函数启动对应的工作进程。 + +最后,函数同样使用 `string_args` 函数将 `args` 对象和 `server_args` 列表转换为字符串格式的命令行参数,用于构建启动服务器的 shell 命令。这些命令通过 `subprocess.run` 函数执行,以实际启动服务器并检查其运行状态。函数结束时,打印消息提示LLM服务启动完毕。 + +**注意**: +- 确保传递给 `launch_all` 函数的 `args` 对象包含所有必要的参数,并且这些参数正确无误。 +- `controller_args`、`worker_args` 和 `server_args` 列表应仔细配置,确保包含启动相应组件所需的所有参数键名。 +- `launch_worker` 函数的调用依赖于 `args.model_path_address` 的格式和内容,如果有多个模型路径,请确保它是一个列表或元组。 +- 此函数涉及到多个外部依赖(如 `base_launch_sh`、`base_check_sh` 和 `LOG_PATH`),请确保这些依赖在调用函数前已正确定义和初始化。 +- 启动过程中可能需要一定时间,特别是工作进程的启动,可能需要3-10分钟不等,请耐心等待。 +- 函数中的日志信息同时使用了中英文,以适应不同用户的需求。 diff --git a/markdown_docs/server/memory/conversation_db_buffer_memory.md b/markdown_docs/server/memory/conversation_db_buffer_memory.md new file mode 100644 index 000000000..09ed17599 --- /dev/null +++ b/markdown_docs/server/memory/conversation_db_buffer_memory.md @@ -0,0 +1,130 @@ +## ClassDef ConversationBufferDBMemory +**ConversationBufferDBMemory**: ConversationBufferDBMemory类的功能是管理和维护与特定对话ID相关的消息缓存,以支持基于历史对话的智能助手响应生成。 + +**属性**: +- `conversation_id`: 字符串,表示对话的唯一标识。 +- `human_prefix`: 字符串,默认为"Human",用于标识人类用户的消息前缀。 +- `ai_prefix`: 字符串,默认为"Assistant",用于标识智能助手的消息前缀。 +- `llm`: BaseLanguageModel的实例,表示底层使用的语言模型。 +- `memory_key`: 字符串,默认为"history",用于标识存储在内存中的对话历史的键。 +- `max_token_limit`: 整数,表示对话历史中允许的最大令牌数。 +- `message_limit`: 整数,表示从数据库中检索的最大消息数量。 + +**代码描述**: +ConversationBufferDBMemory类继承自BaseChatMemory,主要负责处理与对话相关的历史消息的缓存和管理。它通过`conversation_id`定位特定的对话,并根据需要从数据库中检索历史消息。通过`buffer`属性,可以获取到一个经过处理的消息列表,其中包括了人类用户和智能助手的交互消息。这个列表在超出最大令牌限制时会进行裁剪,以确保不会因为历史消息过多而影响性能。`memory_variables`属性和`load_memory_variables`方法用于处理内存变量,支持智能助手基于历史对话生成响应。`save_context`和`clear`方法在这个类中被设计为不执行任何操作,因为所有必要的历史信息都是即时从数据库中检索的。 + +在项目中,ConversationBufferDBMemory类被用于`server/chat/chat.py/chat/chat_iterator`中,以管理和提供对话历史信息。当需要基于历史对话内容生成智能助手的响应时,此类提供的历史消息缓存被用作输入,以辅助生成更加自然和上下文相关的回复。 + +**注意**: +- 在使用ConversationBufferDBMemory类时,需要确保提供有效的`conversation_id`以定位特定的对话。 +- 应注意`max_token_limit`和`message_limit`的设置,以平衡性能和对话历史的完整性。 + +**输出示例**: +假设数据库中有关于特定对话ID的10条消息记录,调用`buffer`属性可能返回如下格式的列表: +```python +[ + HumanMessage(content="你好,助手。"), + AIMessage(content="你好!有什么可以帮助你的吗?"), + HumanMessage(content="我想了解天气预报。"), + AIMessage(content="请告诉我你的城市。"), + ... +] +``` +这个列表包含了人类用户和智能助手之间的交互消息,可用于生成后续的智能助手响应。 +### FunctionDef buffer(self) +**buffer**: 此函数的功能是获取并处理对话缓存中的消息。 + +**参数**: 此函数没有参数。 + +**代码描述**: `buffer`函数首先调用`filter_message`函数,根据当前会话的ID和消息限制来获取最近的聊天记录。这些记录默认按时间降序排列,即最新的消息位于列表的前端。为了让消息顺序与实际对话顺序一致(即早期的消息在前),函数将这个列表反转。 + +接下来,函数遍历这些消息,对于每一条消息,它将用户的查询(query)和系统的回答(response)分别封装成`HumanMessage`和`AIMessage`对象,并将它们添加到`chat_messages`列表中。这样做是为了将原始的文本消息转换为更具体的消息类型,便于后续处理。 + +如果`chat_messages`列表为空,即没有任何消息,则函数直接返回一个空列表。 + +此外,函数还会检查`chat_messages`中的消息总数是否超过了设定的最大令牌限制(`max_token_limit`)。如果超过了,它将从列表的开头开始移除消息,直到总令牌数不再超过限制。这一步骤是为了确保消息缓存不会因为过多的消息而导致处理过程中出现问题。 + +**注意**: +- 在调用此函数之前,需要确保已经正确设置了会话ID(`conversation_id`)和消息限制(`message_limit`)。 +- 此函数依赖于`filter_message`函数来获取聊天记录,因此需要保证数据库连接正常,且`filter_message`函数能够正确执行。 +- 消息的处理(如反转列表、封装成特定类型的消息对象、剪裁消息)是为了适应后续处理流程的需要,开发者在修改或扩展功能时应考虑这些设计决策。 + +**输出示例**: 假设`max_token_limit`足够大,不需要剪裁消息,函数可能会返回如下格式的列表: +``` +[ + HumanMessage(content="用户的问题1"), + AIMessage(content="系统的回答1"), + HumanMessage(content="用户的问题2"), + AIMessage(content="系统的回答2"), + ... +] +``` +此列表包含了按对话顺序排列的消息对象,每个用户的查询和系统的回答都被封装成了相应的消息对象。 +*** +### FunctionDef memory_variables(self) +**memory_variables**: 此函数的功能是始终返回内存变量的列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `memory_variables` 函数是 `ConversationBufferDBMemory` 类的一个方法,它的主要作用是返回一个包含内存键(memory key)的列表。这个内存键是与会话缓冲数据库内存相关联的一个标识符,用于在内部跟踪和管理会话数据。通过这个函数,可以方便地获取当前对象中用于标识内存数据的关键字。此函数被标记为私有(通过 `:meta private:`),这意味着它主要用于类内部,而不建议在类的外部直接调用。 + +**注意**: 虽然此函数被标记为私有,但了解其功能对于理解类如何管理其内部状态是有帮助的。在扩展或修改 `ConversationBufferDBMemory` 类的行为时,应当谨慎使用此函数,以避免破坏类的封装性。 + +**输出示例**: +```python +['memory_key_example'] +``` +在这个示例中,`memory_key_example` 是一个假设的内存键值,实际使用时,它将被替换为实际的内存键,该键是一个字符串,用于唯一标识会话缓冲数据库内存中的数据。 +*** +### FunctionDef load_memory_variables(self, inputs) +**load_memory_variables**: 此函数的功能是返回历史缓冲区。 + +**参数**: +- inputs: 一个字典,包含函数处理所需的输入参数。 + +**代码描述**: `load_memory_variables`函数主要负责处理和返回对话历史缓冲区的内容。首先,它通过访问`self.buffer`属性获取当前的对话缓冲区内容。`buffer`属性的获取和处理逻辑在`ConversationBufferDBMemory`类的`buffer`方法中定义,该方法负责从数据库中检索对话历史,并根据需要进行格式化和裁剪。 + +如果`self.return_messages`属性为真,表示需要直接返回缓冲区中的消息,则`final_buffer`将直接设置为`buffer`的内容。否则,会调用`get_buffer_string`函数,将缓冲区中的消息转换成一个字符串,转换过程中会根据`self.human_prefix`和`self.ai_prefix`为人类和AI的消息添加前缀,以便区分。 + +最终,函数以字典形式返回缓冲区内容,其中键为`self.memory_key`,值为处理后的`final_buffer`。这样的设计使得函数的输出可以灵活地应用于不同的上下文中,例如保存到数据库或作为API响应的一部分返回。 + +**注意**: +- 在调用`load_memory_variables`函数之前,确保已经正确初始化了`ConversationBufferDBMemory`对象,并且相关属性(如`human_prefix`、`ai_prefix`等)已经被正确设置。 +- 该函数依赖于`buffer`方法和`get_buffer_string`函数正确执行,因此在使用前应确保这些依赖项的逻辑正确无误。 +- 根据`return_messages`属性的不同,返回的缓冲区内容格式可能会有所不同,开发者在使用时应注意区分处理。 + +**输出示例**: +假设`self.memory_key`为"conversation_history",且`self.return_messages`为假,`human_prefix`为"User:",`ai_prefix`为"AI:",则函数可能返回如下格式的字典: +``` +{ + "conversation_history": "User: 你好吗?\nAI: 我很好,谢谢。" +} +``` +此字典包含了一个键值对,键为"conversation_history",值为经过格式化的对话历史字符串。 +*** +### FunctionDef save_context(self, inputs, outputs) +**save_context**: 此函数的功能是不保存或更改任何内容。 + +**参数**: +- **inputs**: 一个字典,包含任意类型的值,用于表示输入数据。 +- **outputs**: 一个字典,其值为字符串类型,用于表示输出数据。 + +**代码描述**: +`save_context` 函数是 `ConversationBufferDBMemory` 类的一个方法,设计用于处理对话上下文的保存。然而,根据函数内的注释和实现,此函数实际上并不执行任何操作。它接收两个参数:`inputs` 和 `outputs`。`inputs` 参数是一个字典,其键为字符串类型,值为任意类型,代表了函数的输入数据。`outputs` 参数也是一个字典,但其值被限定为字符串类型,代表了函数的输出数据。尽管函数提供了处理输入和输出数据的参数,但在函数体内部,仅包含一个 `pass` 语句,意味着调用此函数不会有任何副作用,也不会改变任何状态或数据。 + +**注意**: +- 虽然 `save_context` 方法提供了参数以供潜在的数据处理,但实际上它不执行任何操作。这可能是因为在特定的应用场景中,需要一个占位符或者框架上的方法,以便在未来根据需要实现具体的功能。 +- 开发者在使用此函数时应当注意,它不会对输入的 `inputs` 和 `outputs` 数据进行保存或更改。如果在应用中需要对这些数据进行处理,需要实现额外的逻辑或使用其他方法。 +- 此函数的存在可能是为了保持代码的一致性或满足接口要求,而不是为了实现具体的业务逻辑。 +*** +### FunctionDef clear(self) +**函数名称**: clear + +**函数功能**: 清除对话缓存数据库内的所有数据。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `clear` 函数的设计初衷是为了提供一种机制,用于清除对话缓存数据库内的所有数据。然而,在当前的实现中,该函数内部并没有具体的执行逻辑。函数体中的注释“Nothing to clear, got a memory like a vault.” 暗示了这个函数可能是在一个特定的上下文中使用,其中实际上并不需要清除内存中的数据,或者是这个函数作为一个占位符,预留给未来可能的实现。因此,在当前的代码版本中,调用这个函数不会有任何实际的效果。 + +**注意**: 虽然当前的`clear`函数不执行任何操作,但开发者在使用时应当注意,这个函数的存在可能是为了未来的扩展性考虑。在未来的版本中,这个函数可能会被实现具体的逻辑。因此,在调用这个函数时,开发者应当留意后续版本的更新,以确保兼容性和功能的正确性。此外,即使在当前版本中该函数不执行任何操作,开发者也应当遵循良好的编程实践,不要在不必要的场合调用它,以保持代码的清晰和高效。 +*** diff --git a/markdown_docs/server/minx_chat_openai.md b/markdown_docs/server/minx_chat_openai.md new file mode 100644 index 000000000..b229de5ef --- /dev/null +++ b/markdown_docs/server/minx_chat_openai.md @@ -0,0 +1,61 @@ +## ClassDef MinxChatOpenAI +**MinxChatOpenAI**: MinxChatOpenAI类的功能是提供与tiktoken库交互的方法,用于导入tiktoken库和获取编码模型。 + +**属性**: +此类主要通过静态方法实现功能,不直接使用属性存储数据。 + +**代码描述**: +MinxChatOpenAI类包含两个静态方法:`import_tiktoken`和`get_encoding_model`。 + +- `import_tiktoken`方法尝试导入`tiktoken`包,如果导入失败,则抛出`ValueError`异常,提示用户需要安装`tiktoken`。这是为了确保后续操作可以使用`tiktoken`包提供的功能。 + +- `get_encoding_model`方法负责根据模型名称获取相应的编码模型。它首先尝试从`tiktoken`库中获取指定模型的编码信息。如果模型名称是`gpt-3.5-turbo`或`gpt-4`,方法会自动调整为对应的具体版本,以适应模型可能的更新。如果指定的模型在`tiktoken`库中找不到,将使用默认的`cl100k_base`编码模型,并记录一条警告信息。 + +在项目中,`MinxChatOpenAI`类的`get_encoding_model`方法被`get_ChatOpenAI`函数调用,以配置和初始化`ChatOpenAI`实例。这表明`MinxChatOpenAI`类提供的功能是为`ChatOpenAI`实例获取正确的编码模型,这对于处理和理解聊天内容至关重要。 + +**注意**: +- 使用`MinxChatOpenAI`类之前,请确保已经安装了`tiktoken`包,否则将无法成功导入和使用。 +- 在调用`get_encoding_model`方法时,需要注意传入的模型名称是否正确,以及是否准备好处理可能的异常和警告。 + +**输出示例**: +调用`get_encoding_model`方法可能返回的示例输出为: +```python +("gpt-3.5-turbo-0301", ) +``` +这表示方法返回了模型名称和对应的编码对象。 +### FunctionDef import_tiktoken +**import_tiktoken**: 该函数的功能是导入tiktoken库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `import_tiktoken` 函数尝试导入 `tiktoken` Python包。如果导入失败,即 `tiktoken` 包未安装在环境中,函数将抛出一个 `ImportError` 异常。为了向用户提供清晰的错误信息,函数捕获了这个异常并抛出一个新的 `ValueError`,提示用户需要安装 `tiktoken` 包以计算 `get_token_ids`。这个函数是 `MinxChatOpenAI` 类的一部分,主要用于在需要使用 `tiktoken` 功能时确保该库已被导入。在项目中,`import_tiktoken` 被 `get_encoding_model` 方法调用,用于获取特定模型的编码信息。这表明 `tiktoken` 库在处理模型编码方面起着关键作用。 + +在 `get_encoding_model` 方法中,首先通过调用 `import_tiktoken` 函数来确保 `tiktoken` 库可用。然后,根据模型名称(`self.tiktoken_model_name` 或 `self.model_name`)获取相应的编码信息。如果指定的模型名称不被支持,将使用默认的编码模型。这个过程展示了 `import_tiktoken` 在项目中的实际应用,即作为获取模型编码前的必要步骤。 + +**注意**: 使用此函数前,请确保已经安装了 `tiktoken` 包。如果未安装,可以通过运行 `pip install tiktoken` 来安装。此外,当 `tiktoken` 包导入失败时,函数将抛出一个 `ValueError`,提示需要安装该包。开发者应当注意捕获并妥善处理这一异常,以避免程序在未安装 `tiktoken` 包时崩溃。 + +**输出示例**: 由于此函数的目的是导入 `tiktoken` 包,因此它不直接返回数据。成功执行后,它将返回 `tiktoken` 模块对象,允许后续代码调用 `tiktoken` 的功能。例如,成功导入后,可以使用 `tiktoken.encoding_for_model(model_name)` 来获取指定模型的编码信息。 +*** +### FunctionDef get_encoding_model(self) +**get_encoding_model**: 该函数的功能是获取指定模型的编码信息。 + +**参数**: 此函数没有参数。 + +**代码描述**: `get_encoding_model` 方法首先尝试通过调用 `import_tiktoken` 函数来导入 `tiktoken` 库,确保后续操作可以使用 `tiktoken` 提供的功能。接着,根据实例变量 `self.tiktoken_model_name` 或 `self.model_name` 来确定需要获取编码信息的模型名称。如果 `self.tiktoken_model_name` 不为 `None`,则直接使用该值;否则,使用 `self.model_name`。对于特定的模型名称,如 "gpt-3.5-turbo" 或 "gpt-4",方法内部会将其转换为具体的版本名称,以适应模型可能随时间更新的情况。之后,尝试使用 `tiktoken_.encoding_for_model(model)` 获取指定模型的编码信息。如果在此过程中发生异常(例如模型名称不被支持),则会捕获异常并记录警告信息,同时使用默认的编码模型 "cl100k_base"。最后,方法返回一个包含模型名称和编码信息的元组。 + +**注意**: 在使用 `get_encoding_model` 方法之前,确保已经安装了 `tiktoken` 包。如果在尝试导入 `tiktoken` 时遇到问题,会抛出 `ValueError` 异常,提示需要安装 `tiktoken` 包。此外,当指定的模型名称不被支持时,方法会默认使用 "cl100k_base" 编码模型,并记录一条警告信息。 + +**输出示例**: 假设调用 `get_encoding_model` 方法并且指定的模型名称被正确识别,可能的返回值为: + +```python +("gpt-3.5-turbo-0301", ) +``` + +其中,返回的第一个元素是模型名称,第二个元素是该模型对应的编码信息对象。如果模型名称不被支持,返回值可能为: + +```python +("cl100k_base", ) +``` + +这表明方法使用了默认的编码模型 "cl100k_base"。 +*** diff --git a/markdown_docs/server/model_workers/SparkApi.md b/markdown_docs/server/model_workers/SparkApi.md new file mode 100644 index 000000000..f2f75690c --- /dev/null +++ b/markdown_docs/server/model_workers/SparkApi.md @@ -0,0 +1,108 @@ +## ClassDef Ws_Param +**Ws_Param**: Ws_Param 类的功能是生成用于连接 Spark 服务的 URL。 + +**属性**: +- `APPID`: 应用程序的ID。 +- `APIKey`: 用于访问Spark服务的API密钥。 +- `APISecret`: 用于访问Spark服务的API密钥的秘密。 +- `host`: 从Spark服务URL解析出的网络地址。 +- `path`: 从Spark服务URL解析出的路径。 +- `Spark_url`: Spark服务的完整URL。 + +**代码描述**: +Ws_Param 类通过初始化时传入的参数(APPID、APIKey、APISecret、Spark_url)来设置对象的基本属性。其中,`Spark_url`被解析为`host`和`path`,以便后续生成鉴权所需的签名。`create_url`方法用于生成最终的带有鉴权信息的URL。这个过程包括生成RFC1123格式的时间戳、拼接签名原文、使用HMAC-SHA256算法进行签名、将签名编码为Base64格式、构造Authorization头,并将这些鉴权参数编码后附加到原始URL上,生成最终的请求URL。 + +在项目中,`Ws_Param`类被`xinghuo.py`中的`request`函数调用,用于建立与Spark服务的WebSocket连接。`request`函数首先创建`Ws_Param`对象,通过调用其`create_url`方法获取鉴权后的URL,然后使用这个URL建立WebSocket连接,并发送请求数据。 + +**注意**: +- 确保传入`__init__`方法的`Spark_url`格式正确,因为它会被解析为`host`和`path`。 +- 生成的URL包含敏感信息(如APIKey和APISecret),因此在日志或调试信息中打印URL时需要谨慎。 + +**输出示例**: +生成的URL可能看起来像这样: +``` +https://spark.example.com/api?authorization=Base64EncodedString&date=RFC1123Date&host=spark.example.com +``` +这个URL包含了所有必要的鉴权信息,可以直接用于建立与Spark服务的连接。 +### FunctionDef __init__(self, APPID, APIKey, APISecret, Spark_url) +**__init__**: 该函数用于初始化Ws_Param类的实例。 + +**参数**: +- `APPID`: 应用程序的ID。 +- `APIKey`: 用于访问Spark API的API密钥。 +- `APISecret`: 用于访问Spark API的API密钥的秘密。 +- `Spark_url`: Spark服务的URL地址。 + +**代码描述**: +此函数是`Ws_Param`类的构造函数,负责初始化类的实例。它接收四个参数:`APPID`、`APIKey`、`APISecret`以及`Spark_url`。这些参数分别用于存储应用程序ID、API密钥、API密钥的秘密以及Spark服务的URL地址。 + +函数内部,首先将传入的`APPID`、`APIKey`、`APISecret`和`Spark_url`参数分别赋值给实例变量`self.APPID`、`self.APIKey`、`self.APISecret`和`self.Spark_url`。这样做是为了在类的其他方法中可以方便地使用这些值。 + +接着,函数使用`urlparse`函数(来自Python标准库中的`urllib.parse`模块)解析`Spark_url`参数。`urlparse`函数会返回一个解析结果对象,该对象包含了URL的不同组成部分。本函数中,特别使用了该对象的`netloc`和`path`属性来获取URL的网络位置(即主机名加端口号)和路径,分别赋值给实例变量`self.host`和`self.path`。这样的设计使得在需要与Spark服务进行通信时,可以方便地构造请求。 + +**注意**: +- 在使用`Ws_Param`类之前,确保提供的`Spark_url`是有效的,并且可以解析为正确的网络位置和路径。 +- `APPID`、`APIKey`和`APISecret`需要从Spark服务的管理界面获取,确保这些信息的准确性和安全性。 +- 本函数不对传入的参数值进行有效性验证,调用者需要确保提供的参数值是合法且适用于目标Spark服务的。 +*** +### FunctionDef create_url(self) +**create_url**: 此函数的功能是生成用于WebSockets连接的URL,包含鉴权信息。 + +**参数**: 此函数不接受任何外部参数,但使用了对象内部的多个属性,包括`self.host`、`self.path`、`self.APISecret`、`self.APIKey`以及`self.Spark_url`。 + +**代码描述**: `create_url`函数首先生成一个符合RFC1123标准的时间戳,然后构造一个用于签名的原始字符串,该字符串包含了请求的主机、日期和请求行信息。接下来,使用HMAC-SHA256算法对这个字符串进行加密,加密所用的密钥是API密钥的秘密部分。加密完成后,将加密结果转换为Base64格式的字符串,这个字符串将作为鉴权头的一部分。最后,函数将鉴权信息、日期和主机信息组合成一个字典,然后将这个字典转换为URL编码格式,并附加到`self.Spark_url`之后,形成最终的URL。 + +在项目中,`create_url`函数被`xinghuo.py`中的`request`函数调用。在`request`函数中,首先创建`Ws_Param`对象,然后调用`create_url`生成WebSocket连接所需的URL。这个URL包含了所有必要的鉴权信息,确保了连接的安全性。之后,`request`函数使用这个URL建立WebSocket连接,并通过这个连接发送和接收数据。 + +**注意**: 使用此函数时,需要确保`Ws_Param`对象已经被正确初始化,包括API密钥、API秘密、主机地址等信息。此外,生成的URL中包含的鉴权信息是基于当前时间的,因此生成的URL应立即使用,避免因时间差导致鉴权失败。 + +**输出示例**: 假设`self.Spark_url`为`"https://api.example.com/connect"`,`self.host`为`"api.example.com"`,生成的URL可能如下所示: +``` +"https://api.example.com/connect?authorization=dGhpcyBpcyBhIGZha2UgYXV0aG9yaXphdGlvbiBzdHJpbmc%3D&date=Mon%2C%2020%20Sep%202023%2012%3A00%3A00%20GMT&host=api.example.com" +``` +此URL包含了编码后的鉴权信息、日期和主机地址,可用于建立安全的WebSocket连接。 +*** +## FunctionDef gen_params(appid, domain, question, temperature, max_token) +**gen_params**: 该函数用于根据appid和用户的提问来生成请求参数。 + +**参数**: +- **appid**: 应用程序的唯一标识符。 +- **domain**: 请求的领域或类别。 +- **question**: 用户的提问内容。 +- **temperature**: 生成回答时的创造性控制参数。 +- **max_token**: 生成回答的最大令牌数。 + +**代码描述**: +`gen_params` 函数负责构建一个用于发送到Spark API的请求数据结构。这个数据结构包括三个主要部分:`header`、`parameter`和`payload`。在`header`部分,包含了`app_id`和一个固定的`uid`。`parameter`部分定义了与生成回答相关的一些参数,如领域(`domain`)、随机阈值(`random_threshold`)、最大令牌数(`max_tokens`)、审核级别(`auditing`)和创造性控制参数(`temperature`)。`payload`部分则包含了用户的提问(`question`)。这个结构使得Spark API能够理解请求的上下文和需求,从而生成相应的回答。 + +在项目中,`gen_params` 函数被`xinghuo.py`中的`request`函数调用。在`request`函数中,首先通过`SparkApi.Ws_Param`创建了一个WebSocket URL,然后调用`gen_params`函数生成请求参数,最后通过WebSocket连接发送这些参数,并处理返回的数据。这表明`gen_params`函数是与Spark API进行交互的关键一环,它负责生成符合API要求的请求数据。 + +**注意**: +- 确保传入的`appid`、`domain`、`question`、`temperature`和`max_token`参数值正确,因为这些直接影响到请求的成功与否以及返回的结果。 +- `temperature`参数控制生成文本的创造性,较高的值会导致更多样化的回答,而较低的值则使回答更加确定性。 +- `max_token`参数限制了生成回答的长度,需要根据实际需求调整。 + +**输出示例**: +```json +{ + "header": { + "app_id": "your_appid", + "uid": "1234" + }, + "parameter": { + "chat": { + "domain": "your_domain", + "random_threshold": 0.5, + "max_tokens": 100, + "auditing": "default", + "temperature": 0.7 + } + }, + "payload": { + "message": { + "text": "你的问题" + } + } +} +``` +此输出示例展示了一个典型的请求数据结构,其中包含了应用ID、领域、问题文本以及控制生成回答行为的参数。 diff --git a/markdown_docs/server/model_workers/azure.md b/markdown_docs/server/model_workers/azure.md new file mode 100644 index 000000000..c5121e76b --- /dev/null +++ b/markdown_docs/server/model_workers/azure.md @@ -0,0 +1,122 @@ +## ClassDef AzureWorker +**AzureWorker**: AzureWorker类是用于与Azure云服务进行交互,特别是用于处理与Azure API相关的聊天和嵌入功能的工作流程。 + +**属性**: +- `controller_addr`: 控制器地址,用于与模型控制器进行通信。 +- `worker_addr`: 工作器地址,用于标识工作器实例。 +- `model_names`: 模型名称列表,默认为["azure-api"]。 +- `version`: 模型版本,默认为"gpt-35-turbo"。 + +**代码描述**: +AzureWorker类继承自ApiModelWorker类,提供了与Azure API交互的具体实现。在初始化时,它接受控制器地址、工作器地址、模型名称列表和版本等参数,并将这些参数传递给父类构造函数。此外,它还定义了`do_chat`、`get_embeddings`和`make_conv_template`等方法,用于执行与Azure API相关的操作。 + +- `do_chat`方法接受ApiChatParams参数,用于执行聊天功能。它构造了一个请求数据包,包括消息、温度、最大令牌数等,并向Azure API发送请求。该方法通过生成器返回聊天响应,允许实时处理和返回聊天内容。 +- `get_embeddings`方法是一个示例方法,展示了如何打印嵌入信息。在实际应用中,该方法可以根据需要进行扩展,以实现具体的嵌入功能。 +- `make_conv_template`方法用于创建一个会话模板,该模板定义了用户和助手的角色、系统消息以及消息分隔符等。 + +**注意**: +- 在使用AzureWorker类时,需要确保已经配置了正确的Azure API密钥和相关参数,以便能够成功调用Azure服务。 +- `do_chat`方法中使用了HTTP流,这要求在处理响应时必须正确管理连接和数据流。 +- 由于`do_chat`方法是异步的,调用该方法时需要注意异步编程模式,确保异步任务的正确管理和调度。 + +**输出示例**: +在调用`do_chat`方法时,可能的返回值示例为: +```json +{ + "error_code": 0, + "text": "这是由Azure API生成的回复文本。" +} +``` +此示例展示了一个成功的API调用结果,其中`error_code`为0表示成功,`text`字段包含了由Azure API生成的回复文本。 +### FunctionDef __init__(self) +**__init__**: 初始化AzureWorker对象,并配置其基本属性。 + +**参数**: +- `controller_addr`: 字符串类型,控制器地址,默认为None。 +- `worker_addr`: 字符串类型,工作器地址,默认为None。 +- `model_names`: 字符串列表类型,模型名称,默认为["azure-api"]。 +- `version`: 字符串类型,模型版本,默认为"gpt-35-turbo"。 +- `**kwargs`: 接收任意数量的关键字参数。 + +**代码描述**: +此初始化函数用于创建一个AzureWorker对象,并对其进行基本配置。首先,通过关键字参数(`**kwargs`)更新模型名称(`model_names`)、控制器地址(`controller_addr`)和工作器地址(`worker_addr`)。这意味着,如果在创建AzureWorker对象时提供了这些参数,它们将被用于更新或设置对象的相应属性。 + +接下来,使用`super().__init__(**kwargs)`调用基类的初始化方法,允许AzureWorker继承并初始化基类中定义的任何属性或方法。这是面向对象编程中常见的做法,确保了类的继承体系能够正确地初始化和配置。 + +最后,将传入的`version`参数值赋给对象的`version`属性。这样,每个AzureWorker对象都会有自己的版本信息,用于标识或处理特定版本的模型。 + +**注意**: +- 在使用AzureWorker对象时,确保提供正确的`controller_addr`和`worker_addr`,这对于确保对象能够正确地与控制器和工作器通信非常重要。 +- `model_names`参数允许自定义模型名称列表,这在处理多个模型时非常有用。默认情况下,它包含一个预设的模型名称"azure-api"。 +- `version`参数用于指定模型的版本,根据需要进行调整。默认值为"gpt-35-turbo",但根据实际使用的模型版本,这个值可能需要更改。 +- 通过`**kwargs`传递额外的参数时,应确保这些参数与基类的初始化方法兼容,以避免引发错误。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是向Azure的OpenAI服务发送聊天请求,并处理返回的聊天结果。 + +**参数**: +- `params`: `ApiChatParams`类型,包含聊天请求所需的参数,如消息列表、温度参数、最大令牌数等。 + +**代码描述**: +`do_chat`函数首先调用`params.load_config`方法,加载与Azure服务相关的配置,如模型名称。然后,构造一个包含聊天请求所需数据的字典,包括消息列表、温度参数、最大令牌数等。接着,函数构造请求的URL,使用`params`中的资源名称、部署名称和API版本号。请求头包括内容类型、接受类型和API密钥。 + +如果启用了详细日志记录,函数会记录URL、请求头和数据到日志中。之后,使用`get_httpx_client`函数获取一个httpx客户端实例,并发起POST请求到Azure的OpenAI服务。函数通过迭代响应中的行来处理返回的数据,如果行包含有效的聊天内容,则将其累加到文本变量中,并以生成器的形式返回包含错误码和累加文本的字典。如果在响应中检测到错误,函数会记录错误信息到日志。 + +此函数与`get_httpx_client`函数关联,后者提供了执行HTTP请求所需的httpx客户端实例。此外,`do_chat`函数依赖于`ApiChatParams`类来获取聊天请求的参数,以及`load_config`方法来加载特定工作器的配置。 + +**注意**: +- 确保在调用`do_chat`函数之前,已经正确设置了`ApiChatParams`中的参数,包括API密钥、资源名称、部署名称等,这些参数对于成功调用Azure的OpenAI服务至关重要。 +- 函数使用生成器返回聊天结果,调用方需要迭代返回的生成器来获取所有聊天内容。 +- 如果遇到请求错误或服务端错误,函数会将错误信息记录到日志中,调用方应当注意检查日志以便及时发现并处理问题。 +- 函数中使用了`stream=True`选项进行HTTP请求,这意味着响应内容将作为流进行处理,有助于处理大量数据或实时数据。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息。 + +**代码描述**: +`get_embeddings`函数是`AzureWorker`类的一个方法,主要用于展示如何处理和打印嵌入信息及其相关参数。当调用此函数时,它首先打印出字符串"embedding",随后打印出传入的`params`参数。这表明该函数可能用于测试或演示如何在控制台上输出信息,尤其是与嵌入向量相关的参数信息。 + +具体来说,该函数接受一个名为`params`的参数,这个参数可以是任何类型的数据结构,如字典、列表或其他,这取决于调用函数时的具体需求。函数内部没有对`params`进行任何形式的处理或操作,仅仅是将其内容直接打印出来。 + +**注意**: +- 在实际应用中,`get_embeddings`函数可能需要进一步开发以实现特定的功能,如从Azure服务获取嵌入向量等。 +- 该函数目前的实现主要用于演示或测试目的,因此在生产环境中使用时需要根据实际需求进行相应的修改和扩展。 +- 在调用此函数时,需要确保传入的`params`参数包含了所有必要的信息,以便函数能够正确地执行其预期的打印操作。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 此函数的功能是创建一个对话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板,此参数在当前实现中未使用。 +- **model_path**: 字符串类型,指定模型路径,此参数在当前实现中未使用。 + +**代码描述**: +`make_conv_template` 函数用于创建一个对话模板实例。它通过调用 `conv.Conversation` 类来实现,生成的对话模板包含以下几个关键属性: +- `name`: 对话的名称,此处使用 `self.model_names[0]` 作为对话名称,即取模型名称列表的第一个元素。 +- `system_message`: 系统消息,这里固定为 "You are a helpful, respectful and honest assistant.",表明助手的角色定位。 +- `messages`: 对话消息列表,初始为空列表。 +- `roles`: 对话中的角色列表,包含 "user" 和 "assistant" 两个角色。 +- `sep`: 消息分隔符,这里设定为 "\n### "。 +- `stop_str`: 对话终止字符串,设定为 "###"。 + +**注意**: +- 虽然 `conv_template` 和 `model_path` 参数在函数定义中存在,但在当前的实现中并未被使用。这可能是为了未来的功能扩展预留的接口。 +- 函数返回的对话模板实例是基于 `conv.Conversation` 类创建的,确保在使用此函数之前已正确导入或定义了 `conv.Conversation` 类。 + +**输出示例**: +假设 `self.model_names[0]` 的值为 "ExampleModel",则函数的返回值可能如下所示: +``` +Conversation( + name="ExampleModel", + system_message="You are a helpful, respectful and honest assistant.", + messages=[], + roles=["user", "assistant"], + sep="\n### ", + stop_str="###", +) +``` +这个返回值展示了一个初始化状态的对话模板,其中包含了基本的对话属性设置。 +*** diff --git a/markdown_docs/server/model_workers/baichuan.md b/markdown_docs/server/model_workers/baichuan.md new file mode 100644 index 000000000..331851e56 --- /dev/null +++ b/markdown_docs/server/model_workers/baichuan.md @@ -0,0 +1,140 @@ +## FunctionDef calculate_md5(input_string) +**calculate_md5**: 该函数的功能是计算输入字符串的MD5加密值。 + +**参数**: +- **input_string**: 需要进行MD5加密的输入字符串。 + +**代码描述**: +`calculate_md5` 函数首先创建一个 `hashlib.md5()` 的实例。然后,它使用输入字符串(在进行编码转换为'utf-8'格式后)更新MD5对象。接着,通过调用 `hexdigest()` 方法,将加密后的数据转换为16进制的字符串形式。最后,函数返回这个加密后的字符串。 + +在项目中,`calculate_md5` 函数被 `BaiChuanWorker` 类的 `do_chat` 方法调用。在 `do_chat` 方法中,`calculate_md5` 用于生成对百川AI聊天API请求的签名。这个签名是通过将API的密钥、请求的JSON数据以及时间戳拼接后,使用 `calculate_md5` 函数加密生成的。生成的MD5签名随后被添加到请求的HTTP头中,作为请求认证的一部分。这显示了 `calculate_md5` 函数在确保API请求安全性方面的重要作用。 + +**注意**: +- 输入字符串必须是可编码为'utf-8'的字符串,否则在执行 `.encode('utf-8')` 时可能会抛出异常。 +- MD5加密是不可逆的,意味着无法从加密后的字符串恢复原始数据。 +- 虽然MD5在很多场合下仍然被广泛使用,但需要注意的是,由于其安全性在某些情况下可能不足,因此在处理高安全性要求的数据时应考虑使用更安全的加密算法。 + +**输出示例**: +调用 `calculate_md5("hello world")` 可能会返回如下字符串: +``` +5eb63bbbe01eeed093cb22bb8f5acdc3 +``` +这是 "hello world" 这个字符串经过MD5加密后的结果。 +## ClassDef BaiChuanWorker +**BaiChuanWorker**: BaiChuanWorker类是用于与百川AI接口进行交互的工作器。 + +**属性**: +- `controller_addr`: 控制器地址,用于与模型控制器进行通信。 +- `worker_addr`: 工作器地址,标识当前工作器的网络位置。 +- `model_names`: 模型名称列表,默认为["baichuan-api"]。 +- `version`: 模型版本,默认为"Baichuan2-53B"。 +- `context_len`: 上下文长度,默认为32768。 + +**代码描述**: +BaiChuanWorker类继承自ApiModelWorker,专门用于处理与百川AI接口的交互。在初始化过程中,该类接受控制器地址、工作器地址、模型名称列表、模型版本等参数,并通过`kwargs`传递给父类ApiModelWorker进行进一步的初始化。此外,BaiChuanWorker还设置了默认的上下文长度为32768。 + +该类重写了`do_chat`方法,用于实现与百川AI的聊天功能。在`do_chat`方法中,首先根据提供的参数构造请求数据,然后通过HTTP POST请求发送到百川AI的聊天接口,并处理响应数据。如果响应码为0,表示请求成功,将返回包含聊天内容的字典;如果响应码非0,表示请求失败,将返回包含错误信息的字典。 + +此外,BaiChuanWorker还提供了`get_embeddings`和`make_conv_template`方法,但这些方法在当前版本中未实现具体功能。 + +**注意**: +- 使用BaiChuanWorker进行聊天时,需要确保提供有效的API密钥和正确的请求参数。 +- BaiChuanWorker的实现依赖于外部函数`calculate_md5`和`get_httpx_client`,这些函数需要在使用前正确定义。 +- 在处理HTTP响应时,BaiChuanWorker采用了流式读取的方式,以适应可能的大量数据传输。 + +**输出示例**: +```json +{ + "error_code": 0, + "text": "这是由百川AI生成的回复文本。" +} +``` +此示例展示了一个成功的聊天请求返回值,其中`error_code`为0表示请求成功,`text`字段包含了百川AI生成的回复文本。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化BaiChuanWorker对象。 + +**参数**: +- `controller_addr`: 字符串类型,控制器地址,默认为None。 +- `worker_addr`: 字符串类型,工作节点地址,默认为None。 +- `model_names`: 字符串列表类型,模型名称,默认为["baichuan-api"]。 +- `version`: 字面量类型,指定版本,默认为"Baichuan2-53B"。 +- `**kwargs`: 接收可变数量的关键字参数。 + +**代码描述**: +此函数是`BaiChuanWorker`类的构造函数,用于初始化该类的实例。在初始化过程中,首先将`model_names`、`controller_addr`和`worker_addr`参数通过`kwargs`字典传递给父类的构造函数。此外,`kwargs`字典中的"context_len"键值对被设置为默认值32768,如果在`kwargs`中未指定"context_len"。然后,调用父类的`__init__`方法,将更新后的`kwargs`字典传递给它。最后,将`version`参数的值赋给实例变量`version`,以记录模型的版本信息。 + +**注意**: +- 在使用`BaiChuanWorker`类初始化对象时,需要注意`controller_addr`和`worker_addr`参数是可选的,如果在特定环境下这两个参数是必需的,则应在实例化时提供它们。 +- `model_names`参数允许用户指定一个或多个模型名称,这对于在不同的工作场景中需要加载不同模型的情况非常有用。 +- `version`参数默认值为"Baichuan2-53B",这意味着如果没有特别指定,将使用这个版本的模型。如果需要使用不同版本的模型,应在实例化时明确指定。 +- 通过`**kwargs`参数,此函数提供了高度的灵活性,允许用户根据需要传递额外的配置选项。但是,使用时应确保传递的关键字参数与父类构造函数或`BaiChuanWorker`类的其他方法兼容。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 该函数用于执行聊天操作,通过向百川AI的聊天API发送请求,并处理响应数据。 + +**参数**: +- `params`: `ApiChatParams`类型,包含了执行聊天所需的各种参数,如消息列表、模型版本和温度参数等。 + +**代码描述**: +`do_chat`函数首先通过`params.load_config`方法加载模型配置,这一步骤确保了聊天请求能够使用正确的模型参数。接着,函数构造了向百川AI聊天API发送请求所需的URL和数据体。数据体中包含了模型版本、消息列表以及其他参数(如温度参数)。 + +为了保证请求的安全性,函数计算了请求的MD5签名。这一过程涉及到`calculate_md5`函数,它将API的密钥、请求的JSON数据以及时间戳进行加密,生成签名。随后,这个签名被添加到请求的HTTP头中,作为请求认证的一部分。 + +函数使用`get_httpx_client`函数获取一个httpx客户端实例,用于发送HTTP请求。这一步骤中,`get_httpx_client`函数提供了对HTTP请求的详细配置,包括代理设置、超时时间等。 + +在发送请求并接收响应之后,函数通过迭代响应的每一行来处理返回的数据。对于每一行数据,函数首先检查其是否为空,然后解析JSON格式的响应内容。如果响应代码为0(表示成功),函数将累加消息内容并生成一个包含错误代码和文本消息的字典,然后通过`yield`返回这个字典。如果响应代码不为0(表示出错),函数同样生成一个包含错误信息的字典,并通过`yield`返回。 + +**注意**: +- 在使用`do_chat`函数时,需要确保传入的`params`参数已经包含了所有必要的聊天请求信息,包括但不限于消息列表、模型版本和温度参数。 +- 该函数使用了`yield`关键字来逐行返回处理结果,这意味着它可以作为一个生成器使用。调用方需要通过迭代的方式来获取所有的响应数据。 +- 函数中的错误处理机制确保了即使在请求失败的情况下,也能够以一种结构化的方式返回错误信息,便于调用方处理。 +- 在构造HTTP请求头时,包含了多个自定义的字段,如`X-BC-Request-Id`和`X-BC-Signature`等,这些字段对于请求的成功执行至关重要。调用方需要确保这些字段被正确设置。 +- 函数内部记录了详细的日志信息,这对于调试和监控请求的执行流程非常有帮助。开发者应当关注这些日志信息,以便于及时发现和解决问题。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息,其具体内容和格式依调用时的实际情况而定。 + +**代码描述**: +`get_embeddings` 函数是 `BaiChuanWorker` 类的一个方法,主要用于展示如何处理和打印传入的参数信息。当调用此函数时,它首先打印出字符串 "embedding",随后打印出传入的 `params` 参数。这表明该函数可能是一个用于测试或演示如何接收和处理参数的示例函数。在实际的生产环境中,此函数可能会被进一步扩展,以实现更复杂的数据处理和嵌入向量的生成逻辑。 + +**注意**: +- 在使用此函数时,需要注意传入的 `params` 参数应该是符合预期格式和数据类型的,以确保函数能够正确地处理和打印参数信息。 +- 目前,此函数的实现较为简单,主要用于演示目的。在实际应用中,可能需要根据具体需求对其进行相应的扩展和优化。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 此函数的功能是创建一个会话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定会话模板,此参数在当前实现中未使用。 +- **model_path**: 字符串类型,指定模型路径,此参数在当前实现中未使用。 + +**代码描述**: +`make_conv_template` 函数是 `BaiChuanWorker` 类的一个方法,用于创建一个会话模板。该方法接受两个参数:`conv_template` 和 `model_path`,但在当前的实现中,这两个参数并未被使用。函数主要通过调用 `conv.Conversation` 构造函数来创建一个会话对象。在创建会话对象时,设置了以下几个关键属性: +- `name`: 使用 `self.model_names[0]` 作为会话的名称,这意味着会话名称将是模型名称列表中的第一个名称。 +- `system_message`: 系统消息被设置为空字符串。 +- `messages`: 消息列表被初始化为空列表。 +- `roles`: 角色被设置为包含“user”和“assistant”的列表,表示会话中的用户角色和助手角色。 +- `sep`: 设置为“\n### ”,这是消息之间的分隔符。 +- `stop_str`: 设置为“###”,作为会话的终止字符串。 + +**注意**: +- 虽然 `conv_template` 和 `model_path` 参数在当前实现中未被直接使用,但它们的存在可能是为了未来的扩展性,允许根据不同的模板或模型路径创建不同的会话模板。 +- 在使用此函数时,需要确保 `self.model_names` 至少包含一个元素,否则在尝试访问 `self.model_names[0]` 时会引发索引错误。 + +**输出示例**: +假设 `self.model_names` 包含一个元素 `"ModelA"`,则函数的返回值可能如下所示: +```python +Conversation( + name="ModelA", + system_message="", + messages=[], + roles=["user", "assistant"], + sep="\n### ", + stop_str="###", +) +``` +这表示创建了一个名为 "ModelA" 的空会话模板,其中没有预设的系统消息或用户消息,定义了用户和助手的角色,并指定了消息分隔符和会话终止字符串。 +*** diff --git a/markdown_docs/server/model_workers/base.md b/markdown_docs/server/model_workers/base.md new file mode 100644 index 000000000..905a0b32c --- /dev/null +++ b/markdown_docs/server/model_workers/base.md @@ -0,0 +1,475 @@ +## ClassDef ApiConfigParams +**ApiConfigParams**: ApiConfigParams类的功能是定义在线API配置参数,允许从默认配置自动填充未提供的值。 + +**属性**: +- `api_base_url`: 可选字符串,API的基础URL。 +- `api_proxy`: 可选字符串,用于API请求的代理。 +- `api_key`: 可选字符串,API的访问密钥。 +- `secret_key`: 可选字符串,API的秘密密钥。 +- `group_id`: 可选字符串,用于minimax的组ID。 +- `is_pro`: 布尔值,标记是否为minimax的专业版。 +- `APPID`: 可选字符串,用于xinghuo的应用ID。 +- `APISecret`: 可选字符串,用于xinghuo的API密钥。 +- `is_v2`: 布尔值,标记是否为xinghuo的v2版本。 +- `worker_name`: 可选字符串,工作器名称。 + +**代码描述**: +ApiConfigParams类继承自BaseModel,用于封装和管理API配置参数。该类提供了灵活的配置方式,允许通过代码直接设置参数,也支持从外部配置文件自动加载未提供的参数值。通过`root_validator`装饰器,该类在实例化时会自动检查并填充那些未明确提供但在外部配置中存在的参数值。此外,`load_config`方法允许在实例化后动态加载或更新配置,进一步增加了灵活性。`Config`子类中的`extra = "allow"`设置允许该模型接受并包含在输入数据中但未在模型声明中明确指定的额外字段,这为扩展性提供了便利。 + +从项目结构来看,ApiConfigParams类被ApiModelParams类和ApiEmbeddingsParams类继承,这表明ApiConfigParams提供了一组基础配置参数,而其子类则根据不同的应用场景扩展了额外的配置项。例如,ApiModelParams类添加了与模型版本和部署相关的参数,而ApiEmbeddingsParams类则专注于嵌入式模型的配置。 + +**注意**: +- 在使用ApiConfigParams类时,应确保相关的外部配置正确设置,以便能够自动填充未提供的参数值。 +- 对于特定的API(如minimax和xinghuo),需要注意其特定参数(如`group_id`、`APPID`等)的正确设置。 + +**输出示例**: +由于ApiConfigParams类主要用于配置管理,其输出示例依赖于具体的配置数据。例如,如果配置了`api_base_url`为`"https://api.example.com"`且`is_pro`为`True`,则ApiConfigParams实例的相关属性将分别反映这些值。 +### ClassDef Config +**Config**: Config 类的功能是定义配置参数的额外处理方式。 + +**属性**: +- extra: 定义了对额外字段的处理策略。 + +**代码描述**: +Config 类是一个简单的配置类,其主要目的是指定如何处理额外的配置参数。在这个类中,只定义了一个属性 `extra`。`extra` 属性的值设置为 `"allow"`,这意味着在处理配置参数时,如果遇到额外的、未明确声明在配置类中的参数,将会允许这些额外的参数存在,而不会引发错误或警告。这种处理方式在某些情况下非常有用,特别是当你希望你的配置能够灵活地接受一些不是事先定义好的参数时。 + +**注意**: +- 使用 Config 类时,需要注意 `extra` 属性的值将直接影响配置参数的处理方式。在默认情况下,`extra` 被设置为 `"allow"`,但根据实际需求,开发者可以修改这个值以适应不同的处理策略,例如拒绝额外的参数或仅接受特定的额外参数。 +- 在实际应用中,Config 类可以根据需要扩展,添加更多的属性和方法来满足更复杂的配置需求。但是,开发者在扩展时应保持对配置处理逻辑的清晰和一致性,以避免引入潜在的错误。 +*** +### FunctionDef validate_config(cls, v) +**validate_config**: 此函数的功能是验证并更新API配置参数。 + +**参数**: +- cls: 类方法的第一个参数,指代当前类。 +- v: 字典类型,包含API配置参数。 + +**代码描述**: `validate_config` 函数首先尝试通过调用`get_model_worker_config`函数,根据传入的配置字典`v`中的`"worker_name"`键值获取模型工作配置。如果成功获取到配置,则遍历当前类(`cls`)的字段(`__fields__`),检查这些字段是否存在于获取到的模型工作配置中。如果存在,将这些字段的值更新为模型工作配置中对应的值。最后,返回更新后的配置字典`v`。 + +此函数与`get_model_worker_config`函数紧密相关,后者负责加载指定模型工作配置项,包括从默认配置、在线模型配置和特定模型配置中合并配置项。`validate_config`函数利用这一特性,确保传入的配置参数中包含了所有必要的、最新的配置信息,特别是当某些配置项可能在类定义中未明确指定默认值时。 + +**注意**: +- 确保在调用此函数之前,已经正确设置了相关模型的配置信息,包括默认配置、在线模型配置和特定模型配置。 +- 此函数主要用于内部配置验证和更新,通常在模型初始化或配置更新时被调用。 + +**输出示例**: 假设存在一个模型工作配置,其中`"worker_name"`对应的值为`"example_worker"`,并且`get_model_worker_config`返回的配置字典包含`{"example_field": "example_value"}`。如果`cls.__fields__`包含`"example_field"`,则调用`validate_config`后返回的字典将包含`{"worker_name": "example_worker", "example_field": "example_value"}`。 +*** +### FunctionDef load_config(self, worker_name) +**load_config**: 此函数的功能是为特定工作器加载配置。 + +**参数**: +- worker_name: 字符串类型,指定要加载配置的工作器名称。 + +**代码描述**: `load_config` 函数首先将传入的`worker_name`保存到实例变量中。接着,它调用`get_model_worker_config`函数,尝试根据`worker_name`获取模型工作器的配置。如果配置获取成功,函数将遍历实例的所有字段(由`self.__fields__`提供),并且如果字段名称存在于配置中,则使用`setattr`函数更新实例的相应字段值为配置中的值。最后,函数返回配置好的实例自身。 + +**注意**: +- 确保在调用此函数之前,`worker_name`对应的配置已经在配置文件或数据库中正确设置。 +- 此函数依赖于`get_model_worker_config`函数来获取具体的配置信息,该函数负责从配置源(如文件、数据库等)中加载配置。 +- `self.__fields__`应包含所有可能需要从配置中加载的字段名称,确保这些字段在类定义中已经声明。 + +**输出示例**: 假设存在一个工作器名称为"example_worker",并且其配置信息如下: +```python +{ + "worker_name": "example_worker", + "max_tokens": 1024, + "temperature": 0.7 +} +``` +调用`load_config("example_worker")`后,实例的`worker_name`将被设置为"example_worker",`max_tokens`和`temperature`字段也将根据配置信息被相应更新。返回的实例将包含这些更新后的字段值。 +*** +## ClassDef ApiModelParams +**ApiModelParams**: ApiModelParams类的功能是扩展ApiConfigParams类,用于定义与模型相关的配置参数。 + +**属性**: +- `version`: 可选字符串,定义模型的版本。 +- `version_url`: 可选字符串,定义模型版本的URL。 +- `api_version`: 可选字符串,专为Azure服务定义的API版本。 +- `deployment_name`: 可选字符串,专为Azure服务定义的部署名称。 +- `resource_name`: 可选字符串,专为Azure服务定义的资源名称。 +- `temperature`: 浮点数,定义生成文本的温度参数。 +- `max_tokens`: 可选整数,定义生成文本的最大令牌数。 +- `top_p`: 可选浮点数,默认为1.0,定义生成文本时的top-p采样参数。 + +**代码描述**: +ApiModelParams类继承自ApiConfigParams类,专门用于配置与模型相关的参数。该类通过添加模型版本、部署名称、资源名称等属性,为特定的模型部署场景(如Azure服务)提供了配置支持。此外,它还包括了控制模型生成文本行为的参数,如`temperature`、`max_tokens`和`top_p`,这些参数对于调整模型输出的质量和长度至关重要。ApiModelParams类通过提供这些额外的配置项,使得开发者能够更灵活地控制模型的行为和性能。 + +**注意**: +- 在使用ApiModelParams类时,应根据实际的部署环境(如是否部署在Azure上)和模型需求,正确设置相关参数。例如,如果模型部署在Azure上,那么`api_version`、`deployment_name`和`resource_name`等参数就需要被正确配置。 +- 对于`temperature`、`max_tokens`和`top_p`等参数,开发者应根据模型的特性和预期的输出效果进行调整,以达到最佳的性能和输出质量。 + +ApiModelParams类在项目中的应用场景包括但不限于ApiChatParams和ApiCompletionParams类,这两个类分别用于配置聊天请求参数和完成请求参数,它们通过继承ApiModelParams类,不仅继承了与模型相关的基础配置,还可以根据需要添加特定于聊天或完成请求的额外配置。这种设计使得模型配置在不同类型的请求之间具有很好的复用性和扩展性。 +## ClassDef ApiChatParams +**ApiChatParams**: 用于定义聊天请求参数的类。 + +**属性**: +- `messages`: 消息列表,每个消息是一个包含字符串键值对的字典。 +- `system_message`: 可选字符串,用于minimax算法中的系统消息。 +- `role_meta`: 字典类型,默认为空,用于minimax算法中的角色元数据。 + +**代码描述**: +ApiChatParams类继承自ApiModelParams类,专门用于配置聊天请求的参数。该类通过`messages`属性接收一个消息列表,每个消息是一个字典,包含角色和内容等信息。此外,它还提供了`system_message`和`role_meta`属性,这些属性主要用于minimax算法中,以支持更复杂的聊天场景。通过继承ApiModelParams类,ApiChatParams不仅包含了与模型相关的基础配置,如模型版本、API版本等,还增加了特定于聊天请求的参数,使得开发者能够灵活地控制聊天模型的行为。 + +**注意**: +- 在使用ApiChatParams类时,开发者需要根据具体的聊天场景和模型要求,正确填充`messages`列表。每个消息都应该是一个字典,至少包含角色和内容信息。 +- 对于使用minimax算法的场景,`system_message`和`role_meta`属性可能需要被设置。这些属性对于控制算法的行为和输出有重要作用,因此在使用时应当仔细阅读相关文档,确保正确使用。 +- 由于ApiChatParams类继承自ApiModelParams类,因此在配置聊天请求参数时,也可以设置与模型行为相关的参数,如`temperature`、`max_tokens`等,以调整模型生成文本的特性。开发者应根据模型的特点和需求,合理配置这些参数,以获得最佳的聊天体验。 +## ClassDef ApiCompletionParams +**ApiCompletionParams**: ApiCompletionParams类的功能是定义完成请求的参数。 + +**属性**: +- `prompt`: 字符串,用于定义模型生成文本的输入提示。 + +**代码描述**: ApiCompletionParams类继承自ApiModelParams类,专门用于配置完成请求的参数。该类通过添加`prompt`属性,允许开发者指定模型生成文本时的输入提示。这是与模型交互时非常关键的参数,因为它直接影响到模型的输出内容和质量。继承自ApiModelParams类意味着ApiCompletionParams不仅包含了`prompt`属性,还继承了ApiModelParams类中定义的所有模型相关的配置参数,如模型版本、温度参数、最大令牌数等。这样的设计使得ApiCompletionParams类在配置完成请求时既具有高度的灵活性,也保持了与其他模型请求参数类似的配置能力。 + +通过继承ApiModelParams类,ApiCompletionParams类能够利用已有的模型配置参数,如`temperature`、`max_tokens`和`top_p`等,这些参数对于控制模型生成文本的行为至关重要。此外,ApiCompletionParams类的设计也考虑到了实际应用场景的需要,比如在聊天机器人或自动文本生成系统中,`prompt`参数是实现定制化输出的关键。 + +**注意**: +- 在使用ApiCompletionParams类时,开发者应确保`prompt`参数被正确设置,因为它直接影响模型的输出结果。 +- 继承自ApiModelParams类意味着开发者还需要关注其他继承的参数,如`temperature`、`max_tokens`等,这些参数需要根据模型的特性和预期的输出效果进行适当调整。 +- 此类的使用应结合实际的模型部署环境和需求,合理配置所有相关参数,以达到最佳的性能和输出质量。 +## ClassDef ApiEmbeddingsParams +**ApiEmbeddingsParams**: ApiEmbeddingsParams类的功能是定义用于嵌入式模型API请求的参数。 + +**属性**: +- `texts`: 字符串列表,表示需要进行嵌入处理的文本。 +- `embed_model`: 可选字符串,默认为None,指定使用的嵌入模型。 +- `to_query`: 布尔值,默认为False,用于指示是否将文本作为查询进行最小化处理。 + +**代码描述**: +ApiEmbeddingsParams类继承自ApiConfigParams类,专门用于配置和管理嵌入式模型API请求所需的参数。该类通过继承ApiConfigParams获得了基础的API配置能力,如API的基础URL、代理、访问密钥等,并在此基础上添加了特定于嵌入式模型请求的参数,如文本列表、嵌入模型标识以及是否作为查询处理的标志。这样的设计使得ApiEmbeddingsParams类能够灵活地应用于不同的嵌入式模型请求场景中。 + +通过设置`texts`属性,用户可以指定一系列需要进行向量化处理的文本。`embed_model`属性允许用户指定使用的嵌入模型,这对于系统支持多个嵌入模型的情况尤其有用。`to_query`属性则用于特定的场景,比如在使用最小化处理时,标识文本是否应作为查询处理,这影响了嵌入向量的生成方式。 + +**注意**: +- 在使用ApiEmbeddingsParams进行API请求时,应确保`texts`属性被正确设置,因为这是进行文本嵌入处理的必要条件。 +- 根据使用的嵌入模型和具体的应用场景,`embed_model`和`to_query`属性的设置可能会影响请求的结果,因此在使用前应仔细考虑这些属性的设置。 +- 由于ApiEmbeddingsParams继承自ApiConfigParams,因此在使用前也应确保相关的API配置(如API基础URL、访问密钥等)已经正确设置。 + +ApiEmbeddingsParams类在项目中主要用于处理文本的向量化请求,通过与不同的模型工作器(如MiniMaxWorker、QianFanWorker等)配合使用,支持多种嵌入模型和API的灵活应用。通过正确配置和使用ApiEmbeddingsParams,开发者可以轻松地将文本数据转换为嵌入向量,进而用于各种文本分析和处理任务。 +## ClassDef ApiModelWorker +**ApiModelWorker**: ApiModelWorker类是用于处理API模型工作流程的基础类。 + +**属性**: +- `DEFAULT_EMBED_MODEL`: 默认的嵌入模型,若为None,则表示不支持嵌入功能。 +- `context_len`: 上下文长度,默认为2048。 +- `semaphore`: 用于限制工作并发数的信号量。 +- `version`: 模型版本,初始化时为None,可在子类中进行指定。 + +**代码描述**: +ApiModelWorker类继承自BaseModelWorker,提供了一系列方法用于处理与API模型相关的工作流程。它允许用户通过构造函数传入模型名称、控制器地址、工作器地址、上下文长度、是否注册等参数,并在初始化过程中设置了一些默认参数值。此外,该类还引入了异步事件循环,以支持异步操作。 + +该类定义了几个关键方法,包括`count_token`用于计算令牌数量、`generate_stream_gate`和`generate_gate`用于生成响应流、以及`do_chat`、`do_embeddings`和`get_embeddings`等方法,这些方法在子类中需要被重写以实现具体的功能。例如,`do_chat`方法用于执行聊天功能,`do_embeddings`用于执行嵌入功能。 + +在项目中,ApiModelWorker类被多个子类继承,如AzureWorker、BaiChuanWorker、FangZhouWorker等,这些子类根据不同的API提供商实现了ApiModelWorker类的方法,以适应不同的API接口和需求。 + +**注意**: +- 在使用ApiModelWorker类及其子类时,需要注意异步编程模式,确保异步任务的正确管理和调度。 +- 子类需要根据具体的API提供商的接口文档,实现`do_chat`、`do_embeddings`等方法,以完成具体的业务逻辑。 +- `DEFAULT_EMBED_MODEL`属性在子类中可以被覆盖,以支持特定的嵌入模型。 + +**输出示例**: +由于ApiModelWorker类主要作为基类,其具体的输出依赖于子类的实现。以下是一个模拟的`do_chat`方法的可能输出示例(假设在某个子类中实现): +```json +{ + "error_code": 0, + "text": "这是由模型生成的回复文本。" +} +``` +此输出示例展示了一个成功的API调用结果,其中`error_code`为0表示成功,`text`字段包含了模型生成的回复文本。 +### FunctionDef __init__(self, model_names, controller_addr, worker_addr, context_len, no_register) +**__init__**: 该函数用于初始化ApiModelWorker对象。 + +**参数**: +- `model_names`: 一个字符串列表,包含要加载的模型名称。 +- `controller_addr`: 控制器地址,默认为None。 +- `worker_addr`: 工作器地址,默认为None。 +- `context_len`: 上下文长度,默认为2048。 +- `no_register`: 一个布尔值,指示是否注册,默认为False。 +- `**kwargs`: 接受额外的关键字参数,用于进一步自定义。 + +**代码描述**: +此函数首先通过`kwargs`设置默认的`worker_id`、`model_path`和`limit_worker_concurrency`。`worker_id`默认为一个随机生成的8位十六进制字符串,`model_path`默认为空字符串,`limit_worker_concurrency`默认为5,限制并发工作器的数量。 + +接着,调用父类的`__init__`方法,传入`model_names`、`controller_addr`、`worker_addr`和`**kwargs`参数。 + +然后,导入`fastchat.serve.base_model_worker`模块,并从中获取`logger`对象用于日志记录。此外,还将`sys.stdout`和`sys.stderr`恢复为标准输出和错误输出,以解决被`fastchat`覆盖的问题。 + +创建一个新的事件循环,并将其设置为当前线程的事件循环,以支持异步操作。 + +初始化`context_len`属性和一个信号量`semaphore`,后者用于控制并发的数量,其最大值由`limit_worker_concurrency`决定。 + +`version`属性被初始化为None,预留以供后续使用。 + +最后,如果`no_register`为False且`controller_addr`不为空,则调用`init_heart_beat`方法,以初始化心跳机制,保持与控制器的通信。 + +**注意**: +- 在使用此函数时,确保传入的`model_names`列表中包含的模型名称是有效的,因为这些模型将被加载并用于后续操作。 +- `controller_addr`和`worker_addr`应为有效的地址字符串,如果提供,将用于网络通信。 +- `context_len`、`no_register`和`limit_worker_concurrency`等参数允许调整性能和行为,应根据具体需求进行配置。 +- 通过`**kwargs`传入的额外参数可以用于进一步自定义行为,但需注意这些参数的默认值可能已经被预设。 +*** +### FunctionDef count_token(self, params) +**count_token**: 此函数的功能是计算并返回给定提示信息的字符数。 + +**参数**: +- `params`: 一个字典,包含需要处理的提示信息。 + +**代码描述**: +`count_token`函数接收一个参数`params`,这是一个字典,其中应包含一个键`"prompt"`。该函数首先从`params`字典中提取`"prompt"`键对应的值,然后将这个值转换为字符串(确保即使输入的不是字符串类型也能正确处理),并计算其长度。最后,函数返回一个新的字典,包含两个键值对:`"count"`,它的值是`prompt`字符串的长度;和`"error_code"`,其值为0,表示操作成功完成,没有错误。 + +**注意**: +- 确保传入的`params`字典中包含`"prompt"`键,否则代码将抛出`KeyError`。 +- 函数返回的`"error_code"`始终为0,表示没有错误。在实际应用中,可能需要根据实际情况调整错误处理逻辑。 + +**输出示例**: +假设传入的`params`字典为`{"prompt": "Hello, world!"}`,则函数的返回值将是: +```python +{"count": 13, "error_code": 0} +``` +这表示给定的提示信息`"Hello, world!"`包含13个字符,且操作成功完成。 +*** +### FunctionDef generate_stream_gate(self, params) +**generate_stream_gate**: 此函数的功能是生成流式聊天门控。 + +**参数**: +- `params`: 字典类型,包含聊天请求所需的参数。 + +**代码描述**: +`generate_stream_gate` 函数是 `ApiModelWorker` 类的一个方法,用于处理聊天请求并生成响应流。该函数首先将调用次数自增,然后尝试解析传入的 `params` 参数。根据 `params` 中的 `prompt` 值,判断该请求是否为聊天模式。如果是聊天模式,则通过 `prompt_to_messages` 方法将 `prompt` 字符串转换为消息列表,随后通过 `validate_messages` 方法对消息进行验证。如果不是聊天模式,则构造一个包含单条消息的列表,消息内容为提示用户继续写作的文本。 + +接下来,使用 `ApiChatParams` 类构造聊天请求参数 `p`,包括消息列表、温度参数(`temperature`)、顶部概率(`top_p`)、最大生成令牌数(`max_tokens`)以及模型版本。然后,调用 `do_chat` 方法执行聊天操作,并对每个响应使用 `_jsonify` 方法进行格式化,最后以生成器的形式返回格式化后的响应流。 + +如果在处理过程中发生异常,将捕获异常并返回包含错误信息的响应。 + +**注意**: +- 在调用此函数之前,确保传入的 `params` 参数字典中包含正确的 `prompt` 和其他可选聊天参数。 +- 此函数利用生成器返回响应流,允许实时处理和传输大量聊天数据,适用于需要流式处理的场景。 +- 异常处理机制确保了即使在发生错误的情况下,也能返回错误信息,避免程序崩溃。 +- 该函数的实现依赖于 `ApiChatParams` 类和 `do_chat` 方法,确保这些依赖项已正确实现并可用。 +*** +### FunctionDef generate_gate(self, params) +**generate_gate**: 此函数的功能是处理聊天请求并返回处理结果。 + +**参数**: +- `params`: 字典类型,包含处理聊天请求所需的参数。 + +**代码描述**: +`generate_gate` 函数是 `ApiModelWorker` 类的一个方法,主要负责处理聊天请求并返回处理结果。该函数首先通过调用 `generate_stream_gate` 方法生成流式聊天门控,该方法返回一个生成器,用于逐步产生聊天响应流。在 `generate_gate` 函数中,通过遍历 `generate_stream_gate` 方法返回的生成器,可以逐个处理聊天响应。最终,函数尝试将最后一个聊天响应的字节流(去除最后一个字节后)解码并加载为JSON格式的数据,然后返回该数据作为聊天处理的结果。 + +如果在处理过程中遇到任何异常,`generate_gate` 函数会捕获这些异常,并返回一个包含错误代码(500)和错误信息的字典,以便调用者可以了解到处理过程中发生的错误。 + +**注意**: +- 在调用 `generate_gate` 函数之前,确保传入的 `params` 参数字典已经正确设置,包括但不限于聊天模式的提示信息(`prompt`)等。 +- 该函数利用了异常处理机制来确保即使在处理过程中遇到错误,也能够给调用者返回一个明确的错误信息,避免程序崩溃。 +- `generate_gate` 函数的实现依赖于 `generate_stream_gate` 方法,后者负责生成流式聊天门控并处理聊天请求,因此确保 `generate_stream_gate` 方法已经正确实现并可用是非常重要的。 + +**输出示例**: +假设聊天处理成功,返回的示例可能如下: +```json +{ + "response": "这是聊天的回复内容。" +} +``` +如果处理过程中发生异常,返回的示例可能如下: +```json +{ + "error_code": 500, + "text": "处理聊天请求时发生错误:错误详情。" +} +``` +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是执行聊天操作。 + +**参数**: +- `params`: 类型为`ApiChatParams`,用于定义聊天请求的参数。 + +**代码描述**: `do_chat`函数是`ApiModelWorker`类的一个方法,旨在执行聊天功能。该方法接收一个`ApiChatParams`类型的参数`params`,该参数包含了执行聊天所需的所有信息,如消息列表、系统消息以及角色元数据等。函数的默认实现返回一个字典,包含`error_code`和`text`两个键。`error_code`为500,表示服务端错误;`text`键对应的值为一个字符串,提示当前模型的第一个名称未实现聊天功能。这表明`do_chat`方法需要在子类中被重写以实现具体的聊天逻辑。 + +**注意**: +- `do_chat`方法的默认实现仅为一个占位符,提示开发者需要在继承`ApiModelWorker`类的子类中实现具体的聊天逻辑。 +- 在调用`do_chat`方法时,必须确保传入的`params`参数是`ApiChatParams`类型的实例,且已正确填充了所有必要的聊天请求信息。 +- 返回的字典中的`error_code`为500时,表示聊天功能未实现或执行中出现了错误,开发者应检查是否在子类中正确重写了`do_chat`方法。 + +**输出示例**: +```python +{ + "error_code": 500, + "text": "模型名称未实现chat功能" +} +``` +此输出示例展示了当聊天功能未被实现时,`do_chat`方法的默认返回值。其中`模型名称`会根据实际调用时`self.model_names[0]`的值动态替换。 +*** +### FunctionDef do_embeddings(self, params) +**do_embeddings**: 此函数的功能是执行文本嵌入处理。 + +**参数**: +- `params`: ApiEmbeddingsParams类型,定义了嵌入式模型API请求的参数。 + +**代码描述**: `do_embeddings`函数是`ApiModelWorker`类的一个方法,旨在执行文本的嵌入处理。默认情况下,此函数使用模块内的`embed_documents`函数(尽管在此代码段中未直接展示该调用)。函数接受一个`ApiEmbeddingsParams`类型的参数`params`,该参数包含了执行嵌入处理所需的所有信息,如需要处理的文本列表、指定的嵌入模型以及是否将文本作为查询进行最小化处理等。 + +在当前的实现中,如果模型未实现嵌入功能,函数将返回一个包含错误代码和消息的字典。这个消息包含了模型名称(通过`self.model_names[0]`获取),指示该模型未实现嵌入功能。这是一种错误处理机制,确保当模型未实现嵌入功能时,用户能够接收到明确的反馈。 + +**注意**: +- 在调用`do_embeddings`函数之前,确保传入的`params`参数已经正确初始化,包括必要的文本列表等信息。 +- 此函数的实现依赖于模型是否支持嵌入功能。如果模型未实现此功能,将返回错误代码和相应的提示信息。 +- 由于`do_embeddings`函数返回的是一个字典,调用者应当准备好处理这个字典,特别是错误处理部分。 + +**输出示例**: +如果模型未实现嵌入功能,函数可能返回如下的字典: +```python +{ + "code": 500, + "msg": "模型名称未实现embeddings功能" +} +``` +其中`模型名称`将根据实际使用的模型名称进行替换。这个返回值提供了错误代码和相应的错误消息,帮助开发者理解问题所在。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是获取嵌入表示。 + +**参数**: +- **params**: 此参数用于传递获取嵌入表示所需的参数。 + +**代码描述**: +`get_embeddings`函数是`ApiModelWorker`类的一个方法,用于获取文本或数据的嵌入表示。在函数实现中,首先打印了字符串"get_embedding",随后打印了传入的`params`参数,这些参数预计包含了获取嵌入表示所需的具体信息。根据代码注释,可以了解到该函数设计是为了与fastchat和LLM(大型语言模型)配合使用,但似乎存在限制,只能使用openai提供的接口。注释还提到,如果尝试通过前端直接使用OpenAIEmbeddings发起请求,会直接出错,这表明在实际使用中需要注意请求的发起方式和参数配置。 + +**注意**: +- 该函数目前只包含打印操作,实际的嵌入表示获取逻辑尚未实现。开发者在使用时需要根据实际需求完成嵌入表示的获取逻辑。 +- 注释中提到的限制和错误提示,暗示在实际部署和使用该函数时,需要特别注意与OpenAI接口的兼容性问题,以及请求的正确发起方式。 +- 由于代码中存在中文注释,建议在实际项目中使用英文进行注释,以保证代码的国际化和更广泛的可读性。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 此函数的功能是创建一个对话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板的内容。默认值为None。 +- **model_path**: 字符串类型,指定模型路径。默认值为None。 + +**代码描述**: +`make_conv_template`函数是`ApiModelWorker`类的一个方法,旨在创建一个对话模板。此函数接受两个参数:`conv_template`和`model_path`。`conv_template`参数用于指定对话模板的具体内容,而`model_path`参数用于指定模型的存储路径。这两个参数都是可选的,如果调用时未提供,它们的默认值将分别为None。 + +函数体内部仅包含一行代码,即`raise NotImplementedError`。这表明`make_conv_template`函数是一个抽象方法,需要在`ApiModelWorker`类的子类中被具体实现。换句话说,当前的函数定义仅提供了一个接口框架,而没有实现具体的功能逻辑。在实际使用中,开发者需要根据具体需求,在继承了`ApiModelWorker`类的子类中重写`make_conv_template`方法,以实现创建对话模板的具体逻辑。 + +**注意**: +- 由于`make_conv_template`函数是一个抽象方法,直接调用它将会引发`NotImplementedError`异常。因此,在使用此函数之前,确保你正在操作的是一个正确实现了该方法的`ApiModelWorker`子类实例。 +- 在设计子类时,重写`make_conv_template`方法时应确保正确处理`conv_template`和`model_path`两个参数,以满足创建对话模板的需求。 +- 考虑到`make_conv_template`方法的抽象性,开发者在实现时应充分考虑对话模板的格式和模型路径的有效性,确保方法的实现能够在实际应用中正确工作。 +*** +### FunctionDef validate_messages(self, messages) +**validate_messages**: 此函数的功能是验证并可能修改传入的消息列表。 + +**参数**: +- messages: 一个字典列表,每个字典代表一条消息。 + +**代码描述**: +`validate_messages` 函数接收一个消息列表作为参数,这个列表是由字典组成的,每个字典代表一条消息。这个函数的主要目的是允许对传入的消息进行验证或者格式上的调整。在默认的实现中,这个函数直接返回传入的消息列表,没有进行任何修改。但是,开发者可以根据需要重写这个函数,以实现特定的消息验证或格式调整逻辑。 + +在项目中,`validate_messages` 函数被`generate_stream_gate`方法调用。在`generate_stream_gate`方法中,根据输入参数`params`中的`prompt`值,决定是直接使用`prompt_to_messages`方法生成的消息列表,还是构造一个特定格式的消息列表。之后,无论是哪种情况,都会调用`validate_messages`函数来对这些消息进行进一步的验证或调整。这样的设计使得消息的生成和验证两个步骤分离,提高了代码的可维护性和可扩展性。 + +**注意**: +- 开发者可以根据API的特殊需求,重写`validate_messages`函数来替换默认的消息验证逻辑。 +- 由于`validate_messages`函数的默认实现是直接返回传入的消息列表,如果不需要对消息进行特殊处理,可以不重写这个函数。 + +**输出示例**: +假设传入的消息列表为: +```python +[{"role": "user", "content": "Hello, how are you?"}] +``` +在默认实现下,`validate_messages`函数将直接返回这个列表。如果开发者重写了这个函数,输出则取决于重写后的逻辑。 +*** +### FunctionDef user_role(self) +**user_role**: 此函数的功能是获取当前用户的角色。 + +**参数**: 此函数没有参数。 + +**代码描述**: `user_role` 函数是 `ApiModelWorker` 类的一个方法,它返回当前会话 (`conv`) 中用户角色列表的第一个元素。在这个项目中,每个会话对象 (`conv`) 都有一个 `roles` 属性,该属性是一个列表,包含了会话中所有角色的标识。由于这个函数返回列表的第一个元素,我们可以推断在这个上下文中,第一个角色被视为“用户角色”。这个方法在多个地方被调用,主要用于确定消息的发送者角色,以及在生成流式门控(stream gate)和处理聊天消息时,区分用户和AI或其他角色的消息。 + +在 `generate_stream_gate` 方法中,`user_role` 被用来构造一个消息,当不支持历史消息时,提示用户继续写作。这表明,`user_role` 在决定消息来源方面起着关键作用。 + +在 `_is_chat` 方法中,通过检查提示信息 (`prompt`) 中是否包含由 `user_role` 定义的角色标识,来判断该提示信息是否由聊天消息拼接而成。这说明 `user_role` 在解析聊天对话时非常重要。 + +在 `prompt_to_messages` 方法中,`user_role` 用于将提示信息拆分成多个消息,每个消息都标记了发送者的角色。这进一步强调了用户角色在消息处理流程中的重要性。 + +在 `validate_messages` 方法中,虽然直接调用的是 `MiniMaxWorker` 类的实例,但该方法通过将消息中的角色映射到特定的发送者类型,间接体现了 `user_role` 在确保消息有效性中的作用。 + +**注意**: 在使用此函数时,需要确保 `conv.roles` 列表已经正确初始化,并且至少包含一个元素,否则会引发索引错误。 + +**输出示例**: 假设当前用户角色标识为 "USER",则调用 `user_role` 函数将返回 `"USER"`。 +*** +### FunctionDef ai_role(self) +**ai_role**: 此函数的功能是获取AI角色名称。 + +**参数**: 此函数没有参数。 + +**代码描述**: `ai_role`函数是`ApiModelWorker`类的一个方法,它的主要作用是从`conv.roles`列表中返回第二个元素,即AI的角色名称。在这个项目中,`conv.roles`被假设为一个包含用户角色和AI角色名称的列表,其中第一个元素是用户角色,第二个元素是AI角色。因此,通过`self.conv.roles[1]`可以获取到AI的角色名称。 + +在项目中,`ai_role`函数被`prompt_to_messages`和`validate_messages`两个方法调用。在`prompt_to_messages`方法中,它用于解析用户输入的提示(prompt),将其拆分成多个消息,并根据消息的开始部分判断是用户角色还是AI角色发出的消息,从而构造出一个包含角色和内容的字典列表。在`validate_messages`方法中,`ai_role`用于构建一个角色映射字典,该字典将消息中的角色名称映射到相应的发送者类型,以便进一步处理消息。 + +**注意**: 在使用`ai_role`函数时,需要确保`conv.roles`列表已经正确初始化,并且包含至少两个元素,否则会引发索引错误。 + +**输出示例**: 假设`conv.roles`列表为`["USER", "assistant"]`,则调用`ai_role`函数将返回`"assistant"`。 +*** +### FunctionDef _jsonify(self, data) +**_jsonify**: 该函数的功能是将数据字典转换为JSON格式字符串,并在末尾添加空字符。 + +**参数**: +- `data`: 需要被转换成JSON格式的字典(Dict)。 + +**代码描述**: +`_jsonify`函数接受一个字典类型的参数`data`,使用`json.dumps`方法将这个字典转换为JSON格式的字符串。在转换过程中,`ensure_ascii=False`参数确保了非ASCII字符可以正确地被转换和表示,而不是被转义。转换完成后,通过`.encode()`方法将字符串转换为字节串,并在其末尾添加一个空字符(`\0`),以满足特定的通信协议或数据格式要求。 + +在项目中,`_jsonify`函数被`generate_stream_gate`方法调用,用于处理和格式化`do_chat`方法产生的响应数据,以及异常情况下的错误信息。这样的设计使得数据在内部处理后可以直接用于网络传输或存储,同时保持了数据格式的一致性和可读性。 + +**注意**: +- 确保传入的`data`参数是字典类型,因为`json.dumps`方法只能处理字典或类似字典的对象。 +- 考虑到输出是字节串,调用此函数的上下文应该能够处理或适配字节串类型的数据。 + +**输出示例**: +如果传入`data`为`{"key": "value"}`,则函数的输出可能为:`'{"key": "value"}\0'`的字节串形式。 +*** +### FunctionDef _is_chat(self, prompt) +**_is_chat**: 此函数的功能是检查传入的提示信息是否由聊天消息拼接而成。 + +**参数**: +- prompt: 一个字符串,代表需要检查的提示信息。 + +**代码描述**: `_is_chat` 函数通过检查传入的提示信息(`prompt`)中是否包含特定的关键字来判断该信息是否由聊天消息构成。这个关键字是由会话分隔符(`self.conv.sep`)和当前用户角色标识(`self.user_role`)拼接而成,形式为`"{分隔符}{用户角色标识}:"`。如果这个关键字存在于提示信息中,则认为该提示信息是由聊天消息拼接而成的,函数返回`True`;否则返回`False`。这个方法在处理聊天对话时非常重要,它帮助系统区分用户直接输入的提示信息和由系统生成的、基于之前聊天历史的提示信息。 + +**注意**: 使用此函数时,需要确保会话分隔符(`self.conv.sep`)和用户角色标识(`self.user_role`)已经正确初始化。此外,由于此方法基于特定格式的关键字来判断信息是否由聊天消息构成,如果提示信息的格式有所变化(例如,分隔符或角色标识的变化),这可能会影响判断的准确性。 + +**输出示例**: 假设会话分隔符为`"||"`,当前用户角色标识为`"USER"`,如果传入的提示信息为`"||USER:你好||AI:你好呀"`,则函数返回`True`。如果传入的提示信息为`"请继续写作"`,则函数返回`False`。 +*** +### FunctionDef prompt_to_messages(self, prompt) +**prompt_to_messages**: 此函数的功能是将prompt字符串拆分成多个消息字典。 + +**参数**: +- prompt: 需要被拆分的字符串,类型为str。 + +**代码描述**: `prompt_to_messages` 方法用于解析由用户和AI角色交互构成的对话字符串,将其拆分为包含角色和内容的消息字典列表。该方法首先通过`self.user_role`和`self.ai_role`获取用户和AI的角色名称,然后根据这些角色名称识别并解析prompt字符串中的每条消息。对话字符串被假定为使用特定分隔符(`self.conv.sep`)分隔的消息序列,其中每条消息以角色名称开头,后跟消息内容。方法遍历这些消息,根据消息的开头确定是用户还是AI发送的消息,并将消息内容去除角色标识和前后空格后,存储在结果列表中。如果遇到既不属于用户也不属于AI的角色标识,方法将抛出运行时错误。 + +**注意**: +- 在使用此函数之前,需要确保`self.conv.roles`已经被正确初始化,并且包含了至少两个元素(用户角色和AI角色)。 +- 此方法假定prompt字符串的格式正确,并且每条消息都遵循“角色: 消息内容”的格式。 +- 如果prompt字符串中包含未知的角色标识,此方法将抛出运行时错误。 + +**输出示例**: +假设`prompt`字符串为`"USER: 你好吗?AI: 我很好,谢谢。"`,`self.conv.sep`为默认的分隔符,`self.user_role`返回`"USER"`,`self.ai_role`返回`"AI"`,则调用`prompt_to_messages(prompt)`将返回如下列表: +```python +[ + {"role": "USER", "content": "你好吗?"}, + {"role": "AI", "content": "我很好,谢谢。"} +] +``` +*** +### FunctionDef can_embedding(cls) +**can_embedding**: 此函数用于判断是否可以进行嵌入模型操作。 + +**参数**: 此函数不接受任何外部参数。 + +**函数描述**: `can_embedding` 是一个类方法,用于判断当前类是否可以进行嵌入模型操作。它通过检查类属性 `DEFAULT_EMBED_MODEL` 是否为 `None` 来实现这一功能。如果 `DEFAULT_EMBED_MODEL` 不为 `None`,则表示该类有默认的嵌入模型可以使用,函数返回 `True`;反之,如果为 `None`,则表示没有可用的嵌入模型,函数返回 `False`。这个方法主要用于在进行模型嵌入操作前,检查是否满足进行嵌入的基本条件。 + +**注意**: 使用此函数前,确保类属性 `DEFAULT_EMBED_MODEL` 已经被正确地设置。如果类设计中没有提供默认嵌入模型的路径或者模型对象,那么这个方法将始终返回 `False`,意味着不能进行嵌入操作。 + +**输出示例**: 假设某个类的 `DEFAULT_EMBED_MODEL` 被设置为了一个有效的模型路径或对象,那么调用 `can_embedding()` 方法将返回 `True`。如果 `DEFAULT_EMBED_MODEL` 为 `None` 或未被设置,那么调用此方法将返回 `False`。 +*** diff --git a/markdown_docs/server/model_workers/fangzhou.md b/markdown_docs/server/model_workers/fangzhou.md new file mode 100644 index 000000000..3bd601350 --- /dev/null +++ b/markdown_docs/server/model_workers/fangzhou.md @@ -0,0 +1,124 @@ +## ClassDef FangZhouWorker +**FangZhouWorker**: FangZhouWorker类是用于与火山方舟API进行交互的工作器。 + +**属性**: +- `model_names`: 模型名称列表,默认为["fangzhou-api"]。 +- `controller_addr`: 控制器地址,用于连接到模型控制器。 +- `worker_addr`: 工作器地址,用于接收和发送数据。 +- `version`: 模型版本,默认为"chatglm-6b-model"。 +- `context_len`: 上下文长度,默认为16384。 + +**代码描述**: +FangZhouWorker类继承自ApiModelWorker,专门用于处理与火山方舟API的交互。在初始化时,它接受模型名称、控制器地址、工作器地址和版本等参数,并将这些参数传递给父类ApiModelWorker。此外,它还设置了默认的上下文长度为16384。 + +该类重写了`do_chat`方法,用于执行聊天功能。在此方法中,首先加载配置,然后创建一个MaasService实例用于与火山方舟API进行通信。通过构造请求并调用`stream_chat`方法,它可以处理聊天请求并逐步返回响应。如果遇到错误,它会记录错误信息并返回相应的错误代码和消息。 + +`get_embeddings`和`make_conv_template`方法在此类中也有定义,但`get_embeddings`方法仅打印参数信息,而`make_conv_template`方法返回一个会话模板实例。 + +**注意**: +- 使用FangZhouWorker时,需要确保提供的API密钥(apiKey和secretKey)是有效的,以便能够成功调用火山方舟API。 +- 在处理聊天请求时,应注意参数的正确性和完整性,以避免请求失败。 +- 错误处理是此类的一个重要部分,开发者应留意日志中的错误信息,以便及时发现和解决问题。 + +**输出示例**: +在调用`do_chat`方法时,可能的返回值示例为: +```json +{ + "error_code": 0, + "text": "这是由模型生成的回复文本。" +} +``` +此示例表示聊天请求成功,其中`error_code`为0表示没有错误,`text`字段包含了模型生成的回复文本。如果请求失败,`error_code`将不为0,并且`text`字段将包含错误消息。 +### FunctionDef __init__(self) +**__init__**: 初始化FangZhouWorker对象,并配置其基本属性。 + +**参数**: +- **model_names**: 一个字符串列表,默认为["fangzhou-api"]。这个列表包含了模型的名称。 +- **controller_addr**: 一个字符串,表示控制器的地址。默认值为None。 +- **worker_addr**: 一个字符串,表示工作节点的地址。默认值为None。 +- **version**: 一个字符串,指定模型的版本。默认值为"chatglm-6b-model"。 +- **kwargs**: 接收一个字典,包含了其他可能需要传递给父类初始化方法的关键字参数。 + +**代码描述**: +此函数是FangZhouWorker类的构造函数,用于初始化一个FangZhouWorker对象。它首先接收几个关键参数,包括模型名称(`model_names`)、控制器地址(`controller_addr`)、工作节点地址(`worker_addr`)以及模型版本(`version`)。这些参数允许用户在创建FangZhouWorker对象时,指定所需的模型、控制器和工作节点的配置。 + +函数内部,首先通过`kwargs.update`方法更新`kwargs`字典,将`model_names`、`controller_addr`和`worker_addr`作为键值对加入到`kwargs`中。这样做是为了将这些参数传递给父类的初始化方法。 + +接着,使用`kwargs.setdefault`方法设置`context_len`的默认值为16384,如果`kwargs`中已经存在`context_len`,则保持原值不变。 + +最后,调用父类的`__init__`方法,通过`**kwargs`将更新后的参数传递给父类,并完成父类的初始化。此外,将`version`参数赋值给实例变量`self.version`,以便后续使用。 + +**注意**: +- 在使用FangZhouWorker类创建对象时,需要注意`controller_addr`和`worker_addr`参数默认为None,这意味着如果不显式提供这些参数,它们将不会被配置。因此,在需要与特定控制器或工作节点通信的场景中,必须提供这些参数的有效值。 +- `version`参数默认为"chatglm-6b-model",如果需要使用不同版本的模型,应在创建对象时指定相应的版本号。 +- 通过`kwargs`传递额外参数时,应确保这些参数是父类初始化方法所支持的,以避免引发错误。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是执行聊天模型的请求并处理响应。 + +**参数**: +- `params`: `ApiChatParams`类型,包含聊天请求所需的所有参数。 + +**代码描述**: +`do_chat`函数首先从`volcengine.maas`导入`MaasService`,用于与方舟API进行交互。通过`params.load_config`方法,根据模型名称加载相关配置,这一步骤涉及到从`ApiChatParams`类继承的属性和方法,以及`load_config`函数的具体实现,后者负责根据工作器名称加载相应的配置信息。 + +接着,函数初始化`MaasService`对象,设置API的访问地址和区域,并通过`set_ak`和`set_sk`方法设置API的访问密钥和安全密钥。 + +函数构造了一个请求字典`req`,其中包含模型名称、请求参数(如最大生成令牌数和温度参数),以及聊天消息。这些参数的值来源于`params`对象,它是`ApiChatParams`类的实例。 + +通过`maas.stream_chat(req)`方法发送请求,并逐个处理返回的响应。如果响应中包含错误信息,则构造并返回一个包含错误代码、错误文本和错误详情的字典。如果响应成功,将返回的文本内容累加,并生成包含错误代码和文本内容的字典。如果遇到未知错误,则记录错误信息并中断循环。 + +**注意**: +- 在调用`do_chat`函数之前,确保`params`对象已经通过`load_config`方法加载了正确的配置信息,这包括API密钥、安全密钥和模型名称等。 +- 函数中的日志记录依赖于外部的日志配置,确保在使用此函数之前已经正确配置了日志系统。 +- 此函数通过生成器`yield`返回数据,调用方需要通过迭代的方式获取所有响应数据。 +- 请求方舟API时可能会遇到各种错误,包括但不限于网络问题、认证失败或请求参数错误等,开发者需要根据实际情况处理这些错误。 +- 函数中提到的API地址和参数仅为示例,实际使用时需要根据方舟API的最新文档进行相应的调整。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息,其具体内容和格式取决于调用此函数时的需求。 + +**代码描述**: +`get_embeddings`函数是`FangZhouWorker`类的一个方法,主要用于展示如何处理和打印传入的参数信息。当调用此函数时,它首先打印出字符串"embedding",随后打印出传入的`params`参数的内容。这个过程可以帮助开发者理解如何在实际应用中接收和处理参数,尽管在当前的实现中,它仅仅是将传入的参数直接打印出来,没有进行进一步的处理或操作。 + +**注意**: +- 在使用`get_embeddings`函数时,需要注意`params`参数的格式和内容,确保它能够正确地被函数接收和处理。 +- 由于此函数目前的实现较为简单,仅用于演示目的,因此在将其应用于实际项目中时,可能需要根据具体需求对其进行相应的扩展和修改。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 该函数用于创建一个会话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定会话模板的内容,可选参数,默认为None。 +- **model_path**: 字符串类型,指定模型路径,可选参数,默认为None。 + +**代码描述**: +`make_conv_template`函数是`FangZhouWorker`类的一个方法,用于生成一个会话模板。该方法接收两个可选参数:`conv_template`和`model_path`,但在当前实现中这两个参数并未直接使用。函数主要工作是创建并返回一个`Conversation`对象,该对象初始化时包含以下关键信息: +- `name`: 使用`self.model_names[0]`作为会话的名称,这里假设`model_names`是一个列表,且至少包含一个元素。 +- `system_message`: 设置为一个固定的字符串,即"你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答。",这条信息描述了人工智能的角色和期望行为。 +- `messages`: 初始化为空列表,表示会话开始时没有任何消息。 +- `roles`: 设置为["user", "assistant", "system"],定义了会话中的角色。 +- `sep`: 设置为"\n### ",定义了消息之间的分隔符。 +- `stop_str`: 设置为"###",定义了会话的终止字符串。 + +**注意**: +- 在使用此函数时,需要确保`self.model_names`已经被正确初始化,且至少包含一个元素,否则会引发索引错误。 +- 该函数的实现暂时没有使用`conv_template`和`model_path`参数,但这为将来的扩展留下了可能性。 +- 返回的`Conversation`对象可以用于进一步的会话处理或模拟。 + +**输出示例**: +假设`self.model_names`的第一个元素为"AI_Model_1",则函数返回的`Conversation`对象可能如下所示(仅展示关键属性): +```python +Conversation( + name="AI_Model_1", + system_message="你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答。", + messages=[], + roles=["user", "assistant", "system"], + sep="\n### ", + stop_str="###", +) +``` +*** diff --git a/markdown_docs/server/model_workers/gemini.md b/markdown_docs/server/model_workers/gemini.md new file mode 100644 index 000000000..c43bcb2bc --- /dev/null +++ b/markdown_docs/server/model_workers/gemini.md @@ -0,0 +1,161 @@ +## ClassDef GeminiWorker +**GeminiWorker**: GeminiWorker类是用于处理与Gemini API交互的工作流程。 + +**属性**: +- `controller_addr`: 控制器地址,用于与控制器进行通信。 +- `worker_addr`: 工作器地址,用于标识工作器的位置。 +- `model_names`: 模型名称列表,默认为["gemini-api"],用于指定要交互的模型。 +- `context_len`: 上下文长度,默认为4096,用于指定处理的文本长度上限。 + +**代码描述**: +GeminiWorker类继承自ApiModelWorker类,专门用于处理与Gemini API的交互。它通过重写父类的方法,实现了与Gemini API特定的交互逻辑。 + +- `__init__`方法用于初始化GeminiWorker对象,接收控制器地址、工作器地址、模型名称等参数,并设置了默认的上下文长度为4096。 +- `create_gemini_messages`方法用于将消息列表转换为Gemini API所需的格式。该方法检查消息历史中是否包含助手的角色,以决定消息转换的方式。 +- `do_chat`方法实现了与Gemini API进行聊天的功能。它首先加载配置,然后创建符合Gemini API要求的消息格式,并发送请求到Gemini API,处理响应并返回生成的文本。 +- `get_embeddings`方法打印了嵌入信息,但未实现具体的嵌入逻辑。 +- `make_conv_template`方法用于创建对话模板,但具体实现依赖于子类。 + +**注意**: +- 使用GeminiWorker时,需要确保提供的控制器地址和工作器地址有效,以及模型名称正确对应于Gemini API提供的模型。 +- `do_chat`方法中使用了HTTPX库进行网络请求,需要注意网络环境和API密钥的配置。 +- 该类中的`create_gemini_messages`和`do_chat`方法是与Gemini API交互的核心,需要根据Gemini API的更新维护这些方法。 + +**输出示例**: +调用`do_chat`方法可能的返回值示例: +```json +{ + "error_code": 0, + "text": "这是由Gemini模型生成的回复文本。" +} +``` +此示例展示了成功调用Gemini API并获取到模型生成的回复文本,其中`error_code`为0表示成功。 +### FunctionDef __init__(self) +**__init__**: __init__函数的作用是初始化GeminiWorker对象。 + +**参数**: +- **controller_addr**: 字符串类型,默认为None,表示控制器的地址。 +- **worker_addr**: 字符串类型,默认为None,表示工作节点的地址。 +- **model_names**: 字符串列表类型,默认为["gemini-api"],表示模型的名称列表。 +- **kwargs**: 关键字参数,可以接受额外的参数,用于扩展或自定义初始化过程。 + +**代码描述**: +此__init__函数是GeminiWorker类的构造函数,用于初始化一个GeminiWorker对象。在初始化过程中,它接受几个参数,包括控制器地址(controller_addr)、工作节点地址(worker_addr)和模型名称列表(model_names)。这些参数允许用户在创建GeminiWorker对象时指定这些重要的配置信息。 + +函数首先将`model_names`、`controller_addr`和`worker_addr`参数通过`kwargs.update()`方法更新到`kwargs`字典中。这样做的目的是将这些参数统一处理,便于后续操作。 + +接着,通过`kwargs.setdefault("context_len", 4096)`设置`context_len`参数的默认值为4096,如果在`kwargs`中已经存在`context_len`,则保持原值不变。这一步骤确保了即使用户没有明确提供`context_len`参数,GeminiWorker对象也有一个默认的上下文长度。 + +最后,通过`super().__init__(**kwargs)`调用基类的构造函数,完成GeminiWorker对象的初始化。这一步骤允许GeminiWorker继承并使用基类提供的方法和属性,同时也确保了任何额外的关键字参数(通过`kwargs`传递)都被正确处理。 + +**注意**: +- 在使用GeminiWorker对象时,确保提供正确的`controller_addr`和`worker_addr`,这对于确保GeminiWorker能够正确连接到控制器和工作节点至关重要。 +- `model_names`参数允许用户指定一个或多个模型名称,这些模型将在GeminiWorker中被加载和使用。默认情况下,它包含"gemini-api"作为模型名称,但用户可以根据需要修改此列表。 +- 通过`kwargs`参数,用户可以提供额外的配置选项,这提供了高度的灵活性和可扩展性。务必注意,任何通过`kwargs`传递的额外参数都应该是GeminiWorker或其基类能够识别和处理的。 +*** +### FunctionDef create_gemini_messages(self, messages) +**create_gemini_messages**: 此函数的功能是将输入的消息列表转换为适用于Gemini模型的格式。 + +**参数**: +- messages: 需要被转换格式的消息列表,每个消息是一个包含'role'和'content'键的字典。 + +**代码描述**: +`create_gemini_messages`函数接收一个消息列表作为输入,这个列表中的每个消息都是一个字典,包含'role'(角色)和'content'(内容)。函数首先检查消息列表中是否存在角色为'assistant'的消息,以确定是否有历史对话记录。接着,函数遍历消息列表,根据角色和是否有历史记录的情况,转换每条消息的格式。如果消息的角色是'system',则跳过不处理。如果有历史记录并且消息角色是'assistant',则将角色改为'model',并将消息内容放入'parts'列表中。如果没有历史记录但消息角色是'user',则直接将消息内容放入'parts'列表中。最后,函数将转换后的消息列表封装成一个字典返回。 + +在项目中,`create_gemini_messages`函数被`do_chat`方法调用。`do_chat`方法使用此函数将用户和系统的交互消息转换为Gemini模型能够处理的格式,然后将这些消息连同生成配置一起发送到Gemini模型的API,以获取模型的响应。这说明`create_gemini_messages`函数在处理用户输入和系统生成的消息,以及准备这些消息以供模型处理方面起着关键作用。 + +**注意**: +- 确保输入的消息列表中的每个消息字典都包含'role'和'content'键。 +- 此函数不处理角色为'system'的消息,因为这些消息通常是系统级别的指令或信息,不适合发送给模型处理。 + +**输出示例**: +假设输入的消息列表为: +```json +[ + {"role": "user", "content": "你好"}, + {"role": "assistant", "content": "你好,有什么可以帮助你的?"} +] +``` +函数的返回值可能会是: +```json +{ + "contents": [ + {"role": "model", "parts": [{"text": "你好,有什么可以帮助你的?"}]}, + {"parts": [{"text": "你好"}]} + ] +} +``` +这个返回值中包含了转换后的消息列表,适用于发送给Gemini模型进行处理。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是执行聊天操作,通过调用Gemini模型的API生成聊天内容。 + +**参数**: +- `params`: `ApiChatParams`类型,包含聊天请求所需的参数。 + +**代码描述**: +`do_chat`函数首先通过`params.load_config`方法加载模型配置,这一步骤确保了聊天操作使用正确的模型参数。接着,函数调用`create_gemini_messages`方法,将用户输入的消息转换为Gemini模型能够理解的格式。之后,函数构建了一个字典`generationConfig`,包含了生成聊天内容所需的配置,如温度(`temperature`)、最大输出令牌数(`maxOutputTokens`)等。 + +函数将生成配置添加到`data`字典中,并构造了一个请求URL,该URL指向Gemini模型的API,并附加了API密钥。随后,设置了HTTP请求的头部信息,并通过`get_httpx_client`函数获取一个httpx客户端实例,用于发送POST请求到模型的API。 + +在发送请求并接收响应的过程中,函数通过迭代响应的每一行来构建完整的JSON字符串。如果在响应中检测到了候选回复(`candidates`),函数将遍历这些候选回复,并从中提取文本内容,最终通过`yield`语句返回包含错误码和文本内容的字典。 + +**注意**: +- 在使用`do_chat`函数时,需要确保传入的`params`参数是`ApiChatParams`类型的实例,且已正确填充了所有必要的字段。 +- 函数依赖于`create_gemini_messages`方法来转换消息格式,确保消息能被Gemini模型正确理解。 +- 函数通过`get_httpx_client`获取httpx客户端实例来发送请求,这一步骤涉及网络通信,因此可能受到网络环境的影响。 +- 函数使用了`json.loads`来解析JSON字符串,如果响应格式不正确,可能会抛出`json.JSONDecodeError`异常。 +- 由于函数使用了`yield`语句,它实际上是一个生成器函数,调用此函数时需要注意迭代接收返回值。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息。 + +**代码描述**: +`get_embeddings` 函数是 `GeminiWorker` 类的一个方法,主要用于展示如何处理和打印传入的参数信息。当调用此函数时,它首先打印出字符串 "embedding",随后打印出传入的 `params` 参数值。这个过程可以帮助开发者理解函数如何接收和处理参数,以及如何在控制台中输出信息。 + +此函数的实现较为简单,主要包括以下两个步骤: +1. 打印出 "embedding" 字符串,表示开始进行嵌入信息的处理。 +2. 打印出传入的 `params` 参数,这可以是任何形式的数据,函数将直接将其输出到控制台。 + +**注意**: +- 在实际应用中,`get_embeddings` 函数可能需要根据实际需求进行扩展和修改,以处理更复杂的数据结构或执行更复杂的嵌入计算。 +- 此函数目前仅用于演示和教学目的,实际使用时可能需要根据具体的业务逻辑进行相应的调整。 +- 参数 `params` 应根据实际情况传入相应的数据,以确保函数能够正确处理和输出期望的信息。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template函数的功能**: 创建一个对话模板实例。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板的具体内容。此参数在当前实现中未直接使用,但保留以便未来扩展。 +- **model_path**: 字符串类型,指定模型路径。此参数在当前实现中未直接使用,但保留以便未来扩展。 + +**代码描述**: +`make_conv_template`函数负责创建一个`Conversation`类的实例。这个实例包含了一系列初始化的属性,用于定义一个对话模板。这些属性包括: +- `name`: 对话的名称,这里使用`self.model_names[0]`,即模型名称列表中的第一个名称。 +- `system_message`: 系统消息,这里固定为"You are a helpful, respectful and honest assistant.",表示助手的行为准则。 +- `messages`: 对话消息列表,初始化为空列表,表示对话开始时没有任何消息。 +- `roles`: 对话中的角色列表,包含"user"和"assistant",分别表示用户和助手。 +- `sep`: 消息分隔符,这里设为"\n### ",用于分隔对话中的不同消息。 +- `stop_str`: 对话终止字符串,这里设为"###",用于标识对话的结束。 + +**注意**: +- 虽然`conv_template`和`model_path`参数在当前函数实现中未被直接使用,但它们的存在为函数提供了扩展性。在未来的版本中,这些参数可能会被用来定制对话模板或指定模型路径。 +- 创建的`Conversation`实例是基于预定义的属性值。如果需要不同的对话设置,需要修改这些属性值。 + +**输出示例**: +假设`self.model_names[0]`的值为"ExampleModel",则函数的返回值可能如下所示: +```python +Conversation( + name="ExampleModel", + system_message="You are a helpful, respectful and honest assistant.", + messages=[], + roles=["user", "assistant"], + sep="\n### ", + stop_str="###", +) +``` +这表示创建了一个名为"ExampleModel"的对话模板,其中包含了初始化的系统消息、空的消息列表、定义的角色和消息分隔符。 +*** diff --git a/markdown_docs/server/model_workers/minimax.md b/markdown_docs/server/model_workers/minimax.md new file mode 100644 index 000000000..2ede0b22c --- /dev/null +++ b/markdown_docs/server/model_workers/minimax.md @@ -0,0 +1,205 @@ +## ClassDef MiniMaxWorker +**MiniMaxWorker**: MiniMaxWorker类是用于与MiniMax API进行交互的工作类。 + +**属性**: +- `DEFAULT_EMBED_MODEL`: 默认嵌入模型标识符,用于嵌入功能,默认值为"embo-01"。 +- `model_names`: 模型名称列表,默认包含"minimax-api"。 +- `controller_addr`: 控制器地址,用于内部通信。 +- `worker_addr`: 工作器地址,用于内部通信。 +- `version`: 模型版本,初始化为"abab5.5-chat"。 +- `context_len`: 上下文长度,默认为16384,继承自ApiModelWorker类。 + +**代码描述**: +MiniMaxWorker类继承自ApiModelWorker类,专门用于处理与MiniMax API的交互。它通过重写父类的方法,实现了与MiniMax API特定功能的交互,包括聊天和嵌入功能。 + +- `__init__`方法用于初始化MiniMaxWorker实例,包括设置模型名称、控制器地址、工作器地址、版本号等,并更新上下文长度。 +- `validate_messages`方法用于验证和转换消息格式,以符合MiniMax API的要求。 +- `do_chat`方法实现了与MiniMax API的聊天功能交互。它构造了API请求,处理响应,并以生成器的形式返回处理结果。 +- `do_embeddings`方法实现了与MiniMax API的嵌入功能交互。它发送请求到MiniMax API,获取文本的嵌入表示,并处理API的响应。 +- `get_embeddings`和`make_conv_template`方法为预留方法,目前在MiniMaxWorker类中未具体实现。 + +**注意**: +- 使用MiniMaxWorker类时,需要确保MiniMax API的可访问性和正确的API密钥。 +- `do_chat`和`do_embeddings`方法中的错误处理非常重要,需要仔细检查返回的错误信息。 +- 由于`do_chat`方法使用了生成器,调用此方法时需要注意迭代器的处理。 + +**输出示例**: +调用`do_chat`方法可能的返回值示例: +```json +{ + "error_code": 0, + "text": "这是由MiniMax模型生成的回复文本。" +} +``` +此示例展示了一个成功的API调用结果,其中`error_code`为0表示成功,`text`字段包含了模型生成的回复文本。 + +调用`do_embeddings`方法可能的返回值示例: +```json +{ + "code": 200, + "data": [[0.1, 0.2, ..., 0.5], [...]], + "msg": "成功获取嵌入向量。" +} +``` +此示例展示了成功获取文本嵌入向量的API调用结果,`code`为200表示成功,`data`字段包含了嵌入向量的列表,`msg`字段提供了操作的反馈信息。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化MiniMaxWorker对象。 + +**参数**: +- **model_names**: 一个字符串列表,默认值为["minimax-api"]。这个列表包含了模型的名称。 +- **controller_addr**: 一个字符串,表示控制器的地址。默认值为None。 +- **worker_addr**: 一个字符串,表示工作节点的地址。默认值为None。 +- **version**: 一个字符串,表示版本号,默认值为"abab5.5-chat"。 +- **kwargs**: 接收一个字典,包含了其他可能需要传递给父类初始化方法的关键字参数。 + +**代码描述**: +此函数是`MiniMaxWorker`类的构造函数,用于创建`MiniMaxWorker`实例。它接受几个参数,包括模型名称列表`model_names`、控制器地址`controller_addr`、工作节点地址`worker_addr`以及版本号`version`。这些参数允许用户在创建`MiniMaxWorker`实例时定制其配置。 + +函数首先将`model_names`、`controller_addr`和`worker_addr`参数通过`kwargs.update`方法更新到`kwargs`字典中。这样做是为了将这些参数以关键字参数的形式传递给父类的初始化方法。 + +接下来,`kwargs.setdefault("context_len", 16384)`用于设置`kwargs`字典中`context_len`键的默认值为16384,如果`context_len`已经在`kwargs`中有值,则保持原值不变。 + +之后,通过`super().__init__(**kwargs)`调用父类的初始化方法,将更新后的`kwargs`字典传递给父类,完成父类的初始化。 + +最后,将传入的`version`参数赋值给实例变量`self.version`,以便在类的其他方法中使用。 + +**注意**: +- 在使用`MiniMaxWorker`类时,需要注意`controller_addr`和`worker_addr`参数是可选的,如果在特定环境下这两个参数是必需的,应在实例化时提供相应的值。 +- `kwargs`参数提供了一种灵活的方式来传递额外的参数给父类的初始化方法,这在需要对父类行为进行定制时非常有用。但是,使用时应确保传递的关键字参数是父类所支持的。 +*** +### FunctionDef validate_messages(self, messages) +**validate_messages**: 此函数的功能是验证并转换消息列表中的角色到对应的发送者类型。 + +**参数**: +- messages: 一个包含字典的列表,每个字典代表一条消息,其中包含角色和内容。 + +**代码描述**: +`validate_messages` 函数接收一个消息列表作为输入,每条消息是一个包含角色和内容的字典。函数内部定义了一个 `role_maps` 字典,用于将消息中的角色("USER"、"assistant"、"system")映射到对应的发送者类型(用户角色、AI角色、系统)。这里的用户角色和AI角色是通过调用 `user_role` 和 `ai_role` 方法获取的,这两个方法分别返回当前会话中用户的角色和AI的角色名称。系统角色则直接映射为字符串 "system"。 + +函数遍历输入的消息列表,对于每条消息,根据其角色使用 `role_maps` 进行映射,并保留消息内容,生成一个新的字典。这个过程转换了原始消息列表中的角色到对应的发送者类型,同时保留了消息内容。最终,函数返回一个新的消息列表,每条消息包含了发送者类型和文本内容。 + +**注意**: +- 在使用此函数之前,需要确保 `conv.roles` 列表已经被正确初始化,并且至少包含用户和AI的角色。 +- 此函数依赖于 `user_role` 和 `ai_role` 方法,这两个方法分别从会话对象中获取用户和AI的角色名称。因此,确保会话对象已正确设置是使用此函数的前提。 + +**输出示例**: +假设输入的消息列表为 `[{"role": "USER", "content": "你好"}, {"role": "assistant", "content": "你好,有什么可以帮助你的?"}]`,并且当前用户角色为 `"USER"`,AI角色为 `"assistant"`,则函数的返回值可能如下: +``` +[ + {"sender_type": "USER", "text": "你好"}, + {"sender_type": "assistant", "text": "你好,有什么可以帮助你的?"} +] +``` +这个输出示例展示了如何将输入的消息列表中的角色转换为对应的发送者类型,并保留了消息内容。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是通过MiniMax API进行聊天对话。 + +**参数**: +- `params`: ApiChatParams类型,包含聊天请求所需的各种参数。 + +**代码描述**: +`do_chat`函数首先调用`load_config`方法,根据模型名称加载相应的配置。然后,构造MiniMax API的请求URL,根据`params`中的`is_pro`字段判断是否使用专业版API。接着,设置HTTP请求头,包括认证信息和内容类型。 + +函数通过调用`validate_messages`方法处理`params.messages`,将消息列表中的角色转换为对应的发送者类型。之后,构造请求体`data`,包含模型版本、是否流式响应、是否屏蔽敏感信息、处理后的消息列表、温度参数、top_p参数和生成的最大令牌数。部分特有的MiniMax参数如`prompt`、`bot_setting`和`role_meta`在此示例中未使用。 + +使用`get_httpx_client`函数获取HTTP客户端实例,并发起POST请求到MiniMax API。请求响应以流式方式处理,逐步读取并解析返回的文本。如果返回的文本不以"data: "开头,则认为是错误的结果,构造错误信息并记录日志。如果返回的数据中包含`choices`字段,则从中提取文本内容并返回。 + +**注意**: +- 在使用`do_chat`函数时,需要确保传入的`params`参数正确设置了API密钥、消息列表等信息。 +- 函数依赖于`validate_messages`方法来处理消息列表,确保消息格式符合MiniMax API的要求。 +- `get_httpx_client`函数用于获取配置好的HTTP客户端实例,支持同步或异步操作,根据项目需要选择合适的模式。 +- 函数中的错误处理逻辑确保了在遇到API请求错误时,能够及时记录日志并向调用者返回错误信息。 +- 由于函数使用了流式响应处理,开发者需要注意处理可能的大量数据和网络延迟问题。 +*** +### FunctionDef do_embeddings(self, params) +**do_embeddings**: 此函数的功能是调用MiniMax API以获取文本的嵌入向量。 + +**参数**: +- `params`: `ApiEmbeddingsParams`类型,包含嵌入模型API请求所需的参数。 + +**代码描述**: +`do_embeddings`函数首先通过`params.load_config`方法加载模型配置,这一步骤确保了使用正确的模型名称进行API请求。接着,构造了一个指向MiniMax嵌入API的URL,其中包含了通过`params`传入的`group_id`。 + +函数定义了HTTP请求的头部信息,包括授权令牌和内容类型。在请求体`data`中,指定了使用的嵌入模型(如果`params.embed_model`未指定,则使用默认值`self.DEFAULT_EMBED_MODEL`)、待处理的文本列表以及请求类型(根据`params.to_query`决定是查询类型还是数据库类型)。 + +通过`get_httpx_client`函数获取一个httpx客户端实例,用于发送HTTP POST请求到MiniMax API。请求以批处理的方式进行,每批处理10个文本,直到所有文本都被处理完毕。对于每个批次的响应,如果成功获取到嵌入向量,则将这些向量添加到结果列表中;如果响应中包含错误信息,则记录错误并提前返回错误信息。 + +**注意**: +- 确保`params`中的`api_key`和`group_id`已经正确设置,因为它们对于API请求的授权和定位至关重要。 +- 文本列表`params.texts`不能为空,因为这是生成嵌入向量的基础数据。 +- 函数中的错误处理确保了在API请求过程中遇到问题时,能够及时反馈给调用者,避免了程序的进一步执行。 + +**输出示例**: +成功调用`do_embeddings`函数可能返回如下格式的字典: +```python +{ + "code": 200, + "data": [ + [0.1, 0.2, 0.3, ...], # 第一个文本的嵌入向量 + [0.4, 0.5, 0.6, ...], # 第二个文本的嵌入向量 + ... + ] +} +``` +如果遇到错误,则返回的字典可能如下所示: +```python +{ + "code": 错误代码, + "msg": "错误信息", + "error": { + "message": "具体的错误信息", + "type": "invalid_request_error", + "param": None, + "code": None, + } +} +``` +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息,其具体内容和格式取决于调用此函数时的上下文环境。 + +**代码描述**: +`get_embeddings`函数是`MiniMaxWorker`类的一个方法,它接受一个参数`params`。函数体内部首先打印出字符串"embedding",随后打印出传入的`params`参数。这表明该函数的主要作用是在控制台上输出与嵌入相关的信息以及传入的参数,用于调试或展示参数信息的目的。 + +**注意**: +- 在使用`get_embeddings`函数时,需要注意`params`参数的内容和格式。由于此函数直接将`params`输出到控制台,因此`params`的内容应当是能够清晰表达意图的信息,以便于开发者理解和调试。 +- 此函数目前看起来主要用于展示或调试目的,因此在生产环境中使用时,可能需要根据实际需求对其进行适当的修改或扩展,以满足特定的业务逻辑。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 该函数用于创建一个对话模板。 + +**参数**: +- `conv_template`: 字符串类型,指定对话模板,此参数在当前实现中未直接使用。 +- `model_path`: 字符串类型,指定模型路径,此参数在当前实现中未直接使用。 + +**代码描述**: +`make_conv_template` 函数负责生成一个对话模板实例。这个实例是通过调用 `conv.Conversation` 类来创建的,其中包含了以下几个关键信息: +- `name`: 对话的名称,这里使用 `self.model_names[0]`,即模型名称列表中的第一个名称。 +- `system_message`: 系统消息,这里设置为“你是MiniMax自主研发的大型语言模型,回答问题简洁有条理。”,用于描述机器人的角色和行为准则。 +- `messages`: 对话消息列表,初始为空列表。 +- `roles`: 对话中的角色列表,这里设置为 `["USER", "BOT"]`,分别代表用户和机器人。 +- `sep`: 消息分隔符,这里设置为 `"\n### "`,用于分隔对话中的不同消息。 +- `stop_str`: 停止字符串,这里设置为 `"###"`,用于标识对话的结束。 + +**注意**: +- 虽然 `conv_template` 和 `model_path` 参数在当前函数实现中未被直接使用,但它们的存在可能是为了未来的功能扩展预留。 +- 在使用此函数创建对话模板时,需要确保 `self.model_names` 列表至少包含一个元素,否则会导致索引错误。 + +**输出示例**: +假设 `self.model_names` 列表中的第一个元素为 `"MiniMaxModel"`,则函数的返回值可能如下所示: +```python +Conversation( + name="MiniMaxModel", + system_message="你是MiniMax自主研发的大型语言模型,回答问题简洁有条理。", + messages=[], + roles=["USER", "BOT"], + sep="\n### ", + stop_str="###", +) +``` +这表示创建了一个名为 "MiniMaxModel" 的对话模板,其中包含了预设的系统消息、空的消息列表、指定的角色列表以及消息分隔符和停止字符串。 +*** diff --git a/markdown_docs/server/model_workers/qianfan.md b/markdown_docs/server/model_workers/qianfan.md new file mode 100644 index 000000000..35f84570c --- /dev/null +++ b/markdown_docs/server/model_workers/qianfan.md @@ -0,0 +1,189 @@ +## FunctionDef get_baidu_access_token(api_key, secret_key) +**get_baidu_access_token**: 该函数的功能是使用API Key(AK)和Secret Key(SK)获取百度API的鉴权签名(Access Token)。 + +**参数**: +- `api_key`: 字符串类型,用户的API Key。 +- `secret_key`: 字符串类型,用户的Secret Key。 + +**代码描述**: +此函数首先定义了一个URL,指向百度的OAuth 2.0 token获取接口。然后,构造了一个参数字典,包含`grant_type`、`client_id`(即`api_key`)和`client_secret`(即`secret_key`)。使用`get_httpx_client`函数获取一个httpx客户端实例,并通过这个实例向百度的接口发起GET请求,传递上述参数。如果请求成功,函数将解析响应的JSON数据,尝试获取并返回`access_token`字段的值。如果在此过程中发生任何异常,函数将捕获这些异常并打印错误信息,但不会返回任何值。 + +**注意**: +- 确保传入的`api_key`和`secret_key`是有效的,否则无法成功获取Access Token。 +- 此函数依赖于`get_httpx_client`函数来创建HTTP客户端实例,该函数支持同步或异步客户端实例的创建,并允许配置代理和超时等参数。 +- 在使用此函数获取Access Token后,应妥善管理和使用Token,避免频繁请求导致的额度消耗。 + +**输出示例**: +假设函数调用成功,返回的`access_token`可能类似于以下字符串: +``` +"24.abcdefghijk1234567890" +``` +如果发生错误,函数不会返回任何值,但会在控制台打印错误信息。 +## ClassDef QianFanWorker +**QianFanWorker**: QianFanWorker类是用于与百度千帆API进行交互的工作器。 + +**属性**: +- `DEFAULT_EMBED_MODEL`: 默认的嵌入模型,此处为"embedding-v1"。 +- `version`: 模型版本,支持"ernie-bot"和"ernie-bot-turbo"两种版本,默认为"ernie-bot"。 +- `model_names`: 模型名称列表,默认为["qianfan-api"]。 +- `controller_addr`: 控制器地址,用于与模型控制器进行通信。 +- `worker_addr`: 工作器地址,用于接收和发送模型处理请求。 + +**代码描述**: +QianFanWorker类继承自ApiModelWorker,专门用于处理与百度千帆API的交互。它通过重写父类的方法,实现了与百度千帆API的聊天和嵌入功能。 + +- `__init__`方法用于初始化QianFanWorker实例,包括设置模型版本、模型名称、控制器地址、工作器地址等,并通过kwargs传递额外的参数。 +- `do_chat`方法实现了与百度千帆API的聊天交互。它构造请求URL和负载,通过HTTP POST请求发送给百度千帆API,并处理响应数据,生成聊天文本。 +- `do_embeddings`方法实现了获取文本嵌入的功能。它通过百度千帆API获取文本的嵌入表示,并返回嵌入结果。 +- `get_embeddings`和`make_conv_template`方法为占位方法,具体实现依赖于项目需求。 + +**注意**: +- 在使用QianFanWorker时,需要确保百度千帆API的访问权限,包括正确的API密钥和访问令牌。 +- `do_chat`和`do_embeddings`方法中的错误处理非常重要,需要仔细检查返回的错误代码和消息,以确保API调用成功。 +- 由于网络请求的不确定性,建议在实际应用中添加适当的异常处理和日志记录,以便于问题追踪和调试。 + +**输出示例**: +一个模拟的`do_chat`方法的可能输出示例为: +```json +{ + "error_code": 0, + "text": "这是由百度千帆模型生成的回复文本。" +} +``` +此输出示例展示了一个成功的API调用结果,其中`error_code`为0表示成功,`text`字段包含了模型生成的回复文本。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化QianFanWorker对象。 + +**参数**: +- `version`: 指定模型的版本,可选值为"ernie-bot"或"ernie-bot-turbo",默认为"ernie-bot"。 +- `model_names`: 一个字符串列表,包含要使用的模型名称,默认为["qianfan-api"]。 +- `controller_addr`: 控制器地址,类型为字符串,可选参数。 +- `worker_addr`: 工作器地址,类型为字符串,可选参数。 +- `**kwargs`: 接受额外的关键字参数,这些参数将被传递给父类的初始化方法。 + +**代码描述**: +此函数是`QianFanWorker`类的构造函数,负责初始化该类的实例。首先,它通过关键字参数的形式接收几个参数,包括模型版本(`version`)、模型名称列表(`model_names`)、控制器地址(`controller_addr`)和工作器地址(`worker_addr`)。这些参数中,`version`和`model_names`有默认值,而`controller_addr`和`worker_addr`是可选的。 + +函数内部首先将`model_names`、`controller_addr`和`worker_addr`这三个参数通过`kwargs.update()`方法更新到`kwargs`字典中,这样做是为了将这些参数以关键字参数的形式传递给父类的初始化方法。接着,使用`kwargs.setdefault()`方法设置`context_len`的默认值为16384,如果`kwargs`中已经存在`context_len`,则保持原值不变。 + +最后,调用父类的`__init__`方法,将更新后的`kwargs`传递给父类,完成父类的初始化。同时,将`version`参数赋值给实例变量`self.version`,以便后续使用。 + +**注意**: +- 在使用`QianFanWorker`类创建实例时,需要注意`version`参数的选值,确保传入的值是支持的版本。 +- `model_names`参数允许用户指定一个或多个模型名称,这些模型将在`QianFanWorker`实例中被使用。 +- 如果提供了`controller_addr`和`worker_addr`参数,它们将被用于配置控制器和工作器的地址。 +- 通过`**kwargs`可以传递额外的参数给父类的初始化方法,这提供了额外的灵活性,但使用时需要确保传递的参数是父类支持的。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是执行聊天操作,通过调用百度AI定制聊天模型接口,发送聊天消息并接收模型的回复。 + +**参数**: +- `params`: `ApiChatParams`类型,包含聊天请求所需的参数,如消息列表、API密钥、温度参数等。 + +**代码描述**: +`do_chat`函数首先调用`load_config`方法,根据模型名称加载相关配置。然后,构造访问百度AI定制聊天模型接口的URL,包括模型版本和访问令牌。接着,使用`get_baidu_access_token`函数获取百度API的访问令牌。如果获取令牌失败,则直接返回错误信息。 + +函数继续构造HTTP请求的负载(payload),包括聊天消息、温度参数和流式响应标志。设置HTTP请求头,然后使用`get_httpx_client`函数获取httpx客户端实例,并通过此实例以流式方式发送POST请求到百度AI聊天模型接口。 + +在接收到响应后,函数遍历响应的每一行,解析JSON格式的数据。如果数据中包含`result`字段,则将其值累加到文本变量中,并生成包含错误码和累加文本的字典作为生成器的输出。如果响应中包含错误信息,则构造包含错误详情的字典,并记录错误日志,同时作为生成器的输出。 + +**注意**: +- 在使用`do_chat`函数之前,确保已正确设置`ApiChatParams`中的参数,包括有效的API密钥和密钥。 +- 函数依赖于`get_httpx_client`来执行HTTP请求,确保网络环境允许访问百度AI接口。 +- 函数以生成器的形式返回响应数据,调用方需要遍历生成器来获取所有响应消息。 +- 在处理响应数据时,函数会累加`result`字段的值,因此调用方应注意处理可能的大量数据累加情况。 +- 函数中的错误处理包括返回带有错误码和错误信息的字典,调用方应检查每个响应项的`error_code`以判断请求是否成功。 +*** +### FunctionDef do_embeddings(self, params) +**do_embeddings**: 该函数的功能是使用百度AI平台的嵌入式模型API,对一组文本进行向量化处理。 + +**参数**: +- `params`: `ApiEmbeddingsParams`类型,包含API请求所需的参数,如文本列表、嵌入模型标识等。 + +**代码描述**: +`do_embeddings`函数首先通过`params.load_config`方法加载模型配置,这一步骤确保了使用正确的模型名称进行处理。接着,函数根据传入的`params`参数中的`embed_model`或类属性`DEFAULT_EMBED_MODEL`确定使用的嵌入模型。之后,通过调用`get_baidu_access_token`函数,使用API Key和Secret Key获取百度API的访问令牌。构造请求URL时,将嵌入模型标识和访问令牌附加到URL中。 + +函数使用`get_httpx_client`获取httpx客户端实例,以支持网络请求。通过分批处理文本列表(每批10个文本),函数对每一批文本发起POST请求,请求百度的嵌入式模型API,并将文本列表作为请求体的一部分。如果响应中包含`error_code`,则表示请求出错,函数将构造错误信息并返回。如果请求成功,函数将从响应中提取嵌入向量,并将它们累加到结果列表中。 + +**注意**: +- 确保传入的`params`参数中的API Key和Secret Key是有效的,以便成功获取访问令牌。 +- 文本列表`params.texts`不应为空,且每个文本的长度应符合百度API的要求。 +- 由于网络请求的存在,函数执行时间可能受网络状况和百度API响应时间的影响。 +- 函数中的错误处理机制确保了在遇到API请求错误时,能够及时返回错误信息,避免程序异常终止。 + +**输出示例**: +假设函数处理成功,返回值可能如下: +```json +{ + "code": 200, + "data": [ + [0.1, 0.2, 0.3, ...], + [0.4, 0.5, 0.6, ...], + ... + ] +} +``` +如果发生错误,返回值可能如下: +```json +{ + "code": 错误码, + "msg": "错误信息", + "error": { + "message": "具体错误信息", + "type": "invalid_request_error", + "param": null, + "code": null + } +} +``` +此函数通过与百度AI平台的嵌入式模型API交互,为开发者提供了一种便捷的方式来将文本转换为嵌入向量,支持后续的文本分析和处理任务。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息,其类型和结构取决于调用此函数时的具体需求。 + +**代码描述**: +`get_embeddings`函数是`QianFanWorker`类的一个方法,主要用于展示如何处理和打印嵌入信息以及传入的参数。当调用此函数时,它首先打印出字符串"embedding",随后打印出传入的`params`参数。这表明此函数可能是一个用于测试或演示目的的桩函数,或者是一个待完善的功能点。 + +在实际应用中,`params`参数可以是任何类型的数据,比如数字、字符串、列表或字典等,具体取决于调用此函数时的上下文环境。因此,开发者在使用此函数时需要注意传入参数的类型和结构,以确保函数能够正确处理并展示预期的信息。 + +**注意**: +- 在当前的实现中,`get_embeddings`函数仅仅进行了基本的打印操作,没有进行任何复杂的数据处理或嵌入向量的生成。因此,在将此函数应用于实际项目中时,可能需要根据具体需求对其进行相应的扩展和完善。 +- 考虑到此函数目前的实现较为简单,开发者在使用时应当清楚其当前的限制,并根据项目的实际需求进行适当的修改和优化。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 此函数用于创建一个对话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板的内容,此参数在当前实现中未直接使用。 +- **model_path**: 字符串类型,指定模型的路径,此参数在当前实现中未直接使用。 + +**代码描述**: +`make_conv_template` 函数是 `QianFanWorker` 类的一个方法,它的主要作用是生成一个对话模板。这个模板是通过调用 `conv.Conversation` 类来创建的,其中包含了以下几个关键的参数: +- `name`: 对话的名称,这里使用的是 `self.model_names[0]`,即模型名称列表中的第一个名称。 +- `system_message`: 系统消息,这里设置为“你是一个聪明的助手,请根据用户的提示来完成任务”,用于向用户展示系统的默认消息。 +- `messages`: 对话中的消息列表,这里初始化为空列表。 +- `roles`: 对话中的角色列表,这里设置为包含“user”和“assistant”的列表,表示对话中包含用户和助手两个角色。 +- `sep`: 消息分隔符,这里设置为“\n### ”,用于分隔对话中的不同消息。 +- `stop_str`: 停止字符串,这里设置为“###”,用于标识对话的结束。 + +**注意**: +- 虽然 `conv_template` 和 `model_path` 参数在函数定义中提供,但在当前的实现中并未直接使用这两个参数。这可能是为了未来的功能扩展预留的接口。 +- 返回的对话模板是一个 `conv.Conversation` 对象,可以用于进一步的对话处理或模拟。 + +**输出示例**: +假设调用 `make_conv_template()` 方法,可能返回的 `conv.Conversation` 对象示例为: +``` +Conversation( + name="模型名称1", + system_message="你是一个聪明的助手,请根据用户的提示来完成任务", + messages=[], + roles=["user", "assistant"], + sep="\n### ", + stop_str="###", +) +``` +这个对象包含了对话的基本框架,包括名称、系统消息、消息列表、角色列表以及消息的分隔符和停止符。 +*** diff --git a/markdown_docs/server/model_workers/qwen.md b/markdown_docs/server/model_workers/qwen.md new file mode 100644 index 000000000..08cf7710b --- /dev/null +++ b/markdown_docs/server/model_workers/qwen.md @@ -0,0 +1,160 @@ +## ClassDef QwenWorker +**QwenWorker**: QwenWorker类是用于处理特定API模型工作流程的高级工作器。 + +**属性**: +- `DEFAULT_EMBED_MODEL`: 默认的嵌入模型,为"text-embedding-v1"。 +- `version`: 模型版本,可选值为"qwen-turbo"或"qwen-plus",默认为"qwen-turbo"。 +- `model_names`: 模型名称列表,默认为["qwen-api"]。 +- `controller_addr`: 控制器地址,初始化时可为None。 +- `worker_addr`: 工作器地址,初始化时可为None。 +- `context_len`: 上下文长度,默认为16384,覆盖了ApiModelWorker类的默认值2048。 + +**代码描述**: +QwenWorker类继承自ApiModelWorker类,专门用于处理与Qwen API相关的工作流程。它通过构造函数接收模型版本、模型名称、控制器地址、工作器地址等参数,并在初始化过程中设置了一些默认参数值。此外,该类还提供了`do_chat`和`do_embeddings`两个主要方法,分别用于执行聊天和生成嵌入向量的功能。 + +- `do_chat`方法通过调用特定API执行聊天功能,返回生成的回复文本。 +- `do_embeddings`方法通过调用特定API生成文本的嵌入向量。 + +此类还包含`get_embeddings`和`make_conv_template`两个方法,其中`get_embeddings`方法用于打印嵌入向量相关信息,`make_conv_template`方法用于创建会话模板。 + +**注意**: +- 在使用QwenWorker类时,需要确保传入的参数符合Qwen API的要求。 +- `do_chat`和`do_embeddings`方法的实现依赖于外部库dashscope的调用,因此需要确保该库正确安装并可用。 +- `make_conv_template`方法返回的会话模板对象需要进一步配置以满足特定的对话需求。 + +**输出示例**: +假设`do_chat`方法成功调用API并获取到回复,可能的输出示例为: +```json +{ + "error_code": 0, + "text": "这是由模型生成的回复文本。" +} +``` +此输出示例展示了一个成功的API调用结果,其中`error_code`为0表示成功,`text`字段包含了模型生成的回复文本。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化QwenWorker对象。 + +**参数**: +- `version`: 指定QwenWorker的版本,可选值为"qwen-turbo"或"qwen-plus",默认为"qwen-turbo"。 +- `model_names`: 一个字符串列表,包含模型名称,默认为["qwen-api"]。 +- `controller_addr`: 控制器地址,字符串类型,默认为None。 +- `worker_addr`: 工作器地址,字符串类型,默认为None。 +- `**kwargs`: 接收额外的关键字参数,这些参数将被传递给父类的初始化方法。 + +**代码描述**: +此函数是`QwenWorker`类的构造函数,用于创建`QwenWorker`实例。它接受几个参数,包括版本信息(`version`)、模型名称列表(`model_names`)、控制器地址(`controller_addr`)和工作器地址(`worker_addr`)。这些参数允许用户自定义`QwenWorker`实例的行为和配置。 + +函数首先将`model_names`、`controller_addr`和`worker_addr`参数通过`kwargs`字典传递给父类的初始化方法。此外,它还使用`setdefault`方法为`kwargs`字典设置一个默认的"context_len"键值对,如果`kwargs`中未包含"context_len"键,则将其值设置为16384。 + +之后,函数调用父类的`__init__`方法,传递更新后的`kwargs`字典。这一步骤确保了父类的初始化方法可以接收到所有必要的参数,并且允许`QwenWorker`类在父类的基础上进行扩展。 + +最后,函数将`version`参数的值赋给实例变量`self.version`,完成`QwenWorker`实例的初始化过程。 + +**注意**: +- 在使用`QwenWorker`类创建实例时,应确保传递的参数类型和值符合要求,特别是`version`参数,它只接受"qwen-turbo"或"qwen-plus"两个选项。 +- `**kwargs`参数提供了一种灵活的方式来传递额外的配置选项给父类的初始化方法,但使用时需要注意确保传递的键值对是父类所支持的。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是执行聊天操作并生成响应。 + +**参数**: +- `params`: ApiChatParams类型,包含聊天请求所需的各种参数。 + +**代码描述**: +`do_chat`函数首先通过`params.load_config`方法加载与当前模型相关的配置,这一步骤确保了聊天操作可以根据特定的模型配置进行。`load_config`方法的详细作用是为特定工作器加载配置,这里的工作器指的是当前模型,其配置信息包括但不限于模型名称、版本、温度参数等。 + +在加载配置之后,如果全局变量`log_verbose`为真,函数会记录当前的参数设置,这对于调试和记录操作日志非常有用。 + +接下来,函数创建了一个`dashscope.Generation`实例,并调用其`call`方法发起聊天请求。这个请求包含了从`params`中获取的各种参数,如模型版本、温度参数、API密钥以及消息内容等。`call`方法的返回值是一个生成器,它会逐个产生聊天响应。 + +函数遍历这些响应,对于每个响应,首先检查其状态码。如果状态码为200,表示请求成功,函数将从响应中提取消息内容并以生成器的形式返回。这里使用了Python的条件赋值表达式来简化代码。如果响应状态码不是200,表示请求出现错误,函数将记录错误信息并以生成器的形式返回错误详情。 + +**注意**: +- 使用`do_chat`函数时,需要确保传入的`params`参数已经包含了所有必要的聊天请求信息,包括但不限于消息内容、API密钥等。 +- 函数的执行依赖于`dashscope.Generation`类的`call`方法,该方法负责与后端聊天模型进行交互,因此需要确保后端服务正常运行。 +- 错误处理是通过检查响应的状态码实现的,开发者在使用时应注意对异常状态进行适当处理,以确保程序的健売性和用户体验。 +- 由于函数使用了生成器来逐个返回响应,调用方需要通过迭代的方式来处理每个响应。这种设计使得函数可以即时返回结果,提高了响应效率,特别是在处理大量聊天请求时。 +*** +### FunctionDef do_embeddings(self, params) +**do_embeddings**: 此函数的功能是执行文本的嵌入处理并返回嵌入结果。 + +**参数**: +- `params`: ApiEmbeddingsParams类型,包含执行嵌入处理所需的参数,如文本列表、嵌入模型标识等。 + +**代码描述**: +`do_embeddings`函数首先通过调用`load_config`方法加载模型的配置信息,这一步骤确保了模型能够根据指定的配置执行嵌入处理。随后,函数检查是否开启了详细日志记录,如果是,则记录传入的参数信息。 + +函数接下来进入一个循环,每次处理最多25条文本。这是因为API可能对一次请求处理的文本数量有限制,通过这种方式可以有效避免超出限制。在循环中,函数调用`dashscope.TextEmbedding.call`方法,向指定的嵌入模型API发送请求,请求的模型可以是通过`params`传入的`embed_model`,或者是使用默认的嵌入模型`DEFAULT_EMBED_MODEL`。 + +如果API响应的状态码不是200,表示请求失败,函数会记录错误信息并返回错误详情。如果请求成功,函数将从响应中提取嵌入结果,并将它们添加到结果列表中。 + +最后,函数返回一个包含状态码200和所有嵌入结果的字典。 + +**注意**: +- 确保在调用此函数之前,已经正确设置了`ApiEmbeddingsParams`中的`texts`属性,因为这是执行嵌入处理的必要条件。 +- 函数依赖于外部API的响应格式,特别是在处理错误和提取嵌入结果时,因此在API更新时需要检查这部分代码的兼容性。 +- 日志记录依赖于全局变量`log_verbose`和`logger`的设置,确保在使用此函数前,这些变量已经被正确配置。 + +**输出示例**: +```json +{ + "code": 200, + "data": [ + [0.1, 0.2, 0.3, ...], + [0.4, 0.5, 0.6, ...], + ... + ] +} +``` +此示例展示了函数成功执行后的返回值结构,其中`data`字段包含了所有文本的嵌入向量列表。每个嵌入向量是一个浮点数列表,代表了对应文本的嵌入表示。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- params: 此参数用于接收传入的参数信息。 + +**代码描述**: +`get_embeddings`函数是`QwenWorker`类的一个方法,主要用于展示如何处理和打印嵌入信息以及传入的参数。当调用此函数时,它首先打印出字符串"embedding",表明当前操作是与嵌入相关的操作。紧接着,它会打印出传入的`params`参数,这可以是任何形式的数据,旨在展示函数是如何接收并处理这些参数的。 + +具体来说,函数体内的第一行代码`print("embedding")`用于输出操作类型,作为日志信息或调试信息的一部分。第二行代码`print(params)`则负责输出传入的参数,这对于验证参数是否正确传递至函数内部非常有用。 + +**注意**: +- 在实际应用中,`get_embeddings`函数可能需要根据实际需求进行扩展,以实现更复杂的嵌入处理逻辑。 +- `params`参数的具体结构和类型应根据实际使用场景事先定义好,以确保函数能够正确处理传入的数据。 +- 本函数目前仅用于演示和调试目的,因此在生产环境中使用时可能需要替换或增加更多的逻辑来满足实际需求。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template函数的功能**: 创建一个对话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板的具体内容,此参数在当前实现中未直接使用。 +- **model_path**: 字符串类型,指定模型路径,此参数在当前实现中未直接使用。 + +**代码描述**: +`make_conv_template`函数负责创建一个对话模板实例。这个实例是通过调用`conv.Conversation`构造函数创建的,其中包含了以下几个关键信息: +- **name**: 对话的名称,这里使用`self.model_names[0]`作为对话名称,即取当前对象的`model_names`列表中的第一个元素。 +- **system_message**: 系统消息,这是一个预设的字符串,用于描述人工智能的角色和它对人类的帮助性质。 +- **messages**: 对话消息列表,初始为空列表。 +- **roles**: 对话中的角色列表,包括"user"(用户)、"assistant"(助手)和"system"(系统)。 +- **sep**: 消息分隔符,这里设定为"\n### "。 +- **stop_str**: 停止字符串,用于标识对话的结束,这里设定为"###"。 + +**注意**: +- 虽然`conv_template`和`model_path`参数在当前函数实现中未被直接使用,但它们的存在可能是为了未来的功能扩展预留的接口。 +- 创建的对话模板实例主要用于初始化对话环境,包括对话参与者的角色定义和基本的对话设置。在实际应用中,可能需要根据具体场景调整对话模板的内容。 + +**输出示例**: +假设`self.model_names[0]`的值为"AI_Assistant",则函数的返回值可能如下所示: +``` +Conversation( + name="AI_Assistant", + system_message="你是一个聪明、对人类有帮助的人工智能,你可以对人类提出的问题给出有用、详细、礼貌的回答。", + messages=[], + roles=["user", "assistant", "system"], + sep="\n### ", + stop_str="###", +) +``` +这表示创建了一个名为"AI_Assistant"的对话模板,其中包含了预设的系统消息和基本的对话设置。 +*** diff --git a/markdown_docs/server/model_workers/tiangong.md b/markdown_docs/server/model_workers/tiangong.md new file mode 100644 index 000000000..7285320cc --- /dev/null +++ b/markdown_docs/server/model_workers/tiangong.md @@ -0,0 +1,125 @@ +## ClassDef TianGongWorker +**TianGongWorker**: TianGongWorker类是为了实现与天工API的交互而设计的,主要用于聊天和获取嵌入向量。 + +**属性**: +- `controller_addr`: 控制器地址,用于与模型控制器进行通信。 +- `worker_addr`: 工作器地址,标识当前工作器的网络位置。 +- `model_names`: 模型名称列表,默认为["tiangong-api"]。 +- `version`: 模型版本,默认为"SkyChat-MegaVerse"。 +- `context_len`: 上下文长度,默认为32768。 + +**代码描述**: +TianGongWorker类继承自ApiModelWorker类,提供了与天工API进行交互的方法。在初始化时,它接受控制器地址、工作器地址、模型名称列表和版本等参数,并将这些参数传递给父类构造函数。此外,它还设置了默认的上下文长度为32768。 + +该类重写了`do_chat`方法,用于实现与天工API的聊天功能。在这个方法中,它首先加载配置,然后构造请求数据和头部信息,包括通过MD5算法生成的签名。之后,它发起POST请求到天工API,并处理响应流。如果响应码为200,表示请求成功,它会从响应中提取文本并返回;如果响应码不为200,表示请求失败,它会记录错误信息并返回。 + +此外,TianGongWorker类还提供了`get_embeddings`和`make_conv_template`方法,但这些方法的具体实现在代码中未给出。 + +**注意**: +- 使用TianGongWorker类时,需要确保提供正确的API密钥和密钥签名,以通过天工API的身份验证。 +- 在处理响应流时,需要注意正确处理流式数据,以避免数据丢失或解析错误。 +- 该类的实现依赖于外部库requests和hashlib,因此在使用前需要确保这些库已正确安装。 + +**输出示例**: +调用`do_chat`方法可能的返回值示例: +```json +{ + "error_code": 0, + "text": "这是天工API返回的回复文本。" +} +``` +此示例展示了一个成功的API调用结果,其中`error_code`为0表示成功,`text`字段包含了天工API返回的回复文本。如果调用失败,`error_code`将不为0,并且`text`字段将包含错误信息。 +### FunctionDef __init__(self) +**__init__**: __init__函数用于初始化TianGongWorker对象。 + +**参数**: +- `controller_addr`: 字符串类型,表示控制器的地址,默认值为None。 +- `worker_addr`: 字符串类型,表示工作节点的地址,默认值为None。 +- `model_names`: 字符串列表类型,表示模型名称,默认值为["tiangong-api"]。 +- `version`: 字面量类型,表示版本,仅接受"SkyChat-MegaVerse"作为值,默认值为"SkyChat-MegaVerse"。 +- `**kwargs`: 接收可变数量的关键字参数。 + +**代码描述**: +此函数是TianGongWorker类的构造函数,用于创建TianGongWorker实例。它接受几个参数,包括控制器地址(`controller_addr`)、工作节点地址(`worker_addr`)、模型名称列表(`model_names`)和版本(`version`)。此外,它还可以接受其他任意数量的关键字参数(`**kwargs`)。 + +函数首先将`model_names`、`controller_addr`和`worker_addr`参数更新到`kwargs`字典中。这意味着,如果这些参数被提供,它们将被用于更新或添加到`kwargs`中,这些`kwargs`随后将被用于父类的初始化。 + +接着,函数使用`setdefault`方法为`kwargs`设置一个默认的`context_len`值,如果`kwargs`中未提供`context_len`,则默认值为32768。 + +最后,通过`super().__init__(**kwargs)`调用父类的构造函数,传入更新后的`kwargs`,完成父类的初始化。同时,将`version`参数的值赋给实例变量`self.version`,以便后续使用。 + +**注意**: +- 在使用TianGongWorker类创建实例时,需要注意`controller_addr`和`worker_addr`参数是可选的,但在实际应用中,根据具体需求提供这些参数可能是必要的。 +- `model_names`参数虽有默认值,但用户可以根据需要提供自定义模型名称列表。 +- `version`参数目前仅支持"SkyChat-MegaVerse"这一版本,需要确保使用时的兼容性。 +- 通过`**kwargs`参数,此函数提供了高度的灵活性,允许用户根据需要传入额外的配置选项。但使用时应注意确保传入的关键字参数与父类构造函数及TianGongWorker类的其他方法兼容。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数的功能是通过调用外部API实现聊天功能,并处理返回的聊天数据。 + +**参数**: +- `params`: `ApiChatParams`类型,包含了进行聊天所需的参数,如消息列表、API密钥等。 + +**代码描述**: +`do_chat`函数首先调用`load_config`方法,为当前工作器加载配置。这一步骤确保了聊天请求能够根据特定的模型名称进行配置,从而使得聊天功能能够根据不同的模型需求灵活调整。 + +接着,函数定义了请求的URL和请求体数据。请求体中包含了消息列表和指定的模型名称"SkyChat-MegaVerse"。此外,为了确保请求的安全性,函数通过计算API密钥、密钥和当前时间戳的MD5哈希值来生成签名。 + +函数设置了请求头,其中包括了API密钥、时间戳、签名以及其他必要的信息,如内容类型和是否处理流式返回内容的标志。 + +通过`requests.post`方法发起对外部API的请求,函数使用了流式请求(`stream=True`)来实时处理返回的数据。在处理响应流时,函数逐行读取响应内容,并将每行数据解析为JSON格式。如果响应代码为200,表示请求成功,函数将累加聊天回复内容,并以生成器的形式逐步返回每次聊天的结果。如果响应代码不为200,函数将记录错误信息并以生成器的形式返回错误代码和错误消息。 + +**注意**: +- 在使用`do_chat`函数之前,确保已经正确配置了`ApiChatParams`中的参数,包括API密钥、密钥和消息列表等。 +- 由于函数使用了生成器来逐步返回聊天结果,调用此函数时需要适当地处理生成器的迭代,以获取所有聊天回复。 +- 函数中的错误处理机制确保了在遇到请求错误时能够及时记录并反馈错误信息,开发者应当注意检查错误日志,以便及时发现并解决问题。 +- 本函数依赖于外部API进行聊天功能的实现,因此网络状况和API服务的稳定性可能会影响到聊天功能的表现和稳定性。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息,其具体内容和格式依调用时的实际情况而定。 + +**代码描述**: +`get_embeddings` 函数是 `TianGongWorker` 类的一个方法,主要用于展示如何处理和打印嵌入信息以及传入的参数。函数体内首先打印出字符串 "embedding",随后打印出传入的 `params` 参数。这表明该函数的主要作用是在控制台上输出相关信息,以便于开发者进行调试或了解参数的传递情况。 + +**注意**: +- 由于此函数主要用于展示和调试目的,因此在实际生产环境中可能需要根据具体需求进行相应的修改或扩展。 +- 参数 `params` 的内容和格式应根据实际使用场景事先定义好,以确保函数能够正确处理传入的数据。 +- 当前函数实现较为简单,仅用于示例,因此在开发复杂应用时可能需要增加额外的逻辑来处理更复杂的数据结构或执行更复杂的操作。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 该函数用于创建一个对话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板,此版本中未使用。 +- **model_path**: 字符串类型,指定模型路径,此版本中未使用。 + +**代码描述**: +`make_conv_template` 函数是 `TianGongWorker` 类的一个方法,它的主要作用是创建一个对话模板。该方法接受两个参数:`conv_template` 和 `model_path`,但在当前版本的实现中,这两个参数并没有被使用。函数返回一个 `Conversation` 对象,该对象是通过调用 `conv.Conversation` 构造函数创建的。创建的 `Conversation` 对象具有以下特点: +- `name` 属性被设置为 `self.model_names[0]`,即模型名称列表中的第一个名称。 +- `system_message` 属性被设置为空字符串。 +- `messages` 属性被设置为一个空列表,表示初始时对话中没有任何消息。 +- `roles` 属性被设置为包含 "user" 和 "system" 的列表,表示对话中的角色。 +- `sep` 属性被设置为 "\n### ",定义了消息之间的分隔符。 +- `stop_str` 属性被设置为 "###",定义了对话的结束标志。 + +**注意**: +- 尽管 `conv_template` 和 `model_path` 参数在当前版本中未被使用,但它们的存在预示着未来版本可能会支持根据模板或模型路径来定制对话模板。 +- 创建的 `Conversation` 对象可以用于进一步的对话处理或模拟,但需要注意的是,初始状态下 `messages` 为空,表示尚未有任何对话内容。 + +**输出示例**: +假设 `self.model_names[0]` 的值为 "ExampleModel",则函数的返回值可能如下所示: +``` +Conversation( + name="ExampleModel", + system_message="", + messages=[], + roles=["user", "system"], + sep="\n### ", + stop_str="###", +) +``` +这表示创建了一个名为 "ExampleModel" 的空对话模板,其中没有系统消息、没有任何对话内容,定义了用户和系统作为对话参与者的角色,以及消息分隔符和对话结束标志。 +*** diff --git a/markdown_docs/server/model_workers/xinghuo.md b/markdown_docs/server/model_workers/xinghuo.md new file mode 100644 index 000000000..42dd216b7 --- /dev/null +++ b/markdown_docs/server/model_workers/xinghuo.md @@ -0,0 +1,182 @@ +## FunctionDef request(appid, api_key, api_secret, Spark_url, domain, question, temperature, max_token) +**request**: 此函数用于通过WebSocket连接发送请求到Spark服务,并异步接收处理结果。 + +**参数**: +- **appid**: 应用程序的唯一标识符。 +- **api_key**: 用于访问Spark服务的API密钥。 +- **api_secret**: 用于访问Spark服务的API密钥的秘密。 +- **Spark_url**: Spark服务的完整URL。 +- **domain**: 请求的领域或类别。 +- **question**: 用户的提问内容。 +- **temperature**: 生成回答时的创造性控制参数。 +- **max_token**: 生成回答的最大令牌数。 + +**代码描述**: +函数首先使用`SparkApi.Ws_Param`类创建一个`wsParam`对象,并通过该对象的`create_url`方法生成用于WebSocket连接的URL。然后,使用`SparkApi.gen_params`函数生成请求数据,该数据包括应用ID、领域、问题、温度和最大令牌数等信息。接下来,函数通过`websockets.connect`建立与Spark服务的WebSocket连接,并使用`json.dumps`将请求数据转换为JSON格式后发送。函数接着进入一个循环,异步接收来自Spark服务的响应。如果响应的头部信息中状态为2,表示处理完成,循环结束。如果响应的有效载荷中包含文本信息,则将该信息的内容生成器返回。 + +**注意**: +- 在使用此函数时,需要确保传入的`appid`、`api_key`、`api_secret`和`Spark_url`等参数正确无误,因为这些参数直接影响到能否成功建立WebSocket连接和发送请求。 +- 函数采用异步编程模式,调用时需要在异步环境下使用`await`关键字。 +- 由于函数使用了生成器`yield`来返回文本内容,调用此函数时需要使用异步迭代器或在异步循环中处理返回的文本内容。 +- 函数中的`temperature`参数控制生成文本的创造性,较高的值会导致更多样化的回答,而较低的值则使回答更加确定性。根据实际需求调整此参数。 +- `max_token`参数限制了生成回答的长度,需要根据实际需求调整。 +## ClassDef XingHuoWorker +**XingHuoWorker**: XingHuoWorker类是用于处理与“星火”API模型交互的工作器。 + +**属性**: +- `model_names`: 模型名称列表,默认为["xinghuo-api"]。 +- `controller_addr`: 控制器地址,用于与模型控制器进行通信。 +- `worker_addr`: 工作器地址,标识当前工作器的网络位置。 +- `version`: 模型版本,用于指定与“星火”API交互时使用的API版本。 +- `context_len`: 上下文长度,默认为8000,用于指定处理请求时考虑的上下文信息的长度。 + +**代码描述**: +XingHuoWorker类继承自ApiModelWorker类,专门用于与“星火”API进行交互。在初始化过程中,它接受模型名称、控制器地址、工作器地址、版本等参数,并将这些参数传递给父类构造函数。此外,它还默认设置了上下文长度为8000,并允许通过关键字参数传递更多设置。 + +该类重写了`do_chat`方法,用于处理聊天功能。在这个方法中,它首先根据传入的版本参数选择合适的API配置,然后通过异步循环发送请求,并处理返回的数据流,最终生成聊天文本。 + +`get_embeddings`方法目前仅打印传入的参数,暗示这个方法可能用于处理嵌入功能,但在当前版本中尚未实现。 + +`make_conv_template`方法用于生成对话模板,这个模板定义了对话的基本结构,包括参与者角色、消息分隔符等。 + +**注意**: +- 使用XingHuoWorker类时,需要确保正确设置了模型名称、控制器地址和工作器地址,这些参数对于确保工作器能够正确与“星火”API进行交互至关重要。 +- 版本参数`version`对于选择正确的API接口非常关键,需要根据“星火”API的版本更新情况进行调整。 +- 由于`do_chat`方法涉及异步编程,使用时需要注意异步环境的配置和管理。 + +**输出示例**: +```json +{ + "error_code": 0, + "text": "这是由模型生成的回复文本。" +} +``` +此示例展示了`do_chat`方法成功调用“星火”API并接收到模型生成的回复文本后的可能输出。`error_code`为0表示调用成功,`text`字段包含了模型生成的文本。 +### FunctionDef __init__(self) +**__init__**: 该函数用于初始化XingHuoWorker对象。 + +**参数**: +- **model_names**: 一个字符串列表,默认值为["xinghuo-api"]。这个列表包含了模型的名称。 +- **controller_addr**: 一个字符串,表示控制器的地址。默认值为None。 +- **worker_addr**: 一个字符串,表示工作节点的地址。默认值为None。 +- **version**: 一个字符串,表示版本号。默认值为None。 +- **kwargs**: 接收一个字典,包含了其他的关键字参数。 + +**代码描述**: +该`__init__`方法是`XingHuoWorker`类的构造函数,用于初始化一个`XingHuoWorker`对象。它接受几个参数,包括模型名称列表`model_names`、控制器地址`controller_addr`、工作节点地址`worker_addr`和版本号`version`。这些参数允许用户在创建`XingHuoWorker`对象时自定义其配置。 + +在方法内部,首先通过`kwargs.update`方法更新`kwargs`字典,将`model_names`、`controller_addr`和`worker_addr`作为关键字参数添加到`kwargs`中。接着,使用`kwargs.setdefault`方法设置`context_len`的默认值为8000,如果`kwargs`中已经存在`context_len`,则保持原值不变。 + +之后,调用父类的`__init__`方法,将更新后的`kwargs`字典传递给父类,以完成父类的初始化过程。这一步是必要的,因为`XingHuoWorker`可能继承自一个需要进行初始化的父类。 + +最后,将`version`参数赋值给`self.version`属性,存储版本号信息。 + +**注意**: +- 在使用`XingHuoWorker`类创建对象时,需要注意`model_names`、`controller_addr`、`worker_addr`和`version`参数的正确设置,这些参数对于对象的配置和后续操作非常重要。 +- `kwargs`参数提供了一种灵活的方式来传递额外的配置选项,但使用时需要确保传递的关键字参数是有效且被支持的。 +- 默认的`context_len`值为8000,但可以通过在`kwargs`中传递`context_len`参数来自定义这个值。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 此函数用于执行聊天操作,通过与Spark服务的WebSocket接口交互,发送聊天请求并接收回答。 + +**参数**: +- `params`: `ApiChatParams`类型,包含聊天请求所需的所有参数。 + +**代码描述**: +`do_chat`函数首先调用`params.load_config`方法,加载模型配置。该方法根据`self.model_names[0]`(模型名称列表的第一个元素)来加载相应的配置。 + +接着,函数定义了一个版本映射`version_mapping`,其中包含不同版本的Spark服务的域名、URL和最大令牌数。通过`get_version_details`函数,可以根据`params.version`(请求参数中指定的版本)获取对应版本的详细信息,包括服务的域名和URL。 + +函数尝试获取当前的事件循环,如果失败,则创建一个新的事件循环。此事件循环用于处理异步操作。 + +`params.max_tokens`被设置为`details["max_tokens"]`和`params.max_tokens`中较小的一个,以确保不超过服务端允许的最大令牌数。 + +通过调用`iter_over_async`函数,`do_chat`可以同步地处理从`request`函数(异步发送聊天请求并接收回答的函数)返回的数据流。`request`函数接收多个参数,包括应用ID、API密钥、API密钥的秘密、Spark服务的URL、域名、消息内容、温度和最大令牌数等,用于建立WebSocket连接并发送聊天请求。 + +当`iter_over_async`函数返回数据块时,`do_chat`函数将这些数据块累加到`text`字符串中,并以字典形式生成器返回,其中包含错误码(`error_code`)和累加后的文本(`text`)。 + +**注意**: +- 确保在调用`do_chat`函数之前,已正确设置`ApiChatParams`中的所有必要参数,包括消息内容、版本等。 +- `do_chat`函数依赖于正确配置的事件循环来处理异步操作,因此在调用此函数时应注意事件循环的管理。 +- 由于`do_chat`函数使用了生成器`yield`来逐步返回处理结果,调用此函数时需要适当地处理生成器返回的数据。 + +**输出示例**: +调用`do_chat`函数可能返回的示例输出为: +```python +{"error_code": 0, "text": "你好,很高兴为你服务。"} +``` +此输出表示聊天请求成功处理,且服务端返回了回答"你好,很高兴为你服务。"。 +#### FunctionDef get_version_details(version_key) +**get_version_details函数的功能**: 根据提供的版本关键字返回相应的版本信息。 + +**参数**: +- **version_key**: 用于查询版本信息的关键字。 + +**代码描述**: +`get_version_details`函数接受一个参数`version_key`,该参数用于在一个预定义的映射(`version_mapping`)中查找对应的版本信息。如果给定的`version_key`在映射中存在,函数将返回该关键字对应的值。如果不存在,函数将返回一个包含`domain`和`url`两个键,它们的值都为`None`的字典。这意味着,当无法根据提供的关键字找到版本信息时,函数提供了一种优雅的失败处理方式,避免了可能的错误或异常。 + +**注意**: +- 确保`version_mapping`是在函数调用之前已经定义并且正确初始化的,且包含所有可能用到的版本关键字及其对应的信息。 +- 调用此函数时,传入的`version_key`应确保是字符串类型,且在`version_mapping`中有对应的条目。 + +**输出示例**: +假设`version_mapping`已经定义如下: +```python +version_mapping = { + "v1.0": {"domain": "example.com", "url": "/api/v1"}, + "v2.0": {"domain": "example.com", "url": "/api/v2"} +} +``` +当调用`get_version_details("v1.0")`时,函数将返回: +```python +{"domain": "example.com", "url": "/api/v1"} +``` +如果调用`get_version_details("v3.0")`(假设`v3.0`不在`version_mapping`中),函数将返回: +```python +{"domain": None, "url": None} +``` +*** +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息。 + +**代码描述**: +`get_embeddings`函数是`XingHuoWorker`类的一个方法,主要用于展示如何处理和打印嵌入信息。当调用此函数时,它首先打印出字符串"embedding",随后打印出传入的`params`参数。这表明该函数可能用于调试或展示传入参数的结构,尤其是在处理嵌入向量或相关信息时。 + +在实际应用中,`params`参数可以是任何类型的数据,但通常期望是与嵌入向量相关的配置或数据。例如,它可以是一个字典,包含了不同的配置选项或者是直接与嵌入向量相关的数据。 + +**注意**: +- 由于此函数主要用于打印信息,因此在生产环境中可能需要根据实际需求进行修改或扩展,以实现更具体的功能。 +- 确保传入的`params`参数包含了函数处理所需的所有必要信息,以避免运行时错误。 +- 此函数目前看起来主要用于演示或调试目的,因此在将其应用于实际项目中时,可能需要进一步开发以满足特定的业务需求。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 该函数用于创建一个对话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定对话模板的具体内容,可选参数。 +- **model_path**: 字符串类型,指定模型路径,可选参数。 + +**代码描述**: +`make_conv_template` 函数是 `XingHuoWorker` 类的一个方法,其主要功能是创建一个对话模板。该方法接受两个参数:`conv_template` 和 `model_path`,它们都是可选的字符串参数。函数内部主要通过调用 `conv.Conversation` 类来创建一个对话实例。在这个实例中,`name` 属性被设置为 `self.model_names[0]`,即取 `model_names` 列表的第一个元素作为名称。`system_message` 属性被设置为一段固定的提示信息:"你是一个聪明的助手,请根据用户的提示来完成任务"。`messages` 属性是一个空列表,表示初始时对话中没有任何消息。`roles` 属性定义了对话中的角色,这里设置为包含 "user" 和 "assistant" 的列表,表示对话参与者。`sep` 和 `stop_str` 属性分别定义了对话中消息的分隔符和停止字符串,用于在对话生成过程中标识消息的边界。 + +**注意**: +- 在使用此函数时,需要确保 `self.model_names` 列表至少包含一个元素,否则在尝试访问 `self.model_names[0]` 时会引发索引错误。 +- 该函数返回的对话实例可以用于进一步的对话处理或模拟,但需要注意的是,返回的对话实例初始时不包含任何实际对话内容。 + +**输出示例**: +假设 `self.model_names` 列表的第一个元素为 "ModelA",则该函数可能返回的对话实例如下所示(此处以伪代码形式展示): +``` +Conversation( + name="ModelA", + system_message="你是一个聪明的助手,请根据用户的提示来完成任务", + messages=[], + roles=["user", "assistant"], + sep="\n### ", + stop_str="###", +) +``` +*** diff --git a/markdown_docs/server/model_workers/zhipu.md b/markdown_docs/server/model_workers/zhipu.md new file mode 100644 index 000000000..8e32a5aba --- /dev/null +++ b/markdown_docs/server/model_workers/zhipu.md @@ -0,0 +1,161 @@ +## FunctionDef connect_sse(client, method, url) +**connect_sse**: 此函数的功能是连接到服务器发送事件(Server-Sent Events, SSE)流。 + +**参数**: +- `client`: 一个`httpx.Client`实例,用于执行HTTP请求。 +- `method`: 字符串,指定HTTP请求的方法(如"GET")。 +- `url`: 字符串,指定请求的URL。 +- `**kwargs`: 接收任意数量的关键字参数,这些参数将直接传递给`client.stream`方法。 + +**代码描述**: +`connect_sse`函数使用`httpx.Client`实例的`stream`方法建立一个到服务器的持久连接,用于接收服务器发送的事件流。这种机制通常用于实时数据传输场景,如实时消息推送、实时数据更新等。 + +函数首先通过`with`语句和`client.stream`方法建立一个上下文管理器,这确保了流的正确打开和关闭。`client.stream`方法被调用时,需要传入HTTP请求的方法(`method`)、请求的URL(`url`)以及任何其他关键字参数(`**kwargs`),这些参数可以包括请求头、查询参数等。 + +在成功建立连接并接收到响应后,函数使用`yield`关键字返回一个`EventSource`实例。`EventSource`是对服务器发送事件(SSE)流的封装,它允许调用者以一种简洁的方式处理接收到的事件。 + +**注意**: +- 使用此函数时,需要确保`httpx`库已正确安装并导入。 +- 传递给此函数的URL应指向支持SSE的服务器端点。 +- 在处理服务器发送的事件时,应注意异常处理和连接的稳定性,确保在网络不稳定或服务器端异常时能够正确处理或重连。 +## FunctionDef generate_token(apikey, exp_seconds) +**generate_token**: 该函数用于生成带有过期时间的认证令牌。 + +**参数**: +- `apikey`: 字符串类型,用户的API密钥,通常由ID和密钥组成,中间以点分隔。 +- `exp_seconds`: 整型,令牌的过期时间,单位为秒。 + +**代码描述**: +`generate_token` 函数首先尝试将传入的 `apikey` 按照点(`.`)分割成ID和密钥两部分。如果分割失败,会抛出异常,提示API密钥无效。之后,函数构造一个包含API密钥ID、过期时间戳(当前时间加上指定的过期秒数)、以及当前时间戳的负载(payload)。这个负载随后被用来生成JWT令牌,使用HS256算法进行编码,并附加一个包含算法和签名类型的头部信息。最终,函数返回这个编码后的令牌。 + +在项目中,`generate_token` 函数被 `ChatGLMWorker` 类的 `do_chat` 方法调用。在 `do_chat` 方法中,使用用户提供的API密钥和固定的过期时间(60秒)来生成令牌。这个令牌随后被用作HTTP请求的授权头部,以获取访问特定API接口的权限。这表明 `generate_token` 函数在项目中主要用于支持与外部服务的安全交互,确保请求在指定时间内有效。 + +**注意**: +- 确保传入的 `apikey` 格式正确,即包含ID和密钥,且以点分隔。 +- 生成的令牌将基于传入的过期时间参数,确保合理设置以满足业务需求。 +- 使用HS256算法要求密钥保持安全,避免泄露。 + +**输出示例**: +```python +"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsInNpZ25fdHlwZSI6IlNJR04ifQ.eyJhcGlfa2V5IjoiMTIzNDU2IiwiZXhwIjoxNjMwMjM0MDAwLCJ0aW1lc3RhbXAiOjE2MzAyMzM5NDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +``` +此输出示例展示了一个编码后的JWT令牌,实际的令牌值将根据输入的 `apikey` 和 `exp_seconds` 以及当前时间而有所不同。 +## ClassDef ChatGLMWorker +**ChatGLMWorker**: ChatGLMWorker类是用于处理基于GLM-4模型的聊天功能的工作器。 + +**属性**: +- `model_names`: 模型名称列表,默认为["zhipu-api"]。 +- `controller_addr`: 控制器地址,用于与控制器进行通信。 +- `worker_addr`: 工作器地址,用于接收来自控制器的请求。 +- `version`: 模型版本,默认为"glm-4"。 +- `context_len`: 上下文长度,默认为4096。 + +**代码描述**: +ChatGLMWorker类继承自ApiModelWorker类,专门用于处理基于GLM-4模型的聊天请求。在初始化过程中,该类接收模型名称、控制器地址、工作器地址等参数,并将这些参数传递给父类ApiModelWorker进行进一步的初始化。此外,ChatGLMWorker类还设置了默认的上下文长度为4096,并重写了父类的一些方法来实现具体的聊天功能。 + +`do_chat`方法是ChatGLMWorker类的核心功能,它接收一个ApiChatParams对象作为参数,该对象包含了聊天请求所需的所有信息。该方法首先加载配置,然后生成一个访问令牌,并构造请求头和请求体。之后,它向指定的URL发送POST请求,并处理响应结果。如果请求成功,它将从响应中提取文本内容,并以生成器的形式返回一个包含错误码和文本内容的字典。 + +`get_embeddings`方法用于打印嵌入信息,目前仅作为示例,没有实现具体功能。 + +`make_conv_template`方法用于创建一个会话模板,该方法接收一个会话模板字符串和模型路径作为参数,返回一个Conversation对象。该方法目前返回的Conversation对象包含了模型名称、系统消息、角色等信息,用于构建会话环境。 + +**注意**: +- 使用ChatGLMWorker类时,需要确保传入的参数正确,特别是`model_names`、`controller_addr`和`worker_addr`,这些参数对于确保工作器能够正确地与控制器通信至关重要。 +- `do_chat`方法中的URL是硬编码的,如果API的地址发生变化,需要相应地更新这个地址。 +- 由于`do_chat`方法使用了httpx.Client进行网络请求,需要确保环境中已安装httpx库。 + +**输出示例**: +```json +{ + "error_code": 0, + "text": "这是由模型生成的回复文本。" +} +``` +此输出示例展示了一个成功的聊天请求结果,其中`error_code`为0表示成功,`text`字段包含了模型生成的回复文本。 +### FunctionDef __init__(self) +**__init__**: __init__函数的功能是初始化ChatGLMWorker对象。 + +**参数**: +- **model_names**: 一个字符串列表,默认值为["zhipu-api"]。这个列表包含了模型的名称。 +- **controller_addr**: 一个字符串,表示控制器的地址。默认值为None。 +- **worker_addr**: 一个字符串,表示工作器的地址。默认值为None。 +- **version**: 一个字符串,指定模型的版本,默认值为"glm-4"。目前只支持"glm-4"版本。 +- **kwargs**: 关键字参数,可以传递额外的参数给父类的初始化方法。 + +**代码描述**: +这个__init__方法是ChatGLMWorker类的构造函数,用于创建ChatGLMWorker对象的实例。在这个方法中,首先将`model_names`、`controller_addr`和`worker_addr`这三个参数通过关键字参数的形式更新到`kwargs`字典中。这样做是为了将这些参数传递给父类的初始化方法。接着,使用`setdefault`方法设置`kwargs`字典中`context_len`键的默认值为4096,如果`context_len`已经在`kwargs`中有值,则保持原值不变。之后,调用父类的__init__方法,并将更新后的`kwargs`字典传递给它。最后,将`version`参数的值赋值给实例变量`self.version`。 + +**注意**: +- 在使用ChatGLMWorker类创建对象时,需要注意`model_names`、`controller_addr`和`worker_addr`这三个参数都是可选的,但如果在特定环境下需要连接到特定的控制器或工作器,应当提供这些参数的值。 +- `version`参数目前只支持"glm-4"版本,如果未来版本有更新,需要检查此处的默认值是否需要调整。 +- 通过`kwargs`传递额外的参数时,应确保这些参数是父类初始化方法所支持的,以避免出现错误。 +*** +### FunctionDef do_chat(self, params) +**do_chat**: 该函数用于执行聊天操作,通过发送请求到指定的API接口,并返回聊天结果。 + +**参数**: +- `params`: ApiChatParams类型,用于定义聊天请求的参数。 + +**代码描述**: +`do_chat`函数首先调用`params.load_config`方法,加载与当前模型相关的配置信息。这一步骤确保了聊天操作能够根据模型的特定需求进行配置。随后,函数使用`generate_token`方法生成一个带有60秒过期时间的认证令牌,该令牌将用于API请求的授权。 + +函数接着构造了一个包含请求头的`headers`字典,其中`Content-Type`设置为`application/json`,并且`Authorization`字段包含了前面生成的令牌。此外,函数还构造了一个`data`字典,其中包含了聊天模型的版本、消息列表、最大令牌数、温度值以及一个指示是否流式传输的`stream`字段。 + +接下来,函数使用`httpx.Client`创建一个HTTP客户端,并通过POST方法向`https://open.bigmodel.cn/api/paas/v4/chat/completions`发送请求,请求体为`data`字典。请求成功后,函数解析响应内容,并通过生成器`yield`返回一个包含错误码和聊天内容的字典。 + +在整个过程中,`do_chat`函数与`generate_token`函数和`ApiChatParams`类的`load_config`方法紧密协作,确保了请求的安全性和配置的正确性,从而使得聊天操作能够顺利执行。 + +**注意**: +- 确保传入的`params`参数正确实例化,并且已经包含了所有必要的聊天请求信息。 +- 生成的认证令牌具有时效性,因此在长时间的聊天会话中可能需要重新生成。 +- 由于网络请求的不确定性,建议在使用此函数时添加异常处理逻辑,以确保程序的健壮性。 +- 函数返回的是一个生成器,因此在使用返回值时需要通过迭代来获取实际的聊天结果。 +*** +### FunctionDef get_embeddings(self, params) +**get_embeddings**: 此函数的功能是打印嵌入信息和参数。 + +**参数**: +- `params`: 此参数用于接收传入的参数信息。 + +**代码描述**: +`get_embeddings` 函数是 `ChatGLMWorker` 类的一个方法,主要用于展示如何处理和打印传入的参数信息。在这个函数中,首先通过 `print("embedding")` 打印出字符串 "embedding",表明当前操作是关于嵌入信息的处理。紧接着,通过 `print(params)` 打印出传入的参数 `params`,这有助于开发者了解当前处理的参数内容。 + +此函数虽然简单,但它为开发者提供了一个处理和展示参数信息的基本框架。在实际应用中,开发者可以在此基础上扩展更复杂的逻辑,比如对 `params` 进行解析和处理,然后生成相应的嵌入信息。 + +**注意**: +- 在使用此函数时,需要确保传入的 `params` 参数包含了所有必要的信息,以便函数能够正确地展示这些信息。 +- 目前,此函数仅用于演示和打印参数信息,未涉及实际的嵌入信息生成逻辑。在将此函数应用于实际项目中时,可能需要对其进行相应的修改和扩展,以满足特定的业务需求。 +*** +### FunctionDef make_conv_template(self, conv_template, model_path) +**make_conv_template**: 该函数用于创建一个会话模板。 + +**参数**: +- **conv_template**: 字符串类型,指定会话模板的内容,可选参数,默认为None。 +- **model_path**: 字符串类型,指定模型的路径,可选参数,默认为None。 + +**代码描述**: +`make_conv_template` 函数是用于生成一个会话模板的函数。它返回一个 `Conversation` 对象,该对象由几个关键部分组成: +- `name`:会话的名称,此处使用 `self.model_names[0]` 作为会话名称,假设 `self.model_names` 是一个列表,包含了模型的名称。 +- `system_message`:系统消息,这里设置为 "你是智谱AI小助手,请根据用户的提示来完成任务",这是在会话开始时系统自动发送的消息。 +- `messages`:会话中的消息列表,这里初始化为空列表,表示会话开始时没有任何消息。 +- `roles`:定义会话中的角色,这里定义了三个角色:"user"(用户),"assistant"(助手)和"system"(系统)。 +- `sep` 和 `stop_str`:分别定义了消息之间的分隔符和会话停止的字符串,这里使用 "\n###" 作为分隔符,"###" 作为停止字符串。 + +**注意**: +- 确保在调用此函数之前,`self.model_names` 已经被正确初始化,且至少包含一个元素。 +- 该函数的参数 `conv_template` 和 `model_path` 在当前代码实现中未直接使用,但可以在扩展功能或自定义会话模板时提供额外的灵活性。 + +**输出示例**: +调用 `make_conv_template()` 函数可能返回如下的 `Conversation` 对象示例: +``` +Conversation( + name="模型名称", + system_message="你是智谱AI小助手,请根据用户的提示来完成任务", + messages=[], + roles=["user", "assistant", "system"], + sep="\n###", + stop_str="###", +) +``` +这个返回值展示了一个初始化状态的会话模板,其中包含了基本的会话设置但不包含任何实际的对话消息。 +*** diff --git a/markdown_docs/server/reranker/reranker.md b/markdown_docs/server/reranker/reranker.md new file mode 100644 index 000000000..06964bb69 --- /dev/null +++ b/markdown_docs/server/reranker/reranker.md @@ -0,0 +1,82 @@ +## ClassDef LangchainReranker +**LangchainReranker**: LangchainReranker的功能是使用`Cohere Rerank API`对文档进行压缩排序。 + +**属性**: +- `model_name_or_path`: 模型名称或路径。 +- `_model`: 私有属性,存储加载的模型实例。 +- `top_n`: 返回的顶部文档数量。 +- `device`: 模型运行的设备,如"cuda"或"cpu"。 +- `max_length`: 输入文档的最大长度。 +- `batch_size`: 批处理大小。 +- `num_workers`: 进行预测时使用的工作线程数量。 + +**代码描述**: +LangchainReranker类继承自BaseDocumentCompressor,主要用于利用Cohere的rerank API对一系列文档进行压缩排序。在初始化时,该类接受模型路径、设备类型等参数,并加载相应的模型。`compress_documents`方法是该类的核心功能,它接受一系列文档和一个查询字符串作为输入,然后使用加载的模型对这些文档进行排序,最终返回排序后的文档序列。 + +在项目中,LangchainReranker被用于`knowledge_base_chat.py`中的`knowledge_base_chat_iterator`函数。在这个场景下,LangchainReranker用于对从知识库中检索到的文档进行重排序,以提高返回给用户的文档的相关性。通过将查询字符串和每个文档内容作为输入对,LangchainReranker能够评估每个文档与查询的相关性,并根据这些评分对文档进行排序。 + +**注意**: +- 在使用LangchainReranker时,需要确保提供的模型路径是有效的,并且模型兼容Cohere的rerank API。 +- `device`参数应根据运行环境选择合适的值,以确保模型能够在指定的设备上运行。 +- 在处理大量文档时,合理设置`batch_size`和`num_workers`可以提高处理速度。 + +**输出示例**: +调用`compress_documents`方法后,可能返回的结果示例为: +```python +[ + Document(page_content="文档内容1", metadata={"relevance_score": 0.95}), + Document(page_content="文档内容2", metadata={"relevance_score": 0.90}), + Document(page_content="文档内容3", metadata={"relevance_score": 0.85}) +] +``` +这个返回值是一个文档对象的列表,每个文档对象包含了原始的页面内容和一个名为`relevance_score`的元数据,表示该文档与查询的相关性评分。 +### FunctionDef __init__(self, model_name_or_path, top_n, device, max_length, batch_size, num_workers) +**__init__**: 此函数的功能是初始化LangchainReranker类的实例。 + +**参数**: +- **model_name_or_path**: 指定模型的名称或路径,类型为字符串。 +- **top_n**: 返回的最高排名结果数量,默认值为3,类型为整数。 +- **device**: 指定运行模型的设备,可以是"cuda"或"cpu",默认为"cuda"。 +- **max_length**: 输入模型的最大长度,默认为1024,类型为整数。 +- **batch_size**: 批处理大小,默认为32,类型为整数。 +- **num_workers**: 加载数据时使用的工作线程数,默认为0,类型为整数。 + +**代码描述**: +此初始化函数首先创建了一个CrossEncoder模型实例,该实例使用提供的`model_name_or_path`作为模型名称或路径,`max_length`作为模型的最大输入长度,以及`device`指定的设备上运行。这里,`max_length`被直接设置为1024,而不是使用传入的参数值,这可能是一个固定的设计选择,以确保模型的输入长度一致性。 + +接着,通过调用`super().__init__`,将`top_n`、`model_name_or_path`、`device`、`max_length`、`batch_size`和`num_workers`等参数传递给父类的初始化函数。这表明LangchainReranker类可能继承自一个具有相似初始化参数需求的父类,且此处的初始化过程涉及到了类的层次结构。 + +需要注意的是,代码中有几个参数(如`show_progress_bar`、`activation_fct`、`apply_softmax`)被注释掉了,这意味着它们在当前版本的实现中不被使用。此外,虽然`max_length`作为一个参数被传递给了父类的初始化函数,但在创建CrossEncoder实例时,它被直接设置为1024,而不是使用传入的参数值。 + +**注意**: +- 在使用此类时,需要确保`model_name_or_path`指向的模型与任务相匹配,且能够被CrossEncoder正确加载。 +- 虽然默认设备被设置为"cuda",在没有GPU支持的环境下应将其更改为"cpu"。 +- `num_workers`的默认值为0,这意味着数据加载操作将在主线程中执行。根据具体的运行环境和需求,可能需要调整此参数以优化性能。 +- 注释掉的参数可能在未来版本中被启用或彻底移除,开发者在使用此类时应留意代码库的更新。 +*** +### FunctionDef compress_documents(self, documents, query, callbacks) +**compress_documents**: 此函数的功能是使用Cohere的rerank API压缩文档序列。 + +**参数**: +- documents: 需要压缩的文档序列。 +- query: 用于压缩文档的查询字符串。 +- callbacks: 压缩过程中运行的回调函数,可选参数。 + +**代码描述**: +`compress_documents`函数接收一个文档序列、一个查询字符串以及可选的回调函数作为输入参数,返回一个压缩后的文档序列。首先,函数检查输入的文档序列是否为空,如果为空,则直接返回空列表以避免进行无效的API调用。接着,函数将文档序列转换为列表,并提取每个文档的页面内容。之后,函数为每个文档与查询字符串创建一对句子,并将这些句子对作为模型预测的输入。模型预测的结果用于选择和返回最相关的文档序列。 + +在项目中,`compress_documents`函数被`knowledge_base_chat_iterator`函数调用,用于在知识库聊天场景中对检索到的文档进行重排序,以提高返回给用户的文档的相关性。通过使用Cohere的rerank API,`compress_documents`函数能够根据与用户查询最相关的内容来优化文档的排序,从而提高用户体验。 + +**注意**: +- 确保传入的文档序列不为空,以避免无效的API调用。 +- 该函数依赖于外部模型进行文档压缩,因此需要确保模型正确配置并可用。 + +**输出示例**: +```python +[ + Document(page_content="文档内容1", metadata={"relevance_score": 0.95}), + Document(page_content="文档内容2", metadata={"relevance_score": 0.90}) +] +``` +此示例展示了一个包含两个文档的序列,每个文档都附带了一个通过模型预测得到的相关性得分。 +*** diff --git a/markdown_docs/server/utils.md b/markdown_docs/server/utils.md new file mode 100644 index 000000000..39e13d313 --- /dev/null +++ b/markdown_docs/server/utils.md @@ -0,0 +1,850 @@ +## FunctionDef wrap_done(fn, event) +**wrap_done**: 此函数的功能是将一个可等待对象(Awaitable)与一个事件(Event)包装起来,以便在可等待对象完成或抛出异常时通知事件。 + +**参数**: +- `fn`: 一个可等待对象(Awaitable),通常是一个异步函数或任务。 +- `event`: 一个`asyncio.Event`事件,用于在`fn`完成或抛出异常时进行通知。 + +**代码描述**: +`wrap_done`函数设计用于异步编程环境中,它接受一个可等待对象和一个事件作为参数。函数内部首先尝试等待可等待对象`fn`的完成。如果在等待过程中`fn`执行成功,则直接进入`finally`块;如果`fn`执行过程中抛出异常,则会被`except`块捕获。在异常捕获块中,首先通过`logging.exception`记录异常信息,然后构造一个包含异常信息的消息,并使用`logger.error`记录错误信息,其中是否记录详细的异常信息取决于`log_verbose`变量的值。无论`fn`的执行结果如何,最终都会执行`finally`块,在这里通过调用`event.set()`方法来通知事件,表示`fn`的执行已经完成或发生了异常。 + +在项目中,`wrap_done`函数被多个模块调用,主要用于处理异步任务的执行并在任务完成或发生异常时进行通知。例如,在`agent_chat_iterator`、`chat_iterator`、`completion_iterator`、`knowledge_base_chat_iterator`和`search_engine_chat_iterator`等异步迭代器中,`wrap_done`被用来包装异步调用链,以便在异步任务完成时通过事件通知机制更新状态或处理结果。这种模式允许项目中的异步流程能够更加灵活地处理异步任务的完成情况,特别是在需要根据异步任务的执行结果进行后续操作时。 + +**注意**: +- 使用`wrap_done`函数时,需要确保传入的`fn`是一个正确的可等待对象,例如异步函数调用或`asyncio`任务。 +- `event`参数应该是一个`asyncio.Event`实例,它用于在`fn`完成或发生异常时进行通知。 +- 在异常处理中,根据`log_verbose`变量的设置决定是否记录详细的异常信息,这需要根据实际的日志记录需求来配置。 +- `wrap_done`函数的使用场景主要集中在需要异步执行并在完成时进行通知的情况,因此在设计异步流程时应考虑如何合理利用此函数以优化异步任务的处理逻辑。 +## FunctionDef get_ChatOpenAI(model_name, temperature, max_tokens, streaming, callbacks, verbose) +**get_ChatOpenAI**: 此函数的功能是初始化并返回一个ChatOpenAI实例。 + +**参数**: +- model_name: 字符串类型,指定要使用的模型名称。 +- temperature: 浮点数,用于控制生成文本的多样性。 +- max_tokens: 整型或None,默认为None,指定生成文本的最大token数量。 +- streaming: 布尔类型,默认为True,指定是否以流式传输模式运行模型。 +- callbacks: 回调函数列表,默认为空列表,用于处理模型生成的文本。 +- verbose: 布尔类型,默认为True,指定是否在控制台输出详细信息。 +- **kwargs: 接受任意额外的关键字参数。 + +**代码描述**: +函数首先调用`get_model_worker_config`函数,根据提供的`model_name`获取模型的配置信息。如果`model_name`为"openai-api",则会根据配置中的`model_name`更新变量`model_name`。接着,函数设置`ChatOpenAI`类的`_get_encoding_model`方法为`MinxChatOpenAI`类的`get_encoding_model`方法,这是为了确保`ChatOpenAI`实例能够获取正确的编码模型。之后,使用提供的参数和配置信息初始化`ChatOpenAI`实例。最终,函数返回这个初始化好的`ChatOpenAI`实例。 + +**注意**: +- 在使用此函数之前,请确保已经正确配置了模型的相关信息,包括API密钥和基础URL等。 +- 如果`model_name`指定的模型不支持或配置有误,可能会导致初始化失败。 +- `callbacks`参数允许用户传入自定义的回调函数,这些函数可以在模型生成文本时被调用,用于处理生成的文本或执行其他自定义逻辑。 + +**输出示例**: +调用`get_ChatOpenAI`函数可能返回的示例输出为: +```python +ChatOpenAI(streaming=True, verbose=True, callbacks=[], openai_api_key="YOUR_API_KEY", openai_api_base="https://api.example.com", model_name="gpt-3.5-turbo", temperature=0.7, max_tokens=1024, openai_proxy=None) +``` +这表示函数返回了一个配置好的`ChatOpenAI`实例,该实例使用了"gpt-3.5-turbo"模型,温度设置为0.7,最大token数量为1024,且启用了流式传输和详细输出。 +## FunctionDef get_OpenAI(model_name, temperature, max_tokens, streaming, echo, callbacks, verbose) +**get_OpenAI**: 此函数的功能是初始化并返回一个配置好的OpenAI模型实例。 + +**参数**: +- model_name: 字符串类型,指定使用的模型名称。 +- temperature: 浮点数,控制生成文本的创造性。 +- max_tokens: 整型或None,默认为None,指定生成文本的最大令牌数。 +- streaming: 布尔类型,默认为True,指示是否启用流式传输。 +- echo: 布尔类型,默认为True,指示是否回显输入。 +- callbacks: 回调函数列表,默认为空列表,用于处理模型的输出。 +- verbose: 布尔类型,默认为True,控制是否输出详细信息。 +- **kwargs: 接受任意额外的关键字参数。 + +**代码描述**: +`get_OpenAI` 函数首先通过调用`get_model_worker_config`函数获取指定模型的配置信息。如果模型名称为"openai-api",则会根据配置信息中的"model_name"更新模型名称。接着,函数创建一个`OpenAI`实例,配置包括是否启用流式传输、是否输出详细信息、回调函数列表、OpenAI API密钥、OpenAI API基础URL、模型名称、温度、最大令牌数、OpenAI代理以及是否回显输入等。最后,函数返回配置好的`OpenAI`模型实例。 + +**注意**: +- 确保在调用此函数之前,已经正确配置了OpenAI API密钥和基础URL。 +- 如果提供的模型名称为"openai-api",则会根据配置自动更新模型名称,因此需要确保相关配置正确。 +- 回调函数列表允许用户自定义处理模型输出的逻辑,根据需要添加回调函数。 + +**输出示例**: +由于`get_OpenAI`函数返回的是一个`OpenAI`实例,因此输出示例将依赖于`OpenAI`类的实现。假设`OpenAI`类的实例化结果如下: +```python +OpenAI( + streaming=True, + verbose=True, + callbacks=[], + openai_api_key="YOUR_API_KEY", + openai_api_base="https://api.openai.com", + model_name="text-davinci-003", + temperature=0.7, + max_tokens=100, + openai_proxy=None, + echo=True +) +``` +此示例展示了一个配置了流式传输、详细输出、无回调函数、指定API密钥和基础URL、使用"text-davinci-003"模型、温度为0.7、最大令牌数为100、无代理、并启用输入回显的`OpenAI`模型实例。 +## ClassDef BaseResponse +**BaseResponse**: BaseResponse 类是用于构建统一的 API 响应格式。 + +**属性**: +- `code`: API 状态码,用于表示请求处理的结果,如200表示成功。 +- `msg`: API 状态消息,用于提供更详细的处理结果信息,如"success"表示操作成功。 +- `data`: API 数据,用于存放请求返回的数据,可以是任意类型。 + +**代码描述**: +BaseResponse 类继承自 BaseModel,利用 Pydantic 库进行数据验证和序列化。它定义了三个主要字段:`code`、`msg`和`data`,分别用于表示 API 的状态码、状态消息和返回的数据内容。此外,通过 Pydantic 的 Field 函数,为每个字段提供了默认值和描述信息,以便于生成 OpenAPI 文档时提供更丰富的信息。例如,`code`字段默认值为200,`msg`字段默认值为"success",而`data`字段默认为None,表示没有数据返回。 + +BaseResponse 类还定义了一个内部类 Config,其中`schema_extra`属性用于提供示例数据,这有助于在自动生成的 API 文档中展示如何使用该响应格式。 + +在项目中,BaseResponse 类被广泛用于各个 API 接口的响应模型。例如,在`mount_app_routes`函数中,通过`response_model=BaseResponse`参数,指定了根路由("/")的响应模型为 BaseResponse,这意味着该路由的响应将遵循 BaseResponse 定义的格式。同样,在其他如`chat_feedback`、`upload_temp_docs`、`file_chat`等多个 API 接口中,也使用了 BaseResponse 作为响应模型,确保了 API 响应的一致性和标准化。 + +**注意**: +- 使用 BaseResponse 作为响应模型时,应根据实际情况填充`code`、`msg`和`data`字段,以确保返回给客户端的信息准确无误。 +- 在定义 API 接口时,通过指定`response_model=BaseResponse`参数,可以让 FastAPI 自动将函数的返回值转换为 BaseResponse 指定的格式,这有助于减少重复代码并提高开发效率。 +- 在实际使用中,可以根据需要对 BaseResponse 进行扩展,添加额外的字段或方法,以满足特定的业务需求。 +### ClassDef Config +**Config**: Config 类的功能是定义一个配置信息的结构和示例。 + +**属性**: +- `schema_extra`: 用于定义配置信息的额外模式示例。 + +**代码描述**: +Config 类中定义了一个名为 `schema_extra` 的类属性。这个属性是一个字典,用于提供配置信息的示例。在这个示例中,包含了两个键值对:"code" 和 "msg"。"code" 的值设置为 200,表示一个成功的状态码;"msg" 的值设置为 "success",表示操作成功的消息。这个结构通常用于API响应的标准格式,帮助开发者理解预期的响应结构和内容。 + +**注意**: +- `schema_extra` 属性主要用于文档和测试中,为开发者提供一个关于如何使用该配置的具体示例。它不会直接影响代码的逻辑功能,但是对于理解代码的结构和预期行为非常有帮助。 +- 修改 `schema_extra` 中的值时,需要确保它们与实际应用中的配置信息保持一致,以避免混淆。 +- 这个类可以根据实际需求扩展更多的配置项和示例,以适应不同的场景和需求。 +*** +## ClassDef ListResponse +**ListResponse**: ListResponse 类用于封装返回给客户端的列表数据响应。 + +**属性**: +- `data`: 存放名字列表的属性,类型为字符串列表。 + +**代码描述**: ListResponse 类继承自 BaseResponse 类,专门用于处理那些需要返回列表数据的API响应。通过使用 Pydantic 的 Field 函数,`data` 属性被定义为必须提供的字段,并附带了描述信息"List of names",说明这个字段用于存放名字列表。此外,ListResponse 类通过内部类 Config 定义了一个示例,展示了如何使用这个类来构造一个包含状态码、状态消息和数据列表的响应体。示例中的数据包括一个成功的状态码200、一个成功消息"success"和一个包含三个文档名的列表。 + +在项目中,ListResponse 类被用于那些需要返回文件名列表或其他字符串列表的API接口。例如,在知识库管理功能中,获取知识库列表和知识库内文件列表的API接口就使用了ListResponse作为响应模型。这样做不仅保证了API响应格式的一致性,也使得API的使用者能够清晰地了解到响应中将包含哪些数据。 + +**注意**: +- 在使用 ListResponse 类时,需要确保`data`属性中填充的是正确的列表数据。虽然 ListResponse 类提供了数据类型和结构的基本验证,但是填充数据的准确性和相关性需要开发者自行保证。 +- ListResponse 类继承自 BaseResponse 类,因此它自动拥有了`code`和`msg`两个属性,分别用于表示API响应的状态码和状态消息。在实际使用中,开发者应根据实际情况设置这两个属性的值,以确保响应信息的准确性和有用性。 +- 通过在 Config 类中定义`schema_extra`属性,ListResponse 类为自动生成的API文档提供了丰富的示例,有助于开发者和API的使用者更好地理解如何使用该响应格式。开发者在扩展或修改ListResponse类时,应考虑更新这些示例数据,以保持文档的准确性和实用性。 +### ClassDef Config +**Config**: Config 类的功能是定义模式额外信息。 + +**属性**: +- `schema_extra`: 用于定义额外的模式信息。 + +**代码描述**: +Config 类是一个简单的配置类,其主要作用是通过 `schema_extra` 属性提供一个示例配置。这个示例配置是一个字典,包含了 `code`、`msg` 和 `data` 三个键。`code` 键对应的值是一个整数,表示状态码;`msg` 键对应的值是一个字符串,表示消息内容;`data` 错对应的值是一个字符串列表,表示数据内容。此配置主要用于文档或API响应示例中,帮助开发者理解预期的响应格式。 + +在这个示例中,`code` 设置为 200,表示请求成功;`msg` 设置为 "success",表示操作成功的消息;`data` 包含了三个字符串,分别是 "doc1.docx"、"doc2.pdf" 和 "doc3.txt",模拟了一个文件列表的返回数据。 + +**注意**: +- `schema_extra` 在这里是作为一个类属性存在的,这意味着它是与类相关联而不是与类的实例相关联的。因此,对 `schema_extra` 的任何修改都会影响到所有使用这个类的地方。 +- 这个类主要用于提供API响应的示例配置,以便在自动生成文档或进行API测试时使用。开发者应根据实际需求调整 `schema_extra` 中的内容,以确保它正确反映了API的预期响应。 +*** +## ClassDef ChatMessage +**ChatMessage**: ChatMessage 的功能是定义聊天消息的数据结构。 + +**属性**: +- `question`: 问题文本。 +- `response`: 响应文本。 +- `history`: 历史文本列表,每个元素也是一个包含字符串的列表,代表一次对话的问答。 +- `source_documents`: 来源文档列表,包含相关文档及其得分的信息。 + +**代码描述**: +ChatMessage 类继承自 BaseModel,用于表示聊天中的一条消息。该类通过 Pydantic 库定义,确保数据有效性和类型安全。每个属性都使用了 Pydantic 的 Field 方法进行详细定义,包括类型信息和描述文本。 + +- `question` 属性定义了提问的文本内容,是一个字符串类型。 +- `response` 属性定义了对提问的回答,同样是一个字符串类型。 +- `history` 属性记录了与当前消息相关的历史对话,是一个列表,其中每个元素也是一个列表,包含了一系列的问答对。 +- `source_documents` 属性提供了生成回答时参考的源文档列表。这些文档可能是从外部数据库、文件或其他信息源中检索到的,用于支持回答的生成。 + +此外,ChatMessage 类中定义了一个 Config 子类,其中的 `schema_extra` 字段提供了一个示例,展示了如何填充 ChatMessage 类的实例。这个示例包括了一个典型的问题、相应的回答、相关的历史对话以及参考的源文档。 + +**注意**: +- 使用 ChatMessage 类时,需要确保所有字段都符合定义的类型和结构要求。特别是 `history` 和 `source_documents` 属性,它们都是列表类型,需要正确地构造列表元素。 +- `schema_extra` 中的示例仅用于说明如何使用 ChatMessage 类,并不意味着实际应用中的数据必须与示例完全一致。开发者应根据实际情况填充这些字段。 +- 由于 ChatMessage 类使用了 Pydantic 库,可以利用 Pydantic 提供的数据验证功能来确保数据的正确性和完整性。在实际应用中,可以通过定义更多的验证规则来进一步增强数据的安全性和可靠性。 +### ClassDef Config +**Config**: Config 类的功能是提供一个示例配置,用于说明如何处理和响应工伤保险相关的查询。 + +**属性**: +- `schema_extra`: 一个字典,包含了一个示例配置,用于展示如何回答有关工伤保险的问题。 + +**代码描述**: +Config 类定义了一个名为 `schema_extra` 的类属性,该属性是一个字典。这个字典内嵌套了一个名为 "example" 的键,其值也是一个字典,用于提供一个具体的示例,展示如何回答关于工伤保险的问题。这个示例包含了问题("question")、回答("response")、历史问答("history")和来源文件("source_documents")四个部分。 + +- "question" 键对应的值是一个字符串,表示提出的问题。 +- "response" 键对应的值是一个字符串,详细描述了对问题的回答,包括工伤保险的办理流程和待遇。 +- "history" 键对应的值是一个列表,每个元素也是一个列表,表示之前相关的问答。 +- "source_documents" 键对应的值是一个列表,包含了回答依据的文档来源,每个元素是一个字符串,描述了文档的出处和相关内容。 + +**注意**: +- Config 类主要用于提供示例配置,帮助开发者理解如何构建和使用类似的配置结构。 +- 在实际应用中,开发者可以根据具体需求修改或扩展 `schema_extra` 中的内容,以适应不同的场景和需求。 +- 示例中的问题、回答、历史问答和来源文件仅用于演示,开发者应根据实际情况填充相应的内容。 +*** +## FunctionDef torch_gc +**torch_gc**: 此函数的功能是清理PyTorch在CUDA或MPS后端上的缓存内存。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `torch_gc`函数首先尝试导入PyTorch库。如果成功,它会检查CUDA是否可用。如果CUDA可用,该函数会调用`torch.cuda.empty_cache()`和`torch.cuda.ipc_collect()`来清空CUDA的缓存内存,以及收集跨进程分配的共享内存。这有助于在使用CUDA进行大量计算时释放未使用的内存,从而避免内存溢出或性能下降的问题。 + +如果CUDA不可用,函数会检查MPS(Apple Metal Performance Shaders)是否可用,这是针对macOS系统的。如果MPS可用,它会尝试从`torch.mps`模块导入并调用`empty_cache()`函数来清理MPS的缓存内存。如果在尝试导入或调用过程中出现任何异常,函数会捕获这些异常并记录一条错误消息,建议用户将PyTorch版本升级到2.0.0或更高版本以获得更好的内存管理支持。 + +在项目中,`torch_gc`函数被`FaissKBService`类的`do_add_doc`方法调用。在`do_add_doc`方法中,`torch_gc`被用于在添加文档到知识库并更新向量存储后,清理PyTorch的缓存内存。这是因为在处理大量数据并使用PyTorch进行向量化操作时,可能会产生大量的内存占用。通过调用`torch_gc`,可以帮助释放这些未使用的内存,从而避免内存溢出错误,确保系统的稳定性和性能。 + +**注意**: 使用`torch_gc`函数时,需要确保PyTorch已正确安装,并且系统支持CUDA或MPS。此外,如果在macOS系统上使用且遇到相关的内存清理问题,应考虑将PyTorch版本升级到2.0.0或更高版本。 +## FunctionDef run_async(cor) +**run_async**: 此函数的功能是在同步环境中运行异步代码。 + +**参数**: +- cor: 需要运行的异步协程对象。 + +**代码描述**: +`run_async` 函数旨在解决在同步代码环境中执行异步协程的需求。它首先尝试获取当前事件循环,如果当前没有事件循环,则会创建一个新的事件循环。此函数接受一个异步协程对象作为参数,并在获取或创建的事件循环中运行这个协程,直到该协程执行完成。通过这种方式,即使在同步代码中,也能够方便地执行异步操作。 + +在函数实现中,首先通过`asyncio.get_event_loop()`尝试获取当前线程的事件循环。如果当前线程没有运行的事件循环,这一步骤可能会抛出异常。为了处理这种情况,函数使用`try-except`结构捕获异常,并通过`asyncio.new_event_loop()`创建一个新的事件循环。最后,使用`loop.run_until_complete(cor)`运行传入的协程对象`cor`,并返回执行结果。 + +**注意**: +- 在使用此函数时,需要确保传入的`cor`参数是一个异步协程对象。 +- 如果在一个已经运行的事件循环中调用此函数,可能会导致错误。因此,最好在确保没有正在运行的事件循环的情况下使用此函数。 +- 在函数执行结束后,事件循环会停止,但不会关闭。如果需要在之后的代码中继续使用事件循环,可能需要手动管理事件循环的生命周期。 + +**输出示例**: +假设有一个异步函数`async_function`,返回值为`"Hello, Async World!"`,则使用`run_async(async_function())`的返回值可能如下: +``` +"Hello, Async World!" +``` +## FunctionDef iter_over_async(ait, loop) +**iter_over_async**: 将异步生成器封装成同步生成器。 + +**参数**: +- **ait**: 需要被封装的异步生成器。 +- **loop**: 可选参数,指定事件循环。如果未提供,则尝试获取当前线程的事件循环,若获取失败,则创建一个新的事件循环。 + +**代码描述**: +`iter_over_async` 函数主要用于将异步生成器的迭代过程转换为同步过程,以便在不支持异步迭代的环境中使用。首先,通过调用`ait.__aiter__()`获取异步迭代器。然后定义一个异步函数`get_next`,该函数尝试通过`await ait.__anext__()`获取下一个元素,如果成功,则返回`(False, obj)`,其中`obj`是获取到的元素;如果迭代结束,捕获`StopAsyncIteration`异常,返回`(True, None)`表示迭代结束。 + +如果调用时没有提供事件循环(`loop`参数为`None`),函数会尝试获取当前线程的事件循环,如果失败,则创建一个新的事件循环。 + +接下来,函数进入一个无限循环,每次循环中通过`loop.run_until_complete(get_next())`同步地执行`get_next`函数,获取下一个元素或者迭代结束的信号。如果迭代结束,循环将中断;否则,yield返回当前获取到的元素,实现了将异步生成器的元素同步地逐个输出。 + +在项目中,`iter_over_async`函数被`server/model_workers/xinghuo.py/XingHuoWorker/do_chat`方法调用,用于处理异步请求的响应数据。在`do_chat`方法中,通过`iter_over_async`函数同步地处理从异步API请求返回的数据流,使得可以在一个同步函数中逐步处理异步获取的数据,提高了代码的可读性和易用性。 + +**注意**: +- 使用此函数时,需要确保传入的`ait`参数是一个异步生成器。 +- 如果在异步环境中使用此函数,应当注意事件循环的管理,避免事件循环的冲突。 + +**输出示例**: +假设有一个异步生成器`async_gen`,每次异步返回一个数字,使用`iter_over_async`进行迭代时,可能的输出为: +```python +for num in iter_over_async(async_gen): + print(num) +``` +输出: +``` +1 +2 +3 +... +``` +### FunctionDef get_next +**get_next函数的功能**: 异步获取下一个对象。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `get_next` 是一个异步函数,旨在从异步迭代器中获取下一个元素。函数首先尝试通过调用 `ait.__anext__()` 异步获取下一个元素。如果成功,函数将返回一个元组,第一个元素为 `False`,表示未到达迭代器的末尾,第二个元素为获取到的对象。如果在尝试获取下一个元素时遇到 `StopAsyncIteration` 异常,表示迭代器已经没有更多元素可以返回,此时函数将返回一个元组,第一个元素为 `True`,表示已到达迭代器的末尾,第二个元素为 `None`。 + +**注意**: 使用此函数时,需要确保 `ait` 是一个异步迭代器对象,并且已经被正确初始化。此外,由于这是一个异步函数,调用它时需要使用 `await` 关键字或在其他异步上下文中。 + +**输出示例**: +- 当迭代器中还有元素时,可能的返回值为 `(False, obj)`,其中 `obj` 是从迭代器中获取的下一个对象。 +- 当迭代器中没有更多元素时,返回值为 `(True, None)`。 +*** +## FunctionDef MakeFastAPIOffline(app, static_dir, static_url, docs_url, redoc_url) +**MakeFastAPIOffline**: 此函数的功能是为FastAPI应用程序提供离线文档支持,使其不依赖于CDN来加载Swagger UI和ReDoc文档页面。 + +**参数**: +- `app`: FastAPI对象,需要被修改以支持离线文档。 +- `static_dir`: 静态文件目录的路径,默认为当前文件所在目录下的"static"文件夹。 +- `static_url`: 服务静态文件的URL路径,默认为"/static-offline-docs"。 +- `docs_url`: Swagger UI文档的URL路径,默认为"/docs"。 +- `redoc_url`: ReDoc文档的URL路径,默认为"/redoc"。 + +**代码描述**: +此函数首先从FastAPI和starlette模块中导入所需的类和函数。然后,它定义了一个内部函数`remove_route`,用于从FastAPI应用中移除指定的路由。接着,函数通过`app.mount`方法挂载静态文件目录,使得Swagger UI和ReDoc所需的静态文件可以从本地服务器提供,而不是通过外部CDN加载。 + +如果`docs_url`参数不为None,函数会移除原有的Swagger UI路由,并添加一个新的路由,该路由返回一个自定义的Swagger UI HTML页面,其中所有资源的URL都被修改为指向本地静态文件目录。 + +类似地,如果`redoc_url`参数不为None,函数会移除原有的ReDoc路由,并添加一个新的路由,该路由返回一个自定义的ReDoc HTML页面,其中资源的URL也被修改为指向本地静态文件目录。 + +此函数通过修改FastAPI应用的路由和静态文件配置,实现了一个不依赖于外部CDN的离线文档系统。 + +**在项目中的应用**: +在项目中,`MakeFastAPIOffline`函数被用于不同的FastAPI应用创建过程中,以确保这些应用能够在没有外部网络连接的环境下,仍然提供完整的API文档。例如,在`create_app`、`create_controller_app`、`create_model_worker_app`和`create_openai_api_app`等函数中,都调用了`MakeFastAPIOffline`来实现离线文档的功能。这表明项目中的多个组件都需要在离线环境下提供API文档,以便开发者和用户即使在没有互联网连接的情况下也能访问和了解API的使用方法。 + +**注意**: +- 确保`static_dir`参数指向的目录中包含了Swagger UI和ReDoc所需的所有静态文件,包括JavaScript、CSS文件和图标等。 +- 修改`docs_url`和`redoc_url`参数时,需要确保这些URL不与应用中已有的路由冲突。 + +**输出示例**: 由于此函数没有返回值,因此没有输出示例。此函数的主要作用是修改传入的FastAPI应用对象,添加离线文档支持。 +### FunctionDef remove_route(url) +**remove_route**: 此函数的功能是从应用中移除指定的路由。 + +**参数**: +- **url**: 需要被移除的路由的URL,类型为字符串。 + +**代码描述**: +`remove_route` 函数接受一个参数 `url`,其目的是从 FastAPI 应用的路由列表中移除与给定 `url` 匹配的路由。函数首先初始化一个名为 `index` 的变量,用于存储需要被移除的路由的索引位置。通过遍历 `app.routes`,即应用中所有路由的列表,函数比较每个路由对象的 `path` 属性(即路由的URL路径)与给定的 `url` 是否相同(这里的比较忽略大小写)。一旦找到匹配的路由,就将其索引赋值给 `index` 并跳出循环。 + +如果 `index` 是一个整数(这意味着找到了匹配的路由),函数则通过 `pop` 方法从 `app.routes` 列表中移除该索引对应的路由对象。这样,指定的路由就从应用中被成功移除。 + +**注意**: +- 在使用此函数时,确保传入的 `url` 参数确实对应于应用中的一个有效路由。如果传入了一个不存在的路由URL,函数将不会执行任何操作。 +- 由于此函数直接修改了 `app.routes`,请谨慎使用,以避免不小心移除了不应该被移除的路由。 +- 确保在调用此函数之前,`app` 对象已经被正确初始化并且包含了路由列表。此函数假定 `app` 是一个全局变量,且已经有路由被添加到了 `app.routes` 中。 +*** +### FunctionDef custom_swagger_ui_html(request) +**custom_swagger_ui_html函数的功能**: 生成并返回一个定制的Swagger UI HTML响应。 + +**参数**: +- `request`: Request对象,用于获取当前请求的信息。 + +**代码描述**: +`custom_swagger_ui_html`函数是一个异步函数,它接收一个`Request`对象作为参数,并返回一个`HTMLResponse`对象。该函数的主要作用是生成一个定制化的Swagger UI页面,用于API文档的展示。 + +函数首先从`request.scope`中获取`root_path`,这是当前应用的根路径。然后,它构造了一个favicon的URL,这是页面标签上显示的小图标的地址。 + +接下来,函数调用`get_swagger_ui_html`函数,传入了多个参数来定制Swagger UI页面: +- `openapi_url`:这是OpenAPI规范文件的URL,用于Swagger UI解析并展示API文档。 +- `title`:页面的标题,这里通过`app.title`获取应用的标题,并附加了" - Swagger UI"。 +- `oauth2_redirect_url`:OAuth2重定向URL,用于OAuth2认证流程。 +- `swagger_js_url`和`swagger_css_url`:分别是Swagger UI的JavaScript和CSS文件的URL,用于页面的样式和功能。 +- `swagger_favicon_url`:页面标签上显示的小图标的URL。 + +**注意**: +- 确保`request.scope`中包含`root_path`,否则可能导致路径解析错误。 +- `get_swagger_ui_html`函数需要从外部导入,确保在使用前已正确导入。 +- 该函数依赖于FastAPI的应用实例`app`和相关配置变量(如`openapi_url`、`swagger_ui_oauth2_redirect_url`等),请确保这些变量在调用函数前已正确设置。 + +**输出示例**: +假设应用的标题为"My API",根路径为"/api",则该函数可能返回的HTMLResponse内容如下(实际内容会包含完整的HTML结构,这里仅展示关键信息): + +```html + + + + My API - Swagger UI + + + + +
+ + + +``` + +这个HTML页面将加载Swagger UI,自动解析`openapi_url`指向的OpenAPI规范文件,并展示API文档。 +*** +### FunctionDef swagger_ui_redirect +**swagger_ui_redirect**: 此函数的功能是重定向到Swagger UI的OAuth2认证页面。 + +**参数**: 此函数没有参数。 + +**代码描述**: `swagger_ui_redirect`函数是一个异步函数,返回一个HTMLResponse对象。该函数调用`get_swagger_ui_oauth2_redirect_html`方法,此方法负责生成并返回一个包含OAuth2认证所需信息的HTML页面。这个页面通常用于API文档中,允许用户通过OAuth2进行认证,以便在测试API时能够进行身份验证。由于这是一个异步函数,它可以在FastAPI或其他支持异步操作的Web框架中使用,以提高处理请求的效率。 + +**注意**: 使用此函数时,需要确保`get_swagger_ui_oauth2_redirect_html`方法可用,并且已正确配置OAuth2认证。此外,由于它返回的是HTMLResponse,调用此函数的路由应该被配置为返回HTML内容。 + +**输出示例**: +```html + + + + OAuth2 Redirect + + + + + +``` +上述输出示例展示了一个可能的HTML页面结构,实际内容将根据`get_swagger_ui_oauth2_redirect_html`方法的实现而有所不同。这个页面包含了处理OAuth2认证重定向所需的所有信息和逻辑。 +*** +### FunctionDef redoc_html(request) +**redoc_html**: 此函数的功能是生成并返回一个用于展示API文档的ReDoc页面的HTML响应。 + +**参数**: +- `request`: Request对象,用于获取当前请求的信息。 + +**代码描述**: +`redoc_html`函数是一个异步函数,它接收一个FastAPI的`Request`对象作为参数。此函数的主要作用是构建并返回一个ReDoc页面的HTML响应,用于展示OpenAPI文档。 + +函数首先从`request.scope`中获取`root_path`,这是当前应用的根路径。然后,它构造了favicon图标的URL,这是通过将根路径、静态文件路径以及favicon文件名拼接而成的。 + +接下来,函数调用`get_redoc_html`函数,传入以下参数: +- `openapi_url`:OpenAPI文档的URL,通过将根路径和OpenAPI文档的路径拼接而成。 +- `title`:页面标题,这里是应用的标题加上" - ReDoc"。 +- `redoc_js_url`:ReDoc JavaScript库的URL,通过将根路径和静态文件路径以及ReDoc库的文件名拼接而成。 +- `with_google_fonts`:一个布尔值,指示是否从Google字体服务加载字体。在此处设置为`False`,表示不从Google加载字体。 +- `redoc_favicon_url`:favicon图标的URL。 + +最后,`get_redoc_html`函数返回一个`HTMLResponse`对象,其中包含了用于展示API文档的ReDoc页面的HTML代码。 + +**注意**: +- 确保在调用此函数之前,应用的根路径、OpenAPI文档的路径以及静态文件路径已经正确设置。 +- 此函数依赖于`get_redoc_html`函数,确保此函数可用且能正确返回`HTMLResponse`对象。 + +**输出示例**: +由于此函数返回的是一个`HTMLResponse`对象,其具体内容取决于`get_redoc_html`函数的实现和传入的参数。一般而言,返回的HTML响应会包含一个完整的ReDoc页面,允许用户通过浏览器查看和交互API文档。 +*** +## FunctionDef list_embed_models +**list_embed_models**: 此函数的功能是获取配置的嵌入模型名称列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `list_embed_models` 函数通过访问全局变量 `MODEL_PATH` 中的 `"embed_model"` 键,获取所有已配置的嵌入模型的名称,并以列表形式返回这些名称。这个函数在项目中主要用于检索可用的本地嵌入模型,以便在需要进行文本向量化处理时,能够选择合适的模型进行操作。 + +在项目的不同部分调用了此函数,以确保在执行文本嵌入或者其他与嵌入模型相关的操作时,能够使用到正确且有效的模型。例如,在 `embed_texts` 和 `aembed_texts` 函数中,通过调用 `list_embed_models` 来验证传入的 `embed_model` 是否为一个有效的、已配置的本地模型。如果是,那么将使用该模型进行文本的向量化处理;如果不是,将尝试其他途径或返回错误信息。此外,在 `knowledge_base_page` 函数中,此函数用于提供一个嵌入模型的列表,以供用户在创建或更新知识库时选择使用哪个模型进行文本嵌入。 + +**注意**: 使用此函数时,需要确保 `MODEL_PATH` 全局变量已正确配置,并且包含 `"embed_model"` 键,其值应为一个字典,字典中包含了所有可用的嵌入模型名称。 + +**输出示例**: 假设 `MODEL_PATH["embed_model"]` 包含了两个模型 `"model1"` 和 `"model2"`,那么调用 `list_embed_models()` 将返回 `["model1", "model2"]`。 +## FunctionDef list_config_llm_models +**list_config_llm_models**: 此函数的功能是获取配置的大型语言模型(LLM)的不同类型。 + +**参数**: 此函数没有参数。 + +**代码描述**: `list_config_llm_models` 函数旨在从系统配置中检索并返回不同类型的大型语言模型(LLM)配置信息。它首先从全局变量 `FSCHAT_MODEL_WORKERS` 中复制所有工作模型配置,并移除默认配置(如果存在)。然后,函数构造并返回一个字典,该字典包含三种类型的模型配置:本地(`local`)、在线(`online`)和工作模型(`worker`)。每种类型下的模型配置也以字典形式组织,其中键为模型名称,值为相应的配置信息。 + +在项目中,`list_config_llm_models` 函数被多个对象调用,说明其在项目中扮演着核心角色。例如,在 `server/llm_api.py/list_config_models` 中,此函数用于根据请求体中指定的类型(如 `local`、`online`)获取相应的模型配置,并进一步获取每个模型的详细配置信息以构建响应数据。在 `server/utils.py/list_online_embed_models` 中,此函数用于获取在线模型的配置,并进一步检查这些模型是否支持嵌入功能,以筛选出可以进行嵌入操作的模型列表。 + +**注意**: 在使用此函数时,需要确保相关的全局变量(如 `FSCHAT_MODEL_WORKERS`、`MODEL_PATH` 和 `ONLINE_LLM_MODEL`)已被正确初始化并包含了有效的配置信息。此外,由于此函数返回的配置信息可能会直接影响到模型的加载和使用,因此在修改配置或扩展模型类型时应格外小心。 + +**输出示例**: +```python +{ + "local": { + "llm_model_1": {"config1": "value1", "config2": "value2"}, + "llm_model_2": {"config1": "value1", "config2": "value2"} + }, + "online": { + "llm_model_online_1": {"config1": "value1", "config2": "value2"}, + "llm_model_online_2": {"config1": "value1", "config2": "value2"} + }, + "worker": { + "llm_model_worker_1": {"config1": "value1", "config2": "value2"}, + "llm_model_worker_2": {"config1": "value1", "config2": "value2"} + } +} +``` +此输出示例展示了函数可能返回的配置信息结构,其中包含了三种类型的模型配置,每种类型下可能包含多个模型及其配置信息。 +## FunctionDef get_model_path(model_name, type) +**get_model_path**: 该函数的功能是根据模型名称和类型获取模型的路径。 + +**参数**: +- model_name: 字符串类型,指定要获取路径的模型名称。 +- type: 字符串类型,可选参数,默认为None,指定模型的类型。 + +**代码描述**: +`get_model_path` 函数主要用于在项目中根据提供的模型名称(`model_name`)和可选的模型类型(`type`)来确定模型文件的存储路径。该函数首先检查是否提供了模型类型,并尝试在预定义的模型路径字典(`MODEL_PATH`)中查找对应的路径。如果没有提供类型或者提供的类型在字典中找不到,函数会遍历字典中所有的值来构建一个包含所有路径的字典。 + +接下来,函数尝试从构建的路径字典中获取模型名称对应的路径字符串。如果找到路径字符串,函数会进行几个判断: +1. 如果路径字符串直接指向一个目录,则返回该目录的绝对路径。 +2. 如果不是直接的目录路径,函数会尝试将`MODEL_ROOT_PATH`作为根目录,结合模型名称或路径字符串,检查是否存在对应的目录。函数会尝试以下几种组合方式来定位目录: + - 使用模型名称作为子目录名。 + - 使用完整的路径字符串作为子目录路径。 + - 使用路径字符串分割后的最后一部分作为子目录名。 + +如果以上步骤都未能定位到一个存在的目录,函数最终会返回原始的路径字符串。 + +在项目中,`get_model_path` 函数被用于不同场景,例如在`load_embeddings`方法中,根据模型名称获取模型的存储路径,用于加载嵌入式模型。在`get_model_worker_config`函数中,用于获取模型工作配置时确定模型路径。 + +**注意**: +- 确保`MODEL_PATH`和`MODEL_ROOT_PATH`变量已根据项目需求正确配置,以便函数能正确解析和返回模型路径。 +- 函数返回的路径可能是一个绝对路径,也可能是相对于某个根目录的相对路径,具体取决于模型的存储方式和配置。 + +**输出示例**: +- 假设`MODEL_ROOT_PATH`为`/models`,`MODEL_PATH`中包含`{"type1": {"modelA": "path/to/modelA"}}`,调用`get_model_path("modelA", "type1")`可能返回`"/models/path/to/modelA"`。 +## FunctionDef get_model_worker_config(model_name) +**get_model_worker_config**: 此函数的功能是加载指定模型工作配置项。 + +**参数**: +- model_name: 字符串类型,可选参数,默认为None,指定要加载配置的模型名称。 + +**代码描述**: `get_model_worker_config` 函数主要用于加载和合并指定模型的配置项。函数首先从`configs.model_config`和`configs.server_config`模块导入`ONLINE_LLM_MODEL`、`MODEL_PATH`和`FSCHAT_MODEL_WORKERS`配置。然后,函数以`FSCHAT_MODEL_WORKERS`中的"default"配置项为基础,创建一个新的配置字典`config`。接下来,函数尝试更新`config`字典,首先使用`model_name`在`ONLINE_LLM_MODEL`中查找并更新配置,然后在`FSCHAT_MODEL_WORKERS`中查找并更新配置。 + +如果`model_name`在`ONLINE_LLM_MODEL`中存在,函数将在`config`中设置`"online_api"`为True,并尝试从`model_workers`模块动态加载指定的`provider`类到`config`的`"worker_class"`中。如果加载过程中出现异常,函数将记录错误信息。 + +对于本地模型,如果`model_name`在`MODEL_PATH["llm_model"]`中存在,函数将调用`get_model_path`函数获取模型路径,并更新`config`中的`"model_path"`。如果路径存在且为目录,`config`中还将设置`"model_path_exists"`为True。最后,函数使用`llm_device`函数确定并设置模型运行的设备类型。 + +**注意**: +- 确保在调用此函数之前,相关的配置文件`model_config`和`server_config`已正确设置,且包含所需的模型名称和默认配置。 +- 函数依赖于`model_workers`模块中定义的类,如果指定的`provider`不存在,将记录错误信息。 +- 此函数同时处理在线模型和本地模型的配置加载,确保`MODEL_PATH`中包含正确的模型路径信息。 + +**输出示例**: +假设`FSCHAT_MODEL_WORKERS`中包含默认配置和名为"example_model"的配置,`ONLINE_LLM_MODEL`中也包含名为"example_model"的配置,调用`get_model_worker_config("example_model")`可能返回如下字典: +```python +{ + "default_key": "default_value", # 来自FSCHAT_MODEL_WORKERS["default"] + "online_api": True, # 因为model_name在ONLINE_LLM_MODEL中存在 + "worker_class": , # 动态加载的provider类 + "model_path": "/path/to/example_model", # 通过get_model_path获取的模型路径 + "model_path_exists": True, # 如果路径存在且为目录 + "device": "cuda", # 通过llm_device函数确定的设备类型 + ... # 其他可能的配置项 +} +``` +此输出示例展示了函数如何合并不同来源的配置,并根据模型名称动态调整配置内容。 +## FunctionDef get_all_model_worker_configs +**get_all_model_worker_configs**: 此函数的功能是获取所有模型工作配置项的字典。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `get_all_model_worker_configs` 函数主要用于收集并返回所有模型工作配置项的详细信息。函数首先创建一个空字典`result`用于存储结果。通过`FSCHAT_MODEL_WORKERS.keys()`获取所有模型名称的集合`model_names`,然后遍历这些模型名称。对于每个模型名称,如果名称不是"default",则调用`get_model_worker_config`函数获取该模型的配置,并将其添加到`result`字典中。这里,`get_model_worker_config`函数的作用是加载指定模型的工作配置项,它会根据模型名称动态地合并默认配置和模型特定的配置项。最终,函数返回包含所有模型配置的字典`result`。 + +**注意**: +- 确保`FSCHAT_MODEL_WORKERS`已经被正确初始化,包含了所有可用模型的配置信息。`FSCHAT_MODEL_WORKERS`是一个关键的全局变量,存储了默认配置以及每个模型特定的配置项。 +- 此函数依赖于`get_model_worker_config`函数来获取每个模型的配置。因此,确保`get_model_worker_config`函数能够正确执行,且相关配置文件和模块已经被正确设置。 + +**输出示例**: +假设`FSCHAT_MODEL_WORKERS`中包含了名为"model1"和"model2"的模型配置,而"default"配置被排除,调用`get_all_model_worker_configs()`可能返回如下字典: +```python +{ + "model1": { + "default_key": "default_value", + "online_api": True, + "worker_class": , + "model_path": "/path/to/model1", + "model_path_exists": True, + "device": "cuda", + ... + }, + "model2": { + "default_key": "default_value", + "online_api": False, + "worker_class": , + "model_path": "/path/to/model2", + "model_path_exists": True, + "device": "cpu", + ... + } +} +``` +此输出示例展示了如何为每个模型动态地收集和合并配置项,从而为后续的模型部署和使用提供详细的配置信息。 +## FunctionDef fschat_controller_address +**fschat_controller_address**: 此函数的功能是获取Fastchat控制器的地址。 + +**参数**: 此函数没有参数。 + +**代码描述**: `fschat_controller_address` 函数首先从配置文件中导入`FSCHAT_CONTROLLER`配置,该配置包含了Fastchat控制器的主机地址和端口号。函数检查主机地址是否为`"0.0.0.0"`,如果是,则将其替换为`"127.0.0.1"`,这是因为在本地环境中,`"0.0.0.0"`表示监听所有可用网络接口,而在实际访问时需要指定为`"127.0.0.1"`。随后,函数将处理后的主机地址和端口号格式化为一个完整的URL字符串,并返回该字符串。 + +在项目中,`fschat_controller_address` 被多个地方调用,包括但不限于`list_running_models`、`stop_llm_model`、`change_llm_model`、`set_httpx_config`、`get_httpx_client`、`get_server_configs`、`run_model_worker`和`run_openai_api`等函数。这些调用点主要用于获取Fastchat控制器的地址,以便进行网络请求或配置网络请求客户端。例如,在`list_running_models`函数中,使用`fschat_controller_address`获取控制器地址来请求已加载模型的列表;在`set_httpx_config`函数中,使用该地址配置HTTP客户端的代理设置,以确保对Fastchat控制器的请求不会被代理拦截。 + +**注意**: 使用此函数时,需要确保`configs.server_config`中的`FSCHAT_CONTROLLER`配置正确,包括有效的主机地址和端口号,以保证能够成功连接到Fastchat控制器。 + +**输出示例**: 假设Fastchat控制器配置的主机地址为`"0.0.0.0"`,端口号为`8080`,则函数返回的字符串为`"http://127.0.0.1:8080"`。如果主机地址已经是具体的IP地址或域名,如`"192.168.1.100"`,则返回的字符串为`"http://192.168.1.100:8080"`。 +## FunctionDef fschat_model_worker_address(model_name) +**fschat_model_worker_address**: 此函数的功能是获取指定模型工作器的地址。 + +**参数**: +- model_name: 字符串类型,指定要获取地址的模型名称,默认为LLM_MODELS列表中的第一个元素。 + +**代码描述**: `fschat_model_worker_address` 函数首先调用`get_model_worker_config`函数,传入模型名称以获取模型的配置信息。如果成功获取到配置信息,函数将从配置字典中提取`host`和`port`字段。如果`host`字段的值为`"0.0.0.0"`,则将其替换为`"127.0.0.1"`,这是因为在本地环境中,`"0.0.0.0"`表示监听所有可用地址,而在实际使用中通常需要指定为本地回环地址`"127.0.0.1"`。最后,函数将`host`和`port`组合成完整的URL地址,格式为`"http://{host}:{port}"`,并返回该地址。如果无法获取模型的配置信息,函数将返回空字符串。 + +**注意**: +- 确保在调用此函数之前,已经通过`get_model_worker_config`函数正确加载了模型的配置信息,包括模型服务的主机地址和端口号。 +- 此函数主要用于内部服务之间的通信,确保服务地址的正确配置对于服务的正常运行至关重要。 + +**输出示例**: +调用`fschat_model_worker_address("example_model")`,假设`example_model`的配置中`host`为`"0.0.0.0"`,`port`为`8080`,则可能返回: +``` +"http://127.0.0.1:8080" +``` +## FunctionDef fschat_openai_api_address +**fschat_openai_api_address**: 该函数的功能是获取FastChat OpenAI API的完整地址。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `fschat_openai_api_address` 函数首先从项目的配置文件中导入 `FSCHAT_OPENAI_API` 配置字典。然后,它从这个配置中提取 `host` 和 `port` 信息,以构建并返回一个格式化的URL字符串,该字符串指向FastChat OpenAI API的服务地址。如果配置中的 `host` 值为 `"0.0.0.0"`,则会将其替换为 `"127.0.0.1"`,这是一个指向本地主机的通用IP地址。最终,函数返回的URL格式为 `"http://{host}:{port}/v1"`,其中 `{host}` 和 `{port}` 分别被替换为实际的主机地址和端口号。 + +在项目中,`fschat_openai_api_address` 函数被多个对象调用,包括 `get_ChatOpenAI`、`get_OpenAI`、`set_httpx_config` 和 `get_httpx_client` 等,这些调用点主要用于配置和初始化与OpenAI API相关的服务。例如,在 `get_ChatOpenAI` 和 `get_OpenAI` 函数中,`fschat_openai_api_address` 的返回值被用作创建 `ChatOpenAI` 和 `OpenAI` 实例时指定OpenAI API基础URL的参数。这表明 `fschat_openai_api_address` 函数在项目中扮演着连接和配置OpenAI API服务的关键角色。 + +**注意**: 使用此函数时,确保 `FSCHAT_OPENAI_API` 配置字典已正确设置在项目的配置文件中,包括有效的 `host` 和 `port` 值。此外,考虑到网络环境的不同,如果API服务部署在远程服务器上,可能需要相应地调整 `host` 值。 + +**输出示例**: 假设 `FSCHAT_OPENAI_API` 配置中的 `host` 为 `"127.0.0.1"`,`port` 为 `"5000"`,则函数的返回值将是 `"http://127.0.0.1:5000/v1"`。 +## FunctionDef api_address +**api_address**: 此函数的功能是生成并返回API服务器的地址。 + +**参数**: 此函数没有参数。 + +**代码描述**: `api_address` 函数首先从项目的配置文件中导入 `API_SERVER` 配置字典。然后,它从这个字典中提取 `host` 和 `port` 值。如果 `host` 的值为 `"0.0.0.0"`,则将其替换为 `"127.0.0.1"`,这是因为在许多情况下,`"0.0.0.0"` 表示监听所有网络接口,而在实际访问时需要指定为 `"127.0.0.1"` 或实际的IP地址。最后,函数将 `host` 和 `port` 组合成一个字符串,格式为 `"http://{host}:{port}"`,并返回这个字符串。 + +在项目中,`api_address` 函数被多个对象调用,包括 `get_server_configs` 函数、`dump_server_info` 函数以及 `ApiRequest` 和 `AsyncApiRequest` 类的构造函数。这些调用表明 `api_address` 函数用于提供API服务器的地址信息,以便其他部分的代码可以使用这个地址来进行网络请求或者在日志和配置信息中显示API服务器的地址。 + +**注意**: 使用此函数时,需要确保 `configs.server_config` 文件中已经正确配置了 `API_SERVER` 字典,包括 `host` 和 `port` 两个键值对。此外,如果API服务器的地址或端口在项目运行期间有变化,需要更新配置文件以确保 `api_address` 函数返回的地址是最新的。 + +**输出示例**: 假设API服务器的 `host` 配置为 `"127.0.0.1"`,`port` 配置为 `"8080"`,那么 `api_address` 函数将返回字符串 `"http://127.0.0.1:8080"`。 +## FunctionDef webui_address +**webui_address**: 此函数的功能是获取Web用户界面(UI)服务器的地址。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `webui_address`函数负责从配置文件中读取Web UI服务器的主机名和端口号,并将它们格式化为一个完整的URL地址。首先,函数从`configs.server_config`模块导入`WEBUI_SERVER`字典,该字典包含了`host`和`port`两个关键字,分别代表服务器的主机名和端口号。然后,函数通过格式化字符串`f"http://{host}:{port}"`将这两个值组合成一个完整的URL地址,并返回该地址。 + +在项目中,`webui_address`函数被`startup.py`模块中的`dump_server_info`函数调用。在`dump_server_info`函数中,`webui_address`的返回值被用来打印Web UI服务器的地址信息,这对于在服务器启动后验证配置和进行故障排查是非常有用的。特别是当`args.webui`参数为真时,表明用户希望获取Web UI服务器的地址信息,此时会打印出通过`webui_address`函数获取到的地址。 + +**注意**: 使用此函数时,需要确保`configs.server_config`模块中的`WEBUI_SERVER`字典已正确配置,包括有效的`host`和`port`值,否则函数将返回无效的地址。 + +**输出示例**: 假设`WEBUI_SERVER`字典中的`host`为`localhost`,`port`为`8080`,则函数的返回值将是`"http://localhost:8080"`。这个返回值可以直接用于Web浏览器中,以访问Web UI服务器。 +## FunctionDef get_prompt_template(type, name) +**get_prompt_template**: 该函数用于从配置中加载指定类型和名称的模板内容。 + +**参数**: +- type: 字符串,指定模板的类型,可选值包括"llm_chat"、"agent_chat"、"knowledge_base_chat"、"search_engine_chat",代表不同的聊天模式或功能。 +- name: 字符串,指定模板的名称,用于从指定类型中进一步确定模板。 + +**代码描述**: +`get_prompt_template`函数首先从`configs`模块导入`prompt_config`配置,然后使用`importlib.reload`方法重新加载`prompt_config`,以确保获取到最新的配置信息。函数通过`type`参数从`prompt_config.PROMPT_TEMPLATES`中索引到对应类型的模板字典,然后使用`name`参数从该字典中获取具体的模板内容。如果指定的`name`在字典中不存在,则返回`None`。 + +在项目中,`get_prompt_template`函数被多个地方调用,以支持不同场景下的模板加载需求。例如,在`server/api.py/mount_app_routes/get_server_prompt_template`中,该函数用于根据API请求中提供的类型和名称参数,动态加载并返回相应的模板内容。在`server/chat/agent_chat.py/agent_chat/agent_chat_iterator`和其他类似的聊天处理函数中,它用于加载特定聊天模式下的提示模板,以构造与用户交互的对话内容。 + +**注意**: +- 在使用`get_prompt_template`函数时,需要确保`type`和`name`参数的值正确无误,且对应的模板已经在`prompt_config`中定义。 +- 由于该函数依赖于外部的配置文件`prompt_config`,因此在修改配置文件后,可能需要重启服务或动态重新加载配置,以确保更改生效。 + +**输出示例**: +假设`prompt_config.PROMPT_TEMPLATES`中包含以下内容: +```python +PROMPT_TEMPLATES = { + "llm_chat": { + "default": "你好,请问有什么可以帮助你的?" + } +} +``` +调用`get_prompt_template(type="llm_chat", name="default")`将返回字符串`"你好,请问有什么可以帮助你的?"`。 +## FunctionDef set_httpx_config(timeout, proxy) +**set_httpx_config**: 此函数用于设置httpx库的默认超时时间和代理配置。 + +**参数**: +- timeout: 浮点数类型,指定httpx请求的默认超时时间。如果未提供,则使用HTTPX_DEFAULT_TIMEOUT作为默认值。 +- proxy: 可以是字符串或字典类型,用于指定httpx请求的代理设置。如果未提供,则不使用代理。 + +**代码描述**: +此函数主要执行以下操作: +1. 修改httpx库的默认超时配置,包括连接超时、读取超时和写入超时,将它们统一设置为函数参数`timeout`指定的值。 +2. 根据`proxy`参数的类型(字符串或字典),在进程范围内设置系统级代理。如果`proxy`是字符串,则为http、https和all协议设置相同的代理地址。如果`proxy`是字典,则根据字典中的键(http、https、all)设置相应协议的代理地址。 +3. 更新系统环境变量中的`NO_PROXY`设置,以确保某些特定的主机地址(如localhost和127.0.0.1)以及通过`fschat_controller_address`、`fschat_model_worker_address`和`fschat_openai_api_address`函数获取的地址不使用代理。 +4. 重写`urllib.request.getproxies`函数,使其返回当前配置的代理设置,这一步骤确保了在使用urllib库进行网络请求时,也能应用上述代理配置。 + +**注意**: +- 在使用此函数之前,确保已经正确设置了`HTTPX_DEFAULT_TIMEOUT`变量,以便在不指定超时时间时使用。 +- 代理设置对于在需要通过代理访问外部网络资源的环境中尤为重要,但请注意,对于本地或内网资源的访问,应通过`NO_PROXY`环境变量确保直连,以避免不必要的代理延迟。 +- 此函数在项目启动时被多个模块调用,包括控制器、模型工作器、OpenAI API服务和API服务器等,以统一配置网络请求的行为。 + +**输出示例**: +此函数没有返回值,其主要作用是对环境和httpx库进行配置,因此不具有直接的输出示例。 +### FunctionDef _get_proxies +**_get_proxies**: 此函数的功能是获取代理设置。 + +**参数**: 此函数没有参数。 + +**代码描述**: `_get_proxies` 函数是一个简单的功能函数,旨在从其所在的作用域中获取代理设置。在当前的代码片段中,`_get_proxies` 函数直接返回名为 `proxies` 的变量。这意味着,此函数的实际作用和返回值完全依赖于 `proxies` 变量当前的值或状态。由于代码片段中没有提供 `proxies` 变量的定义或初始化过程,我们无法直接确定 `proxies` 的具体内容或格式。通常,代理设置是用于配置网络请求通过特定的代理服务器进行,以实现网络匿名、绕过地理限制或提高请求效率等目的。 + +**注意**: 使用此函数时,需要确保在函数被调用的作用域中已经正确定义并初始化了 `proxies` 变量。`proxies` 变量应该是一个字典类型,其中包含了代理配置的详细信息,例如代理服务器的地址和端口。如果 `proxies` 变量未被正确定义或初始化,调用此函数可能会导致错误或异常。 + +**输出示例**: 假设 `proxies` 被定义为 `{"http": "http://10.10.1.10:3128", "https": "https://10.10.1.11:1080"}`,那么调用 `_get_proxies` 函数将返回如下字典: +```python +{ + "http": "http://10.10.1.10:3128", + "https": "https://10.10.1.11:1080" +} +``` +这个返回值展示了一个典型的代理配置,其中包含了对HTTP和HTTPS请求分别使用不同代理服务器的设置。 +*** +## FunctionDef detect_device +**detect_device**: 此函数的功能是检测并返回当前环境可用的设备类型。 + +**参数**: 此函数没有参数。 + +**代码描述**: `detect_device` 函数首先尝试导入 `torch` 库,然后使用 `torch.cuda.is_available()` 方法检查CUDA设备(通常是NVIDIA GPU)是否可用。如果可用,函数返回字符串 `"cuda"`。如果CUDA设备不可用,函数接着检查是否可以使用Apple的Metal Performance Shaders (MPS) 加速,这是通过 `torch.backends.mps.is_available()` 方法实现的。如果MPS可用,函数返回字符串 `"mps"`。如果以上两种加速方式都不可用,函数将返回 `"cpu"`,表示只能使用中央处理器进行计算。此函数通过捕获所有异常来确保在任何情况下都能至少返回 `"cpu"`,保证了其健壮性。 + +在项目中,`detect_device` 函数被 `llm_device` 和 `embedding_device` 函数调用。这两个函数用于确定用于语言模型(LLM)和嵌入计算的设备。它们通过传入的设备参数来尝试指定计算设备,如果传入的设备参数不是 `"cuda"`、`"mps"` 或 `"cpu"` 中的任何一个,或者没有提供设备参数,它们将调用 `detect_device` 函数自动检测并选择一个可用的设备。这样的设计使得在不同的硬件环境下,用户无需手动配置,就能自动选择最优的计算设备,提高了代码的通用性和易用性。 + +**注意**: 在使用此函数时,需要确保 `torch` 库已正确安装,并且根据你的硬件配置(是否有NVIDIA GPU或支持MPS的Apple硬件),`torch` 库的版本应支持CUDA或MPS。 + +**输出示例**: +- 如果检测到NVIDIA GPU,函数将返回 `"cuda"`。 +- 如果检测到支持MPS的设备,函数将返回 `"mps"`。 +- 如果以上两者都不可用,函数将返回 `"cpu"`。 +## FunctionDef llm_device(device) +**llm_device**: 此函数的功能是确定并返回用于语言模型计算的设备类型。 + +**参数**: +- `device`: 一个字符串参数,用于指定计算设备。它的默认值为 `None`。 + +**代码描述**: `llm_device` 函数首先检查传入的 `device` 参数是否已经指定。如果没有指定(即为 `None`),则使用全局变量 `LLM_DEVICE` 作为设备类型。接下来,函数检查 `device` 是否为 `"cuda"`、`"mps"` 或 `"cpu"` 中的一个。如果不是,函数将调用 `detect_device` 函数自动检测当前环境中可用的设备类型。`detect_device` 函数能够检测CUDA设备(如NVIDIA GPU)、Apple的Metal Performance Shaders (MPS) 加速或者回退到CPU,确保在任何环境下都能找到一个可用的计算设备。最终,`llm_device` 函数返回确定的设备类型。 + +**注意**: +- 在调用此函数之前,确保已经根据您的硬件配置安装了支持CUDA或MPS的 `torch` 库版本,以便正确检测设备类型。 +- 此函数依赖于全局变量 `LLM_DEVICE`,确保在使用前已正确设置该变量。 +- 当自动检测设备时,如果既没有检测到CUDA设备也没有检测到MPS设备,函数将默认使用CPU。 + +**输出示例**: +- 如果指定了 `device` 为 `"cuda"` 并且环境支持,函数将返回 `"cuda"`。 +- 如果未指定 `device`,并且自动检测结果为MPS设备可用,函数将返回 `"mps"`。 +- 如果既未指定 `device` 也无法使用CUDA或MPS,函数将返回 `"cpu"`。 + +此函数在项目中的应用场景包括确定模型工作配置中的计算设备类型,以及在服务器启动信息中显示当前使用的计算设备。这确保了在不同硬件环境下,系统能够自动选择最优的计算设备,从而提高了代码的通用性和易用性。 +## FunctionDef embedding_device(device) +**embedding_device**: 此函数的功能是确定并返回用于嵌入计算的设备类型。 + +**参数**: +- device: 一个字符串参数,用于指定计算设备。默认值为None。 + +**代码描述**: `embedding_device` 函数首先检查传入的 `device` 参数是否已经指定。如果没有指定(即为None),则会使用全局变量 `EMBEDDING_DEVICE` 的值。接下来,函数检查 `device` 是否为 `"cuda"`、`"mps"` 或 `"cpu"` 中的一个。如果不是,或者 `EMBEDDING_DEVICE` 也没有提供有效的设备类型,函数将调用 `detect_device` 函数自动检测当前环境中可用的设备类型。`detect_device` 函数能够检测CUDA设备(通常是NVIDIA GPU)、Apple的Metal Performance Shaders (MPS) 加速或者回退到使用CPU。最终,`embedding_device` 函数返回确定的设备类型。 + +**注意**: 使用此函数时,需要确保相关的硬件和软件(如NVIDIA GPU或支持MPS的Apple硬件,以及对应的支持库)已经准备就绪。此外,`EMBEDDING_DEVICE` 全局变量需要在函数外部被正确设置,以便在没有明确指定设备类型时提供默认值。 + +**输出示例**: +- 如果环境中有可用的NVIDIA GPU,并且传入的 `device` 参数为 `"cuda"` 或未指定且 `EMBEDDING_DEVICE` 为 `"cuda"`,函数将返回 `"cuda"`。 +- 如果环境支持MPS加速,并且传入的 `device` 参数为 `"mps"` 或未指定且 `EMBEDDING_DEVICE` 为 `"mps"`,函数将返回 `"mps"`。 +- 如果以上两种情况都不满足,函数将返回 `"cpu"`,表示使用中央处理器进行计算。 +## FunctionDef run_in_thread_pool(func, params) +**run_in_thread_pool**: 该函数的功能是在线程池中批量运行任务,并将运行结果以生成器的形式返回。 + +**参数**: +- `func`: 需要在线程池中执行的函数,该函数应接受关键字参数。 +- `params`: 一个列表,包含字典,每个字典代表传递给`func`的关键字参数。默认为空列表。 + +**代码描述**: +`run_in_thread_pool`函数主要用于在并发环境下执行多个任务,以提高程序的执行效率。它接受一个可调用对象`func`和一个参数列表`params`。`params`中的每个元素都是一个字典,代表了需要传递给`func`的关键字参数。函数内部首先创建一个线程池`ThreadPoolExecutor`,然后遍历`params`列表,为每个参数字典创建一个线程任务,使用`pool.submit(func, **kwargs)`提交到线程池执行。这里的`**kwargs`是Python中的关键字参数展开语法,用于将字典展开为关键字参数。所有任务提交后,函数使用`as_completed`方法等待所有任务完成,并通过生成器`yield`语句返回每个任务的结果。 + +在项目中,`run_in_thread_pool`被用于不同的场景,如文件解析、文件保存等操作,这些操作都需要处理多个文件或数据,且各自操作可以独立并行执行,从而大大提高了处理效率。例如,在`_parse_files_in_thread`函数中,它用于并发地将上传的文件保存到指定目录,并处理文件内容;在`_save_files_in_thread`函数中,它用于并发地将文件保存到知识库目录;在`files2docs_in_thread`函数中,它用于并发地将磁盘文件转化为文档对象。这些调用场景表明`run_in_thread_pool`在处理IO密集型或CPU密集型任务时,能够有效地利用多线程提高程序的执行效率。 + +**注意**: +- 使用`run_in_thread_pool`时,需要确保传递给`func`的操作是线程安全的,以避免数据竞争或其他并发问题。 +- 任务函数`func`应设计为接受关键字参数,以便与`params`中的字典正确匹配。 +- 由于`run_in_thread_pool`返回一个生成器,调用此函数时需要通过迭代来获取所有任务的结果。 +## FunctionDef get_httpx_client(use_async, proxies, timeout) +**get_httpx_client**: 该函数的功能是获取配置好的httpx客户端实例,用于执行HTTP请求。 + +**参数**: +- `use_async`: 布尔类型,默认为`False`。指定返回的httpx客户端是否支持异步操作。 +- `proxies`: 字符串或字典类型,默认为`None`。用于设置代理。 +- `timeout`: 浮点数,默认为`HTTPX_DEFAULT_TIMEOUT`。设置请求超时时间。 +- `**kwargs`: 接收额外的关键字参数,这些参数将直接传递给httpx客户端实例。 + +**代码描述**: +此函数首先定义了一个默认的代理配置,该配置会绕过本地地址的代理设置。然后,它会获取一系列特定地址(例如Fastchat控制器地址、模型工作器地址和OpenAI API地址),并将这些地址添加到代理配置中,确保这些地址的请求不会通过代理。接下来,函数会从系统环境变量中读取代理设置,并合并到默认代理配置中。如果用户提供了`proxies`参数,该函数会将用户指定的代理设置合并到默认代理配置中。 + +此外,函数还支持通过`use_async`参数选择返回同步或异步的httpx客户端实例。在构造httpx客户端实例时,会将超时时间、代理配置以及任何额外的关键字参数传递给客户端构造函数。 + +如果启用了详细日志记录(`log_verbose`为`True`),函数会记录客户端实例的配置参数。 + +**注意**: +- 在使用此函数时,需要注意`proxies`参数的格式,它可以是一个字符串或字典。如果是字符串,将会被解释为所有请求的代理地址;如果是字典,可以为不同的协议指定不同的代理。 +- 确保环境变量中的代理设置是正确的,否则可能会影响到httpx客户端实例的请求。 +- 当需要执行异步HTTP请求时,应将`use_async`参数设置为`True`,以获取支持异步操作的httpx客户端实例。 + +**输出示例**: +由于此函数返回的是一个httpx客户端实例,因此输出示例取决于如何使用该实例进行HTTP请求。例如,如果使用同步客户端发起GET请求,可能会这样使用: +```python +with get_httpx_client() as client: + response = client.get('https://www.example.com') + print(response.text) +``` +如果使用异步客户端发起GET请求,则可能会这样使用: +```python +async with get_httpx_client(use_async=True) as client: + response = await client.get('https://www.example.com') + print(response.text) +``` +## FunctionDef get_server_configs +**get_server_configs**: 此函数的功能是获取服务器的配置信息,并以字典形式返回。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `get_server_configs` 函数首先从多个配置文件中导入了服务器的配置项,包括知识库、搜索引擎、向量搜索类型、分块大小、重叠大小、分数阈值、向量搜索的Top K值、搜索引擎的Top K值、中文标题增强标志、文本分割器字典、文本分割器名称、大型语言模型、历史长度、温度参数以及提示模板。此外,函数还调用了`fschat_controller_address`、`fschat_openai_api_address`和`api_address`三个函数,分别获取Fastchat控制器地址、FastChat OpenAI API地址和API服务器地址,并将这些地址信息存储在一个名为`_custom`的字典中。最后,函数通过合并`locals()`中的局部变量和`_custom`字典,构造并返回一个包含所有配置信息的字典。需要注意的是,函数在返回字典时排除了以`_`开头的局部变量。 + +**注意**: 使用此函数时,需要确保相关配置文件中的配置项已正确设置。此外,由于函数返回的配置信息可能包含敏感数据,如API地址等,因此在将这些信息提供给前端或其他服务时应谨慎处理。 + +**输出示例**: +```python +{ + "DEFAULT_KNOWLEDGE_BASE": "example_kb", + "DEFAULT_SEARCH_ENGINE": "google", + "DEFAULT_VS_TYPE": "example_vs_type", + "CHUNK_SIZE": 512, + "OVERLAP_SIZE": 50, + "SCORE_THRESHOLD": 0.5, + "VECTOR_SEARCH_TOP_K": 10, + "SEARCH_ENGINE_TOP_K": 5, + "ZH_TITLE_ENHANCE": True, + "TEXT_SPLITTER_NAME": "example_splitter", + "LLM_MODELS": ["model1", "model2"], + "HISTORY_LEN": 10, + "TEMPERATURE": 0.7, + "PROMPT_TEMPLATES": {"template1": "Example template."}, + "controller_address": "http://127.0.0.1:8080", + "openai_api_address": "http://127.0.0.1:5000/v1", + "api_address": "http://127.0.0.1:8080" +} +``` +此示例展示了函数可能返回的配置信息字典,包括各种默认配置项、模型参数、提示模板以及三个关键的API地址。实际返回的内容将根据项目配置文件中的设置而有所不同。 +## FunctionDef list_online_embed_models +**list_online_embed_models**: 此函数的功能是列出所有支持嵌入功能的在线模型名称。 + +**参数**: 此函数没有参数。 + +**代码描述**: `list_online_embed_models` 函数首先从 `list_config_llm_models` 函数获取所有配置的在线大型语言模型(LLM)的信息。然后,它遍历这些模型的配置信息,检查每个模型是否有指定的提供者(provider)并且该提供者对应的类是否存在于 `model_workers` 中。如果存在,进一步检查该类是否支持嵌入功能(通过调用 `can_embedding` 方法)。只有当这些条件都满足时,该模型的名称才会被添加到返回列表中。这意味着返回的列表中包含的模型都是可以进行嵌入操作的在线模型。 + +**注意**: 在使用此函数时,需要确保 `model_workers` 中已经定义了相应的模型提供者类,并且这些类实现了 `can_embedding` 方法。此外,由于此函数依赖于 `list_config_llm_models` 函数提供的配置信息,因此需要确保相关的配置信息是准确和最新的。 + +**输出示例**: +```python +["llm_model_online_1", "llm_model_online_2"] +``` +此输出示例展示了函数可能返回的在线模型名称列表,实际返回的内容将根据配置的在线模型和它们是否支持嵌入功能而有所不同。 + +在项目中,`list_online_embed_models` 函数被多个地方调用,包括但不限于 `embed_texts` 和 `aembed_texts` 函数,这些函数用于处理文本的向量化操作。此外,它还被 `load_kb_embeddings` 方法调用,该方法用于加载知识库的嵌入向量。这表明 `list_online_embed_models` 函数在项目中扮演着重要角色,它帮助其他组件确定哪些在线模型可以用于嵌入操作。 +## FunctionDef load_local_embeddings(model, device) +**load_local_embeddings**: 此函数的功能是从缓存中加载并返回指定模型的嵌入向量对象。 + +**参数**: +- `model`: 字符串类型,指定要加载的嵌入模型名称。如果未提供,将使用配置文件中指定的默认嵌入模型。 +- `device`: 字符串类型,指定计算设备。如果未提供,将通过`embedding_device`函数自动检测并选择合适的设备。 + +**代码描述**: +`load_local_embeddings`函数首先检查是否提供了`model`参数,如果没有提供,则使用配置文件中的默认嵌入模型名称。接着,函数调用`embeddings_pool`的`load_embeddings`方法,传入模型名称和设备类型,从而加载并返回嵌入向量对象。这个过程包括从缓存中检索嵌入向量对象,如果缓存中不存在,则会创建并加载新的嵌入向量对象。这个加载过程是线程安全的,可以避免在多线程环境下的竞争条件。 + +**注意**: +- 使用此函数时,需要确保`model`参数对应的嵌入模型已经正确配置,并且支持的设备类型(如CUDA、MPS或CPU)与运行环境相匹配。 +- 此函数依赖于`embedding_device`函数来自动检测或指定计算设备,因此需要确保相关的硬件和软件环境已经准备就绪。 +- 在多线程环境下使用此函数时,可以放心地进行调用,因为内部实现了线程安全的机制。 + +**输出示例**: +调用`load_local_embeddings(model="text-embedding-ada-002", device="cuda")`可能会返回一个已经加载了指定OpenAI嵌入模型的嵌入向量对象,该对象准备好在CUDA设备上进行嵌入向量的计算。 + +在项目中,`load_local_embeddings`函数被多个地方调用,包括但不限于`embed_texts`和`aembed_texts`函数,用于对文本进行向量化处理;以及在`ESKBService`类的初始化过程中,用于加载嵌入模型以支持Elasticsearch的向量搜索功能。此外,它还被`worker`函数用于在Faiss缓存中进行文本的添加、搜索和删除操作。这些调用场景表明,`load_local_embeddings`函数是处理本地嵌入向量加载的核心功能,支持了文本向量化、文本检索等多种应用场景。 +## FunctionDef get_temp_dir(id) +**get_temp_dir**: 该函数用于创建一个临时目录,并返回该目录的路径和文件夹名称。 + +**参数**: +- **id**: 可选参数,字符串类型。如果提供,函数将尝试在基础临时目录下创建或找到一个与之对应的子目录。 + +**代码描述**: +`get_temp_dir` 函数首先从配置文件中导入基础临时目录的路径(`BASE_TEMP_DIR`)。如果调用时提供了`id`参数,并且该`id`对应的目录已经存在于基础临时目录下,则函数将直接返回该目录的路径和名称,不会创建新的临时目录。如果没有提供`id`参数,或者提供的`id`对应的目录不存在,则函数将使用`tempfile.mkdtemp`方法在基础临时目录下创建一个新的临时目录,并返回新目录的路径和名称。 + +在项目中,`get_temp_dir`函数被`upload_temp_docs`函数调用,用于在上传文件并进行处理前,创建或找到一个临时目录来存放这些文件。这个过程中,如果提供了之前的临时目录ID(`prev_id`),则会尝试复用该目录,否则会创建一个新的临时目录。这样做可以有效地管理临时文件,避免重复创建不必要的临时目录,同时也方便后续的文件处理和向量化操作。 + +**注意**: +- 如果在多线程或多进程环境下使用该函数,请确保对临时目录的操作(如读写文件)有适当的同步机制,以避免数据竞争或文件损坏。 +- 临时目录的清理工作需要调用者自行管理,该函数不会自动删除创建的临时目录。 + +**输出示例**: +调用`get_temp_dir()`可能会返回如下形式的元组: +- (`"/tmp/base_temp_dir/abc123"`, `"abc123"`),其中`"/tmp/base_temp_dir/abc123"`是临时目录的完整路径,`"abc123"`是该目录的名称。 diff --git a/markdown_docs/server/webui_allinone_stale.md b/markdown_docs/server/webui_allinone_stale.md new file mode 100644 index 000000000..716dfdf60 --- /dev/null +++ b/markdown_docs/server/webui_allinone_stale.md @@ -0,0 +1,45 @@ +## FunctionDef launch_api(args, args_list, log_name) +**launch_api**: 此函数的功能是启动API服务。 + +**参数**: +- args: 包含API启动所需参数的对象,此对象应具备访问如api_host和api_port等属性的能力。 +- args_list: 一个字符串列表,默认值为api_args,指定了需要转换为命令行参数的键名。 +- log_name: 日志文件的名称。如果未提供,则根据API的主机名和端口动态生成。 + +**代码描述**: +`launch_api` 函数首先打印出启动API服务的提示信息,包括中英文两种语言。接着,如果没有提供`log_name`参数,函数会根据API服务的主机名和端口号生成日志文件的名称,并将其存储在预定义的日志路径下。然后,函数通过调用`string_args`函数,将`args`对象中的参数转换成命令行可接受的字符串格式。`string_args`函数的详细功能和使用方法已在相关文档中描述。 + +之后,`launch_api`函数构建了一个用于启动API服务的shell命令字符串,该字符串包含了启动脚本的名称(`api.py`)、转换后的参数字符串以及日志文件的路径。最后,使用`subprocess.run`方法执行构建的shell命令,以在后台启动API服务,并将标准输出和标准错误重定向到日志文件中。 + +在整个过程中,`launch_api`函数还会打印出日志文件的位置信息,以便于在API服务启动异常时,用户可以轻松地找到并查看日志文件。 + +**在项目中的调用关系**: +`launch_api` 函数在项目中负责启动API服务的核心功能。它通过调用`string_args`函数来处理命令行参数的转换,这显示了`launch_api`与`string_args`之间的直接依赖关系。`string_args`函数为`launch_api`提供了参数字符串化的能力,使得`launch_api`能够有效地构建用于启动API服务的shell命令。 + +**注意**: +- 确保传递给`launch_api`函数的`args`对象包含了所有必要的API启动参数,如`api_host`和`api_port`。 +- 如果`log_name`参数未提供,日志文件的命名将依赖于API服务的主机名和端口号,因此请确保这些信息的准确性。 +- 在使用`launch_api`函数时,应确保相关的API启动脚本(`api.py`)存在于预期的路径下,并且能够正确处理通过命令行传递的参数。 +## FunctionDef launch_webui(args, args_list, log_name) +**launch_webui**: 此函数的功能是启动webui服务。 + +**参数**: +- args: 包含启动webui所需参数的对象。此对象应具备访问各参数值的能力。 +- args_list: 参数列表,默认值为web_args,用于指定哪些参数需要被包含在最终生成的命令行字符串中。 +- log_name: 日志文件的名称。如果未提供,则默认使用LOG_PATH路径下的webui作为日志文件名。 + +**代码描述**: +`launch_webui` 函数主要负责启动webui服务。首先,函数打印出启动webui的提示信息,既包括英文也包括中文,以确保用户了解当前操作。接着,函数检查是否提供了`log_name`参数,如果没有提供,则使用默认的日志文件名。 + +接下来,函数调用`string_args`函数,将`args`对象中的参数转换为命令行可接受的字符串格式。这一步骤是通过检查`args`对象中的参数与`args_list`列表中指定的参数键名,生成最终的参数字符串。 + +根据`args`对象中的`nohup`参数值,`launch_webui`函数决定是否以后台模式启动webui服务。如果`nohup`为真,则构造一个命令行字符串,该字符串将webui服务的输出重定向到指定的日志文件,并在后台运行。否则,直接构造一个命令行字符串以前台模式运行webui服务。 + +最后,使用`subprocess.run`方法执行构造好的命令行字符串,启动webui服务。函数在webui服务启动后打印出完成提示信息。 + +**在项目中的调用关系**: +`launch_webui` 函数在项目中负责启动webui服务的任务。它依赖于`string_args`函数来处理命令行参数的生成。`string_args`函数根据提供的参数对象和参数列表,生成适用于命令行的参数字符串。这种设计使得`launch_webui`函数能够灵活地处理不同的启动参数,同时保持命令行参数生成逻辑的集中和一致性。 + +**注意**: +- 确保传递给`launch_webui`函数的`args`对象中包含了所有必要的参数,特别是`nohup`参数,因为它决定了webui服务是以前台模式还是后台模式运行。 +- 如果在后台模式下运行webui服务,务必检查指定的日志文件,以便于排查可能出现的启动异常。 diff --git a/markdown_docs/startup.md b/markdown_docs/startup.md new file mode 100644 index 000000000..71010ea0a --- /dev/null +++ b/markdown_docs/startup.md @@ -0,0 +1,339 @@ +## FunctionDef create_controller_app(dispatch_method, log_level) +**create_controller_app**: 此函数的功能是创建并配置一个FastAPI应用,用于作为控制器服务。 + +**参数**: +- `dispatch_method`: 字符串类型,指定消息分发的方法。 +- `log_level`: 字符串类型,默认为"INFO",用于设置日志级别。 + +**代码描述**: +此函数首先导入必要的模块和变量,包括`fastchat.constants`用于设置日志目录,以及从`fastchat.serve.controller`导入的`app`(FastAPI实例)、`Controller`类和`logger`对象。函数设置日志级别后,实例化`Controller`对象,并将其注册到`sys.modules`中,以便在整个应用中可以访问到这个控制器实例。 + +接下来,调用`MakeFastAPIOffline`函数,为FastAPI应用提供离线文档支持,这意味着Swagger UI和ReDoc文档页面不会依赖于外部CDN来加载,而是从本地提供所需的静态文件。这一步骤对于在没有外部网络连接的环境中运行应用尤其重要。 + +最后,函数设置FastAPI应用的标题为"FastChat Controller",并将之前创建的`Controller`实例作为应用的一个属性,以便在应用的其他部分中可以直接访问控制器实例。函数返回配置好的FastAPI应用实例。 + +**注意**: +- 确保在调用此函数之前,`LOG_PATH`变量已被正确设置,以便日志文件能被存储在预期的位置。 +- `MakeFastAPIOffline`函数需要确保`static_dir`参数指向的目录中包含了Swagger UI和ReDoc所需的所有静态文件,包括JavaScript、CSS文件和图标等。 + +**输出示例**: +由于此函数返回一个FastAPI应用实例,因此输出示例将是一个配置好的FastAPI对象,具有设置的日志级别、标题、控制器实例以及离线文档支持。这个FastAPI实例随后可以被用于启动Web服务,处理HTTP请求。 +## FunctionDef create_model_worker_app(log_level) +**create_model_worker_app**: 此函数的功能是创建并配置一个FastAPI应用,用于作为模型工作节点,支持不同类型的模型服务。 + +**参数**: +- `log_level`: 字符串类型,默认为"INFO",用于设置日志记录的级别。 +- `**kwargs`: 关键字参数,用于传递额外的配置选项,包括模型名称、控制器地址、工作节点地址等。 + +**代码描述**: +函数首先导入必要的模块和设置日志目录。然后,通过解析`kwargs`参数,根据提供的配置选项动态地设置应用的行为。这包括支持Langchain模型、在线API模型以及离线模型的配置。 + +对于Langchain支持的模型,不需要进行额外的配置。对于在线API模型,需要指定`worker_class`来创建相应的工作节点实例。对于离线模型,根据模型的路径、设备等信息,创建相应的工作节点实例,并配置模型的各种参数,如并行大小、内存使用限制等。 + +此外,函数还调用了`MakeFastAPIOffline`函数,为创建的FastAPI应用添加离线文档支持,确保在没有外部网络连接的环境下,也能提供完整的API文档。 + +最后,函数设置应用的标题,并将工作节点实例绑定到应用上,然后返回这个配置好的FastAPI应用实例。 + +**注意**: +- 确保传递给函数的`kwargs`参数中包含了正确的配置信息,如模型名称、控制器地址等,以便正确地初始化模型工作节点。 +- 使用此函数创建的FastAPI应用已经配置了离线文档支持,无需额外配置即可在离线环境下访问API文档。 + +**输出示例**: +由于此函数返回一个FastAPI应用实例,因此输出示例将取决于具体的配置和使用场景。一般来说,返回的FastAPI应用实例可以直接用于启动一个Web服务,提供模型推理等API接口。例如,如果配置了一个支持Langchain模型的工作节点,那么返回的应用将提供相应的API接口,允许客户端通过HTTP请求进行模型推理操作。 +## FunctionDef create_openai_api_app(controller_address, api_keys, log_level) +**create_openai_api_app**: 此函数的功能是创建并配置一个FastAPI应用,用于提供OpenAI API服务。 + +**参数**: +- `controller_address`: 字符串类型,控制器的地址。 +- `api_keys`: 字符串列表,默认为空列表,用于存放API密钥。 +- `log_level`: 字符串类型,默认为"INFO",用于设置日志级别。 + +**代码描述**: +首先,函数通过修改`fastchat.constants.LOGDIR`变量来设置日志目录。接着,导入`app`和`CORSMiddleware`以及`app_settings`对象,用于FastAPI应用的配置。使用`build_logger`函数创建一个日志记录器,设置其日志级别为传入的`log_level`参数。 + +函数为FastAPI应用添加了一个中间件`CORSMiddleware`,配置了跨源资源共享(CORS)策略,允许所有来源、方法和头部的请求。这是为了确保不同的客户端可以无障碍地与API进行交互。 + +通过修改`sys.modules`中的`logger`对象,将自定义的日志记录器应用于OpenAI API服务器模块。此外,将`controller_address`和`api_keys`参数分别赋值给`app_settings`对象的相应属性,用于配置API服务的控制器地址和API密钥。 + +调用`MakeFastAPIOffline`函数使得FastAPI应用支持离线文档,这意味着Swagger UI和ReDoc文档页面不依赖于外部CDN加载,而是从本地服务器提供。这对于在没有外部网络连接的环境中运行API服务尤为重要。 + +最后,设置FastAPI应用的标题为"FastChat OpenAI API Server",并返回配置好的FastAPI应用对象。 + +**注意**: +- 确保传入的`controller_address`有效,因为它是API服务与控制器通信的关键。 +- 在部署API服务时,考虑到安全性,应当仔细管理`api_keys`列表,避免泄露密钥。 +- 调整`log_level`参数可以控制日志的详细程度,有助于调试和监控API服务的状态。 + +**输出示例**: 由于此函数返回一个FastAPI应用对象,因此输出示例取决于FastAPI框架的实现。通常,返回的对象可以用于启动一个Web服务器,提供RESTful API服务。 +## FunctionDef _set_app_event(app, started_event) +**_set_app_event**: 该函数用于为FastAPI应用设置启动事件。 + +**参数**: +- **app**: FastAPI的实例,表示当前的FastAPI应用。 +- **started_event**: 可选参数,默认为None。它是一个multiprocessing.Event的实例,用于跨进程通信,标记应用是否已启动。 + +**代码描述**: +此函数主要用于在FastAPI应用中注册一个启动事件。当FastAPI应用启动时,如果传入的`started_event`不为None,则会调用`started_event.set()`方法,这通常用于在多进程环境下通知其他进程应用已经准备就绪。 + +在项目中,`_set_app_event`函数被多个不同的启动函数调用,包括`run_controller`、`run_model_worker`、`run_openai_api`和`run_api_server`。这些启动函数分别用于启动不同的服务组件,如控制器服务、模型工作节点、OpenAI API接口和API服务器。在这些函数中,`_set_app_event`通过将FastAPI应用实例和一个可选的`started_event`作为参数传入,来确保在服务组件启动时,相关的启动事件能够被正确设置和触发。 + +通过这种方式,`_set_app_event`函数在项目中扮演了一个重要的角色,它确保了在多进程或分布式环境下,各个服务组件能够协调启动,从而提高了系统的稳定性和响应能力。 + +**注意**: +- 在使用`_set_app_event`函数时,需要确保传入的`app`参数是一个有效的FastAPI应用实例。 +- 如果在多进程环境下使用,`started_event`参数应该是一个通过`multiprocessing.Event`创建的事件实例,这样可以确保跨进程的正确通信。 +- 该函数通过装饰器`@app.on_event("startup")`注册启动事件,因此只有在FastAPI应用启动时,注册的事件处理函数`on_startup`才会被执行。 +### FunctionDef on_startup +**on_startup**: 此函数的功能是在应用启动时设置一个事件标志。 + +**参数**: 此函数没有参数。 + +**代码描述**: `on_startup` 函数是一个异步函数,旨在应用启动时执行特定的操作。函数体内部首先检查全局变量 `started_event` 是否不为 `None`。如果该条件为真,即 `started_event` 已经被定义且不为 `None`,则调用 `started_event.set()` 方法。这个方法的调用将会设置一个事件标志,通常用于指示应用已经成功启动或某个初始化过程已经完成。在多线程或异步编程中,事件标志常用于同步不同部分的执行流程,确保在继续执行其他操作之前,某些关键的初始化步骤已经完成。 + +**注意**: 使用此函数时,需要确保 `started_event` 已经在某处被正确初始化为一个事件对象。此外,由于这是一个异步函数,调用它时需要使用 `await` 关键字或在其他异步上下文中调用。这确保了函数内的异步操作能够被正确处理。 +*** +## FunctionDef run_controller(log_level, started_event) +**run_controller**: 此函数的功能是启动一个FastAPI应用,用于控制和管理模型工作节点。 + +**参数**: +- `log_level`: 字符串类型,默认为"INFO",用于设置日志级别。 +- `started_event`: 可选参数,默认为None。它是一个multiprocessing.Event的实例,用于跨进程通信,标记应用是否已启动。 + +**代码描述**: +首先,函数导入了必要的模块,包括`uvicorn`用于运行ASGI应用,`httpx`用于HTTP客户端请求,`fastapi`中的`Body`用于请求体解析,以及`time`和`sys`模块。接着,调用`set_httpx_config`函数设置httpx库的默认超时时间和代理配置。 + +函数通过调用`create_controller_app`函数创建一个FastAPI应用实例,该实例配置了消息分发方法和日志级别。然后,使用`_set_app_event`函数为FastAPI应用设置启动事件,如果传入了`started_event`参数,则在应用启动时标记事件。 + +在FastAPI应用中添加了一个`/release_worker`的POST接口,用于释放和加载模型工作节点。此接口接收模型名称、新模型名称和是否保留原模型的参数,通过与模型工作节点通信来实现模型的切换或释放。 + +最后,根据配置的主机地址和端口号,以及日志级别,使用`uvicorn.run`函数启动FastAPI应用。如果日志级别设置为"ERROR",则将标准输出和错误输出重定向到系统默认的输出和错误流。 + +**注意**: +- 在启动控制器服务之前,确保已经正确配置了`FSCHAT_CONTROLLER`字典中的`host`和`port`,以及其他相关设置。 +- `set_httpx_config`函数的调用是为了确保在与模型工作节点通信时,请求的超时时间和代理设置符合项目需求。 +- `/release_worker`接口的实现依赖于`app._controller`对象的`list_models`和`get_worker_address`方法,这些方法需要在`create_controller_app`函数中正确初始化。 + +**输出示例**: +由于此函数主要负责启动FastAPI应用并不直接返回数据,因此没有直接的输出示例。但是,一旦应用启动成功,它将开始监听指定的主机地址和端口号,等待接收HTTP请求。 +### FunctionDef release_worker(model_name, new_model_name, keep_origin) +**release_worker**: 此函数的功能是释放当前正在使用的模型,并根据需要加载新模型。 + +**参数**: +- `model_name`: 字符串类型,默认值为`Body(...)`。此参数指定要释放的模型的名称。 +- `new_model_name`: 字符串类型,默认值为`None`。此参数指定释放当前模型后要加载的新模型的名称。 +- `keep_origin`: 布尔类型,默认值为`False`。此参数指定在加载新模型时是否保留原有模型。 + +**代码描述**: +首先,函数通过调用`app._controller.list_models()`获取当前可用的模型列表。如果指定的`new_model_name`已存在于可用模型列表中,则记录信息并返回错误代码500,表示模型切换失败。 + +如果`new_model_name`不为空,函数将记录开始切换模型的信息;如果为空,则记录即将停止模型的信息。接着,检查`model_name`是否在可用模型列表中,如果不在,则记录错误并返回错误代码500,表示指定的模型不可用。 + +函数通过`app._controller.get_worker_address(model_name)`获取要释放的模型的地址。如果地址获取失败,则记录错误并返回错误代码500。 + +使用`get_httpx_client()`函数获取httpx客户端实例,并向模型的地址发送POST请求,请求内容包括新模型的名称和是否保留原模型的标志。如果请求状态码不是200,表示模型释放失败,记录错误并返回错误代码500。 + +如果指定了`new_model_name`,函数将等待新模型注册完成。使用循环检查新模型是否已注册,如果在超时时间内注册成功,则记录成功信息并返回成功代码200;如果超时仍未注册成功,则记录错误并返回错误代码500。 + +如果没有指定`new_model_name`,则直接记录模型释放成功的信息并返回成功代码200。 + +**注意**: +- 在使用此函数时,确保提供的模型名称正确且模型确实存在于系统中。 +- 当`new_model_name`不为空时,此函数不仅会释放指定的模型,还会尝试加载新模型。因此,需要确保新模型名称正确且模型文件已准备好。 +- `keep_origin`参数允许在加载新模型时保留原模型,这在需要同时运行多个模型的场景中非常有用。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "sucess to release model: chatglm-6b" +} +``` +或者在发生错误时: +```json +{ + "code": 500, + "msg": "the model chatglm-6b is not available" +} +``` +*** +## FunctionDef run_model_worker(model_name, controller_address, log_level, q, started_event) +**run_model_worker**: 此函数的功能是启动模型工作节点,用于处理模型推理请求。 + +**参数**: +- `model_name`: 字符串类型,默认为`LLM_MODELS`列表中的第一个元素,指定要启动的模型名称。 +- `controller_address`: 字符串类型,默认为空字符串,指定控制器的地址。 +- `log_level`: 字符串类型,默认为"INFO",指定日志记录的级别。 +- `q`: `mp.Queue`类型,可选参数,默认为None,用于进程间通信的队列。 +- `started_event`: `mp.Event`类型,可选参数,默认为None,用于标记模型工作节点启动完成的事件。 + +**代码描述**: +函数首先导入必要的模块,包括`uvicorn`、`fastapi`等,并设置httpx库的配置。然后,通过调用`get_model_worker_config`函数获取模型工作节点的配置信息,包括主机地址、端口号等,并根据`model_name`动态设置模型路径和其他相关配置。 + +接着,使用`create_model_worker_app`函数创建一个FastAPI应用实例,该实例根据提供的参数和配置信息进行初始化。如果`log_level`设置为"ERROR",则将标准输出和错误输出重定向到系统默认的输出和错误流。 + +函数还定义了一个`release_model`接口,允许通过HTTP POST请求释放当前加载的模型并可选地加载新模型。该接口接收新模型名称和是否保留原模型的参数,并通过向`q`队列发送指令来控制模型的加载和释放。 + +最后,使用`uvicorn.run`函数启动FastAPI应用,监听指定的主机地址和端口号,提供模型推理服务。 + +**注意**: +- 确保传入的`model_name`在配置中正确定义,以便加载正确的模型和配置信息。 +- 如果在多进程环境下使用,`q`和`started_event`参数应通过`multiprocessing`模块创建,以实现进程间的正确通信。 +- `controller_address`参数允许指定控制器的地址,如果为空,则会尝试使用默认的控制器地址。 + +**输出示例**: +由于此函数主要负责启动FastAPI应用并不直接返回数据,因此没有直接的输出示例。但在成功启动后,FastAPI应用将在指定的主机地址和端口号上监听HTTP请求,提供模型推理服务。例如,如果配置的主机地址为`127.0.0.1`,端口号为`8000`,则可以通过`http://127.0.0.1:8000`访问该服务的API接口。 +### FunctionDef release_model(new_model_name, keep_origin) +**release_model**: 该函数的功能是根据参数决定是否保留原模型并加载新模型或替换原模型。 + +**参数**: +- **new_model_name**: 字符串类型,默认值为None。该参数用于指定要加载的新模型名称。 +- **keep_origin**: 布尔类型,默认值为False。该参数用于指定是否保留原模型。如果为True,则加载新模型时保留原模型;如果为False,则替换原模型或停止当前模型。 + +**代码描述**: +该函数接受两个参数:`new_model_name`和`keep_origin`。`new_model_name`用于指定要操作的模型名称,而`keep_origin`决定了是保留原有模型还是替换原有模型。函数内部逻辑如下: +- 如果`keep_origin`为True,并且提供了`new_model_name`,则将模型名称、"start"操作和新模型名称放入队列`q`中,表示启动新模型的同时保留原模型。 +- 如果`keep_origin`为False,有两种情况: + - 如果提供了`new_model_name`,则将模型名称、"replace"操作和新模型名称放入队列`q`中,表示替换当前模型为新模型。 + - 如果没有提供`new_model_name`,则将模型名称、"stop"操作和None放入队列`q`中,表示停止当前模型。 +- 函数最后返回一个字典,包含操作结果的状态码和消息,状态码200表示操作成功。 + +**注意**: +- 确保在调用此函数时,队列`q`已经被正确初始化并且可以被访问。 +- 在实际应用中,需要根据实际情况调整`new_model_name`和`keep_origin`的值以满足不同的模型管理需求。 +- 函数返回的状态码和消息可以用于进一步的逻辑处理或用户反馈。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "done" +} +``` +该输出示例表示操作已成功完成。 +*** +## FunctionDef run_openai_api(log_level, started_event) +**run_openai_api**: 此函数的功能是启动OpenAI API服务。 + +**参数**: +- `log_level`: 字符串类型,默认为"INFO"。用于设置日志级别。 +- `started_event`: 可选参数,默认为None。它是一个multiprocessing.Event的实例,用于跨进程通信,标记服务是否已启动。 + +**代码描述**: +函数首先导入必要的模块,包括`uvicorn`用于运行ASGI应用,`sys`用于系统级操作,以及项目内部的`set_httpx_config`函数用于配置HTTP客户端。接着,调用`set_httpx_config`函数来设置HTTP客户端的配置。 + +通过调用`fschat_controller_address`函数获取控制器的地址,然后使用此地址和`log_level`参数调用`create_openai_api_app`函数创建一个FastAPI应用实例。如果存在`started_event`参数,则通过调用`_set_app_event`函数将此事件与应用实例关联,以便在应用启动时标记事件。 + +接下来,从配置中读取`FSCHAT_OPENAI_API`字典的`host`和`port`字段,用于指定服务的主机地址和端口号。如果`log_level`被设置为"ERROR",则将标准输出和错误输出重定向回系统默认的输出和错误流,这主要用于减少日志输出的详细程度。 + +最后,使用`uvicorn.run`函数启动FastAPI应用,传入之前创建的应用实例、主机地址和端口号作为参数。 + +**注意**: +- 确保`FSCHAT_OPENAI_API`配置中的`host`和`port`字段已正确设置,因为它们决定了服务的网络地址和端口。 +- 在多进程环境下使用`started_event`参数可以帮助其他进程了解OpenAI API服务是否已经准备就绪。 +- 调整`log_level`参数可以控制日志输出的详细程度,有助于在不同的环境中调试和监控服务状态。 +- 此函数在项目的启动流程中被`start_main_server`函数调用,作为启动OpenAI API服务的一部分。 +## FunctionDef run_api_server(started_event, run_mode) +Doc is waiting to be generated... +## FunctionDef run_webui(started_event, run_mode) +**run_webui**: 此函数用于启动Web UI服务器。 + +**参数**: +- `started_event`: 一个`mp.Event`类型的参数,默认为None。用于在进程间同步,标识Web UI服务器启动完成。 +- `run_mode`: 字符串类型的参数,默认为None。用于指定运行模式,特别是在“lite”模式下运行时的特殊配置。 + +**代码描述**: +此函数首先导入`server.utils`模块中的`set_httpx_config`函数,并调用它来设置httpx库的配置,包括默认超时时间和代理配置。接着,函数从全局配置中获取Web UI服务器的主机地址和端口号。然后,构建一个命令行命令列表,该列表包含了启动Streamlit服务器所需的所有参数,包括服务器地址、端口号以及主题相关的配置。如果`run_mode`参数被设置为"lite",则会向命令行参数中添加额外的配置,以适应轻量级运行模式。最后,使用`subprocess.Popen`启动Streamlit进程,并通过`started_event.set()`通知其他进程Web UI服务器已启动,然后等待该进程结束。 + +**注意**: +- 在调用此函数之前,应确保`WEBUI_SERVER`字典中已正确配置了Web UI服务器的`host`和`port`。 +- 此函数依赖于Streamlit库来启动Web UI,因此需要确保Streamlit已安装在环境中。 +- 通过`run_mode`参数,可以灵活地控制Web UI的运行模式,例如在资源受限的环境下使用"lite"模式以减少资源消耗。 +- 此函数在项目的启动流程中被调用,特别是在需要启动Web UI界面时。例如,在`start_main_server`函数中,根据命令行参数决定是否启动Web UI服务器,并通过进程间事件同步机制来确保Web UI服务器启动完成后再继续执行其他任务。 +## FunctionDef parse_args +**parse_args**: 此函数的功能是解析命令行参数,并返回解析后的参数和解析器对象。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `parse_args` 函数使用 `argparse` 库创建一个解析器对象,用于解析命令行参数。它定义了多个命令行参数,每个参数都有其对应的选项(如`-a`、`--all-webui`等),作用(如启动服务器、指定模型名称等),以及存储目的地(如`dest="all_webui"`)。这些参数支持不同的操作模式和配置,以适应不同的运行需求。例如,`--all-webui` 参数会启动包括 API 和 Web UI 在内的全部服务,而 `--model-name` 参数允许用户指定一个或多个模型名称。函数最后调用 `parser.parse_args()` 解析命令行输入的参数,并返回解析后的参数和解析器对象。 + +在项目中,`parse_args` 函数被 `start_main_server` 函数调用。`start_main_server` 函数根据 `parse_args` 返回的参数来决定启动哪些服务和模式。例如,如果指定了 `--all-webui` 参数,那么 `start_main_server` 将启动包括 OpenAI API、模型工作器、API 服务器和 Web UI 在内的所有服务。这种设计使得服务的启动和管理更加灵活和可配置。 + +**注意**: 使用此函数时,需要确保命令行参数的正确性和合理性,因为它们直接影响到服务的启动和运行模式。另外,考虑到 `argparse` 的使用,此函数的调用环境应为命令行界面或兼容命令行参数的环境。 + +**输出示例**: 假设命令行输入为 `python startup.py --all-webui`,则 `parse_args` 函数可能返回的 `args` 对象将包含属性 `all_webui=True`,而其他属性根据定义的默认值或命令行输入进行设置。同时,返回的 `parser` 对象可用于进一步的参数解析或帮助信息的显示。 +## FunctionDef dump_server_info(after_start, args) +**dump_server_info**: 此函数的功能是打印服务器配置和状态信息。 + +**参数**: +- `after_start`: 布尔类型,用于指示是否在服务器启动后调用此函数。默认值为False。 +- `args`: 一个可选参数,包含命令行参数对象。默认值为None。 + +**代码描述**: +`dump_server_info` 函数首先导入所需的模块和函数,包括平台信息、项目版本、以及服务器的API和WEBUI地址等。接着,函数打印出操作系统、Python版本、项目版本以及langchain和fastchat的版本信息。此外,函数还会根据传入的`args`参数(如果有的话),选择性地打印出当前使用的分词器、启动的LLM模型、以及嵌入模型的信息。 + +如果`args`参数中指定了模型名称,则只打印该模型的配置信息;否则,打印所有LLM模型的配置信息。此配置信息通过调用`get_model_worker_config`函数获取,该函数负责加载指定模型的工作配置。 + +在服务器启动后(即`after_start`为True时),函数会额外打印服务器运行信息,包括OpenAI API服务器、Chatchat API服务器和Chatchat WEBUI服务器的地址。这些地址信息通过`fschat_openai_api_address`、`api_address`和`webui_address`函数获取。 + +**注意**: +- 确保在调用此函数之前,所有相关的配置(如项目版本、模型配置等)已经正确设置。 +- 此函数主要用于在服务器启动时或启动后,向终端打印配置和状态信息,以便于开发者和管理员了解当前服务器的运行状况。 +- `args`参数中的模型名称、是否开启API或WEBUI等选项,将影响函数打印的信息内容。因此,在使用此函数时,应根据实际情况传递正确的参数。 +## FunctionDef start_main_server +Doc is waiting to be generated... +### FunctionDef handler(signalname) +**handler**: handler函数的功能是创建并返回一个处理特定信号的闭包函数。 + +**参数**: +- signalname: 该参数指定了需要处理的信号名称。 + +**代码描述**: +handler函数接收一个参数signalname,该参数用于指定需要处理的信号名称。函数内部定义了一个闭包函数f,该闭包函数接收两个参数:signal_received和frame。当接收到指定的信号时,闭包函数会抛出一个KeyboardInterrupt异常,并附带一条消息,表明接收到了哪种信号。 + +值得注意的是,Python 3.9版本引入了`signal.strsignal(signalnum)`方法,因此在该版本及以后,本函数可能不再需要。同样,Python 3.8版本引入了`signal.valid_signals()`方法,可以用来创建相同目的的映射,进一步减少了对此类自定义处理函数的需求。 + +**注意**: +- 使用此函数时,需要确保传入的signalname是有效且可以被程序捕获的信号名称。 +- 抛出的KeyboardInterrupt异常需要在程序的更高层级被捕获和处理,以实现优雅的信号处理逻辑。 +- 由于Python版本的不同,开发者应当根据自己使用的Python版本决定是否需要使用此函数。 + +**输出示例**: +假设调用`handler("SIGINT")`并将返回的闭包函数注册为SIGINT信号的处理函数,当SIGINT信号被触发时,程序将抛出以下异常: +``` +KeyboardInterrupt: SIGINT received +``` +#### FunctionDef f(signal_received, frame) +**f**: 此函数的功能是在接收到特定信号时抛出一个`KeyboardInterrupt`异常。 + +**参数**: +- `signal_received`: 接收到的信号。 +- `frame`: 当前栈帧的引用。 + +**代码描述**: +函数`f`设计用于处理操作系统发送的信号。当操作系统向Python程序发送一个信号时,该函数将被调用。函数接收两个参数:`signal_received`和`frame`。`signal_received`参数代表接收到的信号,而`frame`参数是对当前栈帧的引用,尽管在此函数体内未直接使用。 + +函数的主要行为是抛出一个`KeyboardInterrupt`异常。这是通过`raise`关键字实现的,它用于引发指定的异常。在这种情况下,异常是`KeyboardInterrupt`,这通常用于响应用户的中断操作,如按下Ctrl+C。异常消息中包含了一个字符串,该字符串应该是`signalname`加上"received"的形式,但在提供的代码中,`signalname`并未定义,这可能是一个错误或遗漏。正确的做法应该是在异常消息中明确指出接收到的是哪种信号,例如通过将`signal_received`参数的值转换为对应的信号名称。 + +**注意**: +- 在使用此函数时,需要确保`signal_received`参数能够正确表示接收到的信号类型。此外,考虑到`signalname`在代码中未定义,需要修正异常消息以正确反映接收到的信号。 +- 该函数设计用于在接收到特定信号时优雅地中断程序。然而,抛出`KeyboardInterrupt`异常可能会被上层代码捕获和处理,因此应当在设计程序时考虑到这一点。 +- 在多线程环境中使用信号处理函数时应当小心,因为Python的信号处理主要是在主线程中执行的。 +*** +*** +### FunctionDef process_count +**process_count**: 此函数的功能是计算当前进程总数。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `process_count` 函数旨在计算系统中当前的进程总数。它首先通过访问全局变量 `processes` 来获取进程信息。`processes` 是一个字典,其中包含不同类型的进程列表,例如 `online_api` 和 `model_worker`。函数通过计算 `processes` 字典的长度,加上 `online_api` 列表的长度和 `model_worker` 列表的长度,然后减去2,来得出总进程数。减去2的操作可能是为了调整某些预设的或者非动态计算的进程数。 + +**注意**: 使用此函数时,需要确保全局变量 `processes` 已经被正确初始化,并且包含了 `online_api` 和 `model_worker` 这两个键。此外,减去的数字2应根据实际情况进行调整,以确保进程计数的准确性。 + +**输出示例**: 假设 `processes` 字典包含3个主进程,`online_api` 列表包含2个进程,`model_worker` 列表包含3个进程,那么 `process_count` 函数的返回值将是: + +``` +3 + 2 + 3 - 2 = 6 +``` + +这意味着系统当前总共有6个进程在运行。 +*** diff --git a/markdown_docs/text_splitter/ali_text_splitter.md b/markdown_docs/text_splitter/ali_text_splitter.md new file mode 100644 index 000000000..5c0f6af0d --- /dev/null +++ b/markdown_docs/text_splitter/ali_text_splitter.md @@ -0,0 +1,65 @@ +## ClassDef AliTextSplitter +**AliTextSplitter**: AliTextSplitter类的功能是对文本进行分割,特别是针对PDF文档或其他文本,可以选择是否使用文档语义分割模型进行更加精确的文本分割。 + +**属性**: +- `pdf`: 布尔值,指示是否对PDF文档进行特殊处理,默认为False。 +- `**kwargs`: 接收可变数量的关键字参数,这些参数将传递给父类CharacterTextSplitter的构造函数。 + +**代码描述**: +AliTextSplitter类继承自CharacterTextSplitter类,提供了对文本进行分割的功能。在初始化时,可以通过`pdf`参数指定是否对PDF文档进行特殊处理。如果`pdf`为True,会对文本进行预处理,包括合并多余的换行符和空格,以及移除连续的换行符,以便于后续的文本分割处理。 + +在`split_text`方法中,首先根据`pdf`参数的值对文本进行预处理。然后尝试导入`modelscope.pipelines`模块,如果导入失败,会抛出`ImportError`异常,提示用户需要安装`modelscope`包。 + +使用`modelscope.pipelines`的`pipeline`函数创建一个文档分割任务,模型选择为`damo/nlp_bert_document-segmentation_chinese-base`,并指定设备为CPU。通过调用`pipeline`对象的方法对文本进行分割,得到的结果是一个包含分割后文本的列表。 + +**注意**: +- 使用此类之前,需要确保已安装`modelscope`包,特别是如果要进行文档语义分割,需要安装`modelscope[nlp]`。 +- 文档语义分割模型`damo/nlp_bert_document-segmentation_chinese-base`是基于BERT的中文文档分割模型,对于中文文本有较好的分割效果。 +- 在低配置的GPU环境下,由于模型较大,建议将设备设置为CPU进行文本分割处理,以避免可能的性能问题。 + +**输出示例**: +```python +['这是第一段文本。', '这是第二段文本,包含多个句子。', '这是第三段文本。'] +``` +此输出示例展示了`split_text`方法返回的分割后的文本列表,每个元素代表文档中的一段文本。 +### FunctionDef __init__(self, pdf) +**__init__**: 此函数的功能是初始化AliTextSplitter类的实例。 + +**参数**: +- `pdf`: 一个布尔值,用于指定是否处理PDF文件,默认值为False。 +- `**kwargs`: 接收一个可变数量的关键字参数,这些参数将传递给父类的初始化方法。 + +**代码描述**: +此初始化函数是`AliTextSplitter`类的构造函数,用于创建类的实例时设置初始状态。它接受一个名为`pdf`的参数和多个关键字参数`**kwargs`。`pdf`参数用于指示`AliTextSplitter`实例是否将用于处理PDF文件,其默认值为False,表示默认不处理PDF文件。如果需要处理PDF文件,则在创建`AliTextSplitter`实例时将此参数设置为True。 + +此外,通过`**kwargs`参数,此函数支持接收额外的关键字参数,这些参数不在函数定义中直接声明。这些额外的参数通过`super().__init__(**kwargs)`语句传递给父类的初始化方法。这种设计允许`AliTextSplitter`类在不修改其构造函数签名的情况下,灵活地扩展或修改其父类的行为。 + +**注意**: +- 在使用`AliTextSplitter`类时,应根据实际需求决定是否将`pdf`参数设置为True。如果您的应用场景中需要处理PDF文件,则应将此参数设置为True。 +- 通过`**kwargs`传递给父类的参数应确保与父类的初始化方法兼容,避免传递无效或不相关的参数,以免引发错误。 +*** +### FunctionDef split_text(self, text) +**split_text**: 该函数的功能是对文本进行语义分割。 + +**参数**: +- text: 需要进行分割的文本,数据类型为字符串(str)。 + +**代码描述**: +`split_text`函数主要用于对给定的文本进行语义上的分割。它首先检查是否存在`self.pdf`属性,如果存在,会对文本进行预处理,包括合并过多的换行符、将所有空白字符替换为单个空格以及删除连续的换行符。这一步骤旨在清理PDF文档中常见的格式问题,以便于后续的文档分割。 + +接下来,函数尝试导入`modelscope.pipelines`模块,该模块提供了一个`pipeline`函数,用于加载并执行特定的NLP任务。如果导入失败,会抛出`ImportError`异常,提示用户需要安装`modelscope`包。 + +在成功导入`modelscope.pipelines`后,函数使用`pipeline`函数创建一个文档分割任务,指定使用的模型为`damo/nlp_bert_document-segmentation_chinese-base`,并将计算设备设置为CPU。这个模型基于BERT,由阿里巴巴达摩院开源,专门用于中文文档的语义分割。 + +最后,函数将输入文本传递给模型进行分割,并将分割结果(一个包含分割后文本的列表)返回。分割结果是通过将模型输出的文本按`\n\t`分割,并过滤掉空字符串后得到的。 + +**注意**: +- 使用该函数前,需要确保已经安装了`modelscope[nlp]`包。可以通过执行`pip install "modelscope[nlp]" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html`来安装。 +- 由于使用了基于BERT的模型进行文档分割,对计算资源有一定要求。默认情况下,模型会在CPU上运行,但如果有足够的GPU资源,可以通过修改`device`参数来加速计算。 + +**输出示例**: +```python +['欢迎使用文档分割功能', '这是第二段文本', '这是第三段文本'] +``` +此输出示例展示了`split_text`函数处理后的结果,其中输入文本被分割成了三段,每段文本作为列表的一个元素返回。 +*** diff --git a/markdown_docs/text_splitter/chinese_recursive_text_splitter.md b/markdown_docs/text_splitter/chinese_recursive_text_splitter.md new file mode 100644 index 000000000..fd5cb85b5 --- /dev/null +++ b/markdown_docs/text_splitter/chinese_recursive_text_splitter.md @@ -0,0 +1,101 @@ +## FunctionDef _split_text_with_regex_from_end(text, separator, keep_separator) +**_split_text_with_regex_from_end**: 该函数的功能是使用正则表达式从文本末尾开始分割文本。 + +**参数**: +- text: 需要被分割的文本,类型为str。 +- separator: 用作分割符的正则表达式,类型为str。 +- keep_separator: 一个布尔值,指示是否保留分隔符在返回的列表中。 + +**代码描述**: +此函数接受一个字符串`text`和一个正则表达式`separator`作为参数,以及一个布尔值`keep_separator`,用于控制分割后是否保留分隔符。如果`separator`不为空,函数将根据`separator`分割文本。如果`keep_separator`为真,则分隔符也会被保留在返回的列表中。这是通过将文本与分隔符一起分割,然后将分割后的文本和分隔符重新组合成新的列表项来实现的。如果分割后的列表长度为奇数,表示最后一个元素后没有分隔符,这时会将最后一个元素添加到结果列表中。如果`keep_separator`为假,则简单地根据分隔符分割文本,不保留分隔符。如果`separator`为空,则将文本分割成单个字符的列表。最后,函数返回一个列表,包含非空的分割结果。 + +在项目中,这个函数被`ChineseRecursiveTextSplitter`类的`_split_text`方法调用。`_split_text`方法用于递归地分割文本,根据一系列分隔符逐步将文本分割成更小的块。`_split_text_with_regex_from_end`函数在这个过程中负责使用正则表达式从文本末尾开始进行分割,这是实现文本递归分割的关键步骤之一。通过调整`keep_separator`参数,可以灵活控制分隔符在分割结果中的保留情况,这对于保持文本的原始结构信息是非常有用的。 + +**注意**: +- 确保传入的`separator`是有效的正则表达式,否则`re.split`可能无法正确执行分割操作。 +- 如果文本非常长,使用复杂的正则表达式作为分隔符可能会影响性能。 + +**输出示例**: +假设有以下调用: +```python +_split_text_with_regex_from_end("hello,world,this,is,a,test", ",", True) +``` +可能的返回值为: +```python +["hello,", "world,", "this,", "is,", "a,", "test"] +``` +在这个示例中,文本被逗号分割,并且每个分割后的部分都保留了逗号。 +## ClassDef ChineseRecursiveTextSplitter +**ChineseRecursiveTextSplitter**: 该类的功能是对中文文本进行递归分割。 + +**属性**: +- `separators`: 分隔符列表,用于指定文本分割的规则。 +- `keep_separator`: 布尔值,指定在分割后的文本中是否保留分隔符。 +- `is_separator_regex`: 布尔值,指定分隔符列表中的元素是否为正则表达式。 + +**代码描述**: +ChineseRecursiveTextSplitter类继承自RecursiveCharacterTextSplitter,专门用于处理中文文本的递归分割。它允许用户自定义分隔符列表,以及控制是否保留分隔符和分隔符是否按正则表达式处理。默认的分隔符列表包括常见的中文和英文句子结束符号,如句号、问号、感叹号等。此类通过递归调用`_split_text`方法,能够有效地将长文本分割成更小的片段,同时保证分割后的文本片段不会过长或过短,适合进一步的文本处理或分析。 + +在分割文本时,`_split_text`方法首先确定使用的分隔符,然后根据这个分隔符将文本分割成小片段。如果某个片段长度超过预设的阈值,该方法会递归地对该片段进行进一步分割,直到所有片段的长度都符合要求。最终,方法返回一个经过清理(去除多余的换行符和空白字符)的文本片段列表。 + +**注意**: +- 在使用自定义分隔符时,如果`is_separator_regex`设置为`False`,则需要确保分隔符列表中的元素不包含任何正则表达式特殊字符,或者使用`re.escape`进行转义。 +- 该类适用于处理中文文本,但也支持包含英文句子的文本分割,通过提供适当的分隔符列表可以灵活应对不同的文本分割需求。 + +**输出示例**: +```python +text_splitter = ChineseRecursiveTextSplitter() +text = "这是一个测试文本。包含多个句子!还有英文句子. Yes, it works well." +split_texts = text_splitter.split(text) +# 输出可能为: ['这是一个测试文本。', '包含多个句子!', '还有英文句子.', 'Yes, it works well.'] +``` +在此示例中,`split`方法将输入的文本根据中文和英文的句子结束符号进行分割,返回一个包含四个独立句子的列表。这显示了ChineseRecursiveTextSplitter类在处理混合语言文本时的灵活性和有效性。 +### FunctionDef __init__(self, separators, keep_separator, is_separator_regex) +**__init__**: 该函数的功能是创建一个新的文本分割器。 + +**参数**: +- **separators**: 可选参数,类型为`List[str]`。用于指定分割文本的分隔符列表。如果未提供,则使用默认分隔符列表。 +- **keep_separator**: 布尔类型参数,默认值为`True`。指定在分割文本后,是否保留分隔符。 +- **is_separator_regex**: 布尔类型参数,默认值为`True`。指定分隔符列表中的分隔符是否应被视为正则表达式。 +- **kwargs**: 接收任意额外的关键字参数,这些参数将被传递给父类的初始化方法。 + +**代码描述**: +此函数是`ChineseRecursiveTextSplitter`类的构造函数,用于初始化一个文本分割器实例。它首先调用父类的初始化方法,传递`keep_separator`和任何其他关键字参数(`**kwargs`)。然后,它根据提供的参数初始化内部变量。如果`separators`参数未提供,将使用一个默认的分隔符列表,该列表包括常见的中文和英文句子结束符号,如句号、问号、感叹号及其各自的空格组合形式,以及中文的逗号和分号。`_is_separator_regex`变量用于标记分隔符列表中的元素是否应被视为正则表达式,以便在分割文本时使用。 + +**注意**: +- 在使用默认分隔符时,由于包含正则表达式,可以匹配多种常见的句子结束符号及其后的空格,这对于处理包含多种标点符号的文本非常有用。 +- 如果选择不保留分隔符(`keep_separator=False`),则分割后的文本将不包含任何分隔符。这可能对某些需要精确控制输出格式的应用场景有影响。 +- 当`is_separator_regex`设置为`False`时,分隔符列表中的字符串将被直接用作分割文本的依据,而不是作为正则表达式解析,这在处理非常特定的分隔符需求时可能更为有用。 +*** +### FunctionDef _split_text(self, text, separators) +**_split_text**: 该函数的功能是根据一系列分隔符递归地分割文本,并返回分割后的文本块列表。 + +**参数**: +- text: 需要被分割的文本,类型为str。 +- separators: 用于分割文本的分隔符列表,类型为List[str]。 + +**代码描述**: +`_split_text`函数首先确定使用哪个分隔符来分割文本。它通过遍历`separators`列表并检查每个分隔符是否存在于文本中来实现。一旦找到第一个匹配的分隔符,函数就使用这个分隔符来分割文本,并将后续的分隔符列表更新为新的`new_separators`列表,用于后续的递归分割。 + +分割文本的实际操作是通过调用`_split_text_with_regex_from_end`函数完成的,该函数使用正则表达式从文本末尾开始分割文本。这一步骤允许保留或移除分隔符,具体取决于`_keep_separator`的值。 + +接下来,函数会检查分割后的每个文本块的长度。如果文本块的长度小于设定的`_chunk_size`,则将其添加到结果列表中。对于长度超过`_chunk_size`的文本块,函数会尝试使用`new_separators`列表中的下一个分隔符递归地分割这些文本块。 + +最后,函数返回一个经过清理的文本块列表,其中移除了所有空白文本块,并将连续的换行符替换为单个换行符。 + +**注意**: +- 确保`separators`列表中的分隔符是有效的,且按照从最优先到最不优先的顺序排列。 +- 函数内部使用正则表达式进行文本分割,因此分隔符需要是有效的正则表达式,或者在不使用正则表达式分割时,分隔符将被自动转义。 +- 递归分割可能会导致大量的函数调用,特别是在处理大型文本或复杂的分隔符模式时,应注意性能和栈溢出的风险。 + +**输出示例**: +假设有以下调用: +```python +_split_text("这是一个测试文本。这还是一个测试文本!", ["。", "!"]) +``` +可能的返回值为: +```python +["这是一个测试文本", "这还是一个测试文本"] +``` +在这个示例中,文本被"。"和"!"分隔符分割,每个分割后的部分都是独立的文本块。 +*** diff --git a/markdown_docs/text_splitter/chinese_text_splitter.md b/markdown_docs/text_splitter/chinese_text_splitter.md new file mode 100644 index 000000000..25167a999 --- /dev/null +++ b/markdown_docs/text_splitter/chinese_text_splitter.md @@ -0,0 +1,102 @@ +## ClassDef ChineseTextSplitter +**ChineseTextSplitter**: 该类的功能是对中文文本进行分句处理,特别优化了对PDF文本的处理以及长句的分割。 + +**属性**: +- `pdf`: 布尔值,指示是否对PDF文本进行特殊处理,默认为False。 +- `sentence_size`: 整数,定义了句子的最大长度,超过这个长度的句子将被进一步分割,默认值为250。 + +**代码描述**: +ChineseTextSplitter类继承自CharacterTextSplitter,专门用于处理中文文本的分句。它提供了两个主要的方法:`split_text1`和`split_text`,用于不同的分句逻辑。 + +- `split_text1`方法主要处理PDF文本,通过正则表达式去除多余的换行和空格,然后使用特定的分句符号进行分句。这个方法适用于简单的分句需求。 +- `split_text`方法提供了更复杂的分句逻辑,不仅处理PDF文本的特殊格式,还对长句进行了细致的分割处理。它首先使用标点符号进行初步分句,然后针对超过`sentence_size`属性定义的长度的句子,进行进一步的分割,确保每个句子的长度都不会超过设定的最大值。 + +这两个方法共同支持了对中文文本的高效和灵活的分句处理,特别是在处理PDF来源的文本和长句时,展现了很好的适应性和精确性。 + +**注意**: +- 在使用`split_text`方法进行文本分割时,应注意`sentence_size`属性的设置,以避免过长或过短的句子影响后续处理。 +- 对于PDF文本,建议开启`pdf`属性,以获得更好的分句效果。 +- 此类的分句规则主要基于中文标点符号,对于包含大量英文或其他特殊格式文本的处理可能需要额外的调整。 + +**输出示例**: +```python +splitter = ChineseTextSplitter(pdf=True, sentence_size=250) +text = "这是一个测试文本。这个文本包含多个句子,用于测试。" +result = splitter.split_text(text) +print(result) +``` +假设输出为: +```python +["这是一个测试文本。", "这个文本包含多个句子,用于测试。"] +``` +这个示例展示了如何使用`ChineseTextSplitter`类对一个包含两个句子的文本进行分割,得到一个句子列表作为输出。 +### FunctionDef __init__(self, pdf, sentence_size) +**__init__**: 该函数用于初始化ChineseTextSplitter类的实例。 + +**参数**: +- `pdf`: 一个布尔值,用于指定是否处理PDF文件,默认为False。 +- `sentence_size`: 一个整数,用于指定句子的最大长度,默认为250。 +- `**kwargs`: 接收可变数量的关键字参数,这些参数将传递给父类的初始化方法。 + +**代码描述**: +`__init__`方法是ChineseTextSplitter类的构造函数,用于创建类的实例时初始化其属性。它接收三个参数:`pdf`、`sentence_size`和`**kwargs`。`pdf`参数用于指示是否处理PDF文件,其默认值为False,表示默认不处理PDF文件。`sentence_size`参数用于指定分割文本时每个句子的最大长度,默认值为250个字符。`**kwargs`是一个可变关键字参数,允许传递额外的参数给父类的构造函数,这在类的继承体系中非常有用,以确保父类也能被正确初始化。 + +在方法体内,首先通过`super().__init__(**kwargs)`调用父类的构造函数,确保父类的初始化逻辑得到执行。然后,将`pdf`和`sentence_size`参数的值分别赋值给实例变量`self.pdf`和`self.sentence_size`,这样在类的其他方法中就可以通过这些实例变量访问到这些值了。 + +**注意**: +- 在使用ChineseTextSplitter类时,应根据实际需求设置`pdf`和`sentence_size`参数。如果需要处理的是PDF文件,则应将`pdf`参数设置为True。 +- `sentence_size`参数应根据目标文本的特性和处理需求来调整,以达到最佳的文本分割效果。 +- 通过`**kwargs`传递给父类的参数应确保与父类的构造函数兼容,避免传递无效或错误的参数。 +*** +### FunctionDef split_text1(self, text) +**split_text1**: 此函数的功能是对中文文本进行分句处理。 + +**参数**: +- `text`: 需要分句处理的文本,类型为字符串。 + +**代码描述**: +`split_text1` 函数首先检查对象是否有 `pdf` 属性。如果有,它会对文本进行预处理,包括将连续三个或更多的换行符替换为单个换行符、将所有空白字符替换为单个空格,并删除连续的两个换行符。这些预处理步骤旨在简化文本结构,为分句做准备。 + +接下来,函数使用正则表达式定义了一个分句模式 `sent_sep_pattern`,该模式能够识别中文文本中的句子结束标志,包括常见的中文标点符号(如句号、问号、感叹号等)及其后可能跟随的引号。这个模式是分句的核心,它能够准确地识别出句子的边界。 + +函数接着通过 `sent_sep_pattern.split(text)` 方法将文本分割成多个片段。然后,它遍历这些片段,根据片段是否匹配分句模式来决定是将片段添加到新句子中,还是作为一个新句子独立出来。这个过程最终生成了一个句子列表 `sent_list`,包含了文本中所有独立的句子。 + +**注意**: +- 该函数假设输入的文本是中文,并且特别针对中文标点进行了分句处理。如果输入的文本不是中文,或者使用了非中文的标点符号,分句的效果可能不理想。 +- 函数的分句效果受正则表达式 `sent_sep_pattern` 的准确性影响,可能需要根据具体的文本内容调整正则表达式以达到最佳效果。 + +**输出示例**: +假设输入文本为:"今天天气真好。我们去公园玩吧!你同意吗?",函数的返回值可能如下: +```python +["今天天气真好。", "我们去公园玩吧!", "你同意吗?"] +``` +这个示例展示了如何将包含多个句子的文本分割成单独的句子列表,每个句子作为列表的一个元素。 +*** +### FunctionDef split_text(self, text) +**split_text**: 此函数的功能是将文本分割成句子列表。 + +**参数**: +- `text`: 需要分割的文本,类型为字符串。 + +**代码描述**: +此函数首先检查是否存在`pdf`属性,如果存在,则对文本进行预处理,包括合并多余的换行符、将所有空白字符替换为单个空格以及删除连续的换行符。接下来,函数使用正则表达式对文本进行分句处理。这包括处理单字符断句符(如句号、问号等)、英文和中文的省略号,并考虑双引号后的终止符作为句子的结束。此外,如果段落末尾有多余的换行符,也会被去除。 + +对于超过设定句子长度(`self.sentence_size`)的文本,函数进一步细化分割逻辑,包括对逗号、句号后的文本进行分割,以及处理连续的空格或换行符。这一过程可能会递归进行,以确保没有任何单个句子超过设定的长度限制。 + +最后,函数返回一个列表,其中包含分割后的所有句子,且每个句子都不为空且长度不超过设定的句子大小。 + +**注意**: +- 函数的分句逻辑主要基于中文文本的特点,但也适用于包含英文句号、逗号等标点的文本。 +- 对于特殊格式的文本(如PDF文档中的文本),可能需要先进行预处理以优化分句效果。 +- 分句的精确度受正则表达式的设计影响,可能需要根据实际文本内容调整正则表达式以达到最佳效果。 + +**输出示例**: +假设`self.sentence_size`设定为100,对于输入文本: +``` +"这是第一句。这是第二句,包含,逗号。这是一个超过设定长度的句子,因此需要被进一步分割。" +``` +函数可能返回如下列表: +``` +["这是第一句。", "这是第二句,包含,逗号。", "这是一个超过设定长度的句子,", "因此需要被进一步分割。"] +``` +*** diff --git a/markdown_docs/text_splitter/zh_title_enhance.md b/markdown_docs/text_splitter/zh_title_enhance.md new file mode 100644 index 000000000..a2fb41e3c --- /dev/null +++ b/markdown_docs/text_splitter/zh_title_enhance.md @@ -0,0 +1,52 @@ +## FunctionDef under_non_alpha_ratio(text, threshold) +**under_non_alpha_ratio**: 此函数用于检查文本片段中非字母字符的比例是否超过给定阈值。 + +**参数**: +- text: 需要测试的输入字符串。 +- threshold: 如果非字母字符的比例超过此阈值,则函数返回False。 + +**代码描述**: +`under_non_alpha_ratio`函数主要用于过滤掉那些可能被错误标记为标题或叙述文本的字符串,例如包含大量非字母字符(如"-----------BREAK---------")的字符串。该函数通过计算输入文本中非空格且为字母的字符占非空格字符总数的比例,来判断该比例是否低于给定的阈值。如果是,则认为文本中非字母字符的比例过高,函数返回False。值得注意的是,空格字符在计算总字符数时被忽略。 + +在项目中,`under_non_alpha_ratio`函数被`is_possible_title`函数调用,用于判断一个文本是否可能是一个有效的标题。`is_possible_title`函数通过一系列规则(如文本长度、文本末尾是否有标点符号、文本中非字母字符的比例等)来判断文本是否可能是标题。在这个过程中,`under_non_alpha_ratio`函数负责检查文本中非字母字符的比例是否超过了设定的阈值(默认为0.5),这是判断文本是否可能是标题的重要条件之一。 + +**注意**: +- 如果输入的文本为空,或者在计算比例时发生任何异常(例如除以零的情况),函数将返回False。 +- 函数的阈值参数是可配置的,可以根据实际情况调整,默认值为0.5。 + +**输出示例**: +假设有一个文本`"Hello, World!"`,调用`under_non_alpha_ratio("Hello, World!")`将返回False,因为该文本中字母字符的比例高于默认阈值0.5。而对于文本`"-----BREAK-----"`,调用`under_non_alpha_ratio("-----BREAK-----")`则可能返回True,因为非字母字符的比例超过了阈值。 +## FunctionDef is_possible_title(text, title_max_word_length, non_alpha_threshold) +**is_possible_title**: 此函数用于检查文本是否符合作为有效标题的所有条件。 + +**参数**: +- text: 要检查的输入文本。 +- title_max_word_length: 标题可以包含的最大单词数,默认为20。 +- non_alpha_threshold: 文本被认为是标题所需的最小字母字符比例,默认为0.5。 + +**代码描述**: +`is_possible_title`函数通过一系列条件来判断给定的文本是否可能是一个有效的标题。首先,如果文本长度为0,即文本为空,则直接返回False,表示这不是一个标题。其次,如果文本以标点符号结束,也被认为不是标题。此外,如果文本的长度超过了设定的最大单词数(默认为20),或者文本中非字母字符的比例超过了设定的阈值(通过调用`under_non_alpha_ratio`函数检查),则同样认为不是标题。函数还会检查文本是否以逗号、句号结束,或者文本是否全为数字,这些情况下文本也不会被认为是标题。最后,函数检查文本开头的5个字符中是否包含数字,如果不包含,则认为这不是一个标题。 + +**注意**: +- 函数中使用了正则表达式来检查文本是否以标点符号结束,这是判断文本是否可能是标题的一个条件。 +- 在判断文本长度是否超过最大单词数时,简单地基于空格进行分割,而没有使用复杂的词语分词方法,这是出于性能考虑。 +- `under_non_alpha_ratio`函数被用于计算文本中非字母字符的比例,以帮助判断文本是否可能是标题。 + +**输出示例**: +假设有一个文本`"这是一个可能的标题"`,调用`is_possible_title("这是一个可能的标题")`将返回True,因为该文本满足所有作为标题的条件。而对于文本`"这不是标题。"`,调用`is_possible_title("这不是标题。")`则会返回False,因为它以标点符号结束。 +## FunctionDef zh_title_enhance(docs) +**zh_title_enhance**: 此函数的功能是增强文档集中的标题,并对后续文档内容进行相应的标注。 + +**参数**: +- docs: 一个Document对象,代表需要处理的文档集。 + +**代码描述**: +`zh_title_enhance`函数首先检查传入的文档集`docs`是否为空。如果不为空,它遍历每个文档,使用`is_possible_title`函数来判断当前文档的`page_content`是否可能是一个有效的标题。如果是,它会将当前文档的`metadata`中的`category`设置为`'cn_Title'`,并将该文档的`page_content`作为标题保存。对于随后的文档,如果已经找到了标题,它会在这些文档的`page_content`前添加一段文本,说明这部分内容与之前找到的标题有关。如果传入的文档集为空,则会打印出“文件不存在”的提示。 + +**注意**: +- 此函数依赖于`is_possible_title`函数来判断一个文档内容是否可以作为标题。`is_possible_title`函数根据文本的特征(如长度、标点符号结束、数字比例等)来判断文本是否可能是标题。 +- 函数修改了传入的Document对象,为可能的标题文档添加了元数据标记,并且修改了后续文档的内容以反映它们与找到的标题的关系。 +- 如果文档集为空,函数不会执行任何操作,只会打印提示信息。 + +**输出示例**: +假设传入的文档集包含两个文档,第一个文档的`page_content`是一个有效的标题,第二个文档是正文内容。处理后,第一个文档的`metadata`将包含`{'category': 'cn_Title'}`,而第二个文档的`page_content`将被修改为“下文与(有效标题)有关。原始正文内容”。 diff --git a/markdown_docs/webui_pages/dialogue/dialogue.md b/markdown_docs/webui_pages/dialogue/dialogue.md new file mode 100644 index 000000000..2d7e59b0e --- /dev/null +++ b/markdown_docs/webui_pages/dialogue/dialogue.md @@ -0,0 +1,228 @@ +## FunctionDef get_messages_history(history_len, content_in_expander) +**get_messages_history**: 此函数的功能是获取消息历史记录。 + +**参数**: +- `history_len`: 指定要获取的消息历史记录的长度。 +- `content_in_expander`: 一个布尔值,控制是否返回expander元素中的内容,默认为False。 + +**代码描述**: +`get_messages_history`函数用于从聊天框中筛选并返回指定长度的消息历史记录。它接受两个参数:`history_len`和`content_in_expander`。`history_len`参数指定了需要获取的历史消息的数量,而`content_in_expander`参数控制是否包含expander元素中的内容。这个功能在导出消息历史时特别有用,因为用户可以选择是否需要expander中的额外信息。 + +函数内部,定义了一个名为`filter`的内部函数,用于筛选每条消息中符合条件的内容。它首先筛选出消息元素中输出方法为"markdown"或"text"的内容,然后根据`content_in_expander`参数的值决定是否包含在expander中的内容。最后,将筛选出的内容拼接成字符串,作为消息的内容返回。 + +`get_messages_history`函数通过调用`chat_box.filter_history`方法,并传入`history_len`和`filter`函数作为参数,返回经过筛选的消息历史记录。每条记录包含消息的角色(发送者)和内容。 + +在项目中,此函数被`dialogue_page`函数调用,用于在用户与系统进行交互时获取历史对话记录。这使得系统能够根据过去的交流提供更加个性化和上下文相关的回复。 + +**注意**: +- 当`content_in_expander`设置为True时,返回的消息历史将包含expander元素中的内容,这可能会增加返回数据的大小。 +- 此函数依赖于`chat_box`对象的`filter_history`方法,因此需要确保`chat_box`对象已正确初始化并包含有效的消息历史数据。 + +**输出示例**: +```python +[ + { + "role": "user", + "content": "你好,我想了解更多关于AI的信息。" + }, + { + "role": "ai", + "content": "当然,AI是人工智能的简称,它能够执行很多复杂的任务。" + } +] +``` +此示例展示了一个可能的输出,包含两条消息记录,一条来自用户,另一条来自AI,每条记录都包含发送者的角色和消息内容。 +### FunctionDef filter(msg) +**filter**: 此函数的功能是过滤并整理消息内容。 + +**参数**: +- msg: 包含消息元素的字典,其中“elements”是一个列表,列表中的每个元素都是一个对象,这些对象包含消息的内容和输出方式等信息。 + +**代码描述**: +此函数首先遍历`msg["elements"]`列表,筛选出其中`_output_method`属性值为"markdown"或"text"的元素。这一步骤确保了只有以Markdown或纯文本形式输出的消息内容被选中。接着,如果`content_in_expander`变量不存在或其值为`False`(此处代码中未显示`content_in_expander`的定义,可能是外部变量或前文已定义),则进一步筛选出不在折叠区域(expander)内的消息内容。最后,将筛选出的元素中的内容(`x.content`)提取出来,组成一个新的列表。 + +函数返回一个字典,包含两个键值对: +- "role":直接从输入的`msg`字典中获取其"role"值,表示消息的角色。 +- "content":将上述筛选并提取出的内容列表中的元素用两个换行符`\n\n`连接成一个字符串,表示最终整理好的消息内容。 + +**注意**: +- 确保输入的`msg`字典中包含"elements"键,且其值为一个列表,列表中的元素包含`_output_method`和`content`属性。 +- 此函数未处理`content_in_expander`变量可能未定义的情况,使用时需确保该变量在上下文中有明确的定义和值。 +- 函数的处理逻辑依赖于消息元素的属性,确保消息元素对象有`_output_method`、`_in_expander`和`content`属性。 + +**输出示例**: +假设输入的`msg`字典如下: +```python +{ + "role": "user", + "elements": [ + {"_output_method": "markdown", "content": "Hello, world!", "_in_expander": False}, + {"_output_method": "text", "content": "How are you?", "_in_expander": True} + ] +} +``` +则函数的返回值可能为: +```python +{ + "role": "user", + "content": "Hello, world!" +} +``` +这表示经过筛选,只有不在折叠区域内且输出方式为markdown或text的消息内容被整理并返回。 +*** +## FunctionDef upload_temp_docs(files, _api) +**upload_temp_docs**: 该函数用于将文件上传到临时目录,用于文件对话,并返回临时向量库ID。 + +**参数**: +- `files`: 需要上传的文件列表。 +- `_api`: ApiRequest 类的实例,用于执行与 API 服务器的交互。 + +**代码描述**: +`upload_temp_docs` 函数接收一个文件列表和一个 ApiRequest 类的实例作为参数。它通过调用 `_api` 实例的 `upload_temp_docs` 方法来上传文件到服务器的临时目录,并用于后续的文件对话处理。上传成功后,服务器会返回一个包含临时向量库ID的响应。该函数通过链式调用 `.get("data", {}).get("id")` 来从响应中提取临时向量库ID,并将其返回。 + +在项目中,`upload_temp_docs` 函数被 `dialogue_page` 函数调用,用于实现文件对话功能。用户可以通过上传文件,将文件内容作为知识库的一部分,进而在对话中引用文件内容进行问答。这在处理需要引用大量文档内容的对话场景中非常有用。 + +**注意**: +- 确保 `_api` 参数是一个有效的 ApiRequest 实例,且已正确配置 API 服务器的基础 URL。 +- 上传的文件列表 `files` 应包含有效的文件路径或文件对象,以便函数能够正确处理并上传文件。 + +**输出示例**: +假设上传文件成功,服务器返回的响应如下: +```json +{ + "code": 200, + "msg": "成功", + "data": { + "id": "temp_vector_library_id_123456" + } +} +``` +则该函数的返回值将是字符串 `"temp_vector_library_id_123456"`,表示临时向量库的ID。 +## FunctionDef parse_command(text, modal) +**parse_command**: 此函数用于解析用户输入的自定义命令,并根据命令执行相应的操作。 + +**参数**: +- text: 用户输入的文本,类型为字符串。 +- modal: 一个Modal对象,用于在需要时展示模态对话框。 + +**代码描述**: +`parse_command`函数主要负责处理用户在对话界面中输入的特定命令。这些命令包括创建新会话(`/new`)、删除会话(`/del`)、清除会话内容(`/clear`)以及查看帮助信息(`/help`)。函数首先通过正则表达式匹配用户输入的命令格式,如果匹配成功,则根据命令类型执行相应的操作。 + +- `/help`命令会触发模态对话框的打开,展示可用命令的帮助信息。 +- `/new`命令用于创建一个新的会话。如果用户没有指定会话名称,则自动生成一个默认名称。如果指定的会话名称已存在,则显示错误信息。 +- `/del`命令用于删除一个指定的会话。如果没有指定会话名称,则默认删除当前会话。如果是最后一个会话或指定的会话不存在,则显示错误信息。 +- `/clear`命令用于清除指定会话的聊天历史。如果没有指定会话名称,则默认清除当前会话的聊天历史。 + +该函数与项目中的`dialogue_page`函数紧密相关。在`dialogue_page`函数中,用户的输入首先通过`parse_command`函数进行处理,以判断是否为自定义命令。如果是,根据命令执行相应操作并重新渲染页面;如果不是自定义命令,则按照正常的对话流程继续处理用户的输入。 + +**注意**: +- 在使用此函数时,需要确保`modal`对象已正确初始化,以便在需要时能够展示帮助信息等模态对话框。 +- 函数依赖于全局状态(如`st.session_state`)来管理会话信息,因此在调用此函数之前应确保相关状态已正确设置。 + +**输出示例**: +假设用户输入了`/help`命令,函数将返回`True`,并触发帮助信息的模态对话框展示。如果用户输入的是非命令文本,如“你好”,函数将返回`False`。 +## FunctionDef dialogue_page(api, is_lite) +**dialogue_page**: 此函数用于处理对话页面的逻辑,包括初始化会话、处理用户输入、展示对话历史等。 + +**参数**: +- `api`: ApiRequest 类的实例,用于执行与 API 服务器的交互。 +- `is_lite`: 布尔类型,默认为False,指示是否为轻量级模式。 + +**代码描述**: +`dialogue_page`函数是对话系统的核心,负责处理用户与系统的交互。函数首先初始化会话状态,包括会话ID和文件聊天ID。然后,根据是否为首次访问,展示欢迎信息并初始化聊天框。接着,函数处理自定义命令的帮助信息,并在侧边栏中提供对话模式、LLM模型选择、Prompt模板选择等配置选项。 + +函数中还包含了对不同对话模式(如LLM对话、知识库问答、文件对话等)的处理逻辑,以及对用户输入的处理。用户输入的文本首先检查是否为自定义命令,如果是,则执行相应的命令;如果不是,则根据当前的对话模式调用相应的API进行处理,并展示回复。 + +此外,函数还处理了对话历史的展示、反馈的收集以及对话记录的导出等功能。在处理完所有逻辑后,如果需要,函数会触发页面的重新渲染。 + +**注意**: +- 确保传入的`api`参数是有效的ApiRequest实例,且已正确配置API服务器的地址。 +- 函数依赖于多个全局变量和函数,如`chat_box`、`get_messages_history`等,需要确保这些依赖在调用`dialogue_page`之前已正确初始化。 +- 函数中的模态对话框、侧边栏配置和对话历史展示等UI元素的实现依赖于Streamlit库,确保在使用此函数时已正确设置Streamlit环境。 + +**输出示例**: +由于`dialogue_page`函数主要负责处理页面逻辑并直接与用户交互,而不直接返回数据,因此没有具体的返回值示例。函数执行的结果是在Web UI上展示对话界面,处理用户输入,并根据不同的对话模式和用户操作展示相应的回复或执行相应的命令。 +### FunctionDef on_feedback(feedback, message_id, history_index) +**on_feedback**: 此函数用于处理用户的反馈信息。 + +**参数**: +- `feedback`: 用户反馈的内容,是一个字典,其中至少包含`text`键,表示反馈的原因。 +- `message_id`: 字符串类型,默认为空字符串,指定需要反馈的消息ID。 +- `history_index`: 整型,默认为-1,表示在聊天历史中的索引位置。 + +**代码描述**: +`on_feedback`函数主要负责处理用户对聊天对话的反馈。它首先从`feedback`参数中提取用户的反馈原因,存储在变量`reason`中。然后,调用`chat_box.set_feedback`方法,将用户的反馈内容和历史索引作为参数传递,此方法返回一个整数`score_int`,代表反馈的评分。接下来,函数利用`api.chat_feedback`方法,将`message_id`、`score_int`(评分)和`reason`(反馈原因)作为参数提交给服务器。此过程中,`api.chat_feedback`方法的作用是向服务器发送POST请求,提交用户的反馈信息,具体包括消息ID、评分和评分原因。最后,函数设置`st.session_state["need_rerun"]`为`True`,这是为了通知系统需要重新运行,以便更新用户界面或执行其他必要的更新操作。 + +**注意**: +- 确保`feedback`参数中包含有效的反馈原因。 +- `message_id`和`history_index`参数虽然有默认值,但在实际使用中应根据需要提供具体值,以确保反馈能准确关联到特定的消息。 +- 此函数的执行会触发与服务器的交互,因此需要注意网络状态和服务器响应。 +- 设置`st.session_state["need_rerun"]`为`True`是为了确保用户界面能够根据最新的反馈信息进行更新,开发者在使用此函数时应考虑到这一点。 +*** +### FunctionDef on_mode_change +**on_mode_change**: 此函数用于处理对话模式变更时的响应逻辑。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `on_mode_change` 函数首先从 `st.session_state` 中获取当前对话模式 (`dialogue_mode`),并根据这个模式生成一条提示信息。如果当前模式是 "知识库问答",函数会进一步检查是否已选择了知识库 (`selected_kb`)。如果已选择知识库,提示信息会包含当前选中的知识库名称。最后,使用 `st.toast` 方法显示这条提示信息。 + +具体来说,函数执行的步骤如下: +1. 从 `st.session_state` 中获取 `dialogue_mode` 的值,这代表了当前的对话模式。 +2. 根据获取的模式,生成基本的提示信息,格式为 "已切换到 {mode} 模式。"。 +3. 如果当前模式为 "知识库问答",则尝试从 `st.session_state` 中获取 `selected_kb` 的值,即当前选中的知识库。 +4. 如果存在选中的知识库,提示信息会追加 "当前知识库:`{cur_kb}`。",以告知用户当前正在使用的知识库。 +5. 使用 `st.toast` 方法显示最终的提示信息。 + +**注意**: +- 此函数依赖于 `st.session_state` 来获取当前对话模式和选中的知识库,因此在调用此函数之前,确保 `dialogue_mode` 和 `selected_kb`(如果在知识库问答模式下)已经被正确设置。 +- `st.toast` 方法用于在界面上显示临时消息,这意味着提示信息会在短时间后自动消失,不会干扰用户的正常操作。 +*** +### FunctionDef on_llm_change +**on_llm_change**: 此函数用于处理语言模型变更事件。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: 当语言模型(Large Language Model,简称LLM)发生变更时,`on_llm_change`函数首先检查当前选中的模型(`llm_model`)是否存在。如果存在,它会通过调用`api.get_model_config(llm_model)`获取该模型的配置信息。此处的`api.get_model_config`函数是从`webui_pages/utils.py/ApiRequest/get_model_config`中调用的,其主要功能是获取服务器上指定模型的配置信息。 + +如果获取到的模型配置信息中`"online_api"`字段不存在,即判断为只有本地的`model_worker`可以切换模型,那么函数会将当前模型名称`llm_model`保存到`st.session_state["prev_llm_model"]`中,以便记录上一个模型。无论模型是否可以切换,当前选中的模型名称都会被保存到`st.session_state["cur_llm_model"]`中,这样可以确保系统记录了用户的最新选择。 + +**注意**: +- 本函数依赖于`st.session_state`来存储和跟踪语言模型的变更状态,因此需要确保在调用此函数之前已正确初始化`st.session_state`。 +- 函数的执行依赖于外部API的响应,因此网络状况和服务器状态可能会影响到函数的执行结果。 +- 由于函数内部没有直接的错误处理逻辑,如果`api.get_model_config`调用失败或返回的配置信息不符合预期,可能需要在调用此函数的上层逻辑中进行相应的错误处理。 +*** +### FunctionDef llm_model_format_func(x) +**llm_model_format_func**: 此函数的功能是格式化模型名称,如果模型正在运行中,则在模型名称后添加 "(Running)" 标记。 + +**参数**: +- **x**: 字符串类型,代表模型的名称。 + +**代码描述**: +`llm_model_format_func` 函数接收一个参数 `x`,这个参数是一个字符串,代表了模型的名称。函数首先会检查这个名称是否存在于 `running_models` 列表中,这个列表包含了当前正在运行的模型名称。如果 `x` 存在于 `running_models` 中,函数会返回模型名称后追加 " (Running)" 的字符串,以此来表示该模型当前正在运行。如果 `x` 不在 `running_models` 列表中,函数则直接返回传入的模型名称。 + +**注意**: +- 确保在调用此函数之前,`running_models` 列表已经被正确初始化并包含了所有当前正在运行的模型名称。 +- 此函数的返回值依赖于 `running_models` 列表的当前状态,因此在使用此函数格式化模型名称前,请确保 `running_models` 列表是最新的。 + +**输出示例**: +- 假设 `running_models` 包含 "Model_A",调用 `llm_model_format_func("Model_A")` 将返回 "Model_A (Running)"。 +- 如果 `running_models` 不包含 "Model_B",调用 `llm_model_format_func("Model_B")` 将返回 "Model_B"。 +*** +### FunctionDef prompt_change +**prompt_change**: 此函数的功能是显示一个提示信息,通知用户已经成功切换到了指定的模板。 + +**参数**: 此函数没有参数。 + +**代码描述**: `prompt_change` 函数首先定义了一个文本变量 `text`,该变量包含了一条格式化的消息,指出了当前已切换到的模板名称。这里使用了一个未在代码段中直接定义的变量 `prompt_template_name`,该变量应该在函数调用前被定义,且包含了模板的名称。接着,函数使用 `st.toast` 方法显示了一个短暂的通知,其内容为 `text` 变量中的消息。`st.toast` 方法是用于在界面上显示临时消息的一种方式,常用于反馈操作结果给用户。 + +**注意**: 在使用 `prompt_change` 函数之前,确保变量 `prompt_template_name` 已经被正确定义并且包含了有效的模板名称。此外,此函数依赖于 `st.toast` 方法,该方法是 Streamlit 库的一部分,因此确保你的项目中已经正确安装并导入了 Streamlit。此函数适用于需要向用户反馈模板切换操作结果的场景。 +*** +### FunctionDef on_kb_change +**on_kb_change**: 此函数的功能是在知识库更改时显示一个通知。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `on_kb_change` 函数是一个没有参数的函数,用于在用户界面上显示一个临时通知。当知识库(Knowledge Base,简称KB)发生变化时,此函数被触发。它使用 `st.toast` 方法来显示一个通知,通知内容包括“已加载知识库:”以及当前选中的知识库名称。这里的 `st.session_state.selected_kb` 是一个会话状态变量,用于存储当前选中的知识库名称。`st.toast` 方法是一个简单而有效的方式,用于在用户界面上向用户提供即时反馈。 + +**注意**: 使用此函数时,需要确保 `st.session_state` 中有 `selected_kb` 这一项,并且其值为当前选中的知识库名称。此外,考虑到 `st.toast` 显示的通知是临时的,确保这种反馈方式适合您的应用场景。如果需要更持久的通知方式,可能需要考虑其他UI元素。 +*** diff --git a/markdown_docs/webui_pages/knowledge_base/knowledge_base.md b/markdown_docs/webui_pages/knowledge_base/knowledge_base.md new file mode 100644 index 000000000..800f367d2 --- /dev/null +++ b/markdown_docs/webui_pages/knowledge_base/knowledge_base.md @@ -0,0 +1,76 @@ +## FunctionDef config_aggrid(df, columns, selection_mode, use_checkbox) +**config_aggrid**: 此函数用于配置AG Grid网格视图的选项,以展示和操作pandas DataFrame数据。 + +**参数**: +- `df`: pd.DataFrame类型,表示需要在AG Grid中展示的数据。 +- `columns`: 字典类型,默认为空字典。用于自定义列的配置,键为列名和表头的元组,值为该列的配置字典。 +- `selection_mode`: 字面量类型,可选值为"single"、"multiple"或"disabled",默认为"single"。用于配置行选择模式。 +- `use_checkbox`: 布尔类型,表示是否在行选择时使用复选框。 + +**代码描述**: +此函数首先基于传入的DataFrame `df` 创建一个GridOptionsBuilder实例。接着,为编号列"No"配置宽度为40。然后,遍历`columns`参数中的每一列配置,应用这些自定义配置到相应的列上。此外,函数还配置了行选择功能,包括选择模式、是否使用复选框以及预选中的行。最后,配置了分页功能,包括启用分页、设置自动分页大小为关闭以及每页显示的行数为10。函数返回配置好的GridOptionsBuilder实例。 + +在项目中,`config_aggrid`函数被`knowledge_base_page`函数调用,用于在知识库页面中展示知识库文件的详细信息。通过配置AG Grid,用户可以在网页上查看知识库文件的列表,包括文件名、文档加载器、文档数量等信息,并且可以根据配置选择单个或多个文件进行操作。 + +**注意**: +- 在使用此函数时,确保传入的DataFrame `df` 已正确准备,且`columns`参数中的列名与DataFrame中的列名相匹配。 +- 根据实际需求调整行选择模式和是否使用复选框,以适应不同的用户交互场景。 + +**输出示例**: +由于此函数返回的是一个GridOptionsBuilder实例,而非直接的视觉输出,因此无法提供具体的视觉示例。但可以预期,返回的GridOptionsBuilder实例将被用于AG Grid组件中,生成一个具有分页、自定义列宽和行选择功能的表格视图。 +## FunctionDef file_exists(kb, selected_rows) +**file_exists**: 此函数的功能是检查本地知识库文件夹中是否存在指定的文档文件,并返回该文件的名称和路径。 + +**参数**: +- kb: 字符串类型,表示知识库的名称。 +- selected_rows: 列表类型,包含选中的行信息,通常是文档的元数据。 + +**代码描述**: +`file_exists` 函数接收两个参数:`kb` 和 `selected_rows`。`kb` 参数用于指定知识库的名称,而 `selected_rows` 参数则包含了用户在界面上选中的行信息,通常这些信息中会包含文件的名称。函数首先检查 `selected_rows` 是否非空,如果非空,则从中提取第一行对应的文件名称(`file_name`)。随后,调用 `get_file_path` 函数,传入知识库名称 `kb` 和文件名称 `file_name`,以获取该文件的完整路径。如果该路径对应的文件确实存在(即 `os.path.isfile(file_path)` 返回 `True`),则函数返回文件名称和文件路径。如果 `selected_rows` 为空或文件不存在,则函数返回两个空字符串。 + +**注意**: +- 在调用此函数之前,应确保 `selected_rows` 参数中包含了正确的文件元数据信息,特别是文件名称。 +- 此函数依赖于 `get_file_path` 函数来构造文件的完整路径,因此需要确保 `get_file_path` 函数能够正确执行并返回有效的文件路径。 +- 此函数返回的文件路径是基于服务器的文件系统结构的,因此在客户端使用时需要注意路径的有效性和访问权限。 + +**输出示例**: +假设知识库名称为 `my_knowledge_base`,用户选中的行中包含文件名称 `example.docx`,且该文件确实存在于服务器上的知识库文件夹中,则函数调用 `file_exists('my_knowledge_base', [{'file_name': 'example.docx'}])` 将返回: +``` +('example.docx', '/var/knowledge_bases/my_knowledge_base/content/example.docx') +``` +这个返回值表示了文件名称和该文件在服务器上的完整路径。如果文件不存在或 `selected_rows` 为空,则函数调用将返回两个空字符串:`("", "")`。 +## FunctionDef knowledge_base_page(api, is_lite) +**knowledge_base_page**: 此函数用于在Web UI中展示和管理知识库页面。 + +**参数**: +- `api`: ApiRequest对象,用于执行与后端API的交互。 +- `is_lite`: 布尔类型,可选参数,默认为None,用于指示是否为轻量模式。 + +**代码描述**: +`knowledge_base_page`函数首先尝试获取知识库的详细信息列表,如果获取过程中发生异常,则显示错误信息并停止执行。接着,根据会话状态中选中的知识库名称,确定当前选中的知识库索引。如果会话状态中没有选中的知识库信息,则默认选中第一个知识库。函数进一步提供了创建新知识库的表单,允许用户输入新知识库的名称、简介、向量库类型和嵌入模型。用户可以上传文件到选中的知识库,并对知识库中的文件进行管理,如添加、删除文件或从向量库中删除文件。此外,还提供了重建向量库、删除知识库等高级功能。用户还可以通过侧边栏进行关键字查询和设置匹配条数。 + +**注意**: +- 在使用此函数之前,需要确保后端API服务正常运行,以便能够成功获取知识库信息和执行其他操作。 +- 创建新知识库时,需要确保知识库名称的唯一性,避免与现有知识库重名。 +- 文件上传和知识库管理功能依赖于用户的输入和选择,因此在设计UI时应确保良好的用户体验和输入验证。 +- 重建向量库和删除知识库等操作可能会影响知识库的数据完整性和可用性,应谨慎使用。 + +**输出示例**: +由于`knowledge_base_page`函数主要负责Web UI的展示和交互,其直接的输出是用户界面的变化,而非具体的数据结构。例如,当用户成功创建一个新的知识库后,页面上会显示一个提示信息,如"知识库创建成功",并且新创建的知识库会出现在知识库列表中。如果用户尝试上传文件到知识库,页面上会显示上传进度,并在完成后显示相应的成功或失败信息。 +### FunctionDef format_selected_kb(kb_name) +**format_selected_kb**: 此函数的功能是格式化选定的知识库名称。 + +**参数**: +- `kb_name`: 字符串类型,代表知识库的名称。 + +**代码描述**: +`format_selected_kb`函数接受一个参数`kb_name`,这是一个字符串,代表要格式化的知识库名称。函数首先尝试从一个预定义的字典`kb_list`中获取与`kb_name`对应的知识库信息。如果找到了对应的知识库信息,函数将返回一个格式化的字符串,该字符串包含知识库的名称、其版本类型(`vs_type`)以及嵌入模型(`embed_model`)。格式为`"知识库名称 (版本类型 @ 嵌入模型)"`。如果在`kb_list`中没有找到对应的知识库信息,函数将直接返回输入的知识库名称。 + +**注意**: +- 确保`kb_list`是一个有效的字典,并且已经被正确初始化和填充了相应的知识库信息。 +- 输入的知识库名称`kb_name`应该是一个准确且存在于`kb_list`中的键值,以确保能够正确地获取知识库信息。 +- 此函数返回的字符串格式特别适用于需要展示知识库详细信息的场景,例如用户界面的下拉菜单或信息展示板。 + +**输出示例**: +假设`kb_list`字典中有一个条目是`{"example_kb": {"vs_type": "v1", "embed_model": "model123"}}`,并且调用`format_selected_kb("example_kb")`,那么函数将返回字符串`"example_kb (v1 @ model123)"`。如果`kb_name`不在`kb_list`中,比如调用`format_selected_kb("unknown_kb")`,则函数将返回`"unknown_kb"`。 +*** diff --git a/markdown_docs/webui_pages/model_config/model_config.md b/markdown_docs/webui_pages/model_config/model_config.md new file mode 100644 index 000000000..28e3acca1 --- /dev/null +++ b/markdown_docs/webui_pages/model_config/model_config.md @@ -0,0 +1,13 @@ +## FunctionDef model_config_page(api) +**model_config_page**: 此函数用于处理模型配置页面的请求。 + +**参数**: +- `api`: ApiRequest 类的实例,用于封装与 API 服务器的 HTTP 请求。 + +**代码描述**: +函数 `model_config_page` 是项目中用于处理模型配置页面请求的函数。它接收一个 `ApiRequest` 类型的参数 `api`,该参数是一个封装了 HTTP 请求的对象,简化了与 API 服务器的交互过程。在此函数中,可以通过 `api` 参数调用不同的 API 接口,以实现获取或修改模型配置的功能。当前函数体内部为空,这意味着函数尚未实现具体的逻辑。在实际应用中,开发者需要根据项目需求,在此函数内部添加相应的代码逻辑,以完成对模型配置页面请求的处理。 + +**注意**: +- 在使用 `model_config_page` 函数时,需要确保传入的 `api` 参数已正确初始化,并且 `base_url` 属性已指向正确的 API 服务器地址。 +- 由于当前函数体为空,开发者在实际使用时需要根据具体需求添加实现代码。 +- 此函数是项目中处理模型配置页面请求的关键部分,因此在修改或扩展功能时应保持代码的清晰和稳定性。 diff --git a/markdown_docs/webui_pages/utils.md b/markdown_docs/webui_pages/utils.md new file mode 100644 index 000000000..300a2f700 --- /dev/null +++ b/markdown_docs/webui_pages/utils.md @@ -0,0 +1,1404 @@ +## ClassDef ApiRequest +**ApiRequest**: ApiRequest 类的功能是封装 HTTP 请求,简化与 API 服务器的交互过程。 + +**属性**: +- `base_url`: API 服务器的基础 URL。 +- `timeout`: 请求超时时间,默认值由 `HTTPX_DEFAULT_TIMEOUT` 定义。 +- `_use_async`: 是否使用异步模式,默认为 False。 +- `_client`: 内部使用的 httpx 客户端实例。 + +**代码描述**: +ApiRequest 类提供了一个简化的方式来与 API 服务器进行交互。它支持 GET、POST 和 DELETE HTTP 方法,并且可以处理同步和异步请求。通过内部管理 httpx 客户端实例,它能够有效地重用连接,提高请求效率。此外,ApiRequest 类还提供了流式请求的支持,以及将响应转换为 JSON 或其他格式的便捷方法。 + +- `client` 属性负责创建和获取 httpx 客户端实例。如果当前实例未创建或已关闭,它会根据配置重新创建一个。 +- `get`、`post` 和 `delete` 方法分别对应 HTTP 的 GET、POST 和 DELETE 请求。这些方法支持重试机制,可以在请求失败时自动重试。 +- `_httpx_stream2generator` 方法将 httpx 的流式响应转换为 Python 的生成器,便于处理大量数据。 +- `_get_response_value` 方法用于处理响应数据,支持将响应转换为 JSON 或通过自定义函数处理。 +- 类还包含了一系列特定功能的方法,如 `get_server_configs`、`list_search_engines`、`get_prompt_template` 等,这些方法封装了与 API 服务器交互的具体细节,使得调用者无需关心请求的构造和响应的解析。 + +在项目中,ApiRequest 类被多个模块调用,例如 `dialogue_page`、`knowledge_base_page` 和 `model_config_page` 等,用于实现与后端 API 的交互,包括获取服务器配置、执行对话、管理知识库等功能。这些调用展示了 ApiRequest 类在简化 API 调用方面的实际应用。 + +**注意**: +- 使用 ApiRequest 类时,需要确保 `base_url` 正确指向 API 服务器。 +- 在处理异步请求时,需要注意 `_use_async` 属性的设置,以及相应的异步方法调用。 + +**输出示例**: +假设调用 `get_server_configs` 方法,可能的返回值为: +```json +{ + "code": 200, + "msg": "成功", + "data": { + "server_version": "1.0.0", + "api_version": "1.0.0" + } +} +``` +此示例展示了一个成功获取服务器配置的响应,其中包含了服务器和 API 的版本信息。 +### FunctionDef __init__(self, base_url, timeout) +**__init__**: 此函数的功能是初始化ApiRequest对象。 + +**参数**: +- `base_url`: 字符串类型,默认值为`api_address()`函数的返回值。用于指定API请求的基础URL。 +- `timeout`: 浮点数类型,默认值为`HTTPX_DEFAULT_TIMEOUT`。用于指定请求的超时时间。 + +**代码描述**: `__init__`函数是`ApiRequest`类的构造函数,负责初始化该类的实例。在初始化过程中,首先设置`base_url`属性,其值默认通过调用`api_address`函数获取,该函数返回API服务器的地址。这一步骤确保了`ApiRequest`对象能够知道向哪个服务器地址发送请求。其次,设置`timeout`属性,用于定义网络请求的超时时间,以避免因网络问题导致程序长时间挂起。此外,函数还初始化了两个内部使用的属性:`_use_async`设置为`False`,表示默认不使用异步请求;`_client`初始化为`None`,预留作为HTTP客户端实例的存储位置。 + +从功能角度看,`__init__`函数通过提供灵活的初始化参数(如API服务器地址和请求超时时间),使得`ApiRequest`类的实例能够根据不同的需求进行定制化的网络请求。通过调用`api_address`函数获取API服务器地址,`ApiRequest`类与项目中其他部分共享了统一的服务器地址配置,这有助于维护项目的一致性和可配置性。 + +**注意**: 使用`ApiRequest`类时,需要确保项目配置文件中的API服务器地址(通过`api_address`函数获取)是正确的。此外,考虑到网络请求可能会因各种原因失败,使用`ApiRequest`类进行网络请求时应当做好异常处理。 +*** +### FunctionDef client(self) +**client**: 此函数的功能是获取或创建一个httpx客户端实例。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `client` 函数首先检查 `_client` 属性是否为 `None` 或者该客户端实例是否已经关闭(通过 `is_closed` 属性判断)。如果满足上述任一条件,函数将通过调用 `get_httpx_client` 函数创建一个新的 httpx 客户端实例,并将其赋值给 `_client` 属性。在创建客户端实例时,会传递几个关键参数给 `get_httpx_client` 函数,包括 `base_url`(基础URL)、`use_async`(是否使用异步客户端)以及 `timeout`(请求超时时间)。这些参数的值来源于 `ApiRequest` 类的属性。如果 `_client` 已经存在且没有关闭,函数将直接返回 `_client`。 + +**注意**: +- `_client` 是 `ApiRequest` 类的一个私有属性,用于存储 httpx 客户端实例。 +- `get_httpx_client` 函数用于创建并配置 httpx 客户端实例,支持同步或异步客户端的创建,具体取决于 `use_async` 参数的值。 +- 在多次调用 `client` 函数时,如果已存在一个未关闭的客户端实例,将复用该实例,避免频繁创建新的客户端实例。 + +**输出示例**: 由于此函数的输出是一个 httpx 客户端实例,输出示例将依赖于如何使用该实例进行 HTTP 请求。例如,使用此客户端实例发起 GET 请求的代码可能如下: +```python +api_request = ApiRequest() # 假设 ApiRequest 是包含 client 函数的类的实例 +httpx_client = api_request.client() +response = httpx_client.get('https://www.example.com') +print(response.text) +``` +在这个示例中,首先创建了 `ApiRequest` 类的一个实例 `api_request`,然后通过调用 `client` 函数获取 httpx 客户端实例 `httpx_client`,最后使用该客户端实例发起一个 GET 请求并打印响应内容。 +*** +### FunctionDef get(self, url, params, retry, stream) +**get**: 此函数的功能是通过HTTP GET请求获取指定URL的数据。 + +**参数**: +- `url`: 字符串类型,指定请求的URL。 +- `params`: 可选参数,字典、列表(包含元组)或字节类型,用于指定请求的查询参数。 +- `retry`: 整型,可选参数,默认值为3,指定请求失败时的重试次数。 +- `stream`: 布尔类型,可选参数,默认值为False,指定是否以流的形式获取响应内容。 +- `**kwargs`: 接收任意额外的关键字参数,这些参数将直接传递给httpx的请求方法。 + +**代码描述**: +此函数主要用于执行HTTP GET请求。它首先尝试使用`client`方法获取一个httpx客户端实例,然后根据`stream`参数的值决定是调用`client.stream`方法以流的形式获取响应,还是调用`client.get`方法获取完整的响应内容。如果请求过程中发生异常,函数会记录错误信息,并根据`retry`参数的值决定是否重试请求。重试次数`retry`每次异常捕获后减一,直到重试次数用尽。如果在重试次数用尽前请求成功,函数将返回响应内容;否则,可能返回`None`。 + +**注意**: +- 函数在请求过程中可能会遇到各种异常,例如网络连接问题、服务器错误等。这些异常会被捕获并记录日志,但不会直接抛出,以避免中断程序的执行。 +- 通过`**kwargs`参数,用户可以传递额外的选项给httpx请求,如自定义请求头、超时设置等,这提供了高度的灵活性。 +- 使用`stream`参数可以在处理大文件或实时数据时减少内存消耗,因为它允许逐块处理响应内容。 + +**输出示例**: +由于此函数的返回值依赖于请求的响应,因此输出示例将根据调用情境而异。例如,如果请求成功并且不使用流式响应,函数可能返回一个`httpx.Response`对象,可以通过该对象的属性和方法访问响应状态码、响应头、响应内容等信息。如果使用流式响应,函数将返回一个迭代器,允许逐块读取响应内容。 +*** +### FunctionDef post(self, url, data, json, retry, stream) +**post**: 此函数用于执行HTTP POST请求。 + +**参数**: +- `url`: 字符串类型,指定请求的URL。 +- `data`: 字典类型,默认为None,用于指定要发送的表单数据。 +- `json`: 字典类型,默认为None,用于指定要发送的JSON数据。 +- `retry`: 整型,默认为3,指定请求失败时的重试次数。 +- `stream`: 布尔类型,默认为False,指定是否以流的方式接收响应内容。 +- `**kwargs`: 接收任意额外的关键字参数,这些参数将直接传递给httpx的请求方法。 + +**代码描述**: +此函数首先检查重试次数`retry`是否大于0。如果是,尝试执行POST请求。根据`stream`参数的值,决定是调用httpx客户端的`stream`方法还是`post`方法来发送请求。如果请求过程中发生异常,将捕获异常并记录错误信息,然后重试次数减一,继续尝试发送请求,直到成功或重试次数用尽。异常信息的记录依赖于`logger.error`方法,其中包括异常类型、错误消息和可选的异常信息(取决于`log_verbose`变量的值)。 + +**注意**: +- 函数内部使用了`self.client`来获取httpx客户端实例,该实例的创建和配置详见`client`函数的文档。 +- 当`stream`参数为True时,使用`client.stream`方法以流的方式接收响应,适用于处理大量数据。 +- 通过`**kwargs`参数,可以传递额外的参数给httpx的请求方法,如自定义请求头、超时设置等。 +- 函数捕获并处理了所有异常,确保了网络请求的健壮性。 + +**输出示例**: +由于此函数的返回值依赖于请求的响应,因此具体的输出示例将根据不同的请求URL和参数而有所不同。一般情况下,如果不使用流模式,返回值可能是一个`httpx.Response`对象,可以通过该对象访问响应状态码、响应头、响应体等信息。如果使用流模式,返回值可能是一个迭代器,用于逐块处理响应内容。如果请求失败且重试次数用尽,可能返回None。 +*** +### FunctionDef delete(self, url, data, json, retry, stream) +**delete**: 此函数的功能是通过HTTP DELETE请求删除指定的资源。 + +**参数**: +- `url`: 字符串类型,指定要删除资源的URL。 +- `data`: 字典类型,默认为None,用于指定要发送的数据体。 +- `json`: 字典类型,默认为None,用于指定要发送的JSON数据。 +- `retry`: 整型,默认为3,指定请求失败时的重试次数。 +- `stream`: 布尔类型,默认为False,指定是否以流的形式接收响应数据。 +- `**kwargs`: 接收任意额外的关键字参数,这些参数将直接传递给httpx的请求方法。 + +**代码描述**: +此函数主要用于发送HTTP DELETE请求,以删除指定的资源。它首先会根据`retry`参数指定的次数尝试发送请求。在尝试过程中,如果设置了`stream`参数为True,则会使用`client.stream`方法以流的形式发送DELETE请求;否则,使用`client.delete`方法发送普通的DELETE请求。这里的`client`是通过`ApiRequest`类的`client`方法获取的httpx客户端实例,该实例负责实际的网络通信。在请求过程中,如果遇到异常,会捕获异常并记录错误信息,然后根据`retry`参数决定是否重试。每次重试前,`retry`的值会减1,直到减到0为止。 + +**注意**: +- 在使用此函数时,需要确保传入的`url`参数是有效的,并且有权限进行DELETE操作。 +- 如果服务器响应的内容很大,设置`stream`为True可以减少内存的使用。 +- 通过`**kwargs`参数,可以传递额外的请求选项,如自定义头部、超时时间等,以满足不同的请求需求。 +- 函数可能返回`httpx.Response`对象、`Iterator[httpx.Response]`对象(当`stream`为True时)或者在重试次数用尽仍失败时返回None。 + +**输出示例**: +由于此函数的输出依赖于实际的请求和服务器响应,以下是一个可能的返回值示例: +```python +response = api_request.delete('https://www.example.com/resource') +if response: + print(response.status_code) +else: + print("请求失败,已重试指定次数。") +``` +在这个示例中,首先尝试删除指定URL的资源,然后根据返回值判断请求是否成功。如果请求成功,打印出响应的状态码;如果请求失败且重试次数用尽,则打印失败信息。 +*** +### FunctionDef _httpx_stream2generator(self, response, as_json) +**_httpx_stream2generator**: 该函数的功能是将httpx.stream返回的GeneratorContextManager转化为普通生成器,以便处理异步或同步的HTTP流响应。 + +**参数**: +- `response`: contextlib._GeneratorContextManager类型,表示httpx请求的响应流。 +- `as_json`: 布尔类型,默认为False,指定是否将流中的数据解析为JSON格式。 + +**代码描述**: +_httpx_stream2generator函数旨在处理来自httpx库的HTTP流响应。它提供了异步和同步两种处理方式,根据ApiRequest对象的_use_async属性来决定使用哪种方式。当处理异步流时,它使用`async with`语句管理响应上下文,并通过`aiter_text`异步迭代响应内容。对于同步流,使用`with`语句和`iter_text`方法迭代响应内容。无论哪种方式,函数都会检查每个数据块,如果`as_json`参数为True,则尝试将数据块解析为JSON对象;否则,直接返回数据块。 + +在解析JSON时,函数特别处理了以"data: "开头的数据块,这通常用于服务器发送事件(SSE)。如果数据块以":"开头,则视为SSE的注释行并跳过。如果在解析JSON过程中遇到异常,函数会记录错误信息并继续处理下一个数据块。 + +此外,函数还处理了几种异常情况,包括无法连接API服务器、API通信超时和其他通信错误,对这些异常情况进行了日志记录,并生成包含错误代码和消息的JSON对象作为生成器的输出。 + +在项目中,_httpx_stream2generator函数被多个API请求方法调用,如`chat_chat`、`agent_chat`、`knowledge_base_chat`、`file_chat`和`search_engine_chat`等,用于处理这些方法中的流式响应。这些方法通过API与后端服务进行交互,获取实时的数据流。通过使用_httpx_stream2generator函数,这些方法能够以一种统一和高效的方式处理来自后端服务的流式数据。 + +**注意**: +- 使用此函数时,需要确保传入的response参数是一个有效的httpx的响应流对象。 +- 当处理大量数据或需要实时响应时,正确选择异步或同步模式对性能有重要影响。 + +**输出示例**: +```python +# 如果as_json为True,且流中的数据是JSON格式 +{"name": "example", "value": 123} + +# 如果as_json为False +"data: example stream data\n" +``` +#### FunctionDef ret_async(response, as_json) +**ret_async**: 此函数的功能是异步处理HTTP响应,根据参数决定是否将响应内容作为JSON解析,并以生成器的形式返回数据。 + +**参数**: +- `response`: 一个异步的HTTP响应对象,此对象应支持异步上下文管理和异步迭代。 +- `as_json`: 一个布尔值,指示是否应将响应内容解析为JSON。 + +**代码描述**: +`ret_async` 函数是一个异步生成器,用于处理来自HTTP请求的响应。它首先尝试异步地与响应对象进行交互。通过迭代响应内容的每个文本块,函数可以根据`as_json`参数的值决定处理方式。 + +- 当`as_json`为True时,函数尝试将每个块解析为JSON。如果块以`data: `开头,它会去除前缀和后缀后尝试解析JSON;如果块以冒号`:`开头,则视为SSE(Server-Sent Events)注释行并跳过;否则,直接尝试解析整个块为JSON。解析成功后,将解析后的数据作为生成器的下一个值。如果解析失败,会记录错误信息并继续处理下一个块。 + +- 当`as_json`为False时,直接将文本块作为生成器的下一个值,不进行JSON解析。 + +函数还处理了几种异常情况,包括连接错误(`httpx.ConnectError`)、读取超时(`httpx.ReadTimeout`)以及其他异常。在遇到这些异常时,会记录相应的错误信息,并生成包含错误代码和消息的字典作为生成器的下一个值。 + +**注意**: +- 使用此函数时,需要确保传入的`response`对象支持异步操作。 +- 函数内部捕获并处理了多种异常,调用者应注意处理生成器可能产生的错误信息字典。 +- 由于函数使用了异步特性,调用此函数时需要在异步环境中使用`async for`来获取数据。 +- 函数的错误日志依赖于外部的`logger`对象和`log_verbose`变量,需要确保这些依赖在调用环境中正确配置。 +*** +#### FunctionDef ret_sync(response, as_json) +**ret_sync**: 此函数用于同步处理HTTP响应,并根据需要将响应内容转换为JSON或直接文本。 + +**参数**: +- `response`: HTTP响应对象,此对象应支持上下文管理协议以及迭代文本内容的方法。 +- `as_json`: 布尔值,指示是否应将响应内容解析为JSON。 + +**代码描述**: +`ret_sync` 函数首先尝试处理传入的HTTP响应。使用`response`对象的上下文管理器确保安全地处理响应。函数迭代响应内容的每个文本块,跳过任何空块,这是为了处理某些API在开始和结束时可能发送的空字节。 + +如果`as_json`参数为真,函数会尝试将文本块解析为JSON。特别地,如果文本块以"data: "开头,函数会去除这个前缀和最后的两个字符后尝试解析JSON;如果文本块以":"开头,则认为这是一个SSE(Server-Sent Events)的注释行并跳过;否则,直接尝试解析整个文本块为JSON。如果在解析过程中遇到任何异常,会记录错误信息,并根据`log_verbose`变量的值决定是否记录详细的异常信息。 + +如果`as_json`参数为假,函数则直接将文本块作为迭代器的一部分返回,不进行JSON解析。 + +函数还处理了几种特定的异常情况,包括连接错误(`httpx.ConnectError`)、读取超时(`httpx.ReadTimeout`)以及其他异常。在这些情况下,会记录相应的错误信息,并通过迭代器返回包含错误代码和消息的字典。 + +**注意**: +- 使用此函数时,需要确保传入的`response`对象支持所需的操作,包括上下文管理和文本迭代。 +- 当选择以JSON格式解析响应时,应注意处理可能的解析错误,并准备好接收错误信息。 +- 异常处理部分显示了如何处理特定的连接和超时错误,这对于调试和错误处理非常有用。 +- 此函数的设计考虑了SSE(Server-Sent Events)格式的响应,这在实时数据传输中非常常见。 +*** +*** +### FunctionDef _get_response_value(self, response, as_json, value_func) +**_get_response_value**: 此函数的功能是转换HTTP响应对象,根据指定的参数返回处理后的数据。 + +**参数**: +- `response`: httpx.Response对象,代表一个HTTP响应。 +- `as_json`: 布尔值,默认为False。当设置为True时,函数会尝试将响应体解析为JSON。 +- `value_func`: 可调用对象,默认为None。用户可以通过此参数传入一个函数,该函数接收一个参数(响应体或其JSON解析结果),并返回处理后的数据。 + +**代码描述**: +此函数主要用于处理API请求的响应数据。它提供了灵活的处理方式,支持直接返回响应体、返回响应体的JSON解析结果,或通过`value_func`参数自定义处理逻辑。函数内部首先定义了一个`to_json`的内部函数,用于尝试将响应体解析为JSON,如果解析失败,则记录错误信息并返回一个包含错误代码和信息的字典。接着,根据`_use_async`属性判断当前是否使用异步模式,并据此选择同步或异步的处理方式。如果`as_json`参数为True,则使用`to_json`函数处理响应体;如果用户通过`value_func`参数提供了自定义处理函数,则最终返回的数据会经过该函数处理。 + +在项目中,`_get_response_value`函数被多个API请求函数调用,用于处理这些函数获取的HTTP响应。例如,在获取服务器配置、列出搜索引擎、获取提示模板等场景中,都使用了此函数来处理响应数据,并根据需要将响应解析为JSON或通过自定义函数进一步处理。这种设计使得响应数据的处理更加灵活和统一。 + +**注意**: +- 当使用`as_json`参数时,需要确保响应体可以被成功解析为JSON,否则会返回错误信息。 +- 如果提供了`value_func`参数,需要确保传入的函数能够正确处理输入的数据(响应体或其JSON解析结果),并返回期望的结果。 + +**输出示例**: +假设响应体为`{"code": 200, "msg": "成功", "data": {"key": "value"}}`,并且`as_json`参数为True,没有提供`value_func`参数,则函数的返回值可能为: +```python +{"code": 200, "msg": "成功", "data": {"key": "value"}} +``` +#### FunctionDef to_json(r) +**to_json**: 该函数的功能是将响应对象转换为JSON格式。 + +**参数**: +- r: 需要被转换为JSON格式的响应对象。 + +**代码描述**: +`to_json`函数旨在处理API响应,尝试将响应对象`r`转换为JSON格式。这个过程中,函数首先尝试使用`r.json()`方法来解析响应内容。如果在解析过程中遇到任何异常(例如,响应内容不是有效的JSON格式),则会捕获这个异常,并构造一个包含错误代码500、错误消息以及空数据的JSON对象返回。错误消息会附加异常信息,以便于调试和错误追踪。如果启用了详细日志(`log_verbose`为真),则会记录错误信息和异常类型到日志中,以供后续分析。 + +在项目中,`to_json`函数被`ret_async`函数调用,用于异步处理API响应。在`ret_async`中,根据`as_json`参数的值决定是否需要将响应转换为JSON。如果需要,`ret_async`会使用`to_json`函数处理经过`await`获取的响应对象,然后将转换后的JSON数据传递给`value_func`函数进行进一步处理。这表明`to_json`函数在处理异步API响应中起到了关键的数据格式转换作用。 + +**注意**: +- 在使用`to_json`函数时,需要确保传入的响应对象具有`.json()`方法,这通常意味着该对象是一个HTTP响应对象。 +- 函数内部捕获的异常是广泛的,因此在调用此函数时,应当注意异常处理,以避免隐藏潜在的错误。 + +**输出示例**: +如果响应内容是有效的JSON,例如`{"name": "test"}`,则`to_json`函数将返回这个JSON对象。 +如果响应内容不是有效的JSON,假设发生了一个解析异常,函数可能返回如下格式的JSON对象: +```json +{ + "code": 500, + "msg": "API未能返回正确的JSON。解析错误信息", + "data": None +} +``` +*** +#### FunctionDef ret_async(response) +**ret_async**: 该函数的功能是异步处理API响应,并根据需要将其转换为JSON格式或直接返回。 + +**参数**: +- response: 需要被处理的异步响应对象。 + +**代码描述**: +`ret_async`函数是设计用来异步处理API响应的。它接受一个`response`参数,这是一个异步响应对象。函数内部首先判断是否需要将响应转换为JSON格式,这是通过检查`as_json`变量的值来决定的。如果`as_json`为真,则调用`to_json`函数将响应转换为JSON格式;否则,直接返回响应内容。 + +在转换为JSON格式的过程中,`ret_async`函数使用`await`关键字等待`response`对象的异步操作完成,然后将结果传递给`to_json`函数进行处理。处理完成后,将转换后的JSON数据传递给`value_func`函数进行进一步处理。 + +如果不需要将响应转换为JSON格式,`ret_async`函数同样使用`await`关键字等待响应内容的异步操作完成,然后直接将结果传递给`value_func`函数。 + +这个函数展示了异步编程在处理API响应时的应用,特别是在需要对响应数据进行格式转换或其他处理时的灵活性。 + +**注意**: +- 在调用`ret_async`函数时,需要确保传入的`response`对象支持异步操作。 +- `as_json`变量和`value_func`函数在代码片段中未显示定义,需要在`ret_async`函数被调用的上下文中提供。 +- `to_json`函数的作用是将响应对象转换为JSON格式,因此在`as_json`为真时,需要确保响应对象能够被成功转换。 + +**输出示例**: +- 如果`as_json`为真,并且响应内容是有效的JSON,例如`{"name": "test"}`,`ret_async`函数可能返回经过`value_func`处理的JSON对象。 +- 如果`as_json`为假,假设响应内容是字符串"response content",`ret_async`函数将返回经过`value_func`处理的字符串"response content"。 +*** +*** +### FunctionDef get_server_configs(self) +**get_server_configs**: 此函数用于获取服务器配置信息。 + +**参数**: +- `**kwargs`: 可变关键字参数,允许传递任意数量的参数名及其对应的值,这些参数将直接传递给内部的`post`方法。 + +**代码描述**: +`get_server_configs`函数通过调用`post`方法向服务器发送HTTP POST请求,请求的URL为`"/server/configs"`。该函数接受任意数量的关键字参数(`**kwargs`),这些参数将直接传递给`post`方法。在发送请求后,函数通过调用`_get_response_value`方法处理响应,将响应体转换为JSON格式的字典并返回。`_get_response_value`方法支持将响应体解析为JSON,并且可以通过传入的参数自定义处理逻辑,以满足不同的数据处理需求。 + +**注意**: +- 使用此函数时,可以通过`**kwargs`传递额外的参数给`post`方法,例如自定义请求头、超时设置等,这提供了灵活的请求配置能力。 +- 函数依赖于`post`方法来发送HTTP请求,因此其性能和异常处理能力与`post`方法的实现紧密相关。 +- 返回的数据格式为JSON,调用方应确保处理JSON格式的数据。 + +**输出示例**: +调用`get_server_configs`函数可能返回的示例数据如下: +```python +{ + "code": 200, + "msg": "成功", + "data": { + "config1": "value1", + "config2": "value2", + // 更多配置项... + } +} +``` +此示例展示了一个包含状态码、消息和数据的标准响应结构,其中`data`字段包含了服务器配置的详细信息。实际返回的数据结构可能根据服务器的不同配置而有所不同。 +*** +### FunctionDef list_search_engines(self) +**list_search_engines**: 此函数用于列出可用的搜索引擎列表。 + +**参数**: +- `**kwargs`: 接收任意额外的关键字参数,这些参数将直接传递给内部的POST请求方法。 + +**代码描述**: +`list_search_engines` 函数通过发送一个HTTP POST请求到`/server/list_search_engines`路径,获取可用的搜索引擎列表。它使用了`post`方法来执行这个请求,并且可以接受任意额外的关键字参数(`**kwargs`),这些参数将直接传递给`post`方法。在获取到响应后,函数使用`_get_response_value`方法来处理响应数据,这个处理包括将响应体解析为JSON格式,并从中提取`data`字段的值作为最终的返回结果。 + +**注意**: +- 函数内部依赖于`post`方法来发送HTTP请求,因此确保`post`方法能够正确执行是使用此函数的前提。 +- 函数还依赖于`_get_response_value`方法来处理响应数据,确保该方法能正确解析响应体并提取所需数据。 +- 由于此函数可以接受任意额外的关键字参数,这提供了一定的灵活性,例如可以通过这些参数来定制HTTP请求头或设置超时等。 + +**输出示例**: +假设服务器端返回的响应体为`{"code": 200, "msg": "成功", "data": ["Google", "Bing", "DuckDuckGo"]}`,则`list_search_engines`函数的返回值将是一个列表,如下所示: +```python +["Google", "Bing", "DuckDuckGo"] +``` +这个列表包含了所有可用的搜索引擎名称。 +*** +### FunctionDef get_prompt_template(self, type, name) +**get_prompt_template**: 此函数用于获取指定类型和名称的提示模板。 + +**参数**: +- `type`: 字符串类型,默认值为"llm_chat",用于指定请求的提示模板类型。 +- `name`: 字符串类型,默认值为"default",用于指定请求的提示模板名称。 +- `**kwargs`: 接收任意额外的关键字参数,这些参数将直接传递给内部的`post`方法。 + +**代码描述**: +`get_prompt_template`函数首先构造一个包含`type`和`name`的字典`data`,然后使用`post`方法向服务器发送请求,请求的URL为`/server/get_prompt_template`,并且将`data`字典作为JSON数据传递。此外,任何通过`**kwargs`传递的额外参数也会被直接传递给`post`方法。接收到的响应通过`_get_response_value`方法处理,该方法允许通过`value_func`参数自定义响应值的处理逻辑。在本函数中,`value_func`被设置为一个lambda函数,该函数接收响应对象并返回其文本内容。因此,`get_prompt_template`函数最终返回的是服务器响应的文本内容。 + +**注意**: +- 函数内部通过`post`方法发送HTTP POST请求,因此需要确保网络连接的稳定性。 +- `_get_response_value`方法用于处理响应数据,可以根据需要自定义处理逻辑,但在本函数中仅返回响应的文本内容。 +- 通过`**kwargs`参数,可以向`post`方法传递额外的请求参数,如自定义请求头、超时设置等,增加了函数的灵活性。 + +**输出示例**: +假设服务器对于请求的提示模板返回了文本内容`"Welcome to the chat!"`,则函数的返回值可能为: +``` +"Welcome to the chat!" +``` +此输出示例展示了函数在成功获取提示模板时可能返回的文本内容。实际返回的内容将根据服务器的响应而有所不同。 +*** +### FunctionDef chat_chat(self, query, conversation_id, history_len, history, stream, model, temperature, max_tokens, prompt_name) +**chat_chat**: 该函数用于处理与聊天相关的API请求。 + +**参数**: +- `query`: 字符串类型,用户的查询内容。 +- `conversation_id`: 字符串类型,默认为None,表示会话的唯一标识符。 +- `history_len`: 整型,默认为-1,表示需要考虑的历史消息数量。 +- `history`: 列表类型,默认为空列表,包含历史对话内容的列表,每个元素是一个字典。 +- `stream`: 布尔类型,默认为True,指定是否以流的方式接收响应内容。 +- `model`: 字符串类型,默认为LLM_MODELS列表的第一个元素,指定使用的语言模型。 +- `temperature`: 浮点类型,默认为TEMPERATURE,控制生成文本的创造性。 +- `max_tokens`: 整型,可选参数,默认为None,指定生成文本的最大令牌数。 +- `prompt_name`: 字符串类型,默认为"default",指定使用的提示模板名称。 +- `**kwargs`: 接收任意额外的关键字参数。 + +**代码描述**: +函数首先构造一个包含请求所需所有参数的字典`data`,然后使用`self.post`方法向"/chat/chat"路径发送POST请求,请求体为`data`字典。请求时,`stream`参数被设置为True,表示以流的方式接收响应内容。最后,函数调用`self._httpx_stream2generator`方法,将httpx库返回的流响应转换为普通生成器,并指定以JSON格式解析流中的数据,最终返回该生成器。 + +**注意**: +- 函数内部调用了`post`方法发送HTTP POST请求,该方法的详细描述可参考`post`函数的文档。 +- 函数还调用了`_httpx_stream2generator`方法来处理流式响应,该方法的详细描述可参考`_httpx_stream2generator`函数的文档。 +- 通过`**kwargs`参数,可以向`post`方法传递额外的HTTP请求参数,例如自定义请求头或超时设置等。 +- 函数设计为支持流式响应,适用于处理实时数据或大量数据的场景。 + +**输出示例**: +由于函数返回的是一个生成器,具体的输出取决于响应内容。以下是一个可能的输出示例,假设流中的数据是JSON格式: +```python +{ + "text": "这是由模型生成的回答。", + "message_id": "123456789" +} +``` +在实际使用中,生成器将逐步产生此类JSON对象,每个对象包含模型生成的文本和消息ID等信息。 +*** +### FunctionDef agent_chat(self, query, history, stream, model, temperature, max_tokens, prompt_name) +**agent_chat**: 该函数用于处理代理聊天的请求,并将查询发送到后端服务。 + +**参数**: +- `query`: 字符串类型,用户的查询内容。 +- `history`: 列表类型,默认为空列表,包含字典类型的元素,用于传递对话历史。 +- `stream`: 布尔类型,默认为True,指定是否以流的方式接收响应内容。 +- `model`: 字符串类型,默认为`LLM_MODELS`列表的第一个元素,用于指定处理请求的模型。 +- `temperature`: 浮点类型,默认为`TEMPERATURE`,用于控制生成文本的多样性。 +- `max_tokens`: 整型,可选参数,用于指定生成文本的最大令牌数。 +- `prompt_name`: 字符串类型,默认为"default",用于指定使用的提示模板名称。 + +**代码描述**: +`agent_chat`函数首先构造一个包含请求参数的字典`data`,然后使用`self.post`方法发送POST请求到`/chat/agent_chat`端点。该请求以流的方式接收响应内容。函数最后调用`_httpx_stream2generator`方法,将httpx的流响应转换为普通生成器,以便于处理异步或同步的HTTP流响应,并将其作为返回值。 + +**注意**: +- 该函数依赖于`post`方法来发送HTTP POST请求,`post`方法的详细行为请参考`post`函数的文档。 +- `agent_chat`函数的返回值是一个生成器,它允许调用者以流式方式处理来自后端服务的响应数据。这对于处理大量数据或需要实时响应的场景特别有用。 +- 函数中使用了`LLM_MODELS`和`TEMPERATURE`这两个全局变量,它们需要在函数外部定义。 + +**输出示例**: +由于`agent_chat`函数返回的是一个生成器,其具体输出取决于后端服务的响应内容。假设后端服务返回的数据是JSON格式,且`as_json`参数为True,则可能的输出示例为: +```python +{ + "answer": "这是一个示例回答。", + "confidence": 0.95 +} +``` +如果`as_json`参数为False,则可能直接输出后端服务返回的原始文本数据。 +*** +### FunctionDef knowledge_base_chat(self, query, knowledge_base_name, top_k, score_threshold, history, stream, model, temperature, max_tokens, prompt_name) +**knowledge_base_chat**: 该函数用于通过知识库进行聊天对话。 + +**参数**: +- `query`: 字符串类型,用户的查询语句。 +- `knowledge_base_name`: 字符串类型,指定要查询的知识库名称。 +- `top_k`: 整型,默认值为VECTOR_SEARCH_TOP_K,指定返回的相关知识条目数量上限。 +- `score_threshold`: 浮点型,默认值为SCORE_THRESHOLD,设置返回知识条目的分数阈值。 +- `history`: 列表类型,默认为空列表,包含字典类型的历史对话记录。 +- `stream`: 布尔类型,默认为True,指定是否以流的方式接收响应内容。 +- `model`: 字符串类型,默认为LLM_MODELS列表的第一个元素,指定使用的语言模型。 +- `temperature`: 浮点型,默认值为TEMPERATURE,控制生成文本的多样性。 +- `max_tokens`: 整型,可选参数,指定生成文本的最大令牌数。 +- `prompt_name`: 字符串类型,默认为"default",指定使用的提示模板名称。 + +**代码描述**: +函数首先构造一个包含所有输入参数的字典`data`,然后使用`self.post`方法向`/chat/knowledge_base_chat`路径发送POST请求,并将`data`作为JSON数据传递。请求的响应以流的形式接收,并通过调用`self._httpx_stream2generator`方法将httpx的响应流转换为普通生成器,以便于处理异步或同步的HTTP流响应。该方法返回一个生成器,可以迭代获取处理后的响应数据。 + +**注意**: +- 函数内部调用了`self.post`方法来发送HTTP POST请求,该方法的详细行为请参考`post`函数的文档。 +- 通过`self._httpx_stream2generator`方法处理响应流,该方法的详细行为请参考`_httpx_stream2generator`函数的文档。 +- 函数的行为受到传入参数的影响,特别是`stream`参数决定了响应内容的接收方式。 +- 使用该函数时,需要确保`knowledge_base_name`参数指定的知识库已经存在并可用。 + +**输出示例**: +由于该函数返回一个生成器,因此输出示例将依赖于具体的响应内容。假设响应内容为JSON格式的数据,一个可能的输出示例为: +```python +{ + "answer": "这是根据您的查询从知识库中检索到的答案。", + "docs": [ + {"title": "文档1", "content": "文档1的内容", "score": 0.95}, + {"title": "文档2", "content": "文档2的内容", "score": 0.90} + ] +} +``` +在实际使用中,生成器将逐步产生上述格式的数据块,直到所有相关的响应数据被处理完毕。 +*** +### FunctionDef upload_temp_docs(self, files, knowledge_id, chunk_size, chunk_overlap, zh_title_enhance) +**upload_temp_docs**: 此函数用于上传临时文档到知识库。 + +**参数**: +- `files`: 文件列表,可以是字符串、路径或字节数据的列表。 +- `knowledge_id`: 字符串类型,指定知识库的ID,默认为None。 +- `chunk_size`: 整型,指定分块上传时每个块的大小,默认值由`CHUNK_SIZE`常量决定。 +- `chunk_overlap`: 整型,指定分块上传时块之间的重叠大小,默认值由`OVERLAP_SIZE`常量决定。 +- `zh_title_enhance`: 布尔值,指定是否增强中文标题,默认值由`ZH_TITLE_ENHANCE`常量决定。 + +**代码描述**: +此函数首先定义了一个内部函数`convert_file`,用于将输入的文件转换为适合上传的格式。如果文件是字节数据,则将其封装在`BytesIO`对象中;如果文件是可读对象,则直接使用;如果文件是路径,则打开文件并读取为二进制数据。之后,将所有文件通过`convert_file`函数转换,并构造上传数据的字典,包括知识库ID、分块大小、块重叠大小和中文标题增强选项。最后,使用`post`方法向`/knowledge_base/upload_temp_docs`路径发送POST请求,上传文件,并通过`_get_response_value`方法处理响应,返回JSON格式的响应数据。 + +此函数与`post`和`_get_response_value`方法紧密相关。`post`方法负责执行HTTP POST请求,发送文件和数据到服务器;`_get_response_value`方法则用于处理服务器的响应,将其转换为JSON格式或其他用户定义的格式。这种设计实现了功能的模块化,使得上传文件的过程清晰且易于管理。 + +**注意**: +- 确保传入的`files`参数中的文件路径存在或文件数据有效,以避免在上传过程中出现错误。 +- `chunk_size`和`chunk_overlap`参数应根据服务器的接受能力和网络条件合理设置,以优化上传性能。 +- 函数依赖于`post`方法的实现,确保`post`方法能够正确处理文件上传的请求。 +- 使用`_get_response_value`处理响应时,确保服务器的响应可以被正确解析为JSON格式。 + +**输出示例**: +假设上传成功,服务器响应如下JSON数据: +```python +{ + "code": 200, + "msg": "上传成功", + "data": { + "file_ids": ["file1_id", "file2_id"] + } +} +``` +此时,`upload_temp_docs`函数的返回值可能为: +```python +{ + "code": 200, + "msg": "上传成功", + "data": { + "file_ids": ["file1_id", "file2_id"] + } +} +``` +#### FunctionDef convert_file(file, filename) +**convert_file**: 此函数的功能是将传入的文件转换为文件名和文件对象的形式。 + +**参数**: +- **file**: 可以是字节串、具有read方法的文件对象或本地文件路径。 +- **filename**: 可选参数,用于指定文件名。如果未提供,则会根据文件对象或路径自动确定文件名。 + +**代码描述**: +此函数首先检查`file`参数的类型,以确定其是字节串、文件对象还是文件路径,并据此进行相应的处理: +- 如果`file`是字节串(`bytes`类型),则使用`BytesIO`将其转换为文件对象。 +- 如果`file`具有`read`方法(即,它是一个文件对象),则直接使用该对象。如果`filename`参数未提供,将尝试从文件对象的`name`属性获取文件名。 +- 如果`file`既不是字节串也没有`read`方法,则假定它是一个本地文件路径。函数将尝试打开该路径指向的文件(以二进制读取模式),并根据需要设置文件名。 + +在处理完毕后,函数返回一个包含文件名和文件对象的元组。 + +**注意**: +- 确保传入的文件路径是有效的,否则在尝试打开文件时会引发异常。 +- 如果传入的是文件对象,确保它已经以适当的模式(如二进制读取模式)打开。 + +**输出示例**: +假设有一个位于`/path/to/document.pdf`的文件,调用`convert_file('/path/to/document.pdf')`将返回: +``` +('document.pdf', <_io.BufferedReader name='/path/to/document.pdf'>) +``` +如果传入的是字节串,假设不提供文件名,调用`convert_file(b'some binary data')`可能返回: +``` +(None, <_io.BytesIO object at 0x7f4c3b2f1e50>) +``` +请注意,由于字节串没有显式的文件名,所以在这种情况下文件名可能为`None`或者是根据上下文在函数外部指定的。 +*** +*** +### FunctionDef file_chat(self, query, knowledge_id, top_k, score_threshold, history, stream, model, temperature, max_tokens, prompt_name) +**file_chat**: 该函数用于处理文件对话请求,通过发送查询到后端并接收处理结果。 + +**参数**: +- `query`: 字符串类型,用户的查询内容。 +- `knowledge_id`: 字符串类型,指定知识文件的唯一标识符。 +- `top_k`: 整型,默认值为`VECTOR_SEARCH_TOP_K`,指定返回的最相关结果的数量。 +- `score_threshold`: 浮点型,默认值为`SCORE_THRESHOLD`,指定返回结果的分数阈值。 +- `history`: 列表类型,默认为空列表,包含字典类型的历史对话记录。 +- `stream`: 布尔类型,默认为True,指定是否以流的方式接收响应内容。 +- `model`: 字符串类型,默认为`LLM_MODELS[0]`,指定使用的语言模型。 +- `temperature`: 浮点型,默认为`TEMPERATURE`,控制生成文本的创新性。 +- `max_tokens`: 整型,可选参数,指定生成文本的最大令牌数。 +- `prompt_name`: 字符串类型,默认为"default",指定使用的提示模板名称。 + +**代码描述**: +`file_chat`函数首先构造一个包含所有必要信息的数据字典,然后使用`self.post`方法向`/chat/file_chat`端点发送POST请求,并将数据字典作为JSON数据传递。请求以流的方式发送,以便处理可能的大量数据。函数接收到的响应通过`self._httpx_stream2generator`方法转换为生成器,以便于异步处理响应数据。该方法允许以JSON格式逐块处理响应内容,适用于实时数据流的场景。 + +**注意**: +- 在使用`file_chat`函数时,需要确保`knowledge_id`正确指向了一个有效的知识文件标识符。 +- `history`参数允许传递历史对话记录,这有助于模型更好地理解上下文,从而生成更准确的回复。 +- 通过调整`top_k`和`score_threshold`参数,可以控制返回结果的数量和质量。 +- `stream`参数默认为True,这意味着响应以流的方式处理,适合大数据量的场景。 + +**输出示例**: +由于`file_chat`函数的输出是通过`self._httpx_stream2generator`方法处理的生成器,因此具体的输出示例将依赖于后端服务的响应。一般情况下,可能会得到类似以下格式的JSON数据流: +```json +{ + "answer": "这是根据您的查询和提供的文件内容生成的回答。", + "docs": [ + { + "title": "相关文档1", + "content": "文档内容摘要。", + "score": 0.95 + }, + { + "title": "相关文档2", + "content": "文档内容摘要。", + "score": 0.90 + } + ] +} +``` +这个示例展示了一个可能的回答以及与查询最相关的文档列表和它们的匹配分数。 +*** +### FunctionDef search_engine_chat(self, query, search_engine_name, top_k, history, stream, model, temperature, max_tokens, prompt_name, split_result) +**search_engine_chat**: 此函数用于通过搜索引擎进行聊天式搜索。 + +**参数**: +- `query`: 字符串类型,用户的查询语句。 +- `search_engine_name`: 字符串类型,指定使用的搜索引擎名称。 +- `top_k`: 整型,默认为`SEARCH_ENGINE_TOP_K`,指定返回的搜索结果数量。 +- `history`: 列表类型,默认为空列表,包含字典类型的元素,用于传递对话历史。 +- `stream`: 布尔类型,默认为True,指定是否以流的方式接收响应内容。 +- `model`: 字符串类型,默认为`LLM_MODELS[0]`,指定使用的语言模型。 +- `temperature`: 浮点类型,默认为`TEMPERATURE`,用于调整生成文本的随机性。 +- `max_tokens`: 整型,可选参数,指定生成文本的最大令牌数。 +- `prompt_name`: 字符串类型,默认为"default",用于指定使用的提示模板名称。 +- `split_result`: 布尔类型,默认为False,指定是否分割返回的结果。 + +**代码描述**: +此函数首先构造一个包含所有输入参数的字典`data`,然后使用`self.post`方法向`/chat/search_engine_chat`路径发送POST请求,并传递`data`作为请求体。请求的响应以流的方式接收,并通过`self._httpx_stream2generator`方法转换为普通生成器,以便于处理异步或同步的HTTP流响应。这使得函数能够处理实时数据流,并根据需要将数据块解析为JSON格式或直接返回。 + +**注意**: +- 函数依赖于`self.post`方法来发送HTTP POST请求,该方法的具体实现和行为可能会影响`search_engine_chat`函数的行为和性能。 +- 使用`stream=True`参数调用`self.post`方法,意味着响应内容将以流的方式接收,适用于处理大量数据或实时数据流。 +- `self._httpx_stream2generator`方法用于处理httpx库返回的HTTP流响应,根据`as_json=True`参数,将流中的数据解析为JSON格式。 + +**输出示例**: +假设搜索引擎返回了关于查询“Python编程”的两条结果,函数可能返回如下格式的生成器输出: +```python +[ + {"title": "Python官方文档", "url": "https://docs.python.org", "snippet": "Python官方文档提供了详细的语言参考..."}, + {"title": "Python教程", "url": "https://www.learnpython.org", "snippet": "这个Python教程适合所有级别的编程者..."} +] +``` +此输出示例展示了以JSON格式返回的搜索结果,包含每个结果的标题、URL和摘要信息。实际输出将根据搜索引擎的响应和处理逻辑而有所不同。 +*** +### FunctionDef list_knowledge_bases(self) +**list_knowledge_bases**: 此函数的功能是列出所有可用的知识库。 + +**参数**: 此函数没有参数。 + +**代码描述**: `list_knowledge_bases` 函数通过发送 HTTP GET 请求到 `/knowledge_base/list_knowledge_bases` 路径,来获取所有可用的知识库列表。函数首先调用 `get` 方法发送请求,并接收返回的响应。然后,它使用 `_get_response_value` 方法处理这个响应,将响应体解析为 JSON 格式,并从中提取 `data` 字段的值。如果 `data` 字段不存在,则默认返回一个空列表。这个过程使得函数能够以结构化的方式返回知识库列表,便于后续的处理和使用。 + +**注意**: +- 函数依赖于 `get` 方法来发送 HTTP 请求,因此需要确保网络连接正常,且目标服务器能够响应 `/knowledge_base/list_knowledge_bases` 路径的请求。 +- 函数返回的知识库列表以 JSON 格式提供,这要求调用方能够处理 JSON 格式的数据。 +- 在处理服务器响应时,如果响应体不能被成功解析为 JSON,或者 `data` 字段不存在,函数将返回一个空列表,而不是抛出异常。这意味着调用方需要对返回的列表进行检查,以确认是否成功获取了知识库列表。 + +**输出示例**: +假设服务器成功响应并返回了两个知识库的信息,函数可能返回如下格式的数据: +```python +[ + {"id": "kb1", "name": "知识库1", "description": "这是第一个知识库的描述"}, + {"id": "kb2", "name": "知识库2", "description": "这是第二个知识库的描述"} +] +``` +如果服务器没有返回任何知识库信息,或者请求失败,函数将返回一个空列表: +```python +[] +``` +*** +### FunctionDef create_knowledge_base(self, knowledge_base_name, vector_store_type, embed_model) +**create_knowledge_base**: 此函数用于创建一个新的知识库。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要创建的知识库的名称。 +- `vector_store_type`: 字符串类型,默认为`DEFAULT_VS_TYPE`,指定向量存储的类型。 +- `embed_model`: 字符串类型,默认为`EMBEDDING_MODEL`,指定用于嵌入的模型。 + +**代码描述**: +`create_knowledge_base`函数主要负责通过API接口创建一个新的知识库。函数首先构造一个包含知识库名称、向量存储类型和嵌入模型的数据字典。然后,使用`post`方法向`/knowledge_base/create_knowledge_base`路径发送POST请求,请求体为上述数据字典。最后,通过调用`_get_response_value`方法处理响应,如果指定`as_json=True`,则尝试将响应体解析为JSON格式并返回。 + +**注意**: +- 确保传入的`knowledge_base_name`不为空,且为唯一的知识库名称,以避免创建重复的知识库。 +- `vector_store_type`和`embed_model`参数应根据实际需求选择合适的类型和模型,这将影响知识库的性能和效果。 +- 函数依赖于`post`方法来发送HTTP请求,该方法提供了重试机制和异常处理,确保网络请求的稳定性。 +- 函数的返回值取决于API的响应结果,通常包含操作的状态码和消息,可能还包含创建的知识库的详细信息。 + +**输出示例**: +假设成功创建了一个名为"ExampleKB"的知识库,且使用默认的向量存储类型和嵌入模型,函数可能返回如下JSON格式的数据: +```python +{ + "code": 200, + "msg": "已新增知识库 ExampleKB", + "data": { + "knowledge_base_name": "ExampleKB", + "vector_store_type": "DEFAULT_VS_TYPE", + "embed_model": "EMBEDDING_MODEL" + } +} +``` +如果尝试创建一个已存在的知识库名称,可能返回的数据如下: +```python +{ + "code": 404, + "msg": "已存在同名知识库 ExampleKB" +} +``` +*** +### FunctionDef delete_knowledge_base(self, knowledge_base_name) +**delete_knowledge_base**: 此函数用于删除指定的知识库。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要删除的知识库名称。 + +**代码描述**: +`delete_knowledge_base` 函数通过发送HTTP POST请求到`/knowledge_base/delete_knowledge_base`端点,请求删除指定名称的知识库。函数接收一个参数`knowledge_base_name`,该参数指定了要删除的知识库的名称。在发送请求时,该名称作为JSON数据体的一部分被发送。请求的响应通过调用`_get_response_value`函数处理,以确保以JSON格式正确解析响应内容。如果响应成功,该函数将返回解析后的JSON数据。 + +**注意**: +- 确保传入的`knowledge_base_name`确实存在于系统中,否则可能会导致删除失败。 +- 删除知识库是一个不可逆的操作,一旦执行,知识库中的所有数据将被永久删除。 +- 在调用此函数之前,建议进行适当的确认流程,以防止意外删除重要数据。 + +**输出示例**: +假设成功删除名为`example_kb`的知识库,函数可能返回如下JSON格式的数据: +```python +{ + "code": 200, + "msg": "成功", + "data": None +} +``` +此输出表示请求已成功处理,知识库已被删除。`code`字段表示操作的状态码,200代表成功。`msg`字段提供了关于操作的简短描述。`data`字段在此操作中通常为空,因为删除操作不返回额外数据。 +*** +### FunctionDef list_kb_docs(self, knowledge_base_name) +**list_kb_docs**: 此函数的功能是列出指定知识库中的文件列表。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要查询的知识库名称。 + +**代码描述**: +`list_kb_docs`函数通过调用`get`方法,向`/knowledge_base/list_files`端点发送HTTP GET请求,以获取指定知识库的文件列表。请求时,将`knowledge_base_name`作为查询参数传递。接收到响应后,利用`_get_response_value`方法处理响应数据,该方法支持将响应体解析为JSON格式,并通过`value_func`参数提供的函数进一步处理解析后的数据,最终返回一个包含文件列表的数组。 + +**注意**: +- 确保传入的`knowledge_base_name`参数正确,以便能够查询到正确的知识库文件列表。 +- 此函数依赖于`get`和`_get_response_value`方法,确保这些依赖方法能够正常工作。 +- 函数处理的响应数据格式依赖于后端API的设计,确保后端`/knowledge_base/list_files`端点的响应格式与此函数的处理逻辑相匹配。 + +**输出示例**: +假设知识库中存在文件`["document1.pdf", "document2.pdf"]`,则函数可能返回如下数组: +```python +["document1.pdf", "document2.pdf"] +``` +此输出示例展示了函数调用成功时,返回的文件列表数组。实际返回的数据将根据指定知识库中实际包含的文件而有所不同。 +*** +### FunctionDef search_kb_docs(self, knowledge_base_name, query, top_k, score_threshold, file_name, metadata) +**search_kb_docs**: 此函数用于在知识库中搜索文档。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要搜索的知识库名称。 +- `query`: 字符串类型,默认为空字符串,指定搜索查询的内容。 +- `top_k`: 整型,默认为`VECTOR_SEARCH_TOP_K`,指定返回的最大文档数量。 +- `score_threshold`: 整型,默认为`SCORE_THRESHOLD`,指定搜索结果的分数阈值。 +- `file_name`: 字符串类型,默认为空字符串,指定要搜索的文件名。 +- `metadata`: 字典类型,默认为空字典,指定要搜索的元数据。 + +**代码描述**: +此函数首先构造一个包含搜索参数的字典`data`,然后使用`post`方法向`/knowledge_base/search_docs`路径发送POST请求,请求体为`data`字典。请求成功后,使用`_get_response_value`方法处理响应,将响应内容解析为JSON格式并返回。这个过程涉及到与后端API的交互,用于在指定的知识库中根据给定的查询条件搜索文档。 + +**注意**: +- 函数内部调用了`post`方法来执行HTTP POST请求,该方法的详细行为请参考`post`函数的文档。 +- 函数还调用了`_get_response_value`方法来处理HTTP响应,该方法的详细行为请参考`_get_response_value`函数的文档。 +- 在使用此函数时,需要确保`knowledge_base_name`正确指向一个存在的知识库,且该知识库中有符合搜索条件的文档。 +- `top_k`和`score_threshold`参数可以用来调整搜索结果的数量和质量,根据实际需求进行设置。 + +**输出示例**: +假设搜索查询返回了两个文档,函数的返回值可能如下: +```python +[ + { + "doc_id": "123", + "title": "文档标题1", + "content": "文档内容示例1", + "score": 0.95, + "metadata": {"author": "作者1", "date": "2023-01-01"} + }, + { + "doc_id": "456", + "title": "文档标题2", + "content": "文档内容示例2", + "score": 0.90, + "metadata": {"author": "作者2", "date": "2023-02-01"} + } +] +``` +此输出示例展示了搜索结果的结构,包括文档ID、标题、内容、匹配分数和元数据。实际的输出将根据搜索查询和知识库中的文档而有所不同。 +*** +### FunctionDef update_docs_by_id(self, knowledge_base_name, docs) +**update_docs_by_id**: 此函数用于根据文档ID更新知识库中的文档。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要更新文档的知识库名称。 +- `docs`: 字典类型,包含要更新的文档ID及其对应的更新内容。 + +**代码描述**: +`update_docs_by_id`函数主要通过发送HTTP POST请求到`/knowledge_base/update_docs_by_id`接口,实现对指定知识库中文档的更新操作。函数接收两个参数:`knowledge_base_name`和`docs`。`knowledge_base_name`参数指定了要更新文档所在的知识库名称,而`docs`参数则是一个字典,其中包含了文档ID及其对应的更新内容。 + +在函数内部,首先构造了一个包含`knowledge_base_name`和`docs`的字典`data`,然后调用`post`方法发送POST请求。`post`方法是`ApiRequest`类的一个成员方法,用于执行HTTP POST请求。在调用`post`方法时,将`/knowledge_base/update_docs_by_id`作为请求的URL,并将`data`字典作为JSON数据传递给该方法。 + +请求成功发送并接收到响应后,函数调用`_get_response_value`方法处理响应数据。`_get_response_value`是`ApiRequest`类的另一个成员方法,负责转换HTTP响应对象,并根据指定的参数返回处理后的数据。在本函数中,`_get_response_value`方法用于解析响应数据,并返回处理结果。 + +**注意**: +- 确保传入的`knowledge_base_name`和`docs`参数格式正确,且`docs`中的文档ID存在于指定的知识库中。 +- 此函数的返回值依赖于`_get_response_value`方法的处理结果,通常为布尔值,表示更新操作是否成功。 + +**输出示例**: +假设更新操作成功,函数可能返回`True`。如果更新操作失败,可能返回`False`或者具体的错误信息。具体的返回值取决于`_get_response_value`方法的实现细节及服务器响应的内容。 +*** +### FunctionDef upload_kb_docs(self, files, knowledge_base_name, override, to_vector_store, chunk_size, chunk_overlap, zh_title_enhance, docs, not_refresh_vs_cache) +**upload_kb_docs**: 此函数用于上传文档到知识库,并可选择性地将文档内容添加到向量存储中。 + +**参数**: +- `files`: 文件列表,可以是字符串、路径对象或字节数据的列表。 +- `knowledge_base_name`: 知识库名称,指定要上传文档的目标知识库。 +- `override`: 布尔值,默认为False。如果为True,则在上传文件时覆盖同名文件。 +- `to_vector_store`: 布尔值,默认为True。决定是否将上传的文档内容添加到向量存储中。 +- `chunk_size`: 整数,指定文档分块的大小,默认值为CHUNK_SIZE。 +- `chunk_overlap`: 整数,指定分块之间的重叠大小,默认值为OVERLAP_SIZE。 +- `zh_title_enhance`: 布尔值,指定是否启用中文标题加强,默认值为ZH_TITLE_ENHANCE。 +- `docs`: 字典,可用于提供文档的额外元数据,默认为空字典。 +- `not_refresh_vs_cache`: 布尔值,默认为False。指定是否在添加文档到向量存储后刷新向量存储的缓存。 + +**代码描述**: +此函数首先将`files`参数中的每个文件转换为适合上传的格式。对于字节数据,将其包装为`BytesIO`对象;对于具有`read`方法的文件对象,直接使用;对于文件路径,将其打开为二进制读取模式。然后,构造一个包含所有必要信息的`data`字典,包括知识库名称、是否覆盖、是否添加到向量存储、分块大小、分块重叠、中文标题加强、文档元数据以及是否刷新向量存储的缓存。如果`docs`参数是字典,则将其转换为JSON字符串。最后,使用`post`方法向`/knowledge_base/upload_docs`路径发送POST请求,上传文件和相关数据,并通过`_get_response_value`方法处理响应,返回JSON格式的响应数据。 + +**注意**: +- 在上传大量数据或大文件时,考虑适当调整`chunk_size`和`chunk_overlap`参数以优化处理性能。 +- 如果`to_vector_store`参数设置为True,确保知识库配置支持向量存储。 +- 使用`docs`参数传递额外的文档元数据时,确保其格式正确,以便成功解析。 + +**输出示例**: +假设上传操作成功,函数可能返回如下格式的数据: +```python +{ + "code": 200, + "msg": "上传成功", + "data": { + "failed_files": [] + } +} +``` +如果上传过程中有文件因为各种原因失败,`failed_files`列表将包含这些文件的信息。 +#### FunctionDef convert_file(file, filename) +**convert_file**: 此函数的功能是将不同类型的文件输入转换为文件名和文件对象的形式。 + +**参数**: +- **file**: 可以是字节串、具有read方法的文件对象或本地文件路径。 +- **filename**: 可选参数,用于指定文件名。如果未提供,则会根据文件对象或路径自动确定文件名。 + +**代码描述**: +此函数处理三种类型的输入: +1. 如果输入是字节串(`bytes`),则将其转换为`BytesIO`对象,以便像文件一样操作。 +2. 如果输入具有`read`方法(例如,已打开的文件对象),则直接使用该对象。如果提供了`filename`参数,则使用该参数值;如果未提供,则尝试从文件对象的`name`属性获取文件名。 +3. 如果输入既不是字节串也没有`read`方法(即假定为本地文件路径),则尝试打开该路径指向的文件(以二进制读取模式),并自动确定文件名。如果提供了`filename`参数,则使用该参数值;如果未提供,则从路径中提取文件名。 + +**注意**: +- 输入的文件路径应该是有效且可访问的,否则在尝试打开文件时会引发异常。 +- 当输入为字节串时,不会自动确定文件名,因此在这种情况下提供`filename`参数尤为重要。 + +**输出示例**: +假设有一个本地文件路径`"/path/to/document.pdf"`,调用`convert_file("/path/to/document.pdf")`将返回: +``` +("document.pdf", <_io.BufferedReader name='/path/to/document.pdf'>) +``` +这表示函数返回了文件名`"document.pdf"`和一个文件对象,后者可以用于进一步的文件操作。 +*** +*** +### FunctionDef delete_kb_docs(self, knowledge_base_name, file_names, delete_content, not_refresh_vs_cache) +**delete_kb_docs**: 此函数用于从知识库中删除指定的文档。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要操作的知识库名称。 +- `file_names`: 字符串列表,指定要删除的文件名称列表。 +- `delete_content`: 布尔类型,默认为False,指定是否同时删除文件内容。 +- `not_refresh_vs_cache`: 布尔类型,默认为False,指定是否不刷新向量搜索的缓存。 + +**代码描述**: +此函数首先构造一个包含知识库名称、文件名称列表、是否删除内容以及是否刷新向量搜索缓存的字典`data`。然后,调用`post`方法向`/knowledge_base/delete_docs`路径发送POST请求,请求体为`data`字典。最后,调用`_get_response_value`方法处理响应,并以JSON格式返回处理结果。 + +**注意**: +- 在调用此函数时,需要确保`knowledge_base_name`和`file_names`参数正确指向存在的知识库和文件,否则可能导致删除失败。 +- `delete_content`参数控制是否删除文件的实际内容,如果设置为True,则文件将被完全删除;如果为False,则只从知识库的索引中移除文件,文件本身保留。 +- `not_refresh_vs_cache`参数用于控制是否刷新向量搜索的缓存,如果为True,则在删除文件后不刷新缓存,这可能会影响后续的搜索结果准确性。 + +**输出示例**: +假设成功删除了指定的文件,函数可能返回如下的JSON对象: +```python +{ + "code": 200, + "msg": "成功", + "data": { + "failed_files": [] + } +} +``` +如果指定的文件不存在或删除失败,返回的JSON对象中`failed_files`列表将包含这些文件的名称。 +*** +### FunctionDef update_kb_info(self, knowledge_base_name, kb_info) +**update_kb_info**: 此函数用于更新知识库的信息。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要更新的知识库名称。 +- `kb_info`: 字符串类型,提供知识库的新信息。 + +**代码描述**: +`update_kb_info`函数主要负责向后端发送请求,更新指定知识库的信息。它首先构造一个包含知识库名称(`knowledge_base_name`)和新的知识库信息(`kb_info`)的字典`data`。然后,使用`post`方法发送一个HTTP POST请求到`/knowledge_base/update_info`端点,携带上述`data`作为JSON数据。请求成功后,通过调用`_get_response_value`方法处理响应,如果指定`as_json=True`,则尝试将响应体解析为JSON格式并返回。 + +**注意**: +- 调用此函数时需要确保提供的知识库名称(`knowledge_base_name`)在系统中已存在,否则可能无法成功更新。 +- 更新的信息(`kb_info`)应为字符串格式,可以包含知识库的描述、元数据等信息。 +- 函数内部通过`post`方法发送HTTP请求,并通过`_get_response_value`方法处理响应,这两个方法的具体实现和异常处理机制对于理解函数行为非常重要。 + +**输出示例**: +假设更新知识库信息成功,返回的JSON响应可能如下: +```python +{ + "code": 200, + "msg": "知识库信息更新成功", + "data": { + "knowledge_base_name": "example_kb", + "kb_info": "更新后的知识库描述" + } +} +``` +此输出示例展示了一个典型的成功响应,其中包含状态码`200`、成功消息以及更新后的知识库名称和描述。实际返回的数据结构可能根据后端实现的不同而有所变化。 +*** +### FunctionDef update_kb_docs(self, knowledge_base_name, file_names, override_custom_docs, chunk_size, chunk_overlap, zh_title_enhance, docs, not_refresh_vs_cache) +**update_kb_docs**: 此函数用于更新知识库中的文档。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要更新文档的知识库名称。 +- `file_names`: 字符串列表,包含需要更新的文件名。 +- `override_custom_docs`: 布尔类型,默认为False,指定是否覆盖自定义文档。 +- `chunk_size`: 整型,指定文档分块的大小,默认值由`CHUNK_SIZE`常量决定。 +- `chunk_overlap`: 整型,指定文档分块之间的重叠大小,默认值由`OVERLAP_SIZE`常量决定。 +- `zh_title_enhance`: 布尔类型,指定是否增强中文标题,默认值由`ZH_TITLE_ENHANCE`常量决定。 +- `docs`: 字典类型,包含要更新的文档内容,默认为空字典。 +- `not_refresh_vs_cache`: 布尔类型,默认为False,指定是否不刷新向量搜索缓存。 + +**代码描述**: +此函数首先构造一个包含所有参数的字典`data`,用于作为HTTP请求的负载。如果`docs`参数是字典类型,则将其转换为JSON字符串。然后,调用`post`方法向`/knowledge_base/update_docs`路径发送POST请求,请求体为`data`字典。最后,调用`_get_response_value`方法处理响应,如果指定`as_json`为True,则返回JSON格式的响应数据。 + +**注意**: +- 在调用此函数之前,确保知识库名称和文件名正确无误,以避免更新错误的文档。 +- 当`override_custom_docs`为True时,将覆盖知识库中的自定义文档,需谨慎使用此选项。 +- `chunk_size`和`chunk_overlap`参数影响文档分块的方式,不当的值可能影响搜索效果。 +- 如果`docs`参数非空,函数将更新指定的文档内容;否则,仅更新文件名列表中的文件。 +- `not_refresh_vs_cache`为True时,更新文档后不刷新向量搜索缓存,可能影响搜索结果的实时性。 + +**输出示例**: +```python +{ + "code": 200, + "msg": "文档更新成功", + "data": { + "failed_files": [] + } +} +``` +此示例表示更新操作成功执行,且所有指定的文件都已成功更新,没有失败的文件。 +*** +### FunctionDef recreate_vector_store(self, knowledge_base_name, allow_empty_kb, vs_type, embed_model, chunk_size, chunk_overlap, zh_title_enhance) +**recreate_vector_store**: 此函数用于重建知识库中的向量存储。 + +**参数**: +- `knowledge_base_name`: 字符串类型,指定要重建向量存储的知识库名称。 +- `allow_empty_kb`: 布尔类型,默认为True,指定是否允许空的知识库。 +- `vs_type`: 字符串类型,默认为`DEFAULT_VS_TYPE`,指定向量存储的类型。 +- `embed_model`: 字符串类型,默认为`EMBEDDING_MODEL`,指定用于嵌入的模型。 +- `chunk_size`: 整型,默认为`CHUNK_SIZE`,指定文本块的大小。 +- `chunk_overlap`: 整型,默认为`OVERLAP_SIZE`,指定文本块之间的重叠大小。 +- `zh_title_enhance`: 布尔类型,默认为`ZH_TITLE_ENHANCE`,指定是否增强中文标题。 + +**代码描述**: +函数首先构造一个包含所有参数的字典`data`,然后通过调用`self.post`方法,向`/knowledge_base/recreate_vector_store`路径发送POST请求,请求体为`data`字典。此请求旨在后端服务中重建指定知识库的向量存储。请求的响应通过`self._httpx_stream2generator`方法转换为生成器,以便以流的方式处理响应数据。如果`as_json`参数为True,则响应数据将被解析为JSON格式。 + +**注意**: +- 该函数依赖于`self.post`方法来发送HTTP POST请求,`self.post`方法的详细行为请参考其文档。 +- `self._httpx_stream2generator`方法用于处理流式响应,其详细行为请参考其文档。 +- 函数的执行结果依赖于后端服务的实现和状态,以及提供的参数是否符合后端服务的要求。 + +**输出示例**: +```python +[ + {"code": 200, "msg": "向量存储重建成功"}, + {"finished": 1, "total": 10, "msg": "正在处理..."}, + ... +] +``` +此输出示例展示了函数返回值的可能形式,其中包含了多个字典,每个字典代表了重建过程中的一个状态或结果。`code`为200表示操作成功,`finished`和`total`字段表示当前处理进度,`msg`提供了额外的状态信息或错误消息。 +*** +### FunctionDef list_running_models(self, controller_address) +**list_running_models**: 此函数用于获取Fastchat中正运行的模型列表。 + +**参数**: +- `controller_address`: 字符串类型,可选参数,默认为None。用于指定控制器的地址。 + +**代码描述**: +`list_running_models`函数主要通过发送HTTP POST请求到`/llm_model/list_running_models`端点,来获取当前Fastchat中正在运行的模型列表。函数首先构造一个包含`controller_address`的字典作为请求的数据。如果`log_verbose`变量为真,则会通过日志记录器记录发送的数据。随后,使用`post`方法发送请求,并通过`_get_response_value`方法处理响应,最终以JSON格式返回模型列表。如果响应中不存在"data"键,则默认返回空列表。 + +**注意**: +- 函数内部调用了`post`方法来执行HTTP POST请求,该方法的详细行为请参考`post`方法的文档。 +- 函数还调用了`_get_response_value`方法来处理HTTP响应,该方法支持自定义处理逻辑,具体细节请参考`_get_response_value`方法的文档。 +- 函数的执行依赖于`controller_address`参数,该参数用于指定控制器的地址,如果未提供,则默认为None。 +- 函数的返回值是通过`_get_response_value`方法处理后的结果,通常是一个包含运行中模型信息的列表。 + +**输出示例**: +```python +[ + { + "model_name": "model1", + "status": "running", + "controller_address": "192.168.1.100" + }, + { + "model_name": "model2", + "status": "running", + "controller_address": "192.168.1.101" + } +] +``` +此示例展示了函数可能的返回值,其中包含了两个正在运行的模型的信息,每个模型信息包括模型名称、状态以及控制器地址。 +*** +### FunctionDef get_default_llm_model(self, local_first) +**get_default_llm_model**: 此函数的功能是从服务器上获取当前运行的LLM(大型语言模型)模型名称及其运行位置(本地或在线)。 + +**参数**: +- `local_first`: 布尔值,默认为True。当设置为True时,函数会优先返回本地运行的模型;当设置为False时,会根据LLM_MODELS配置的顺序返回模型。 + +**代码描述**: +`get_default_llm_model`函数首先定义了两个内部函数`ret_sync`和`ret_async`,用于同步和异步环境下获取默认的LLM模型。函数根据`self._use_async`的值选择使用哪个内部函数。这两个内部函数的逻辑基本相同,区别在于`ret_async`使用了异步的方式来获取正在运行的模型列表。 + +函数逻辑如下: +1. 获取当前正在运行的模型列表。 +2. 遍历配置中的LLM模型(LLM_MODELS),检查每个模型是否在运行列表中。 +3. 如果找到了在运行列表中的模型,会根据`local_first`参数和模型是否为本地模型(通过检查`online_api`字段判断)来决定是否选择该模型。 +4. 如果没有根据上述逻辑找到模型,那么会选择运行列表中的第一个模型作为默认模型。 +5. 返回选择的模型名称和该模型是否为本地模型的信息。 + +在项目中,`get_default_llm_model`函数被用于不同的场景,例如在`test_get_default_llm`测试用例中验证函数返回值的类型,以及在`dialogue_page`函数中获取默认的LLM模型并在用户界面上显示当前运行的模型信息。这表明该函数在项目中扮演着获取当前有效LLM模型信息的关键角色,以便其他部分可以基于这些信息进行进一步的操作或显示。 + +**注意**: +- 在使用此函数时,需要确保`LLM_MODELS`配置正确,且`list_running_models`方法能够正确返回当前运行的模型列表。 +- 函数的异步版本`ret_async`需要在支持异步的环境中运行。 + +**输出示例**: +```python +("gpt-3", True) +``` +此输出表示当前运行的默认LLM模型为"gpt-3",且该模型是本地运行的。 +#### FunctionDef ret_sync +**ret_sync**: 此函数用于同步返回当前可用的本地或在线模型名称及其类型。 + +**参数**: 此函数不接受任何参数。 + +**代码描述**: `ret_sync`函数首先调用`list_running_models`方法获取当前正在运行的模型列表。如果没有模型正在运行,则返回一个空字符串和False。接下来,函数遍历预定义的模型列表`LLM_MODELS`,检查每个模型是否在运行中的模型列表里。如果找到一个在运行列表中的模型,会进一步检查该模型是否为本地模型(即不是通过在线API运行的模型)。如果`local_first`变量为真且当前模型不是本地模型,则继续检查下一个模型。如果找到符合条件的模型,则返回该模型名称和它是否为本地模型的布尔值。如果`LLM_MODELS`中的所有模型都不在运行中的模型列表里,则默认选择运行列表中的第一个模型,并返回其名称和它是否为本地模型的布尔值。 + +**注意**: +- `list_running_models`方法的返回值是关键,因为它决定了`ret_sync`函数能否找到有效的模型。该方法的详细行为请参考其文档。 +- `local_first`变量控制优先选择本地模型还是在线模型,但在代码片段中未显示其定义,通常应在函数外部定义。 +- 此函数假设`LLM_MODELS`是一个预定义的模型名称列表,用于指定优先考虑的模型顺序。 +- 函数返回的模型名称和是否为本地模型的信息,可以用于后续操作,比如初始化模型或者决定使用哪个模型提供服务。 + +**输出示例**: +```python +("model1", True) +``` +此示例表示函数返回了名为"model1"的模型,且该模型是本地运行的。 +*** +#### FunctionDef ret_async +**ret_async**: 此函数用于异步获取当前最适合的语言模型及其运行位置。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `ret_async`函数首先通过调用`list_running_models`方法异步获取当前正在运行的模型列表。如果没有模型正在运行,则函数返回一个空字符串和False。接着,函数遍历预定义的语言模型列表`LLM_MODELS`,检查每个模型是否在运行中的模型列表里。对于每个正在运行的模型,函数检查该模型是否标记为本地运行(即不通过在线API运行)。如果`local_first`变量为真且模型不是本地运行的,则跳过该模型。一旦找到符合条件的模型,函数将其作为结果返回。如果`LLM_MODELS`中的所有模型都不在运行中的模型列表里,则选择`running_models`中的第一个模型作为结果返回。最后,函数根据模型是否通过在线API运行,返回模型名称和一个表示是否本地运行的布尔值。 + +此函数与`list_running_models`方法紧密相关,后者负责提供当前正在运行的模型列表。这种设计使得`ret_async`能够基于实时的模型运行状态,智能地选择最合适的模型进行操作。 + +**注意**: +- 该函数是异步的,需要在支持异步操作的环境中运行。 +- `local_first`变量控制是否优先选择本地运行的模型,但该变量的定义和赋值在代码片段之外,需要根据实际使用场景进行配置。 +- 函数返回的模型名称为空字符串和布尔值False表示没有找到任何可用的模型。 + +**输出示例**: +```python +("model1", True) +``` +此示例表示函数返回了名为"model1"的模型,且该模型是本地运行的。 +*** +*** +### FunctionDef list_config_models(self, types) +**list_config_models**: 此函数用于获取服务器中配置的模型列表。 + +**参数**: +- `types`: 字符串列表,默认值为["local", "online"]。用于指定需要获取的模型类型。 + +**代码描述**: +`list_config_models`函数主要用于从服务器获取配置的模型列表。它接受一个参数`types`,这个参数是一个字符串列表,用于指定要获取的模型类型。默认情况下,这个列表包括"local"和"online"两种类型,分别代表本地模型和在线模型。 + +函数内部首先构造一个包含`types`的字典`data`,然后使用`self.post`方法向服务器发送一个POST请求,请求的URL为"/llm_model/list_config_models",请求体为`data`字典。`self.post`方法是一个执行HTTP POST请求的函数,具体实现请参考`post`函数的文档。 + +请求成功返回后,函数使用`self._get_response_value`方法处理响应。`self._get_response_value`是一个转换HTTP响应对象的函数,它可以根据指定的参数返回处理后的数据。在本函数中,它被用来解析响应体,并尝试将其解析为JSON格式。如果解析成功,函数将返回一个字典,这个字典的结构为`{"type": {model_name: config}, ...}`,其中`type`是模型的类型,`model_name`是模型的名称,`config`是模型的配置信息。 + +**注意**: +- 函数依赖于`self.post`和`self._get_response_value`两个方法,确保这两个方法在使用前已正确实现。 +- 返回的模型列表和配置信息的具体结构可能会根据服务器端的实现有所不同,请根据实际情况进行调整。 + +**输出示例**: +```python +{ + "local": { + "model1": {"config1": "value1"}, + "model2": {"config2": "value2"} + }, + "online": { + "model3": {"config3": "value3"}, + "model4": {"config4": "value4"} + } +} +``` +此示例展示了函数可能的返回值,其中包含了两种类型的模型("local"和"online")及其配置信息。 +*** +### FunctionDef get_model_config(self, model_name) +**get_model_config**: 此函数用于获取服务器上指定模型的配置信息。 + +**参数**: +- `model_name`: 字符串类型,指定要查询配置的模型名称。默认值为None。 + +**代码描述**: +`get_model_config`函数首先构造一个包含模型名称的字典`data`,然后使用`post`方法向服务器发送请求,请求的URL为`"/llm_model/get_model_config"`。这里的`post`方法是`ApiRequest`类的一个成员方法,用于执行HTTP POST请求。请求成功返回的响应通过`_get_response_value`方法处理,以获取JSON格式的响应数据。`_get_response_value`是另一个`ApiRequest`类的成员方法,负责转换HTTP响应对象,并根据指定的参数返回处理后的数据。在本函数中,`_get_response_value`方法使用了一个lambda函数作为`value_func`参数,该lambda函数尝试从响应数据中获取`"data"`字段的值,如果不存在则返回空字典。 + +**注意**: +- 函数通过`post`方法发送HTTP POST请求,因此需要确保网络连接正常,且服务器能够正确处理该请求。 +- 返回的模型配置信息以字典形式提供,具体包含的配置项取决于服务器端模型配置的实现细节。 +- 如果服务器响应中不包含`"data"`字段,或者`model_name`参数指定的模型不存在,函数将返回空字典。 + +**输出示例**: +假设服务器上存在名为`"example_model"`的模型,其配置信息包括模型的版本号和支持的语言,那么函数的返回值可能如下所示: +```python +{ + "version": "1.0", + "supported_languages": ["English", "Chinese"] +} +``` +在实际使用中,返回的字典将包含服务器上指定模型的具体配置信息。 +*** +### FunctionDef list_search_engines(self) +**list_search_engines**: 此函数的功能是获取服务器支持的搜索引擎列表。 + +**参数**: 此函数没有参数。 + +**代码描述**: `list_search_engines` 函数首先通过调用 `post` 方法向服务器发送一个 HTTP POST 请求,请求的 URL 是 "/server/list_search_engines"。这个请求不需要任何额外的数据或参数。接收到服务器的响应后,函数利用 `_get_response_value` 方法处理这个响应。`_get_response_value` 方法被配置为以 JSON 格式解析响应内容,并通过一个 lambda 函数提取响应 JSON 中的 "data" 字段。如果 "data" 字段不存在,则默认返回一个空字典。最终,此函数返回一个包含搜索引擎名称的字符串列表。 + +**注意**: +- 函数依赖于 `post` 方法来发送 HTTP 请求,该方法提供了重试机制和异常处理,确保网络请求的稳定性。 +- `_get_response_value` 方法用于解析 HTTP 响应,支持同步或异步模式,并允许通过自定义函数进一步处理解析后的数据。 +- 返回的搜索引擎列表取决于服务器配置和可用性,可能会随时间或服务器设置的变化而变化。 + +**输出示例**: +```python +["Google", "Bing", "DuckDuckGo"] +``` +此示例展示了函数可能返回的搜索引擎名称列表。实际返回的列表取决于服务器当前支持的搜索引擎。 +*** +### FunctionDef stop_llm_model(self, model_name, controller_address) +**stop_llm_model**: 此函数用于停止某个LLM模型。 + +**参数**: +- `model_name`: 字符串类型,指定要停止的LLM模型的名称。 +- `controller_address`: 字符串类型,默认为None,指定控制器的地址。 + +**代码描述**: +`stop_llm_model`函数主要用于停止指定的LLM模型。在Fastchat的实现中,这通常意味着停止运行该LLM模型的`model_worker`。函数接收两个参数:`model_name`用于指定要停止的模型名称,`controller_address`用于指定控制器的地址,后者是可选的。 + +函数首先构造一个包含`model_name`和`controller_address`的字典`data`,然后通过调用`post`方法向`/llm_model/stop`路径发送POST请求,请求的数据体为`data`字典。`post`方法是`ApiRequest`类的一个成员方法,用于执行HTTP POST请求,并能够处理重试逻辑、异常捕获等。 + +在发送POST请求并接收到响应后,函数调用`_get_response_value`方法来处理响应。`_get_response_value`方法能够将HTTP响应对象转换为JSON格式(如果`as_json`参数为True),或者根据提供的`value_func`函数自定义处理逻辑。在本函数中,`as_json`参数被设置为True,意味着期望将响应体解析为JSON格式。 + +**注意**: +- 在使用此函数时,需要确保提供的`model_name`确实存在,并且有对应的`model_worker`在运行。 +- 如果`controller_address`未指定,将使用默认的控制器地址。确保默认地址的正确性或显式提供地址参数。 +- 函数的执行结果依赖于网络请求的成功与否,以及LLM模型的状态。因此,调用此函数后应检查返回的JSON数据,确认模型是否成功停止。 + +**输出示例**: +假设成功停止了名为`example_model`的LLM模型,函数可能返回如下JSON格式的数据: +```python +{ + "code": 200, + "msg": "模型停止成功", + "data": { + "model_name": "example_model", + "status": "stopped" + } +} +``` +此输出示例展示了一个成功的停止操作,其中`code`字段表示操作成功,`msg`字段提供了操作成功的消息,`data`字段包含了被停止模型的名称和其新状态。 +*** +### FunctionDef change_llm_model(self, model_name, new_model_name, controller_address) +**change_llm_model**: 此函数用于请求切换当前运行的大型语言模型(LLM)至另一个模型。 + +**参数**: +- `model_name`: 字符串类型,表示当前正在运行的模型名称。 +- `new_model_name`: 字符串类型,表示要切换到的新模型名称。 +- `controller_address`: 字符串类型,可选参数,默认为None,表示控制器的地址。 + +**代码描述**: +`change_llm_model` 函数首先检查`model_name`和`new_model_name`是否被指定,如果没有指定,则返回一个包含错误代码和消息的字典。接着,根据`self._use_async`的值决定是同步执行还是异步执行模型切换逻辑。 + +在同步(`ret_sync`)或异步(`ret_async`)执行逻辑中,首先获取当前正在运行的模型列表和配置中的模型列表。如果新模型名称与当前模型名称相同,或新模型已在运行中,则返回无需切换的消息。如果指定的当前模型未在运行中,或新模型未在配置中,则返回相应的错误消息。 + +如果检查通过,则构造一个包含模型名称和控制器地址的数据字典,通过POST请求向`/llm_model/change`端点发送请求,请求切换模型。最后,返回请求的响应值。 + +在项目中,`change_llm_model`函数被`webui_pages/dialogue/dialogue.py/dialogue_page`对象调用,用于处理用户通过界面选择切换LLM模型的操作。当用户选择一个新的模型并触发模型切换时,此函数负责向后端发送切换模型的请求,并处理响应,如显示成功或错误消息。 + +**注意**: +- 确保`model_name`和`new_model_name`正确指定,且新模型已在系统配置中定义。 +- 异步执行需要在支持异步的环境中运行。 + +**输出示例**: +```json +{ + "code": 200, + "msg": "模型切换成功" +} +``` +或者在错误情况下: +```json +{ + "code": 500, + "msg": "指定的模型'example_model'没有运行。当前运行模型:['model1', 'model2']" +} +``` +#### FunctionDef ret_sync +**ret_sync**: 此函数用于同步切换模型,并返回切换结果。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `ret_sync`函数首先调用`list_running_models`方法获取当前正在运行的模型列表。然后,它检查`new_model_name`是否等于`model_name`或是否已存在于运行模型列表中,如果是,则返回一个包含状态码200和消息"无需切换"的字典。如果指定的`model_name`不在运行模型列表中,则返回一个包含状态码500和相应错误消息的字典,指出指定模型未运行。接着,函数调用`list_config_models`方法获取配置中的模型列表,如果`new_model_name`不在配置模型列表中,则返回一个包含状态码500和错误消息的字典,指出要切换的模型未在配置中设置。 + +如果以上检查都通过,则构造一个包含`model_name`、`new_model_name`和`controller_address`的数据字典,使用`post`方法向`/llm_model/change`端点发送请求,请求切换模型。最后,调用`_get_response_value`方法处理响应,并以JSON格式返回结果。 + +**注意**: +- 函数内部逻辑依赖于`list_running_models`、`list_config_models`、`post`和`_get_response_value`四个方法,确保这些方法在使用前已正确实现。 +- 函数中使用的`model_name`、`new_model_name`和`controller_address`变量应在函数外部定义并传递给函数,本文档中未显示这些变量的来源和定义方式。 +- 返回的状态码和消息用于指示操作的结果,包括是否需要切换模型、指定模型是否运行以及是否在配置中找到要切换的模型。 + +**输出示例**: +```python +{ + "code": 200, + "msg": "无需切换" +} +``` +或 +```python +{ + "code": 500, + "msg": "指定的模型'model_name'没有运行。当前运行模型:['model1', 'model2']" +} +``` +或 +```python +{ + "code": 500, + "msg": "要切换的模型'new_model_name'在configs中没有配置。" +} +``` +此示例展示了函数可能的返回值,包括不需要切换、指定模型未运行和要切换的模型未配置等情况。 +*** +#### FunctionDef ret_async +**ret_async**: 此函数用于异步切换当前运行的语言模型。 + +**参数**: 此函数不接受任何外部参数。 + +**代码描述**: `ret_async` 函数首先通过调用 `list_running_models` 方法获取当前正在运行的模型列表。然后,它检查请求切换的新模型名称 `new_model_name` 是否已经是当前模型或已存在于运行模型列表中,如果是,则返回一个状态码为200的消息,表示无需切换。如果指定的当前模型 `model_name` 不在运行模型列表中,则返回一个状态码为500的消息,提示指定模型没有运行。接着,函数通过调用 `list_config_models` 方法获取配置中的模型列表,检查新模型名称是否在配置的模型列表中,如果不在,则返回一个状态码为500的消息,提示要切换的模型在配置中未找到。 + +如果以上检查都通过,函数将构造一个包含模型名称、新模型名称和控制器地址的数据字典,然后使用 `post` 方法向 `/llm_model/change` 端点发送请求以执行模型切换操作。最后,通过调用 `_get_response_value` 方法处理响应,并以JSON格式返回结果。 + +**注意**: +- 函数内部使用了 `self.list_running_models` 和 `self.list_config_models` 方法来获取当前运行的模型列表和配置的模型列表,确保这些方法能够正确返回所需的数据。 +- 使用 `self.post` 方法发送HTTP请求,该方法的详细行为请参考 `post` 方法的文档。 +- 使用 `_get_response_value` 方法来处理HTTP响应,该方法支持将响应体解析为JSON格式,具体细节请参考 `_get_response_value` 方法的文档。 +- 函数的执行依赖于 `model_name`、`new_model_name` 和 `controller_address` 这几个变量的正确设置,这些变量需要在函数调用之前被正确赋值。 + +**输出示例**: +假设请求切换的新模型已经在运行或配置中不存在,函数可能返回以下示例之一的JSON格式数据: +```python +{ + "code": 200, + "msg": "无需切换" +} +``` +或 +```python +{ + "code": 500, + "msg": "指定的模型'model_name'没有运行。当前运行模型:['model1', 'model2']" +} +``` +或 +```python +{ + "code": 500, + "msg": "要切换的模型'new_model_name'在configs中没有配置。" +} +``` +*** +*** +### FunctionDef embed_texts(self, texts, embed_model, to_query) +**embed_texts**: 此函数用于对文本进行向量化,支持使用本地嵌入模型或在线支持嵌入的模型。 + +**参数**: +- `texts`: 字符串列表,表示需要进行向量化的文本列表。 +- `embed_model`: 字符串类型,默认为`EMBEDDING_MODEL`,指定使用的嵌入模型。 +- `to_query`: 布尔类型,默认为False,指示是否将结果用于查询。 + +**代码描述**: +`embed_texts`函数首先构造一个包含`texts`、`embed_model`和`to_query`的字典`data`,然后通过调用`post`方法向`/other/embed_texts`路径发送POST请求,请求体为`data`字典。此请求旨在获取指定文本的向量化表示。`post`方法负责执行HTTP POST请求,具体实现包括重试逻辑和异常处理,确保网络请求的健壮性。成功发送请求并接收响应后,`embed_texts`函数通过调用`_get_response_value`方法处理响应。`_get_response_value`方法负责转换HTTP响应,可以根据需要返回响应体的JSON解析结果或通过自定义函数进一步处理。在本函数中,`_get_response_value`使用了一个lambda函数作为`value_func`参数,该lambda函数接收响应的JSON解析结果,并返回其中的`data`字段,即向量化后的文本数据。 + +**注意**: +- 确保传入的`texts`参数为有效的文本列表,且`embed_model`参数指定的模型支持文本向量化。 +- `to_query`参数应根据实际使用场景设置,以确保向量化结果的正确应用。 +- 函数依赖于`post`和`_get_response_value`方法,确保这些方法能够正确处理HTTP请求和响应。 + +**输出示例**: +假设对两个文本`["你好", "世界"]`进行向量化,且函数成功执行,可能的返回值为: +```python +[ + [0.1, 0.2, 0.3, ...], # "你好"的向量化表示 + [0.4, 0.5, 0.6, ...] # "世界"的向量化表示 +] +``` +此输出示例展示了每个文本向量化后的浮点数列表,具体向量的维度和值取决于使用的嵌入模型。 +*** +### FunctionDef chat_feedback(self, message_id, score, reason) +**chat_feedback**: 此函数用于提交对话反馈评价。 + +**参数**: +- `message_id`: 字符串类型,指定需要反馈的消息ID。 +- `score`: 整型,表示对话的评分。 +- `reason`: 字符串类型,默认为空字符串,提供评分的原因。 + +**代码描述**: +`chat_feedback`函数主要用于收集用户对聊天消息的反馈,包括评分和原因。它通过构造一个包含`message_id`、`score`和`reason`的字典`data`,然后调用`post`方法向服务器的`/chat/feedback`路径发送POST请求,提交用户的反馈信息。`post`方法负责执行HTTP POST请求,并根据提供的参数发送数据。在成功发送请求并接收到响应后,`chat_feedback`函数通过调用`_get_response_value`方法处理响应数据,该方法负责转换HTTP响应对象,并根据指定的参数返回处理后的数据。最终,`chat_feedback`函数返回处理后的响应数据。 + +**注意**: +- 确保`message_id`和`score`参数正确无误,因为它们是提交反馈的关键信息。 +- `score`参数应该是一个整数,代表用户对该消息的满意程度。 +- `reason`参数虽然是可选的,但提供具体的反馈原因可以帮助改进服务或对话质量。 +- 此函数的执行结果依赖于服务器的响应,因此需要确保服务器端正确处理反馈请求。 + +**输出示例**: +由于此函数的返回值依赖于服务器的响应,具体的输出示例将根据不同的请求URL和参数而有所不同。一般情况下,如果服务器处理成功,可能返回一个包含处理结果的整数值,例如`200`表示成功。 +*** +## ClassDef AsyncApiRequest +**AsyncApiRequest**: AsyncApiRequest 类的功能是提供异步 API 请求的封装。 + +**属性**: +- `base_url`: API 服务器的基础 URL。 +- `timeout`: 请求超时时间,默认值由 `HTTPX_DEFAULT_TIMEOUT` 定义。 +- `_use_async`: 表示是否使用异步模式,在此类中默认为 True。 + +**代码描述**: +AsyncApiRequest 类继承自 ApiRequest 类,专门用于处理异步 API 请求。它通过构造函数接收基础 URL 和超时时间作为参数,并在初始化时将 `_use_async` 属性设置为 True,这表明所有的请求都将以异步方式进行。这一设计使得 AsyncApiRequest 类能够在需要处理大量或长时间运行的网络请求时,提高程序的效率和响应性。 + +在项目中,AsyncApiRequest 类与 ApiRequest 类共同构成了 API 请求的核心处理机制。ApiRequest 类提供了基础的同步和异步请求处理能力,包括 GET、POST 和 DELETE 方法的封装,以及请求重试、流式请求和响应数据处理等功能。AsyncApiRequest 类通过继承 ApiRequest 类,专注于异步请求的处理,使得在需要异步处理网络请求的场景中,开发者可以更方便地实现高效的网络通信。 + +**注意**: +- 在使用 AsyncApiRequest 类时,需要确保传入的 `base_url` 参数正确指向目标 API 服务器。 +- 由于 AsyncApiRequest 类处理的是异步请求,因此在调用其方法时,需要在相应的调用处使用 `await` 关键字,以确保异步操作能够正确执行并获取到结果。 +- 在处理异步请求的过程中,可能会遇到网络延迟或服务器响应超时的情况,因此合理设置 `timeout` 参数对于提高程序的健壮性和用户体验非常重要。 +### FunctionDef __init__(self, base_url, timeout) +**__init__**: 此函数的功能是初始化一个异步API请求对象。 + +**参数**: +- `base_url`: 字符串类型,代表API服务器的基础URL。默认值通过调用`api_address`函数获取。 +- `timeout`: 浮点数类型,代表请求超时时间。默认值为`HTTPX_DEFAULT_TIMEOUT`。 + +**代码描述**: `__init__`函数是`AsyncApiRequest`类的构造函数,用于创建一个新的异步API请求对象。在这个函数中,首先通过调用父类的构造函数`super().__init__(base_url, timeout)`来初始化基础URL和超时时间。这里的`base_url`参数默认通过调用`api_address`函数获得,该函数从项目配置中读取并返回API服务器的地址。`timeout`参数则指定了网络请求的超时时间,默认值为`HTTPX_DEFAULT_TIMEOUT`,这是一个预设的常量,代表了HTTPX库中默认的请求超时时间。 + +接着,函数设置了一个私有属性`_use_async`为`True`,这表明该请求对象将使用异步方式进行网络请求。这是`AsyncApiRequest`类与同步请求类`ApiRequest`的主要区别之一,即它支持异步操作,能够在不阻塞主线程的情况下发送网络请求和接收响应。 + +**注意**: 使用`AsyncApiRequest`类时,需要确保`api_address`函数能够正确返回API服务器的地址,这要求项目的配置文件中已经正确设置了API服务器的`host`和`port`。此外,考虑到异步请求的特性,开发者在使用此类进行网络请求时应当熟悉Python的异步编程模式,如使用`async`和`await`关键字。 +*** +## FunctionDef check_error_msg(data, key) +**check_error_msg**: 该函数的功能是检查API请求返回的数据中是否包含错误信息,并返回相应的错误消息。 + +**参数**: +- `data`: 可以是字符串、字典或列表,表示API请求返回的数据。 +- `key`: 字符串类型,默认值为"errorMsg",表示在字典数据中查找错误信息的键名。 + +**代码描述**: +`check_error_msg`函数主要用于处理API请求后的响应数据,以判断是否发生了错误。它首先检查`data`参数的类型。如果`data`是一个字典,并且包含了指定的`key`(默认为"errorMsg"),则直接返回该键对应的值作为错误信息。如果字典中包含"code"键且其值不等于200,这通常表示请求未成功,函数将返回"msg"键对应的值作为错误信息。如果上述条件都不满足,函数将返回一个空字符串,表示没有发生错误。 + +在项目中,`check_error_msg`函数被多个地方调用,用于处理不同API请求的响应。例如,在`dialogue_page`和`knowledge_base_page`中,该函数用于检查与对话管理、知识库操作相关API请求的结果,以便在发生错误时向用户显示适当的错误消息。这有助于提高用户体验,通过即时反馈帮助用户了解操作失败的原因。 + +**注意**: +- 在使用`check_error_msg`函数时,需要确保传入的`data`参数格式正确,且与函数内部处理逻辑相匹配。 +- 函数的返回值是一个字符串,可能是具体的错误信息或空字符串。调用方需要根据返回值判断是否需要进一步处理。 + +**输出示例**: +- 如果API返回的数据是`{"errorMsg": "无效的请求参数"}`,`check_error_msg`函数将返回"无效的请求参数"。 +- 如果API返回的数据是`{"code": 404, "msg": "未找到资源"}`,函数将返回"未找到资源"。 +- 如果API返回的数据不包含错误信息,函数将返回空字符串""。 +## FunctionDef check_success_msg(data, key) +**check_success_msg**: 此函数的功能是检查API请求返回的数据中是否包含成功消息。 + +**参数**: +- `data`: 可以是字符串、字典或列表,代表API请求返回的数据。 +- `key`: 字符串类型,默认值为"msg",表示在返回的数据中查找成功消息的键。 + +**代码描述**: +`check_success_msg`函数主要用于处理API请求的返回数据,以确认是否成功执行了请求。函数首先检查`data`参数的类型是否为字典,并且该字典中是否包含`key`指定的键和"code"键。如果这些条件都满足,并且"code"的值为200,表示请求成功,函数将返回与`key`对应的值,通常是一个表示成功的消息。如果任一条件不满足,函数将返回一个空字符串,表示没有成功消息。 + +在项目中,`check_success_msg`函数被用于处理不同场景下API请求的返回值。例如,在`dialogue_page`和`knowledge_base_page`中,此函数用于检查更改LLM模型、上传知识库文档等操作的返回结果,以向用户反馈操作是否成功。通过检查返回数据中的"msg"键对应的值,可以向用户展示成功或错误的提示信息,从而提高用户体验。 + +**注意**: +- 确保API请求的返回数据格式符合函数处理的预期,特别是当预期返回数据为字典时,需要包含"code"和`key`指定的键。 +- 函数返回的是一个字符串,可能是一个空字符串或包含成功消息的字符串。在使用此函数时,应根据返回值来决定后续的操作或显示逻辑。 + +**输出示例**: +- 如果API请求成功,并且返回的数据中包含`{"code": 200, "msg": "操作成功"}`,则`check_success_msg`函数将返回"操作成功"。 +- 如果API请求失败,或返回的数据不包含"code"为200的情况,函数将返回一个空字符串。