知识库助手的构建之路:ChatGLM3-6B和LangChain的深度应用

ChatGLM3-6B和LangChain构建知识库助手

安装依赖库

使用pip命令安装以下库:

pip install modelscope langchain==0.1.7 chromadb==0.5.0 sentence-transformers==2.7.0 unstructured==0.13.7 markdown==3.0.0 docx2txt==0.8  pypdf==4.2.0

依赖库简介:

ModelScope:一个用于机器学习模型管理和部署的库LangChain:一个用于构建语言模型应用的框架ChromaDB:一个用于高效存储和检索嵌入向量的数据库,支持相似性搜索Sentence Transformers:一个用于生成句子和文本嵌入的库,基于Transformer模型。Unstructured:一个用于处理非结构化数据的库,提供了多种工具来提取和转换数据Markdown:一个用于将Markdown文本转换为HTML的库docx2txt:一个用于从DOCX文件中提取文本的库PyPDF:一个用于处理PDF文件的库,支持读取、写入和修改PDF文档

下载大模型

from modelscope import snapshot_download# 下载指定模型
model_dir = snapshot_download('ZhipuAI/chatglm3-6b',  # 模型的名称cache_dir='/root/models',  # 缓存目录,用于存储下载的模型文件revision='master'  # 指定模型的版本,通常为'master'表示最新版本
)

下载向量模型

from modelscope import snapshot_download# 下载指定模型
model_dir = snapshot_download('AI-ModelScope/bge-large-zh',  # 模型的名称cache_dir='/root/models'  # 缓存目录,用于存储下载的模型文件
)

自定义LLM 类

在本地部署的ChatGLM3-6B基础上,构建LLM应用需要自定义一个LLM类,并将ChatGLM接入到LangChain框架中。通过自定义LLM类,可以实现与LangChain接口的完全一致调用方式,无需担心底层模型调用的不一致性。

创建ChatGLM_LLM.py文件,需从LangChain.llms.base.LLM类继承一个子类,并重写构造函数与_call函数

from typing import Any, List, Optionalimport torch
from langchain.callbacks.manager import CallbackManagerForLLMRun
from langchain.llms.base import LLM
from transformers import AutoTokenizer, AutoModelForCausalLM# 自定义GLM类
class ChatGLMLLM(LLM):"""自定义 LLM 类,用于加载和使用 ChatGLM 模型"""tokenizer: AutoTokenizer = Nonemodel: AutoModelForCausalLM = Nonedef __init__(self, model_path: str):""":param model_path: 从本地初始化模型"""super().__init__()print("-------------开始加载LLM模型-------------")# 加载分词器self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)# 加载模型self.model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).to(torch.bfloat16).cuda()# 设置模型为评估模式self.model = self.model.eval()print("-------------模型LLM加载完毕-------------")# 定义_call方法:进行模型的推理def _call(self, prompt: str, stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None, **kwargs: Any):""" 重写调用函数 在给定的提示和输入下运行 LLM """response, history = self.model.chat(self.tokenizer, prompt, history=[])return response@propertydef _llm_type(self) -> str:""" 返回模型类型 """return "ChatGLM3-6B"

文件读取与处理

创建File_Proces.py文件,递归指定文件夹路径,返回所有满足条件的文件路径,并使用LangChain提供的各类Loader对象加载文件,解析出纯文本内容

import os
from typing import Listfrom langchain_community.document_loaders import TextLoader, UnstructuredMarkdownLoader, PyPDFLoader, Docx2txtLoader
from tqdm import tqdmclass FileProces:def get_files(self, dir_path):"""根据路径,递归获取路径下的文件列表"""# 指定要筛选的文件扩展名列表extensions = [".pdf", ".docx", ".md", "txt"]file_list = []"""os.walk 函数将递归遍历指定文件夹filepath: 当前遍历到的文件路径,包含文件名。dirnames: 一个包含当前目录中所有子目录名的列表。filenames: 一个包含当前目录中所有文件名的列表"""for filepath, dirnames, filenames in os.walk(dir_path):for filename in filenames:# 检查文件后缀是否在指定的扩展名列表中if any(filename.endswith(ext) for ext in extensions):# 将符合条件的文件的绝对路径添加到列表中file_list.append(os.path.join(filepath, filename))return file_listdef get_text(self, file_lst):"""根据传入文件列表,分别获取每个文件对象的文本信息"""# docs 存放加载之后的纯文本对象docs = []# 定义文件类型对应的加载器字典loader_mapping = {'pdf': PyPDFLoader,'docx': Docx2txtLoader,'md': UnstructuredMarkdownLoader,'txt': TextLoader}# tqdm是一个 Python 库,用于在循环中展示进度条,帮助用户实时了解循环迭代的进度for file in tqdm(file_lst):# 文件名按照.分割成多个部分,选择列表中的最后一个元素file_type = file.split('.')[-1]# 根据文件类型选择对应的加载器loader = loader_mapping.get(file_type)if loader:loader_instance = loader(file)doc = loader_instance.load()docs.extend(doc)else:# 如果文件类型不在loader_mapping中,跳过当前文件continuereturn docsdef getALLDocs(self, tar_dir: List):"""传入目标目录,返回目录下所有文档列表"""# 处理文件all_docs = []for dir_path in tar_dir:# 得到目标文件路径列表file_list = self.get_files(dir_path)print("文档列表:", file_list)docs = self.get_text(file_list)# 合并所有文档all_docs.extend(docs)return all_docs

