基于ChatGLM+Langchain离线搭建本地知识库(免费)

news2024/12/27 11:52:26

目录

简介

服务部署

实现本地知识库

测试

番外


简介

ChatGLM-6B是清华大学发布的一个开源的中英双语对话机器人。基于 General Language Model (GLM) 架构,具有 62 亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署(INT4 量化级别下最低只需 6GB 显存)。

LangChain提供了丰富的生态,可以非常方便的封装自己的工具,并接入到LangcChain的生态中,从而实现语言模型的交互,将多个组件链接在一起,并集成额外的资源,例如 API 和数据库。

服务部署

我是在一台离线服务器上,GPU内存16G,其中python3.10以上,torch1.10以上。首先github下载ChatGLM-6B(https://github.com/THUDM/ChatGLM-6B),方便调用接口,里面有一个 requirements.txt文件,直接安装里面环境即可,然后在Huggingface下载模型chatglm-6b(https://huggingface.co/THUDM/chatglm3-6b),最后将下载好的模型离线打包到离线服务器上。如下所示,其中kownledge文件夹里面包含了我要输入的知识文档(自己的一些文档、pdf、csv文件等)。

当环境搭建好之后,进入ChatGLm-6B文件夹下,打开api.py文件,将tokenizer和model的模型路径修改成从Huggingface下载下来的chatglm-6b模型路径,这里我用的是相对路径。

然后在服务器上运行api.py文件,服务在端口8000运行。

写一个测试代码api_access.py,看看服务是否能被正常使用。值得注意的是,如果你是在本地运行,这里的url写localhost:8000或者127.0.0.1:8000,如果是服务器运行,则写服务器的ip地址。

import requests

def chat(prompt, history):
    resp = requests.post(
        #url = 'http://127.0.0.1:8000',
        url = 'http://172.27.171.194:8000',
        json = {"prompt": prompt, "history": history },
        headers = {"Content-Type": "application/json;charset=utf-8"}
    )
    return resp.json()['response'], resp.json()['history']


history = []
while True:
    response, history = chat(input("Question:"), history)
    print('Answer:',response)

运行结果如下所示,说明该api服务能够正常使用。

实现本地知识库

首先在Huggingface下载向量化模型,我选择了text2vec-base-chinese(https://huggingface.co/shibing624/text2vec-base-chinese/tree/main)

然后编写一个embedding.py文件,主要存放各种方法,完整代码如下所示。值得注意的是,由于我的服务器有多张显卡,因此我将cuda设置为1,你如果只有一张显卡,就直接是cuda:0。

from langchain_community.document_loaders import  Docx2txtLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from transformers import BertModel, BertTokenizer
import torch
import os

# -*- coding: utf-8 -*-

class EmbeddingFunction:
    def __init__(self, embedding_function):
        self.embedding_function = embedding_function

    def embed_query(self, query):
        return self.embedding_function(query)

    def embed_documents(self, documents):
        return [self.embedding_function(doc) for doc in documents]


class EmbeddingRetriever:
    def __init__(self):
        # 加载embedding
        self.embedding_model_dict = {
            "text2vec3": "shibing624/text2vec-base-chinese",
            "bert-base-chinese": "/home/ai/bert-base-chinese",
        }

    def load_documents(self,directory='kownledge'):
        documents = []
        for item in os.listdir(directory):
            if item.endswith("docx") or item.endswith("pdf"):
                split_docs = self.add_document(directory, item)
                documents.extend(split_docs)
        return documents

    def add_document(self, directory='kownledge', doc_name=''):
        file_path = os.path.join(directory, doc_name)
        if doc_name.endswith("docx"):
            loader = Docx2txtLoader(file_path=file_path)
        elif doc_name.endswith("pdf"):
            loader = PyPDFLoader(file_path=file_path)
        data = loader.load()
        text_spliter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)

        split_docs = text_spliter.split_documents(data)
        return split_docs

    def load_embedding_mode(self,model_name="text2vec3"):
        model_path = self.embedding_model_dict[model_name]
        tokenizer = BertTokenizer.from_pretrained(model_path)
        model = BertModel.from_pretrained(model_path).to("cuda:1")

        def embedding_function(text):
            inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True, max_length=512).to("cuda:1")
            with torch.no_grad():
                outputs = model(**inputs)
            embedding = outputs.last_hidden_state.mean(dim=1).squeeze().cpu().numpy().tolist()
            return embedding

        return embedding_function
    def store_chroma(self,docs, db):
        db.add_documents(docs)
        db.persist()
        return db

简单解释如下,在load_documents和add_document方法中,由于我的知识文档是docx和pdf格式的,因此我就只写了两个类型,你如果有其他类型比如csv或者txt可以修改调用方式,如:

