LangChain + ChatGLM 实现本地知识库问答

基于LangChain + ChatGLM 搭建融合本地知识的问答机器人


在这里插入图片描述

1 背景介绍

在这里插入图片描述

近半年以来,随着ChatGPT的火爆,使得LLM成为研究和应用的热点,但是市面上大部分LLM都存在一个共同的问题:模型都是基于过去的经验数据进行训练完成,无法获取最新的知识,以及各企业私有的知识。因此很多企业为了处理私有的知识,主要借助以下两种手段来实现:

  • 利用企业私有知识,基于开源大模型进行微调
  • 基于LangChain集成向量数据库以及LLM搭建本地知识库的问答

我们将基于LangChain+ChatGLM搭建本地知识的问答机器人系统。该系统需要能够根据用户提供的问题,在本地的知识库(离线)中查找并返回相关答案。

本次项目以"某东商品衣服"为例,以衣服属性构建本地知识,测试问答效果。使用者可以自由更新本地知识,用户问题的答案也是基于本地知识生成的。

关于ChatGLM:

ChatGLM是由清华技术成果转化的公司智谱AI研发的支持中英双语的对话机器人,ChatGLM通过建立大规模的语言模型库,并在实时数据流中进行分析和生成,以实现高效、实时的文本生成和响应;该技术可以快速对大量数据进行处理和分析,通过深度学习模型实时分析用户问题或需求,提高工作效率。

2 项目介绍

在这里插入图片描述

该项目的基本原理:

  • 加载文件
  • 读取文件
  • 文本分割
  • 文本向量化
  • 问句向量化
  • 在文本向量中匹配出与问句向量相似的top_k个
  • 匹配出的文本作为上下文和问题一起添加到prompt中
  • 提交给LLM生成答案

该问答机器人的主要功能包括:

  • 基于本地知识库的问答:系统可以根据用户的提问,在本地的知识库中进行搜索,并返回相关的答案。
  • 多模型支持:项目支持使用不同的语言模型,可以根据需求选择合适的模型进行使用。
  • 离线私有化:可以将该问答系统部署在本地环境中,确保数据的安全性和隐私性。

3 项目流程

准备本地知识库:

  • 首先,你需要一个本地知识库。这可以是一个结构化的数据库,如SQLite、MySQL等,或者是一个非结构化的文档集合,如PDF文件、文本文件等。

  • 确保你的知识库包含了你想要机器人回答的问题的相关信息。

设置LangChain环境:

  • 安装LangChain库。如果你使用的是Python,可以通过pip install langchain来安装。

集成ChatGLM
构建问答逻辑
实现与本地知识库的交互
整合ChatGLM与LangChain

4 环境配置

在这里插入图片描述

4.1 安装依赖

  • 首先,确保你的机器安装了Python3.8-Python3.11
# 终端查看python的版本
python --version
  • 紧接着安装项目的依赖
# 安装全部依赖
pip install faiss-cpu
pip install langchain
pip install qianfan

4.2 模型下载

如需在本地或离线环境下运行本项目,需要首先将项目所需的模型下载至本地,通常开源 LLM 与 Embedding 模型可以从 HuggingFace 下载。

本项目中默认使用的 LLM 模型 THUDM/ChatGLM-6B 与 Embedding 模型 moka-ai/m3e-base

5 代码实现

在这里插入图片描述

5.1 自定义GLM类

  • 目的:使用LLMs模块封装ChatGLM,load本地模型。使用LLM模块封装我们的模型接口的一个好处是有利于后续跟LangChain的其他模块协同。

  • 代码路径:/Users/**/PycharmProjects/llm/langchain_apply/Knowledge_QA/model.py

  • 具体代码

  • 导入必备的工具包

from langchain.llms.base import LLM
from langchain.llms.utils import enforce_stop_tokens
from transformers import AutoTokenizer, AutoModel
from typing import List, Optional
  • 自定义GLM类
# 自定义ChatGLM2
class ChatGLM2(LLM):
    max_token: int = 4096
    temperature: float = 0.8
    top_p = 0.9
    tokenizer: object = None
    model: object = None
    history = []

    def __init__(self):
        super().__init__()

    @property
    def _llm_type(self) -> str:
        return "ChatGLM2"

    # 定义load_model方法,进行模型的加载
    def load_model(self, model_path=None):
        self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
        self.model = AutoModel.from_pretrained(model_path, trust_remote_code=True).float()

    # 实现_call方法,进行模型的推理
    def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
        response, _ = self.model.chat(
            self.tokenizer,
            prompt,
            history=self.history,
            max_length=self.max_token,
            temperature=self.temperature,
            top_p=self.top_p)
        if stop is not None:
            response = enforce_stop_tokens(response, stop)
        self.history = self.history + [[None, response]]
        return response