构建向量数据库

创建Embedding_LLM.py文件,加载词向量模型,把经过文件的读取与处理后得到的纯文本对象列表引入LangChain框架,对文本进行分块,进行向量化处理,然后构建向量数据库。

# 首先导入所需第三方库from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceBgeEmbeddingsfrom File_Proces import FileProcesclass EmbeddingLLM():embeddings: HuggingFaceBgeEmbeddings = Nonevectordb = None# 定义持久化路径persist_directory = './vectorDB/chroma'def __init__(self, model_path: str):""":param model_path: 加载词向量模型"""print("-------------开始加载词向量模型-------------")model_kwargs = {"device": "cuda"}encode_kwargs = {"normalize_embeddings": True}# 加载开源词向量模型self.embeddings = HuggingFaceBgeEmbeddings(model_name=model_path, model_kwargs=model_kwargs,encode_kwargs=encode_kwargs)print("-------------词向量模型加载完毕-------------")# 初始化向量数据库self.vectordb = Chroma(persist_directory=self.persist_directory,embedding_function=self.embeddings)def docsToEmbedding(self, docs):"""文档转向量,同时持久化到本地目录"""# 对文本进行分块text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)split_docs = text_splitter.split_documents(docs)# 保存向量数据vectordb = Chroma.from_documents(documents=split_docs,embedding=self.embeddings,persist_directory=self.persist_directory  # 持久化的目录)# 将加载的向量数据库持久化到磁盘上vectordb.persist()print("向量数据持久化完成")if __name__ == '__main__':# 初始化向量内嵌模型llm = EmbeddingLLM(model_path="./models/bge-large-zh")# 目标文件目录tar_dir = ["./data"]# 获取指定目录下的所有文档内容fileproces = FileProces()all_docs = fileproces.getALLDocs(tar_dir=tar_dir)# 开始向量化处理llm.docsToEmbedding(docs=all_docs)

执行日志如下:

-------------开始加载词向量模型-------------
-------------词向量模型加载完毕-------------
文档列表: ['./data/《Scrum指南》中文版.pdf', './data/README.md', './data/demo.txt']
100%|██████████| 3/3 [00:03<00:00,  1.17s/it]
向量数据持久化完成

本地文件存储情况如下:
在这里插入图片描述

构建检索问答链

LangChain通过提供RetrievalQA对象实现了对RAG全流程的封装。通过初始化一个RetrievalQA对象,并填入已构建的数据库和自定义LLM作为参数,就能方便地完成检索增强问答的全流程。

LangChain会自动根据用户提问进行检索、获取相关文档、生成适当的提示,并将其传递给LLM进行问答的整个过程。

创建Retrieval.py文件,创建一个构建检索问答链函数

from langchain.chains import RetrievalQA
from langchain_core.prompts import PromptTemplatedef builder_chain(llm, embeddingLlm):# 构造Prompt模板template = """使用以下上下文来回答问题。如果你不知道答案,你需要澄清,不要试图编造答案。请简明扼要的回答。”。{context}问题: {question}回答:"""# 实例化Template对象,context和question两个变量会被检索到的文档片段和用户提问填充qa_chain_prompt = PromptTemplate(input_variables=["context", "question"], template=template)# 构建检索链vectordb = embeddingLlm.vectordbqa_chain = RetrievalQA.from_chain_type(llm, retriever=vectordb.as_retriever(), return_source_documents=True,chain_type_kwargs={"prompt": qa_chain_prompt})return qa_chain

