Skip to content

3、基于 InternLM 和 LangChain 搭建知识库

wwewwt edited this page Jan 10, 2024 · 1 revision

环境准备

1、安装依赖包

image

2、下载模型

下载大模型源文件internlm-chat-7b 略 下载词向量模型Sentence Transformer image 下载NLTK相关资源

cd /root
git clone https://gitee.com/yzy0612/nltk_data.git  --branch gh-pages
cd nltk_data
mv packages/*  ./
cd tokenizers
unzip punkt.zip
cd ../taggers
unzip averaged_perceptron_tagger.zip

下载项目代码

cd /root/data
git clone https://github.com/InternLM/tutorial

数据准备

语料下载

进入到数据库盘

cd /root/data
git clone https://gitee.com/open-compass/opencompass.git
git clone https://gitee.com/InternLM/lmdeploy.git
git clone https://gitee.com/InternLM/xtuner.git
git clone https://gitee.com/InternLM/InternLM-XComposer.git
git clone https://gitee.com/InternLM/lagent.git
git clone https://gitee.com/InternLM/InternLM.git

接着,为语料处理方便,我们将选用上述仓库中所有的 markdown、txt 文件作为示例语料库。都是纯文本文件,简单的处理方式就是根据长度分割

代码数据找实现方案 注意,也可以选用其中的代码文件加入到知识库中,但需要针对代码文件格式进行额外处理(因为代码文件对逻辑联系要求较高,且规范性较强,在分割时最好基于代码模块进行分割再加入向量数据库)。

数据预处理:

1、获得用于创建知识库的文件路径

image

2、遍历文件,解析成文本,装入列表[langchain.schema.document.Document]

from langchain.document_loaders import **UnstructuredFileLoader
from langchain.document_loaders import **UnstructuredMarkdownLoader

这两个解析文档的Loader要去langchain文档中了解一下

image

3、文本分割

264篇文档(docs),按chunk_size=500, chunk_overlap=150切割成2478个文本块(split_docs),超参数,效果待评估 image

4、加载词向量模型,构建向量数据库

为什么vectordb中的embeddings 是 None image

5、将加载的向量数据库持久化到磁盘上

vectordb.persist()

路径:/root/code/data_base/vector_db/chroma

知识库助手部署

1、实例化自定义 LLM 与 Prompt Template

llm = InternLM_LLM(model_path = "/root/data/model/Shanghai_AI_Laboratory/internlm-chat-7b")
llm.predict("你是谁")

from langchain.prompts import PromptTemplate

我们所构造的 Prompt 模板
template = """使用以下上下文来回答用户的问题。如果你不知道答案,就说你不知道。总是使用中文回答。
问题: {question}
可参考的上下文:
···
{context}
···
如果给定的上下文无法让你做出回答,请回答你不知道。
有用的回答:"""

调用 LangChain 的方法来实例化一个 Template 对象,该对象包含了 context 和 question 两个变量,在实际调用时,这两个变量会被检索到的文档片段和用户提问填充
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context","question"],template=template)

2、定义检索链函数

image

3、定义检索链调用类

image

为了方便对比使用检索链和不使用检索链的效果,我定义了一个不使用检索链的调用类: image

我修改了gradio,最后效果如下:

image

import gradio as gr

# 实例化核心功能对象
model_center = Model_center()
model_center_ori = Model_center_ori()
# 创建一个 Web 界面
block = gr.Blocks()
with block as demo:
    with gr.Row(equal_height=True):   
        with gr.Column(scale=15):
            # 展示的页面标题
            gr.Markdown("""<h1><center>InternLM</center></h1>
                <center>书生浦语</center>
                """)

    with gr.Row():
        with gr.Column(scale=2):
            # 创建一个聊天机器人对象
            chatbot = gr.Chatbot(height=450, show_copy_button=True)
            # 创建一个文本框组件,用于输入 prompt。
            #msg = gr.Textbox(label="Prompt/问题")

                
        with gr.Column(scale=2):
            chatbot2 = gr.Chatbot(height=450, show_copy_button=True)
            #msg = gr.Textbox(label="Prompt/问题")

    with gr.Row():
            msg = gr.Textbox(label="Prompt/问题")

    with gr.Row():
        with gr.Row():
          # 创建提交按钮。
            db_wo_his_btn = gr.Button("Chat with LangChain")
            db_wo_his_btn2 = gr.Button("Chat with not LangChain")

    # 设置按钮的点击事件。当点击时,调用上面定义的 qa_chain_self_answer 函数,并传入用户的消息和聊天历史记录,然后更新文本框和聊天机器人组件。
    db_wo_his_btn.click(model_center.qa_chain_self_answer, inputs=[msg, chatbot], outputs=[msg, chatbot])
    db_wo_his_btn2.click(model_center_ori.qa_chain_self_answer, inputs=[msg, chatbot2], outputs=[msg, chatbot2])

    with gr.Row():
      # 创建一个清除按钮,用于清除聊天机器人组件的内容。
        clear = gr.ClearButton(
        components=[chatbot,chatbot2], value="Clear console")
                

    gr.Markdown("""提醒:<br>
    1. 初始化数据库时间可能较长,请耐心等待。
    2. 使用中如果出现异常,将会在文本输入框进行展示,请不要惊慌。 <br>
    """)
gr.close_all()
# 直接启动
demo.launch(debug=True)