5.2 构建Faiss索引

  • 目的:构建向量库

  • 代码位置:/Users/**/PycharmProjects/llm/langchain_apply/Knowledge_QA/get_vector.py

  • 具体代码

  • 导入必备的工具包

from langchain.document_loaders import UnstructuredFileLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS # 向量数据库
  • 定义main()方法

def main():
    # 定义向量模型路径
    EMBEDDING_MODEL = "moka-ai/m3e-base"

    # 第一步:加载文档
    loader = UnstructuredFileLoader("衣服属性.txt")
    # 将文本转成 Document 对象
    data = loader.load()
    print(f'documents:{len(data)}')

    # 第二部:切分文本
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
    # 切割加载的 document
    split_docs = text_splitter.split_documents(data)
    # print("split_docs size:",len(split_docs))
    # print(split_docs)


    # 第三步:初始化 hugginFace 的 embeddings 对象
    embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)

    # 第四步:将 document通过embeddings对象计算得到向量信息并永久存入FAISS向量数据库,用于后续匹配查询
    db = FAISS.from_documents(split_docs, embeddings)
    db.save_local("./faiss/product")

    return split_docs

result = main()
print(result)

在这里插入图片描述

5.3 实现QA本地知识库问答

  • 代码路径:/Users/ligang/PycharmProjects/llm/langchain_apply/Knowledge_QA/main.py
  • 代码实现
# coding:utf-8
# 导入必备的工具包
from langchain import PromptTemplate
from get_vector import *
from model import ChatGLM2
# 加载FAISS向量库
EMBEDDING_MODEL = "moka-ai/m3e-base"
embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
db = FAISS.load_local("faiss/product",embeddings)


def get_related_content(related_docs):
    related_content = []
    for doc in related_docs:
        related_content.append(doc.page_content.replace("\n\n", "\n"))
    return "\n".join(related_content)

def define_prompt():
    question = '我身高170,体重140斤,买多大尺码'
    docs = db.similarity_search(question, k=1)
    related_content = get_related_content(docs)

    PROMPT_TEMPLATE = """
        基于以下已知信息,简洁和专业的来回答用户的问题。不允许在答案中添加编造成分。
        已知内容:
        {context}
        问题:
        {question}"""

    prompt = PromptTemplate(
        input_variables=["context", "question"],
        template=PROMPT_TEMPLATE,)

    my_pmt = prompt.format(context=related_content,
                        question=question)

    return my_pmt

def qa():
    llm = ChatGLM2()
    llm.load_model("/Users/**/PycharmProjects/llm/ChatGLM-6B/THUDM/chatglm-6b")
    my_pmt = define_prompt()
    result = llm(my_pmt)
    return result



if __name__ == '__main__':
    result = qa()
    print(result)


小结

主要介绍了基于LangChain+ChatGLM-6B模型实现本地知识库的问答实现原理+过程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《精通ChatGPT:从入门到大师的Prompt指南》附录C:专业术语表

附录C:专业术语表 本附录旨在为读者提供一本全面的术语表,帮助理解《精通ChatGPT:从入门到大师的Prompt指南》中涉及的各种专业术语。无论是初学者还是高级用户,这些术语的定义和解释将为您在使用ChatGPT时提供重要参考。 A AI&…

【数据结构与算法】使用单链表实现队列:原理、步骤与应用

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《数据结构与算法》 期待您的关注 ​ 目录 一、引言 🎄队列的概念 🎄为什么要用单链表实现队列 二、单…

深圳中赢娱乐控股集团至江西省宜春市袁州区访问交流

2024年6月7日,深圳中赢娱乐控股集团受邀来到江西省宜春市袁州区就“短剧文旅”项目展开深度座谈,并与飞剑潭乡达成合作意向。 下午2:30,深圳中赢控股集团董事李平进带团队一行12人,访问宜春市袁州区,宜春市副市长谢萍、…

《C++ Primer Plus》第十三章复习题和编程练习

目录 一、复习题**二、编程练习 一、复习题** 1. 派生类从基类那里继承了什么? 答:在类的继承和派生中,C中的派生类能够继承基类的所有数据成员和大部分成员函数。但是基类中不同访问控制权限的成员在派生中的访问权限也不相同。公有成员直…

PGL图学习之图游走类metapath2vec模型[系列五]

本项目链接:https://aistudio.baidu.com/aistudio/projectdetail/5009827?contributionType1 有疑问查看原项目 相关项目参考: 关于图计算&图学习的基础知识概览:前置知识点学习(PGL)系列一 https://aistudio.…

