ChatGLM系列六:基于知识库的问答

news2024/11/17 12:23:23

在这里插入图片描述

1、安装milvus

下载milvus-standalone-docker-compose.yml并保存为docker-compose.yml

wget https://github.com/milvus-io/milvus/releases/download/v2.3.2/milvus-standalone-docker-compose.yml -O docker-compose.yml

运行milvus

sudo docker-compose up -d

2、文档预处理

import os
import re
import jieba
import torch
import pandas as pd
from pymilvus import utility
from pymilvus import connections, CollectionSchema, FieldSchema, Collection, DataType
from transformers import AutoTokenizer, AutoModel

connections.connect(
    alias="default",
    host='localhost',
    port='19530'
)

# 定义集合名称和维度
collection_name = "document"
dimension = 768
docs_folder = "./knowledge/"

tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
model = AutoModel.from_pretrained("bert-base-chinese")


# 获取文本的向量
def get_vector(text):
    input_ids = tokenizer(text, padding=True, truncation=True, return_tensors="pt")["input_ids"]
    with torch.no_grad():
        output = model(input_ids)[0][:, 0, :].numpy()
    return output.tolist()[0]


def create_collection():
    # 定义集合字段
    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True, description="primary id"),
        FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=50),
        FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=10000),
        FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=dimension),
    ]

    # 定义集合模式
    schema = CollectionSchema(fields=fields, description="collection schema")

    # 创建集合

    if utility.has_collection(collection_name):
    	# 如果你想继续添加新的文档可以直接 return。但你想要重新创建collection,就可以执行下面的代码
        # return
        utility.drop_collection(collection_name)
        collection = Collection(name=collection_name, schema=schema, using='default', shards_num=2)
        # 创建索引
        default_index = {"index_type": "IVF_FLAT", "params": {"nlist": 2048}, "metric_type": "IP"}
        collection.create_index(field_name="vector", index_params=default_index)
        print(f"Collection {collection_name} created successfully")
    else:
        collection = Collection(name=collection_name, schema=schema, using='default', shards_num=2)
        # 创建索引
        default_index = {"index_type": "IVF_FLAT", "params": {"nlist": 2048}, "metric_type": "IP"}
        collection.create_index(field_name="vector", index_params=default_index)
        print(f"Collection {collection_name} created successfully")


def init_knowledge():
    collection = Collection(collection_name)
    # 遍历指定目录下的所有文件,并导入到 Milvus 集合中
    docs = []
    for root, dirs, files in os.walk(docs_folder):
        for file in files:
            # 只处理以 .txt 结尾的文本文件
            if file.endswith(".txt"):
                file_path = os.path.join(root, file)
                with open(file_path, "r", encoding="utf-8") as f:
                    content = f.read()
                # 对文本进行清洗处理
                content = re.sub(r"\s+", " ", content)
                title = os.path.splitext(file)[0]
                # 分词
                words = jieba.lcut(content)
                # 将分词后的文本重新拼接成字符串
                content = " ".join(words)
                # 获取文本向量
                vector = get_vector(title + content)
                docs.append({"title": title, "content": content, "vector": vector})

    # 将文本内容和向量通过 DataFrame 一起导入集合中
    df = pd.DataFrame(docs)
    collection.insert(df)
    print("Documents inserted successfully")


if __name__ == "__main__":
    create_collection()
    init_knowledge()

3、知识库匹配

通过向量索引库计算出与问题最为相似的文档

import torch
from document_preprocess import get_vector
from pymilvus import Collection

collection = Collection("document")  # Get an existing collection.
collection.load()
DEVICE = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"


# 定义查询函数
def search_similar_text(input_text):
    # 将输入文本转换为向量
    input_vector = get_vector(input_text)
	# 查询前三个最匹配的向量ID
    similarity = collection.search(
        data=[input_vector],
        anns_field="vector",
        param={"metric_type": "IP", "params": {"nprobe": 10}, "offset": 0},
        limit=3,
        expr=None,
        consistency_level="Strong"
    )
    ids = similarity[0].ids
    # 通过ID查询出对应的知识库文档
    res = collection.query(
        expr=f"id in {ids}",
        offset=0,
        limit=3,
        output_fields=["id", "content", "title"],
        consistency_level="Strong"
    )
    print(res)
    return res


