使用 Easysearch 打造企业内部知识问答系统

news2024/9/9 1:38:46

大家可能都有这样的经历,刚入职一家企业时,同事往往会给你分享一些文档资料,有可能是产品信息、规章制度等等。这些文档有的过于冗长,很难第一时间找到想要的内容。有的已经有了新版本,但员工使用的还是老版本。

基于这种背景,我们可以利用 Easysearch 加 LLM 实现一个内部知识的 QA 问答系统。这个系统将利用 LangChain 框架调用本地部署的大模型和 Easysearch,实现理解员工的提问,并基于最新的文档,给出精准答案。

开发框架


整个框架分为四个部分:

  • 数据源:数据可以有很多种,可以是非结构化的,比如 PDF、docx、txt 等。也可以是结构化的数据,甚至代码也行。在本次示例中,我们使用 PDF 的非结构化数据。
  • 大模型应用:应用与大模型交互,生成我们需要的答案。
  • 大模型:系统执行相关任务需要用到的大模型,可以有多个。
  • Q&A 场景:基于大模型为引擎的 QA 场景,使用 web 框架,构建一个交互界面。

数据准备

本次我们使用的资料是 “INFINI 产品安装手册.pdf” ,文档部分内容展示如下:

首先我们使用 LangChain 的 document_loaders 来加载文件。document_loaders 集成了数百种数据源格式,可以很方便的加载数据。我们的数据的 pdf 格式的,导入 PyPDFLoader 类来进行处理。代码如下:

import os

# 导入 Document Loaders
from langchain_community.document_loaders import PyPDFLoader

# Load Pdf
base_dir = '.\\easysearch' # 文档的存放目录
docs = []
for file in os.listdir(base_dir):
    file_path = os.path.join(base_dir, file)
    if file.endswith('.pdf'):
        loader = PyPDFLoader(file_path)
        documents.extend(loader.load())

上面的代码将 pdf 文件的内容存储在 docs 这个列表中,以便后续进行处理。

文本分割

一个文件的文本内容可能很大,无法适应许多模型的上下文窗口,也不利于检索和存储。因此,通常我们会将文本内容分割成更小的块,这将帮助我们在运行时只检索文档中最相关的部分。LangChain 提供了工具来进行处理文本分割,非常方便。
我们将把文档分割成 1000 个字符的块,每个块之间有 200 个重叠字符。这种重叠有助于减少将语句与相关的重要上下文分离的可能性。

# 2.将Documents切分成块
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=20)
chunked_documents = text_splitter.split_documents(docs)

上面的代码将 docs 的内容按 1000 字符大小进行切分,存储在 chunked_documents 中,以便后续进行处理。
注意,实际运行中,切分及重叠的大小,都会影响应用效果,需自行调试。

向量库 Easysearch

接下来,我们将这些文本块转换成向量的形式,并存储在一个向量数据库中。在本示例中,我们使用 mxbai-embed-large 模型来生成向量,然后将向量和原始内容存入 easysearch 。

本地部署模型,我使用的是 ollama ,大家可以使用自己喜欢的工具。

# 3. 定义embedding模型
from langchain_community.embeddings import OllamaEmbeddings
ollama_emb = OllamaEmbeddings(
    model="mxbai-embed-large",
)

# 4. 定义 easysearch 集群的信息,以及存放向量的索引名称 infini
from langchain_community.vectorstores import EcloudESVectorStore
ES_URL = "https://192.168.56.3:9200"
USER = "admin"
PASSWORD = "e5ac1b537785ae27c187"
indexname = "infini"

docsearch = EcloudESVectorStore.from_documents(
    chunked_documents,
    ollama_emb,
    es_url=ES_URL,
    user=USER,
    password=PASSWORD,
    index_name=indexname,
    verify_certs=False,
)

通过上面的步骤,我们成功将文本块转换成了向量,并存入到了 easysearch 集群的 infini 索引中。

我们看看 infini 索引内容是怎样的

text 字段存放了文本块的原始内容,vector 字段存放着对应的向量表示。

检索及生成答案

在这一步,我们会定义一个生成式大模型。然后创建一个 RetrievalQA 链,它是一个检索式问答模型,用于生成问题的答案。
在 RetrievalQA 链中有下面两大重要组成部分。

  • LLM 是大模型,负责回答问题。
  • retriever(vectorstore.as_retriever())负责根据用户的问题检索相关的信息。先是找最近似的“向量块”,再把”向量块“对应的“文档块”作为知识信息,和问题一起传递进入大模型。之所以要先检索,是因为从互联网信息训练而来的大模型不可能拥有一个私营企业的内部知识。
# 5. Retrieval 准备模型和Retrieval链
import logging
# MultiQueryRetriever工具
from langchain.retrievers.multi_query import MultiQueryRetriever
# RetrievalQA链
from langchain.chains import RetrievalQA

# # 设置Logging
logging.basicConfig()
logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO)