企业网页制作

随着互联网的普及,企业网站已成为企业展示自己形象、吸引潜在客户、开拓新市场的重要方式。而企业网页制作则是构建企业网站的基础工作,它的质量和效率对于企业网站的成败至关重要。 首先,企业网页制作需要根据企业的特点和需求进行规划。在网…

MySQL的PrepareStatement真的是预编译语句么?

PrepareStatement真的是预编译语句么? ChatGPT对PrepareStatement的定义是: PrepareStatement 是 Java 数据库连接(JDBC)API 中用于执行预编译 SQL 语句的接口。通过使用 PreparedStatement,可以预编译 SQL 语句&…

Python代码大使用Paramiko轻松判断文件类型,提取上级目录

哈喽,大家好,我是木头左! 一、Paramiko简介 Paramiko是一个用于SSHv2协议的Python实现,提供了客户端和服务器功能。它可以用于远程连接和管理服务器,执行命令、上传下载文件等。本文将介绍如何使用Paramiko判断文件类…

前端 Vue 操作文件方法(导出下载、图片压缩、文件上传和转换)

一、前言 本文对前端 Vue 项目开发过程中,经常遇到要对文件做一些相关操作,比如:文件导出下载、文件上传、图片压缩、文件转换等一些处理方法进行归纳整理,方便后续查阅和复用。 二、具体内容 1、后端的文件导出接口,…

C++程序设计:对数据文件的操作与文件流

姚老师小课堂开课啦! 一、文件的分类: 1.ASCII码文件: ASCII文件使用方便,比较直观,便于阅读,便于对字符进行输入输出,但一般占用存储空间较多,而且需要花费转换时间(二…

逆市创新高!水电“双雄“是怎样炼成的? 博通,赢麻了!

高分红夏季用电高峰AI的尽头是电力 6月7日,长江电力(600900)、华能水电(600025)股价双双上涨。截至收盘,长江电力股价上涨1%,收于28.31元/股;华能水电股价上涨1.52%,收于…

sqli-labs 靶场 less-8、9、10 第八关到第十关详解:布尔注入,时间注入

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。Less 8 SQLI DUMB SERIES-8判断注入点 当输入id为1时正常显示: 加上单引号就报错了 …

Kafka 架构

1 整体架构 1.1 Zookeeper Zookeeper 是一个分布式协调服务,用于管理 Kafka 的元数据。它负责维护 Kafka 集群的配置信息、Broker 列表和分区的 Leader 信息。 Zookeeper 确保了 Kafka 集群的高可用性和可靠性。 但 Zookeeper 已经成为 Kafka 性能瓶颈,…

什么是 AOF 重写?AOF 重写机制的流程是什么?

引言:在Redis中,持久化是确保数据持久性和可恢复性的重要机制之一。除了常见的RDB(Redis Database)持久化方式外,AOF(Append Only File)也是一种常用的持久化方式。AOF持久化通过记录Redis服务器…

基于xml的Spring应用(理解spring注入)

目录 问题: 传统Javaweb开发的困惑? 问题: IOC、DI和AOP的思想提出 问题: Spring框架的诞生 1. BeanFactory快速入门 2. ApplicationContext快速入门 3. BeanFactory和ApplicationContext的关系 基于xml的Spring应用 1. SpringBean的…

Mamba v2诞生:3 SMA与Mamba-2

大模型技术论文不断,每个月总会新增上千篇。本专栏精选论文重点解读,主题还是围绕着行业实践和工程量产。若在某个环节出现卡点,可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技(Mamba,xLSTM,KAN)则提…

312. 戳气球 Hard

有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和 i 相邻…

JDK17 | Windows环境配置

众所周知, Jdk8做了很大的提升,网上的访谈,问到当下程序员要不要升级JDK版本的时候,得到异口同声的答案,不需要。这么多年过去了,数据是不会骗人的,现在Star最多的是JDK17,今天&…

STM32中ADC在cubemx基础配置界面介绍

ADCx的引脚,对应的不同I/O口,可以复用。 Temperature :温度传感器通道。 Vrefint :内部参照电压。 Conversion Trigger: 转换触发器。 IN0 至 IN15,是1ADC1的16个外部通道。本示例中输出连接的是ADC2的IN5通道,所以只勾选IN5.Temperature Sensor Cha…

搭建自己的组件库<2>dialog 组件

目录 设置title 插槽显示 控制宽高 关闭对话框 transition实现动画 引入深度选择器 同样创建组件dialogue.vue后全局注册 dialogue模版&#xff1a; <template><!-- 对话框的遮罩 --><div class"miao-dialog_wrapper"><!-- 真的对话框 …