if __name__ == "__main__":
	question = input('Please enter your question: ')
    search_similar_text(question)

4、完成回答

from transformers import AutoModel, AutoTokenizer
from knowledge_query import search_similar_text


tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b-int4", trust_remote_code=True)
model = AutoModel.from_pretrained("THUDM/chatglm-6b-int4", trust_remote_code=True).half().cuda()
model = model.eval()


def predict(input, max_length=2048, top_p=0.7, temperature=0.95, history=[]):
	res = search_similar_text(input)
	prompt_template = f"""基于以下已知信息,简洁和专业的来回答用户的问题。
如果无法从中得到答案,请说 "当前会话仅支持解决一个类型的问题,请清空历史信息重试",不允许在答案中添加编造成分,答案请使用中文。

已知内容:
{res}

问题:
{input}
"""
	query = prompt_template
	for response, history in model.stream_chat(tokenizer, query, history, max_length=max_length, top_p=top_p,
	                                           temperature=temperature):
	    chatbot[-1] = (parse_text(input), parse_text(response))
	
	    yield chatbot, history

from transformers import AutoModel, AutoTokenizer
import gradio as gr
import mdtex2html

from knowledge_query import search_similar_text

tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b-int4", trust_remote_code=True)
model = AutoModel.from_pretrained("THUDM/chatglm-6b-int4", trust_remote_code=True).half().cuda()
model = model.eval()
is_knowledge = True

"""Override Chatbot.postprocess"""


def postprocess(self, y):
    if y is None:
        return []
    for i, (message, response) in enumerate(y):
        y[i] = (
            None if message is None else mdtex2html.convert((message)),
            None if response is None else mdtex2html.convert(response),
        )
    return y


gr.Chatbot.postprocess = postprocess


def parse_text(text):
    """copy from https://github.com/GaiZhenbiao/ChuanhuChatGPT/"""
    lines = text.split("\n")
    lines = [line for line in lines if line != ""]
    count = 0
    for i, line in enumerate(lines):
        if "```" in line:
            count += 1
            items = line.split('`')
            if count % 2 == 1:
                lines[i] = f'<pre><code class="language-{items[-1]}">'
            else:
                lines[i] = f'<br></code></pre>'
        else:
            if i > 0:
                if count % 2 == 1:
                    line = line.replace("`", "\`")
                    line = line.replace("<", "&lt;")
                    line = line.replace(">", "&gt;")
                    line = line.replace(" ", "&nbsp;")
                    line = line.replace("*", "&ast;")
                    line = line.replace("_", "&lowbar;")
                    line = line.replace("-", "&#45;")
                    line = line.replace(".", "&#46;")
                    line = line.replace("!", "&#33;")
                    line = line.replace("(", "&#40;")
                    line = line.replace(")", "&#41;")
                    line = line.replace("$", "&#36;")
                lines[i] = "<br>"+line
    text = "".join(lines)
    return text


def predict(input, chatbot, max_length, top_p, temperature, history):
    global is_knowledge

    chatbot.append((parse_text(input), ""))
    query = input
    if is_knowledge:
        res = search_similar_text(input)
        prompt_template = f"""基于以下已知信息,简洁和专业的来回答用户的问题。
如果无法从中得到答案,请说 "当前会话仅支持解决一个类型的问题,请清空历史信息重试",不允许在答案中添加编造成分,答案请使用中文。

已知内容:
{res}

问题:
{input}
"""
        query = prompt_template
        is_knowledge = False
    for response, history in model.stream_chat(tokenizer, query, history, max_length=max_length, top_p=top_p,
                                               temperature=temperature):
        chatbot[-1] = (parse_text(input), parse_text(response))

        yield chatbot, history


def reset_user_input():
    return gr.update(value='')


def reset_state():
    global is_knowledge

    is_knowledge = False
    return [], []


