梳理Langchain-Chatchat知识库API接口

时间:2024-01-24 07:31:06

一.Langchain-Chatchat 知识库管理

1.Langchain-Chatchat 对话和知识库管理界面

  Langchain-Chatchat v0.28 完整的界面截图,如下所示:

2.知识库中源文件和向量库

  知识库 test 中源文件和向量库的位置,如下所示:

3.知识库表结构

  knowledge_base 数据表内容,如下所示:

二.知识库操作 1

序号 操作名字 功能解释 链接 备注
1 获取知识库列表 就是上面的 samples(faiss @ bge-large-zh)和 test (faiss @ bge-large-zh)。 http://127.0.0.1/knowledge_base/list_knowledge_bases -
2 选择知识库 选中一个知识库 没有对应 API 接口 -
3 新建知识库 新建一个知识库 http://127.0.0.1/knowledge_base/create_knowledge_base,如下所示:{ "knowledge_base_name": "LLM", "vector_store_type": "faiss", "embed_model": "bge-large-zh"} 创建知识库
4 上传知识文件 向知识库上传文件,比如限制每个文件 200MB,类型可为 HTML, MD, JSON, JSONL, CSV, PDF, PNG, JPG, JPEG, BMP, EML, MSG, EPUB, XLSX, XLSD, IPYNB, ODT, PY, RST, RTF, SRT, TOML, TSV, DOCX, DOC, XML, PPT, PPTX, TXT, HTM 只是上传并显示了一个文件,并没有真的将文件上传到知识库中。 -
5 知识库介绍 知识库描述 http://127.0.0.1/knowledge_base/update_info,如下所示:{ "knowledge_base_name": "samples", "kb_info": "这是一个知识库"} -
6 单段文本最大长度 就是将长文本分割成多个较短的段落,每个段落的长度都不超过这个限制。 可通过更新现有文件到知识库接口 update_docs 实现。 -
7 相邻文本重合长度 将长文本分割成多个较短的段落时,相邻段落之间重复的文本的长度。这通常是为了确保 LLM 能够理解文本的上下文。 可通过更新现有文件到知识库接口 update_docs 实现。 -
8 开启中文标题加强 参考 kb_config.py 解释:1.是否开启中文标题加强,以及标题增强的相关配置;2.通过增加标题判断,判断哪些文本为标题,并在 metadata 中进行标记;3.然后将文本与往上一级的标题进行拼合,实现文本信息的增强。 可通过更新现有文件到知识库接口 update_docs 实现。 -
9 添加文件到知识库 将上传的文件添加到知识库中 http://127.0.0.1/knowledge_base/upload_docs 说明:接口调用格式 POST -> Body -> form-data。 -
1.获取知识库列表

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\api.py,如下所示:

app.get("/knowledge_base/list_knowledge_bases",
        tags=["Knowledge Base Management"],
        response_model=ListResponse,
        summary="获取知识库列表")(list_kbs)

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\knowledge_base\kb_api.py,如下所示:

def list_kbs():
    # Get List of Knowledge Base
    return ListResponse(data=list_kbs_from_db())

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\db\repository\knowledge_base_repository.py,如下所示:

@with_session
def list_kbs_from_db(session, min_file_count: int = -1):
    # 根据文件数量筛选知识库,-1表示不筛选,返回所有知识库
    kbs = session.query(KnowledgeBaseModel.kb_name).filter(KnowledgeBaseModel.file_count > min_file_count).all()
    # 遍历结果,取出知识库名称
    kbs = [kb[0for kb in kbs]
    return kbs

  http://127.0.0.1/knowledge_base/list_knowledge_bases,返回结果:

{
    "code"200,
    "msg""success",
    "data": [
        "samples",
        "test"
    ]
}
2.选中知识库

  选中知识库并没有对应的接口,主要是选中知识库后,更新界面的(1)知识库介绍(2)知识库文档信息,包括源文件(遍历文件夹)和向量库(遍历数据库)。

(1)遍历文件夹

  比如 test 知识库对应的 L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\knowledge_base\test 文件夹。

(2)遍历数据库

  主要是 knowledge_file 数据表,包括 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。

3.新建知识库

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\api.py,如下所示:

app.post("/knowledge_base/create_knowledge_base",
         tags=["Knowledge Base Management"],
         response_model=BaseResponse,
         summary="创建知识库"
         )(create_kb)

(1)拿到 FaissKBService 实例

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\knowledge_base\kb_api.py

def create_kb(knowledge_base_name: str = Body(..., examples=["samples"]),
            vector_store_type: str = Body("faiss"),
            embed_model: str = Body(EMBEDDING_MODEL),
            )
 -> BaseResponse:

    # Create selected knowledge base
    if not validate_kb_name(knowledge_base_name):  # 验证知识库名称
        return BaseResponse(code=403, msg="Don't attack me")
    if knowledge_base_name is None or knowledge_base_name.strip() == "":  # 知识库名称不能为空
        return BaseResponse(code=404, msg="知识库名称不能为空,请重新填写知识库名称")

    kb = KBServiceFactory.get_service_by_name(knowledge_base_name)  # 验证知识库是否存在
    if kb is not None:  # 已存在同名知识库
        return BaseResponse(code=404, msg=f"已存在同名知识库 {knowledge_base_name}")  # 404

    kb = KBServiceFactory.get_service(knowledge_base_name, vector_store_type, embed_model)  # 返回FaissKBService实例
    try:
        kb.create_kb()  # 创建知识库
    except Exception as e:
        msg = f"创建知识库出错: {e}"
        logger.error(f'{e.__class__.__name__}{msg}',
                     exc_info=e if log_verbose else None)
        return BaseResponse(code=500, msg=msg)

    return BaseResponse(code=200, msg=f"已新增知识库 {knowledge_base_name}")

(2)创建知识库

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\knowledge_base\kb_service\base.py,如下所示:

def create_kb(self):
    <em>"""</em>
<em>    创建知识库</em>
<em>    """
</em>
<em>    </em>if not os.path.exists(self.doc_path):  # 如果文档路径不存在
        os.makedirs(self.doc_path)  # 创建文档路径
    self.do_create_kb()  # 创建知识库
    status = add_kb_to_db(self.kb_name, self.kb_info, self.vs_type(), self.embed_model)  # 添加知识库到数据库
    return status  # 返回状态

(3)添加知识库到数据库

  L:\20231106_ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\db\repository\knowledge_base_repository.py,如下所示:

@with_session
def add_kb_to_db(session, kb_name, kb_info, vs_type, embed_model):
    # 创建知识库实例
    kb = session.query(KnowledgeBaseModel).filter_by(kb_name=kb_name).first()  # 查询知识库是否存在
    if not kb:  # 如果不存在,创建新的知识库
        kb = KnowledgeBaseModel(kb_name=kb_name, kb_info=kb_info, vs_type=vs_type, embed_model=embed_model)  # 创建知识库实例
        session.add(kb)  # 添加到数据库knowledge_base表中
    else:  # update kb with new vs_type and embed_model
        kb.kb_info = kb_info  # 更新知识库介绍
        kb.vs_type = vs_type  # 更新向量存储类型
        kb.embed_model = embed_model  # 更新嵌入模型
    return True

(4)接口调用

  http://127.0.0.1/knowledge_base/create_knowledge_base,如下所示:

{
    "knowledge_base_name""LLM",
    "vector_store_type""faiss",
    "embed_model""bge-large-zh"
}

  特别说明:没有找到知识库简介字段(确定没有)。参考更新知识库介绍/knowledge_base/update_info。

  数据表 knowledge_base 信息,如下所示:

  LangChain-Chatchat 知识库管理界面信息,如下所示:

4.上传知识文件

  st.file_uploader 创建一个文件上传组件,显示一个选择文件的按钮。如下所示:

files = st.file_uploader("上传知识文件:",
                         [i for ls in LOADER_DICT.values() for i in ls],
                         accept_multiple_files=True,
                         )

  只是显示了一个文件,并没有真的将文件上传到知识库中。

5.知识库介绍

(1)知识库更新实现

  F:\ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\api.py,如下所示:

app.post("/knowledge_base/update_info",
         tags=["Knowledge Base Management"],
         response_model=BaseResponse,
         summary="更新知识库介绍"
         )(update_info)

  对应的接口实现,如下所示:

def update_info(
        knowledge_base_name: str = Body(..., description="知识库名称", examples=["samples"]),
        kb_info: str = Body(..., description="知识库介绍", examples=["这是一个知识库"]),
)
:

    if not validate_kb_name(knowledge_base_name):
        return BaseResponse(code=403, msg="Don't attack me")

    kb = KBServiceFactory.get_service_by_name(knowledge_base_name)
    if kb is None:
        return BaseResponse(code=404, msg=f"未找到知识库 {knowledge_base_name}")
    kb.update_info(kb_info)

    return BaseResponse(code=200, msg=f"知识库介绍修改完成", data={"kb_info": kb_info})

  本质上还是更新数据库 knowledge_base,对知识库介绍字段进行更新。

(2)接口调用

http://127.0.0.1/knowledge_base/update_info,如下所示:

6.单段文本最大长度

  可通过更新现有文件到知识库接口 update_docs 实现。

7.相邻文本重合长度

  可通过更新现有文件到知识库接口 update_docs 实现。

8.开启中文标题加强

  可通过更新现有文件到知识库接口 update_docs 实现。

9.添加文件到知识库,并/或向量化

  F:\ConversationSystem\ChatCopilot\Langchain\Langchain-Chatchat-0.2.8\server\api.py,如下所示:

app.post("/knowledge_base/upload_docs",
         tags=["Knowledge Base Management"],
         response_model=BaseResponse,
         summary="上传文件到知识库,并/或进行向量化"
         )(upload_docs)

(1)upload_docs 函数

def upload_docs(
        file: List[UploadFile] = File(..., description="上传文件,支持多文件"),
        knowledge_base_name: str = Form(..., description="知识库名称", examples=["samples"]),
        override: bool = Form(False, description="覆盖已有文件"),
        to_vector_store: bool = Form(True, description="上传文件后是否进行向量化"),
        chunk_size: int = Form(CHUNK_SIZE, description="知识库中单段文本最大长度"),
        chunk_overlap: int = Form(OVERLAP_SIZE, description="知识库中相邻文本重合长度"),
        zh_title_enhance: bool = Form(ZH_TITLE_ENHANCE, description="是否开启中文标题加强"),
        docs: Json = Form({}, description="自定义的docs,需要转为json字符串",
                          examples=[{"test.txt": [Document(page_content="custom doc")]}])
,
        not_refresh_vs_cache: bool = Form(False, description="暂不保存向量库(用于FAISS)"),
)
 -> BaseResponse:

序号 字段名 类型 解释 备注
1 file List[UploadFile] 上传文件,支持多文件 -
2 knowledge_base_name str 知识库名称 -
3 override bool 覆盖已有文件 -
4 to_vector_store bool 上传文件后是否进行向量化 -
5 chunk_size int 知识库中单段文本最大长度 就是将长文本分割成多个较短的段落,每个段落的长度都不超过这个限制。
6 chunk_overlap int 知识库中相邻文本重合长度 将长文本分割成多个较短的段落时,相邻段落之间重复的文本的长度。这通常是为了确保 LLM 能够理解文本的上下文。
7 zh_title_enhance bool 是否开启中文标题加强 参考 kb_config.py 解释:1.是否开启中文标题加强,以及标题增强的相关配置;2.通过增加标题判断,判断哪些文本为标题,并在 metadata 中进行标记;3.然后将文本与往上一级的标题进行拼合,实现文本信息的增强。