from langchain_community.document_loaders import  TextLoader,CSVLoader

测试

编写一个问答代码my_qa.py,完整代码如下所示,记得修改url地址。

from langchain_community.vectorstores import Chroma
import requests
from embedding import EmbeddingRetriever,EmbeddingFunction

# -*- coding: utf-8 -*-

def chat(prompt, history=None):
    plyload = {
        "prompt": prompt, "history": [] if not history else history
    }
    headers = {"Content-Type": "application/json"}
    resp = requests.post(
        url = 'http://172.27.171.194:8000',
        json = plyload,
        headers = headers
    ).json()
    return resp['response']

retriever = EmbeddingRetriever()
embedding_function = EmbeddingFunction(retriever.load_embedding_mode())
db = Chroma(embedding_function=embedding_function, persist_directory='VectorStore')

# 添加知识文档
if True:
    documents = retriever.add_document(doc_name='课程表.docx')
    #documents = retriever.load_documents()
    db = retriever.store_chroma(documents,db)

while True:
    query = input("question:")

    similar_docs = db.similarity_search(query,k=3)

    prompt = "基于以下给出的资料,回答问题:\n"
    for doc in similar_docs:
        prompt += f"{doc.page_content}\n"
    prompt += f"问题: {query}"

    response = chat(prompt,[])
    print("Bot:", response)

简单解释如下:

在服务器上运行python my_qa.py,结果如下:

可以看到,准确度还是相当不错的。如果自己输入的知识库数量越多,回答越准确。

最后看看我的服务器上的文档位置。

可能出现的问题

1、解决transformers和sentence-transformers版本冲突问题

使用pip install -U sentence-transformers下载sentence-transformers时会下载最新版2.7.0并且把最新版的transformers4.39.3一起附带下载下来,但是在ChatGLM中要求的transformers版本是4.27.1,因此如果使用最新版的transformers在运行api.py接口时会报错提示没有xxxx属性。解决方式有两种,第一种就是手动降低版本(但可能会报出其他错误),第二种就是修改chatglm-6b的配置文件,如下所示:

就是将从Huggingface下载的模型chatglm-6b下的tokenization_chatglm.py文件进行修改,将第222行的代码注释,放在第196行,也就是super().__init__上面。

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

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

相关文章

SSM【Spring SpringMVC Mybatis】—— Spring(一)

目录 1、初识Spring 1.1 Spring简介 1.2 搭建Spring框架步骤 1.3 Spring特性 1.5 bean标签详解 2、SpringIOC底层实现 2.1 BeanFactory与ApplicationContexet 2.2 图解IOC类的结构 3、Spring依赖注入数值问题【重点】 3.1 字面量数值 3.2 CDATA区 3.3 外部已声明be…

地图涟漪效果

参考API echarts图表集 useEcharts.js import { onBeforeUnmount, onDeactivated } from "vue"; // import * as echarts from "echarts";/*** description 使用 Echarts (只是为了添加图表响应式)* param {Element} myChart Echarts实例 (必传)* param …

【IC前端虚拟项目】axi ddr/sram验证组件思路与编写

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 在完成了所有的utils包括apb_utils之后,就要进行验证环境的整体搭建,因此我们再把验证环境拿出来看一下: 按照由底至顶层的思路,接下主要有五大部分需要我们完成:ram_model、reference_model、env、…

软件体系结构总结

文章目录 一、软件体系结构概述1.1 基本概念1.1.1 背景1.1.2 定义1.1.3 系统1.1.3.1 定义1.1.3.2 特性1.1.3.3 系统的体系结构 1.1.4 软件设计的层次性1.1.5 体系结构的类别(类型)1.1.6 重要性(意义) 1.2 模块及其设计1.2.1 定义1…

值得收藏!!《软考信息处理技术员》必背100母题,轻松45+

距离软考考试的时间越来越近了,趁着这两周赶紧准备起来 今天给大家整理了——软考信息处理技术员100道经典母题,年年从里面抽,有PDF,可打印,每天刷几道。 第一章 电脑的基本操作 1、( )不是国产…

OC foudation框架(上)学习

foundation框架 文章目录 foundation框架字符串(NSString && NSMutableString)NSString的其他功能NSMutableString 日期与时间 (NSDate)2.1 日期与时间(NSDate)2.2日期格式器日历与日期组件定时器&…

文献速递:多模态深度学习在医疗中的应用--多模态深度学习用于阿尔茨海默病痴呆评估