with gr.Blocks() as demo:
    gr.HTML("""<h1 align="center">ChatGLM</h1>""")

    chatbot = gr.Chatbot()
    with gr.Row():
        with gr.Column(scale=4):
            with gr.Column(scale=12):
                user_input = gr.Textbox(show_label=False, placeholder="Input...", lines=10).style(
                    container=False)
            with gr.Column(min_width=32, scale=1):
                submitBtn = gr.Button("Submit", variant="primary")
        with gr.Column(scale=1):
            emptyBtn = gr.Button("Clear History")
            max_length = gr.Slider(0, 4096, value=2048, step=1.0, label="Maximum length", interactive=True)
            top_p = gr.Slider(0, 1, value=0.7, step=0.01, label="Top P", interactive=True)
            temperature = gr.Slider(0, 1, value=0.95, step=0.01, label="Temperature", interactive=True)

    history = gr.State([])

    submitBtn.click(predict, [user_input, chatbot, max_length, top_p, temperature, history], [chatbot, history],
                    show_progress=True)
    submitBtn.click(reset_user_input, [], [user_input])

    emptyBtn.click(reset_state, outputs=[chatbot, history], show_progress=True)

demo.queue().launch(share=False, inbrowser=True)

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

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

相关文章

华为云1核2G2M带宽HECS云服务器价格和性能测评

华为云1核2G2M带宽HECS云服务器优惠价一年51元&#xff0c;高IO_40G系统盘&#xff0c;自带独立公网IP地址&#xff0c;可选北京、乌兰察布、上海和广州地域&#xff0c;华为云1核2G2M带宽服务器适用于小型网站、软件及应用。活动链接&#xff1a;atengyun.com/go/huawei 活动打…

在Win11上部署ChatGLM2-6B详细步骤--(下)开始部署

接上一章《在Win11上部署ChatGLM2-6B详细步骤--&#xff08;上&#xff09;准备工作》 这一节我们开始进行ChatGLM2-6B的部署 三&#xff1a;创建虚拟环境 1、找开cmd执行 conda create -n ChatGLM2-6B python3.8 2、激活ChatGLM2-6B conda activate ChatGLM2-6B 3、下载…

echarts将展示全天的数据,如一天的电费,一个停车场一天的饱和度等问题

项目场景&#xff1a; 我们的项目是通过ai识别停车场的停车数,来展示此停车场全天的饱和度,如下 问题描述 后台接口给的数据,就是这种,返回所有有停车数量的时间段,但是我们的x轴要求展示全天的数据,并且可伸缩刻度展示具体时间的停车情况 [{time:2023-10-27 08:20:20,carS…

vue的双向绑定的原理,和angular的对比

目录 前言 Vue的双向绑定用法 代码 Vue的双向绑定原理 Angular的双向绑定用法 代码 Angular的双向绑定原理 理解 图片 关于Vue的双向绑定原理和与Angular的对比&#xff0c;我们可以从以下几个方面进行深入探讨&#xff1a; 前言 双向绑定是现代前端框架的核心特性之…

【sql】sql中true,false 和 null之间and、or运算的理解。

select true and null "tan",false and null "fan",true or null "ton",false or null "fon";结果如下&#xff1a; 怎么理解呢&#xff1f; 很简单&#xff0c;把null当做介于true和false中间的值&#xff0c;也就是如果true1,false…

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。

1、在vscode终端执行 get-ExecutionPolicy &#xff0c;显示Restricted&#xff0c;说明状态是禁止的。 2、更改状态: set-ExecutionPolicy RemoteSigned 出现需要管理员权限提示&#xff0c;可选择执行 Set-ExecutionPolicy -Scope CurrentUser 出现的ExecutionPolicy参数后输…

《ATTCK视角下的红蓝对抗实战指南》一本书构建完整攻防知识体系

一. 网络安全现状趋势分析 根据中国互联网络信息中心&#xff08;CNNIC&#xff09;发布的第51次《中国互联网络发展状况统计报告》&#xff0c;截至2022年12月&#xff0c;我国网民规模为10.67亿&#xff0c;互联网普及率达75.6%。我国有潜力建设全球规模最大、应用渗透最强的…

【AI视野·今日NLP 自然语言处理论文速览 第五十七期】Wed, 18 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 18 Oct 2023 Totally 82 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers VeRA: Vector-based Random Matrix Adaptation Authors Dawid Jan Kopiczko, Tijmen Blankevoort, Yuki Marku…

使用 RAG、Langchain 和 Streamlit 制作用于文档问答的 AI 聊天机器人

