之前教过咱们运用 langchain + ChatGLM-6B 完成个人专属知识库,非常简单易上手。最近,智谱 AI 研发团队又推出了 ChatGLM 系列的新模型 ChatGLM2-6B,是开源中英双语对话模型 ChatGLM-6B 的第二代版别,功能更强悍。

树先生之所以现在才更新 ChatGLM2-6B 知识库教程,是想等模型本身再多迭代几个版别,不至于刚出的教程很快不适配,或者项目本身一堆 bug,那样咱们运用体会也不好。

ChatGLM2-6B 介绍

ChatGLM2-6B 在保留了初代模型对话流畅、布置门槛较低等众多优异特性的基础之上,引入了如下新特性:

  • 更强大的功能:依据 ChatGLM 初代模型的开发经验,全面晋级了基座模型。ChatGLM2-6B 运用了 GLM 的混合目标函数,通过了 1.4T 中英标识符的预练习与人类偏好对齐练习,评测成果显示,比较于初代模型,ChatGLM2-6B 在 MMLU(+23%)、CEval(+33%)、GSM8K(+571%) 、BBH(+60%)等数据集上的功能获得了大幅度的提高,在同尺度开源模型中具有较强的竞争力。

LangChain + ChatGLM2-6B 搭建个人专属知识库

  • 更长的上下文:依据 FlashAttention 技能,将基座模型的上下文长度(Context Length)由 ChatGLM-6B 的 2K 扩展到了 32K,并在对话阶段运用 8K 的上下文长度练习,允许更多轮次的对话。
  • 更高效的推理:依据 Multi-Query Attention 技能,ChatGLM2-6B 有更高效的推理速度和更低的显存占用:在官方的模型完成下,推理速度比较初代提高了 42%,INT4 量化下,6G 显存支撑的对话长度由 1K 提高到了 8K。

LangChain + ChatGLM2-6B 搭建个人专属知识库

  • 更敞开的协议:ChatGLM2-6B 权重对学术研究彻底敞开,在获得官方的书面答应后,亦允许商业运用

比较于初代模型,ChatGLM2-6B 多个维度的能力都获得了提高,以下是一些官方比照示例。

LangChain + ChatGLM2-6B 搭建个人专属知识库

总的来说,看起来效果还不错,下面跟着树先生一同来试试水~

本文我将分 3 步带着咱们一同实操一遍,并与之前 ChatGLM-6B 进行比照。

  • ChatGLM2-6B 布置

  • ChatGLM2-6B 微调

  • LangChain + ChatGLM2-6B 构建个人专属知识库

ChatGLM2-6B 布置

这儿咱们仍是白嫖阿里云的机器学习 PAI 平台,运用 A10 显卡,这部分内容之前文章中有介绍。

免费布置一个开源大模型 MOSS

环境预备好了以后,就能够开端预备布置工作了。

下载源码

git clone https://github.com/THUDM/ChatGLM2-6B

装置依靠

cd ChatGLM2-6B
# 其中 transformers 库版别引荐为 4.30.2,torch 引荐运用 2.0 及以上的版别,以获得最佳的推理功能
pip install -r requirements.txt

下载模型

# 这儿我将下载的模型文件放到了本地的 chatglm-6b 目录下
git clone https://huggingface.co/THUDM/chatglm2-6b $PWD/chatglm2-6b

参数调整

# 因为前面改了模型默许下载地址,所以这儿需求改下途径参数
# 修正 web_demo.py 文件
tokenizer = AutoTokenizer.from_pretrained("/mnt/workspace/chatglm2-6b", trust_remote_code=True)
model = AutoModel.from_pretrained("/mnt/workspace/chatglm2-6b", trust_remote_code=True).cuda()
# 假如想要本地访问,需求修正此处
demo.queue().launch(share=True, inbrowser=True, server_name='0.0.0.0', server_port=7860)

Web 形式发动

官方引荐用 Streamlit 发动会更流程一些,但受限于 PAI 平台没有分配弹性公网,所以仍是用老的 gradio 发动吧。

python web_demo.py

LangChain + ChatGLM2-6B 搭建个人专属知识库

ChatGLM2-6B 比照 ChatGLM-6B

先让 ChatGPT 作为考官,出几道题。

LangChain + ChatGLM2-6B 搭建个人专属知识库

ChatGLM-6B 答复:

LangChain + ChatGLM2-6B 搭建个人专属知识库

ChatGLM2-6B 答复:

LangChain + ChatGLM2-6B 搭建个人专属知识库

明显能够看出,ChatGLM2-6B 比较于上一代模型响应速度更快,问题答复精确度更高,且具有更长的(32K)上下文!

LangChain + ChatGLM2-6B 搭建个人专属知识库

依据 P-Tuning 微调 ChatGLM2-6B