Title 题目 Multimodal deep learning for Alzheimer’s disease dementia assessment 多模态深度学习用于阿尔茨海默病痴呆评估 01 文献速递介绍 全球每年新发痴呆症病例近1000万例,其中阿尔茨海默病(AD)最为常见。需要新的措施来改善因…

Linux(centos7)系统配置 ntpd服务设置时间同步

一 、应用场景 两台服务器,要求使他们时间同步,有人问为什么要时间同步?如果一个集群中,时间相差很大,那么会出现很多诡异的问题,你也不想在一个无法解决的问题上浪费几天时间吧!总之,设置服务器之间时间同步,为了避免很多问题的发生! ntpd(Network Time Protocol …

【ZYNQ】Vivado 封装自定义 IP

在 FPGA 开发设计中,IP 核的使用通常是不可缺少的。FPGA IP 核是指一些已经过验证的、可重用的模块或者组件,可以帮助构建更加复杂的系统。本文主要介绍如何使用 Vivado 创建与封装用户自定义 IP 核,并使用创建的 IP 核进行串口回环测试。 目…

[开发|安卓] Android Studio 开发环境配置

Android Studio下载 Android Studio下载地址 下载SDK依赖 1.点击左上角菜单 2.选择工具 3.打开SDK管理中心 4.下载项目目标Android版本的SDK 配置安卓虚拟机 1.打开右上角的设备管理 2.选择合适的手机规格 3.下载并选择项目目标Android系统 4.点击完成配置 …

SpringBoot 3.2.5 + ElasticSearch 8.12.0 - SpringData 开发指南

目录 一、SpringData ElasticSearch 1.1、环境配置 1.2、创建实体类 1.3、ElasticSearchTemplate 的使用 1.3.1、创建索引库,设置映射 1.3.2、创建索引映射注意事项 1.3.3、简单的 CRUD 1.3.4、三种构建搜索条件的方式 1.3.5、NativeQuery 搜索实战 1.3.6…

使用socat做端口转发

最近买的云上mongo数据库但是数据库不支持外网访问,准备做iptables转发但是一直不成功,腾讯云官方给予的解释是受服务器内启动的docker影响 做iptables转发会冲突,所以只能另想办法,我发现使用socat做转发也很好用,所以…

01.基本概念

操作系统 为什么要有操作系统? 计算机时一个十分复杂的系统,又cpu、内存、磁盘、IO设备、网络接口等等复杂的硬件组成,人的精力是有限的,不可能了解所有的硬件接口,但是程序可以。 所以我们在计算机上安装了一层软件&…

网易云新玩法:教你赚取第一桶金!

在现今的音乐应用市场中,有几款软件备受广大用户的青睐。 其中,QQ音乐、酷狗音乐以及网易云音乐都是大家耳熟能详的名字。 这些平台不仅提供了丰富的音乐资源,还具备了许多便捷的功能,使得用户们能够享受到更为优质的音乐体验。…

五一 大项目

Docker 中的 Nginx 服务为什么要启用 HTTPS 一安装容器 1 安装docker-20.10.17 2 安装所需的依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm23 添加Docker官方仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos…

linux安装配置Docker保姆级教程

Docker到底是什么? Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。 容器是完全使用沙箱机制,相互之间…

【MySQL的内置函数】

文章目录 一、日期函数1.current_date()2.current_time()3.current_timestamp4. date_add 穿越未来5.date_sub 回到过去6.datediff案例 二、字符串函数2.1charset2.2 concat ——拼接字符串2.3 ucase——转化成大写2.4 lcase——转化成小写2.5 left()2.6…

vue3 element plus el-date-picker组件在日期上做标识

1.先看效果图,带红点的就是我要做标识的日期 2.直接把代码拿出来就可以用 (1)html部分 <el-date-pickerv-model"startTime"type"datetime"placeholder"选择开始日期"format"YYYY-MM-DD HH:mm"value-format"YYYY-MM-DD HH:mm…

测试新人常问:如何开始自动化测试,必须知道的10点!

随着互联网技术的发展&#xff0c;无论哪个公司&#xff0c;哪个团队都在谈论自动化测试、动手实现自动化测试&#xff0c;从而让测试显得更加“高大上”。 那么是不是所有的业务都适合自动化&#xff1f;是不是自动化做的越多&#xff0c;效果越好呢&#xff1f;下面就自己一…

物联网平台之单体架构

介绍本文主要介绍平台的单体架构&#xff0c;包括各个组件之间的数据流描述以及所做的一些架构选择。在单体架构模式下&#xff0c;所有 ThingsKit 组件都在单个 Java 虚拟机 (JVM) 中启动&#xff0c;并共享相同的操作系统资源。由于 ThingsKit 是用 Java 编写的&#xff0c;因…