在这篇文章中&#xff0c;我们将探索创建一个简单但有效的聊天机器人&#xff0c;该机器人根据上传的 PDF 或文本文件的内容响应查询。该聊天机器人使用 Langchain、FAISS 和 OpenAI 的 GPT-4 构建&#xff0c;将为文档查询提供友好的界面&#xff0c;同时保持对话上下文完整。…

EtherCAT转Profinet协议网关使西门子和倍福的PLC实现通讯的方法

通过倍福PLC协议&#xff0c;远创智控YC-ECTM-PN网关能与倍福系列的PLC进行通信&#xff0c;一起探索下如何操作吧。 1.网关通过网线和倍福 PLC、电脑进行连接&#xff0c;如果网口不够&#xff0c;可以使用交换机连接。 开VS软件&#xff0c;新建一个工程&#xff0c;选择对应…

mac idea 解决0% classes 0% lines covered不显示,非快捷键办法

问题如下 网上说了一堆快捷键&#xff0c;冲突了用不了&#xff0c;页面按下面这样点就可以了点击no coverage就行了

高并发下的缓存击穿、雪崩、穿透和分布式锁(三)

一.缓存穿透 概念&#xff1a; 去查询缓存和数据库都不存在的数据&#xff0c;然后大量请求不存在的数据&#xff0c;导致数据库压力过大崩溃。 解决方案&#xff1a; 把不存在的数据null存入缓存&#xff0c;并给个短期的过期时间。 二.缓存雪崩 概念&#xff1a; 缓存采用…

树莓派 Qt中 QCameraInfo 无法使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、QCameraInfo 是什么&#xff1f;二、使用步骤1.测试代码2.解决方案2.1输入命令2.2输出 3. 成功打印了摄像头的信息 总结 前言 提示&#xff1a;这里可以添…

苹果秋季发布会官宣,新款Mac将搭载M3芯片,来势迅猛!

苹果宣布将于 10 月 31 日上午 8 点&#xff08;北京时间&#xff09;举行发布会&#xff0c;这次发布会的主题是「来势迅猛」&#xff0c;旨在为全球的苹果粉丝和科技爱好者带来令人期待的新品发布。这次发布会引人瞩目&#xff0c;因为它将聚焦在 Mac 系列产品以及全新的 M3 …

Spring源码解析-注册配置信息

1、注册方法概述 register(componentClasses) 注册配置类的信息。其中componentClasses 为传入的配置类class。 通过AnnotatedBeanDefinitionReader 的register(this.reader.register(componentClasses))方法。AnnotatedBeanDefinitionReader 已经注册了系统自带的处理器以及方…

程序化广告系列之一---名词解释

基础 1、DSP&#xff1a;全称“Demand-Side Platform”&#xff0c;需求方平台&#xff0c;是为广告主、代理商提供一个综合性的管理平台&#xff0c;通过统一界面管理多个数字广告和数据交换账户。 2、SSP&#xff1a;SSP是Sell-Side Platform的缩写&#xff0c;即供应方平台…

边缘计算技术的崭新篇章:赋能未来智能系统

边缘计算是近年来云计算和物联网技术发展的重要趋势。通过将数据处理和分析从云端迁移到设备边缘&#xff0c;边缘计算能够实现更低的延迟和更高的数据安全。本文将探索边缘计算技术的最新进展及其在不同行业中的应用场景。 1. 实时数据处理与决策 在需要快速响应的场景中&…

电脑技巧:Win10飞行模式相关知识介绍

目录 一、飞行模式简介 二、如何开关Windows 10中的飞行模式 方法一&#xff1a;使用硬件开关 方法二&#xff1a;使用Windows 10操作中心 方法三&#xff1a;使用Windows 10设置 三、飞行模式开关被卡住、变灰或不工作时怎么办 什么是 Windows 10 飞行模式? 用户如何打…

matlab simulink ADRC控制样例

1、内容简介 略 3-可以交流、咨询、答疑 2、内容说明 用adrc控制传递函数&#xff0c;保证输出达到预期 ADRC控制器、传递函数 3、仿真分析 4、参考论文 略

计算机网络重点概念整理-第六章 应用层【期末复习|考研复习】

第六章 应用层 【期末复习|考研复习】 计算机网络系列文章传送门&#xff1a; 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 第六章 应用层 【期末复习|考研复习…