测试

from ChatGLM_LLM import ChatGLMLLM
from Embedding_LLM import EmbeddingLLM
from Retrieval import builder_chainif __name__ == '__main__':# 初始化大模型llm = ChatGLMLLM(model_path="./models/chatglm3-6b")# 初始化向量内嵌模型embeddingLlm = EmbeddingLLM(model_path="./models/bge-large-zh")qa_chain = builder_chain(llm, embeddingLlm)# 检索问答链回答效果question = "Scrum理论是什么"result = qa_chain({"query": question})print("检索问答的结果:")print(result["result"])# LLM回答效果result_2 = llm(question)print("大模型回答的结果:")print(result_2)

对比检索问答链和纯LLM的问答效果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/62375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL中的count函数

1. COUNT() 是什么&#xff1f; 在 MySQL 中&#xff0c;COUNT() 是一个聚合函数&#xff0c;用于统计结果集中行的数量。它常见的几种用法包括&#xff1a; COUNT(*)&#xff1a;统计结果集中所有行的数量&#xff0c;包括包含 NULL 的行。COUNT(1)&#xff1a;统计结果集中所…

shell(2)永久环境变量和字符串显位

shell&#xff08;2&#xff09;永久环境变量和字符串显位 声明&#xff01; 学习视频来自B站up主 ​泷羽sec​​ 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习…

基于pytorch使用仿真数据集来训练一个深度学习模型进行相位解包裹

使用 PyTorch 来训练一个深度学习模型进行相位解包裹是一种常见的方法。下面是一个详细的示例&#xff0c;展示如何生成仿真数据集并在 PyTorch 中训练模型。 1. 生成仿真数据集 首先&#xff0c;我们生成一些仿真数据集&#xff0c;包含多个包裹相位图和对应的解包裹相位图。…

使用 Python 的 pdfplumber 库高效解析 PDF 文件

使用 Python 的 pdfplumber 库高效解析 PDF 文件 PDF 文件是日常办公和数据处理中常见的文件格式&#xff0c;而 pdfplumber 是一个专为 PDF 文件解析设计的 Python 库&#xff0c;可以轻松提取文本、表格、图像等内容。本文将介绍 pdfplumber 的基本功能、使用方法&#xff0…

Java实现IP代理池

文章目录 Java实现IP代理池一、引言二、构建IP代理池1、代理IP的获取2、代理IP的验证1. 导入必要的库2. 设置代理IP和端口3. 发起HTTP请求4. 检查请求结果5. 完整的验证方法 注意事项 三、使用IP代理池四、总结 Java实现IP代理池 一、引言 在网络爬虫或者需要频繁请求网络资源…

微服务保护和分布式事务

文章目录 一、微服务保护1.1 微服务保护方案&#xff1a;1.1.1 请求限流&#xff1a;1.1.2 线程隔离&#xff1a;1.1.3 服务熔断&#xff1a; 1.2 Sentinel&#xff1a;1.2.1 介绍和安装&#xff1a;1.2.2 微服务整合&#xff1a; 1.3 请求限流&#xff1a;1.4 线程隔离&#x…

后端 Java发送邮件 JavaMail 模版 20241128测试可用

配置授权码 依赖 <dependency><groupId>javax.mail</groupId><artifactId>javax.mail-api</artifactId><version>1.5.5</version> </dependency> <dependency><groupId>com.sun.mail</groupId><artifa…

MySQL安装与卸载(linux)

MySQL安装与卸载 MySQL8.0.26-安装1. 准备一台Linux服务器2. 下载Linux版MySQL安装包3. 上传MySQL安装包4. 创建目录,并解压5. 安装mysql的安装包6. 启动MySQL服务7. 查询自动生成的root用户密码8. 修改root用户密码9. 创建用户10. 并给root用户分配权限11. 重新连接MySQL MySQ…

LayaBox1.8.4实现自定义3DMesh

实现mesh的原理可参考我写的Unity中的自定义mesh的原理&#xff0c; 碰撞检测算法——分离轴算法在Unity中实现&#xff08;一&#xff09;_unity 自定义高性能碰撞检测方案-CSDN博客 实现可传入shader两张贴图的顶点声明如下&#xff1a; var vertexDeclarationLaya.Vertex…

设置ip和代理DNS的WindowsBat脚本怎么写?