# # 实例化一个大模型工具
from langchain_community.chat_models import ChatOllama
llm = ChatOllama(model="qwen2:latest")

from langchain.prompts import PromptTemplate
my_template = PromptTemplate(
    input_variables=["question"],
    template="""You are an AI language model assistant. Your task is
    to generate 3 different versions of the given user
    question in Chinese to retrieve relevant documents from a vector  database.
    By generating multiple perspectives on the user question,
    your goal is to help the user overcome some of the limitations
    of distance-based similarity search. Provide these alternative
    questions separated by newlines. Original question: {question}""",
)

# # 实例化一个MultiQueryRetriever
retriever_from_llm = MultiQueryRetriever.from_llm(retriever=docsearch.as_retriever(), llm=llm,prompt=my_template,include_original=True)

# # 实例化一个RetrievalQA链
qa_chain = RetrievalQA.from_chain_type(llm,retriever=retriever_from_llm)

这里我们使用 ollama 在本地部署一个 qwen2 大模型,负责问题改写和生成答案。

启动 qwen2 大模型:ollama run qwen2

我们获取到用户问题后,先通过 MultiQueryRetriever 类调用大模型 qwen2 进行改写,生成 3 个同样语义的问题,然后再调用 easyearch 进行向量检索,搜索相关内容。

最后把所有相关内容,合并、去重后,与原始问题一起提交给大模型 qwen2,进行答案生成。

虽然这里使用的是向量检索,但实际上我们可以同时使用全文检索和向量检索。这也是使用 easysearch 作为检索库的优势之一。

前端展示

这一步我们创建一个 Flask 应用(需要安装 Flask 包)来接收用户的问题,并生成相应的答案,最后通过 index.html 对答案进行渲染和呈现。

在这个步骤中,我们使用了之前创建的 RetrievalQA 链来获取相关的文档和生成答案。然后,将这些信息返回给用户,显示在网页上。

# 6. Q&A系统的UI实现
from flask import Flask, request, render_template
app = Flask(__name__) # Flask APP

@app.route('/', methods=['GET', 'POST'])
def home():
    if request.method == 'POST':

        # 接收用户输入作为问题
        question = request.form.get('question')

        # RetrievalQA链 - 读入问题,生成答案
        result = qa_chain({"query": question})

        # 把大模型的回答结果返回网页进行渲染
        return render_template('index.html', result=result)

    return render_template('index.html')

if __name__ == "__main__":
    app.run(host='0.0.0.0',debug=True,port=5000)

效果演示

我们模仿用户进行提问。

Q&A 系统进行回答,回答速度取决于本地的计算资源。

内容校验,在原始文档内用 ctrl+F 搜索关键字 LOGGING_ES_ENDPOINT 得到如下内容。

嗯,回答的还不错,达到预期目的。如果还有其他要求,可修改 my_template 中的提示词或者替换成别的大模型也是可以的。

小结

通过这次示例,我们演示了如何基于 LangChain 和 easysearch 以及大模型,快速开发出一个内部知识问答系统。怎么样,是不是觉得整个流程特别简单易懂?

如有任何问题,请随时联系我,期待与您交流!

关于 Easysearch 有奖征文活动

黑神话悟空

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。

详情查看:Easysearch 征文活动

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

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

相关文章

centos7-8/redhat7-8一键安装配置vsftp服务

1.脚本介绍 1.1.介绍: linux下一键安装及配置vsftpd服务 ,通过执行install.sh脚本,脚本会根据参数区域的值执行安装和配置vsftp服务,安装后会创建一个默认ftp用户wangxf密码wangxf2023 1、支持自定义安装(更改脚本内参数值) 2、…

javaweb_01:http

一、什么是http HTTP 是一个简单的请求-响应协议,它通常运行在TCP之上,它指定了客户端可能发送给服务器什么样的消息,以及得到什么样的响应。请求和响应都是以ASCll码的形式给出;而消息内容则具有一个类似MIME的格式。这个简单模…

面试Redis篇

本篇主要总结一下面试官可能会在Redis上询问的主要问题。 Redis的使用场景 问:你的项目中哪些场景中用到了Redis? 答:根据你的项目回答,一般会在一下几个部分缓存、分布式锁...... 缓存 缓存穿透 查询一个不存在的数据&#xff…

黑马点评--给店铺类型查询添加缓存

controller/ShopTypeController.java /*** 店铺分类查询,用于展示首页头部店铺分类* return*/GetMapping("list")public Result queryTypeList() {return typeService.queryList();} service/IShopTypeService.java Result queryList(); service/impl/S…

4234324

作者主页: 作者主页 本篇博客专栏:C 创作时间 :2024年6月20日 最后: 十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我: 1.一个冷知识: …

alg-in-go-1:动态连通性问题

前言: 有本算法书叫:Algorithms 4th Edition.pdf,它是用java实现的,但是算法的内核是一样,不在乎于语言,考虑到java当今的…, 咱们尝试用golang学习算法. 问题: 思考🤔&#xff…