ChatGLM2-6B 环境已经有了,接下来开端模型微调,这儿咱们运用官方的 P-Tuning v2 对 ChatGLM2-6B 模型进行参数微调,P-Tuning v2 将需求微调的参数量削减到原来的 0.1%,再通过模型量化、Gradient Checkpoint 等方法,最低只需求 7GB 显存即可运转。

装置依靠

# 运转微调需求 4.27.1 版别的 transformers
pip install transformers==4.27.1
pip install rouge_chinese nltk jieba datasets

禁用 W&B

# 禁用 W&B,假如不禁用可能会中止微调练习,以防万一,仍是禁了吧
export WANDB_DISABLED=true

预备数据集

这儿为了简化,我只预备了5条测试数据,别离保存为 train.json 和 dev.json,放到 ptuning 目录下,实践运用的时候肯定需求大量的练习数据。

{"content": "你好,你是谁", "summary": "你好,我是树先生的帮手小6。"}
{"content": "你是谁", "summary": "你好,我是树先生的帮手小6。"}
{"content": "树先生是谁", "summary": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。"}
{"content": "介绍下树先生", "summary": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。"}
{"content": "树先生", "summary": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。"}

参数调整

修正 train.shevaluate.sh 中的 train_filevalidation_filetest_file为你自己的 JSON 格局数据集途径,并将 prompt_columnresponse_column 改为 JSON 文件中输入文本和输出文本对应的 KEY。可能还需求增大 max_source_lengthmax_target_length 来匹配你自己的数据集中的最大输入输出长度。并将模型途径 THUDM/chatglm2-6b 改为你本地的模型途径。

1、train.sh 文件修正

PRE_SEQ_LEN=32
LR=2e-2
NUM_GPUS=1
torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \
    --do_train \
    --train_file train.json \
    --validation_file dev.json \
    --preprocessing_num_workers 10 \
    --prompt_column content \
    --response_column summary \
    --overwrite_cache \
    --model_name_or_path /mnt/workspace/chatglm2-6b \
    --output_dir output/adgen-chatglm2-6b-pt-$PRE_SEQ_LEN-$LR \
    --overwrite_output_dir \
    --max_source_length 128 \
    --max_target_length 128 \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --predict_with_generate \
    --max_steps 3000 \
    --logging_steps 10 \
    --save_steps 1000 \
    --learning_rate $LR \
    --pre_seq_len $PRE_SEQ_LEN

train.sh 中的 PRE_SEQ_LENLR 别离是 soft prompt 长度和练习的学习率,能够进行调节以获得最佳的效果。P-Tuning-v2 方法会冻住悉数的模型参数,可通过调整 quantization_bit 来改变原始模型的量化等级,不加此选项则为 FP16 精度加载。

2、evaluate.sh 文件修正

PRE_SEQ_LEN=32
CHECKPOINT=adgen-chatglm2-6b-pt-32-2e-2
STEP=3000
NUM_GPUS=1
torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \
    --do_predict \
    --validation_file dev.json \
    --test_file dev.json \
    --overwrite_cache \
    --prompt_column content \
    --response_column summary \
    --model_name_or_path /mnt/workspace/chatglm2-6b \
    --ptuning_checkpoint ./output/$CHECKPOINT/checkpoint-$STEP \
    --output_dir ./output/$CHECKPOINT \
    --overwrite_output_dir \
    --max_source_length 128 \
    --max_target_length 128 \
    --per_device_eval_batch_size 1 \
    --predict_with_generate \
    --pre_seq_len $PRE_SEQ_LEN

CHECKPOINT 实践便是 train.sh 中的 output_dir

练习

bash train.sh

5 条数据大概练习了 50 分钟左右。

LangChain + ChatGLM2-6B 搭建个人专属知识库

推理

bash evaluate.sh

LangChain + ChatGLM2-6B 搭建个人专属知识库

履行完成后,会生成评测文件,评测目标为中文 Rouge score 和 BLEU-4。生成的成果保存在 ./output/adgen-chatglm2-6b-pt-32-2e-2/generated_predictions.txt。咱们预备了 5 条推理数据,所以相应的在文件中会有 5 条评测数据,labels 是 dev.json 中的猜测输出,predict 是 ChatGLM2-6B 生成的成果,比照猜测输出和生成成果,评测模型练习的好坏。假如不满意调整练习的参数再次进行练习。

{"labels": "你好,我是树先生的帮手小6。", "predict": "你好,我是树先生的帮手小6。"}
{"labels": "你好,我是树先生的帮手小6。", "predict": "你好,我是树先生的帮手小6。"}
{"labels": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。", "predict": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。"}
{"labels": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。", "predict": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。"}
{"labels": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。", "predict": "树先生是一个程序员,热衷于用技能探究商业价值,继续尽力为粉丝带来价值输出,运营大众号《程序员树先生》。"}

布置微调后的模型

这儿咱们先修正 web_demo.sh 的内容以符合实践情况,将 pre_seq_len 改成你练习时的实践值,将 THUDM/chatglm2-6b 改成本地的模型途径。

PRE_SEQ_LEN=32
CUDA_VISIBLE_DEVICES=0 python3 web_demo.py \
    --model_name_or_path /mnt/workspace/chatglm2-6b \
    --ptuning_checkpoint output/adgen-chatglm2-6b-pt-32-2e-2/checkpoint-3000 \
    --pre_seq_len $PRE_SEQ_LEN

然后再履行。

bash web_demo.sh

成果比照

原始模型

LangChain + ChatGLM2-6B 搭建个人专属知识库

微调后模型

LangChain + ChatGLM2-6B 搭建个人专属知识库

LangChain + ChatGLM2-6B 构建知识库

LangChain 知识库技能原理

目前市面上绝大部分知识库都是 LangChain + LLM + embedding 这一套,完成原理如下图所示,进程包含加载文件 -> 读取文本 -> 文本切割 -> 文本向量化 -> 问句向量化 -> 在文本向量中匹配出与问句向量最类似的top k个 -> 匹配出的文本作为上下文和问题一同增加到 prompt 中 -> 提交给 LLM 生成答复。

LangChain + ChatGLM2-6B 搭建个人专属知识库

LangChain + ChatGLM2-6B 搭建个人专属知识库

从上面就能看出,其核心技能便是向量 embedding,将用户知识库内容通过 embedding 存入向量知识库,然后用户每一次发问也会通过 embedding,运用向量相关性算法(例如余弦算法)找到最匹配的几个知识库片段,将这些知识库片段作为上下文,与用户问题一同作为 promt 提交给 LLM 答复,很好了解吧。一个典型的 prompt 模板如下:

"""
已知信息:
{context} 
依据上述已知信息,简练和专业的来答复用户的问题。假如无法从中得到答案,请说 “依据已知信息无法答复该问题” 或 “没有提供满足的相关信息”,不允许在答案中增加假造成分,答案请运用中文。 
问题是:{question}
"""

更多关于向量 embedding 的内容能够参阅我之前写的一篇文章。

ChatGPT 引爆向量数据库赛道

项目布置

下载源码

git clone https://github.com/imClumsyPanda/langchain-ChatGLM.git

装置依靠

cd langchain-ChatGLM
pip install -r requirements.txt

下载模型

# 装置 git lfs
git lfs install
# 下载 LLM 模型
git clone https://huggingface.co/THUDM/chatglm2-6b $PWD/chatglm2-6b
# 下载 Embedding 模型
git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese $PWD/text2vec
# 模型需求更新时,可翻开模型所在文件夹后拉取最新模型文件/代码
git pull

参数调整

模型下载完成后,请在 configs/model_config.py 文件中,对embedding_model_dictllm_model_dict参数进行修正。

embedding_model_dict = {
    "ernie-tiny": "nghuyong/ernie-3.0-nano-zh",
    "ernie-base": "nghuyong/ernie-3.0-base-zh",
    "text2vec-base": "shibing624/text2vec-base-chinese",
    "text2vec": "/mnt/workspace/text2vec",
    "m3e-small": "moka-ai/m3e-small",
    "m3e-base": "moka-ai/m3e-base",
}
llm_model_dict = {
    ...
    "chatglm2-6b": {
        "name": "chatglm2-6b",
        "pretrained_model_name": "/mnt/workspace/chatglm2-6b",
        "local_model_path": None,
        "provides": "ChatGLM"
    },
    ...
}
# LLM 名称改成 chatglm2-6b
LLM_MODEL = "chatglm2-6b"

项目发动

Web 形式发动

python webui.py

假如报了这个错:

LangChain + ChatGLM2-6B 搭建个人专属知识库

晋级下 protobuf 即可。

pip install --upgrade protobuf==3.19.6

发动成功!

LangChain + ChatGLM2-6B 搭建个人专属知识库

模型装备

LangChain + ChatGLM2-6B 搭建个人专属知识库

上传知识库

LangChain + ChatGLM2-6B 搭建个人专属知识库

依据 ChatGLM2-6B 的知识库问答

LangChain + ChatGLM2-6B 搭建个人专属知识库

定制 UI

因为 LangChain 项目更新了接口,树先生之前开发的定制 UI 也同步更新进行了适配。

选择知识库

LangChain + ChatGLM2-6B 搭建个人专属知识库

依据知识库问答

LangChain + ChatGLM2-6B 搭建个人专属知识库

显示答案来历

LangChain + ChatGLM2-6B 搭建个人专属知识库

LangChain + ChatGLM2-6B 搭建个人专属知识库

好了,这一篇还挺长的,不过许多内容之前文章中都有提到,适当所以一篇 LangChain + LLM + embedding 构建知识库的总结篇了,咱们收藏好这一篇就行了~