今天分享一个我们在工作时&#xff0c;常见的在Windows中通过批处理脚本&#xff08;.bat 文件&#xff09;来设置IP地址、代理以及DNS 相关配置的示例&#xff0c;大家可以根据实际需求进行修改调整。 一、设置静态IP地址脚本示例 以下脚本用于设置本地连接&#xff08;你可…

施工车辆,工程车类型识别,可识别装载机,搅拌车,挖掘机,拉土车等,支持YOLO,COCO,VOC三种格式带标记

1338总图像数 数据集分割 训练组 87&#xff05; 1170图片 有效集 8% 112图片 测试集 4% 56图片 预处理 自动定向&#xff1a; 已应用 调整大小&#xff1a; 拉伸至 640x640 增强 每个训练示例的输出&#xff1a; 3 旋转&#xff1a; -15 至 15 之间 …

oracle 用户手册

Oracle用户手册 一、Oracle数据库概述 定义与用途 Oracle数据库是一款功能强大的关系型数据库管理系统(RDBMS)。它用于存储和管理大量的结构化数据,广泛应用于企业级应用、金融系统、电商平台等各种需要高效数据处理和存储的场景。例如,银行使用Oracle数据库来存储客户账户…

新版布谷直播软件源码开发搭建功能更新明细

即将步入2025年也就是山东布谷科技专注直播系统开发,直播软件源码出售开发搭建等业务第9年,山东布谷科技不断更新直播软件功能&#xff0c;以适应当前新市场环境下的新要求。山东布谷科技始终秉承初心&#xff0c;做一款符合广大客户需求的直播系统软件。支持广大客户提交更多个…

科技赋能:企业如何通过新技术提升竞争力的策略与实践

引言 在当今瞬息万变的商业环境中&#xff0c;科技的迅猛发展正在重新定义行业的游戏规则。无论是小型企业还是跨国巨头&#xff0c;都感受到数字化转型的迫切需求。过去&#xff0c;企业竞争力更多依赖于成本控制、资源调配或市场覆盖&#xff0c;而如今&#xff0c;新技术的引…

回调函数-一文读懂

回调函数(Callback Function)是指通过函数指针传递给另一个函数的函数。调用者可以在合适的时机(例如事件发生时)调用这个回调函数。回调函数常用于实现一些插件化或动态响应的设计模式,如事件处理、异步编程、函数定制等。 回调函数的基本概念 定义:回调函数是由一个函…

Python编程实例-实现环形缓冲(Ring Buffer)

实现环形缓冲(Ring Buffer) 文章目录 实现环形缓冲(Ring Buffer)1、了解环形缓冲2、环形缓冲工作原理3、代码实现4、总结1、了解环形缓冲 环形缓冲区(Circular Buffer),又称循环缓冲区或环形队列,是一种固定大小的先进先出(FIFO)数据结构。它广泛应用于实时系统、音频处…

项目自动化部署,持续集成/持续交付(CI/CD)工具有那些?他们的优劣势分别是什么?共计15个工具进行对比分析。

项目自动化部署&#xff0c;持续集成/持续交付&#xff08;CI/CD&#xff09;工具有那些&#xff1f;他们的优劣势分别是什么&#xff1f; 主要对比的工具有&#xff1a;Jenkins 、阿里云云效、华为云DevCloud、腾讯云CODING、百度智能云DevOps、 GitLab CI/CD、CircleCI、Trav…

Web登录页面设计

记录第一个前端界面&#xff0c;暑假期间写的&#xff0c;用了Lottie动画和canvas标签做动画&#xff0c;登录和注册也连接了数据库。 图片是从网上找的&#xff0c;如有侵权私信我删除&#xff0c;谢谢啦~

洛谷 P2385 [USACO07FEB] Bronze Lilypad Pond B C语言 bfs

题目&#xff1a; https://www.luogu.com.cn/problem/P2385 题目看仔细&#xff0c;是M行N列.八个方向数组依靠M1,M2&#xff0c;所以初始化方向数组要在主函数里面&#xff0c;传入bfs函数里。 #include <iostream> #include<algorithm> #include<queue>…

如何在ubuntu上调试core dump

启用core dump 确认ulimit 状态 ulimit -c 如果输出是0&#xff0c;表示core dump被禁用了 运行 ulimit -c unlimited 再次运行 ulimit -c 确认输出是ulimited 设置core dump路径和文件名格式 下面命令表示设置core dump文件在当前目录&#xff08;%e表示程序名&#x…