弹幕背后:B站UP主创作服务解析

引言 在B站,每一条飘过的弹幕都是一个故事的碎片,它们汇聚成一幅幅生动的社交画卷。这里,不仅仅是一个视频分享平台,弹幕背后更是一个充满活力的创作者生态系统。B站以其独特的弹幕文化,为创作者和观众之间搭建起了一座…

【电控笔记-xuan】各种估测器扰动估计性能比较

各种扰动观测器观测结果 蓝色: 扰动值 隆博戈估测器扰动补偿 论文53disturb扰动补偿 2order eso 观测

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-01-层次式体系结构概述

文章目录 1. 常用层次是架构2. 层次式架构设计的注意点2.1 污水池反模式2.2 应用变得庞大 本章教材又赘述了一遍架构的定义和层次架构风格的概述,我之前的笔记都写了 架构的定义回看《第7章-系统架构设计基础知识-01-软件架构(Software Architecture&…

AD的问题

连续放置同规则元件:先选择再按Tab编辑放置; 拖动元件:(shift 空格 :旋转元件;原理图中按x水平,按y垂直翻转)按ctrl键可以丝滑流畅放置 测试距离:RM 距离单位转…

初学Mybatis之动态 SQL

动态 SQL 是指根据不同的条件生成不同的 SQL 语句 动态 SQL 详情请看链接 搭建环境: mysql 建立博客表 CREATE TABLE blog(id VARCHAR(50) NOT NULL COMMENT 博客id,title VARCHAR(100) NOT NULL COMMENT 博客标题,author VARCHAR(30) NOT NULL COMMENT 博客作者…

华为od机试真题:悄悄话(Python)

2024华为OD机试(C卷D卷)最新题库【超值优惠】Java/Python/C合集 题目描述 给定一个二叉树,每个节点上站一个人,节点数字表示父节点到该节点传递悄悄话需要花费的时间。 初始时,根节点所在位置的人有一个悄悄话想要传…

windows家庭版安装Hyper-V

uniapp开发鸿蒙需要开启Hyper-V,但家庭版默认没有,去网上搜索整理了一下。 1.检查是否安装过Hyper-V 直接搜索 Hyper-V,如果出现就代表有,如果没出现,就搜索 启用或关闭windows功能 。 如果有Hyper-V这一项&…

eclipse手动安装Ivy插件

1、下载四个文件 (1)从这个网址选择一个自己需要的版本的“ivy-”开头的文件夹进去(是“ivy”开头,不是“ivyde”) https://archive.apache.org/dist/ant/ivyde/updatesite/ 我这里选的是“ivy-2.5.0.final_201910201…

TortoiseSVN迁移到本地git

TortoiseSVN迁移到本地git 文章目录 TortoiseSVN迁移到本地git0 背景1 环境准备2 SVN库迁移到VisualSVN2.1 导出dump2.2 将dump文件灌入VisualSVN2.3 获取SVN仓最新URL 3 迁移到Git库中4 迁移分支到Git库 0 背景 之前在前东家工作都是采用git进行项目管理,高效便捷…

大模型应用中常听说的投毒实验是什么?

大模型应用中常听说的投毒实验是什么? 大模型投毒实验是指在训练或使用大规模人工智能模型(如GPT-4等)时,通过有意加入恶意数据或修改训练过程,使模型产生不正确或有害输出的行为。随着人工智能技术的快速发展&#x…

【深度学习】声码器(Vocoder),Vocos 论文

Vocos: Closing the gap between time-domain and Fourier-based neural vocoders for high-quality audio synthesis https://arxiv.org/abs/2306.00814 https://github.com/gemelo-ai/vocos?tabreadme-ov-file 文章目录 Vocos:弥合时域和基于傅里叶的神经声码器…

必看!50个ChatGPT顶尖学术论文指令,助你高效学术研究

随着人工智能技术的进步,AI已成为学术创作的重要工具。本文将为您展示如何利用AI来润色您的论文。我们精心整理了50个顶级ChatGPT学术论文指令,强烈建议您加以利用! 这些指令不仅实用,还能大幅提升您的写作效率。无论是翻译难懂的…

高效的知识付费SaaS平台构建:探索Spring Cloud结合Spring Boot的最佳实践

知识付费平台:引领在线教育的未来 在数字化教育的浪潮中,知识付费平台以其便捷、高效的学习方式,迅速成为教育领域的新宠。该平台围绕用户需求构建,提供职业技能、生活兴趣、人文社科等多领域的专业知识,并通过视频播…

【时时三省】(C语言基础)for循环

山不在高,有仙则名。水不在深,有龙则灵。 ——csdn时时三省 语法 fou(表达式1;表达式2;表达式3) 循环语句 表达式1 表达式1为初始化部分,用于初始化循环变量的。 表达式2 表达式2为条件判断部分,用于判…