知识库助手的构建之路: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.rhkb.cn/news/480581.html

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

相关文章

面经-综合面/hr面

面经-综合面/hr面 概述1.大学期间遇到的困难&#xff0c;怎么解决的2. 大学期间印象最深/最难忘的是什么3. 大学里面担任了什么职务没&#xff1f;做了什么工作&#xff1f;4. 大学最大的遗憾是什么&#xff1f;5. 对自己的未来规划6. 对自己的评价7. 自己的优缺点8. 对公司的认…

群控系统服务端开发模式-应用开发-邮箱配置功能开发

邮箱配置主要是将管理员数据做归属。具体见下图&#xff1a; 一、创建表 1、语句 CREATE TABLE cluster_control.nc_param_mail (id int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 编号,title varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT…

sd webui整合包怎么安装comfyui

环境: sd webui整合包 comfyui 问题描述: sd webui整合包怎么安装comfyui 扩展安装不成功 解决方案: 1.直接下载 ,解压到SD文件夹里(或者git拉一下) 2.ComfyUI模型共享:如果本机部署过Webui,那么ComfyUI可以与WebUI公用一套模型,防止复制大量模型浪费空间 将…

python基础(二)

函数 函数定义 函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一或相关联功能的代码段。 python函数定义规则&#xff1a; def my_max(a,b): #定义函数用def关键字开头&#xff0c;函数名-》my_max ()定义参数 if a>b: #函数体以&#xff1a…

【Springboot入门知识总结】

SpringBoot Web入门 一.Spring1.springBoot入门程序2.Spring官方脚手架连接不上的解决方案3.为什么一个main方法就将web应用 二. HTTP协议1.http协议的概念和特点2.Get请求和Post请求的区别3.http响应状态码分类4.获取http的参数 三.springBoot中的常用注解四.分层解耦五.总结 …

华为IPD流程学习之——深入解读123页华为IPD流程体系设计方法论PPT

该方案全面介绍了华为IPD流程体系设计方法论&#xff0c;包括流程体系建设的背景、理念、架构、核心特征、构建模型、与组织和战略的关系、运营机制、数字化转型以及流程管理组织等内容&#xff0c;旨在为企业提供一套系统的流程体系建设指导&#xff0c;以提升运营效率、质量和…

使用docker搭建hysteria2服务端

原链接&#xff1a;https://github.com/apernet/hysteria/discussions/1248 官网地址&#xff1a;https://v2.hysteria.network/zh/docs/getting-started/Installation/ 首选需要安装docker和docker compose 切换到合适的目录 cd /home创建文件夹 mkdir hysteria创建docke…

力扣hot100

文章目录 力扣hot100-哈希题目&#xff1a;两数之和方法1-暴力方法2-哈希 题目&#xff1a;字母异位词分组题解 题目&#xff1a;最长连续序列题解解释代码 力扣hot100-双指针题目&#xff1a;移动零题解 题目&#xff1a;盛最多水的容器题解 题目&#xff1a;三数之和题解 题目…

Scala身份证上的秘密以及Map的遍历

object test {def main(args: Array[String]): Unit {val id "42032220080903332x"//1.生日是&#xff1f;//字符串截取val birthday id.substring(10,14) //不包括终点下标println(birthday)val year id.substring(6,10) //println(year)//性别&#xff1a;倒数第…

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

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

【机器学习】—逻辑回归

逻辑回归实现详解 介绍 逻辑回归&#xff08;Logistic Regression&#xff09;是一种广泛应用于分类问题的统计模型&#xff0c;尤其适用于二分类问题。本文将通过一个简单的例子&#xff0c;使用Python和PyTorch库实现逻辑回归&#xff0c;并通过可视化展示模型的训练过程和…

华为仓颉编程环境搭建

1、仓颉介绍 摘自华为官方&#xff1a;仓颉编程语言作为一款面向全场景应用开发的现代编程语言&#xff0c;通过现代语言特性的集成、全方位的编译优化和运行时实现、以及开箱即用的 IDE 工具链支持&#xff0c;为开发者打造友好开发体验和卓越程序性能。 其具体特性表现为&am…

Vue.js当中v-if和v-show的区别

作者&#xff1a;CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境&#xff1a;WebStorm 目录 v-if和v-show举例 v-if 定义 特点 v-show 定义 特点 代码示例 v-if和v-show区别 原理 性能 适用性 v-if和v-show举例 首先我们还是简单回顾一下vue当中两…

【iOS】知乎日报总结

文章目录 前言首页网络请求轮播图上滑加载图片请求 文章详情页WKWebView的使用点赞、收藏持久化——FMDB的使用 其他问题沙盒问题单元格点击其他 总结 前言 在系统学习了OC语言和UI控件后&#xff0c;知乎日报是第一个比较大的项目&#xff0c;耗时一个多月时间&#xff0c;里面…

NLP信息抽取大总结:三大任务(带Prompt模板)

信息抽取大总结 1.NLP的信息抽取的本质&#xff1f;2.信息抽取三大任务&#xff1f;3.开放域VS限定域4.信息抽取三大范式&#xff1f;范式一&#xff1a;基于自定义规则抽取&#xff08;2018年前&#xff09;范式二&#xff1a;基于Bert下游任务建模抽取&#xff08;2018年后&a…

【Linux】网络连接模式,VM:桥接、NAT、仅主机如何选择?

1、网络类型 虚拟机建立时的常见网络类型有3种&#xff1a;桥接、NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;、仅主机&#xff08;Host Only&#xff09; 桥接&#xff1a;VM直接连接路由器&#xff0c;与物理机地位相同&#xff1b;N…

Spring Boot 3启动加载器详解(含源码解析)

一、引言 Spring Boot 3启动加载器是提升开发效率和应用程序启动速度的关键组件。本文将详细介绍Spring Boot 3的启动加载器&#xff0c;包括其实现方式、应用场景及工作原理等。 说明&#xff1a;本文分析使用的Spring Boot源码版本为3.3.5 二、启动加载器简介 启动加载器…

UDP客户端服务器通信

在这篇博客中&#xff0c;我们将探索 UDP&#xff08;用户数据报协议&#xff09; 通信&#xff0c;简要地说&#xff0c;UDP 是一种无连接、快速但不可靠的通信协议&#xff0c;适用于需要快速数据传输但对丢包容忍的场景&#xff0c;比如视频流和在线游戏。就像《我是如此相信…

手机实时提取SIM卡打电话的信令声音-智能拨号器的双SIM卡切换方案

手机实时提取SIM卡打电话的信令声音 --智能拨号器app的双SIM卡切换方案 一、前言 在蓝牙电话的方案中&#xff0c;由于采用市场上的存量手机来做为通讯呼叫的载体&#xff0c;而现在市面上大部分的手机都是“双卡双待单通”手机&#xff0c;简称双卡双待手机。即在手机开机后…

Spring Boot 同时接受文件和实体及 Postman 测试实战

Spring Boot 文件上传及 Postman 测试指南 在本文中&#xff0c;我们将介绍如何使用 Spring Boot 上传文件并通过 Postman 测试接口。我们会基于以下接口作为示例&#xff1a; Boolean importDevicePushConfig(RequestParam("file") MultipartFile file,DevicePush…