(四)、基于 LangChain 实现大模型应用程序开发 | 基于知识库的个性化问答 (基本功能介绍)

⭐ 使用大语言模型构建一个能够回答关于给定文档和文档集合的问答系统是一种非常实用和有效的应用场景。与仅依赖模型预训练知识不同,这种方法可以进一步整合用户自有数据,实现更加个性化和专业的问答服务。 例如,我们可以收集某公司的内部文档、产品说明书等文字资料,导入问答系统中。然后用户针对这些文档提出问题时,系统可以先在文档中检索相关信息,再提供给语言模型生成答案。

这样,语言模型不仅利用了自己的通用知识,还可以充分运用外部输入文档的专业信息来回答用户问题,显著提升答案的质量和适用性。构建这类基于外部文档的问答系统,可以让语言模型更好地服务于具体场景,而不是停留在通用层面。这种灵活应用语言模型的方法值得在实际使用中推广。

基于文档问答的这个过程,我们会涉及 LangChain 中的其他组件,比如:嵌入模型(Embedding Models)和向量储存(Vector Stores)等;

文章目录

  • 01、给LLM引入外部知识库的流程
  • 02、初始化openai环境
  • 03、本章内容采用以下两种方式实现
  • 一、方式1:直接使用向量存储查询
    • 1.1 导入数据
    • 1.2 基于文档加载器创建向量存储
    • 1.3 查询创建的向量存储
  • 二、 方式2:结合表征模型和向量存储
    • 2.1 导入数据
    • 2.2 文本向量表征模型
    • 2.3 基于向量表征创建并查询向量存储
    • 2.4 使用查询结果构造提示来回答问题
    • 2.5 使用检索问答链 RetrievalQA 来回答问题
  • Reference

01、给LLM引入外部知识库的流程

引入外部知识的主要流程如下(引用 LangChain-Chatchat (原 Langchain-ChatGLM) 项目的图):
在这里插入图片描述

  • (1)加载文件
  • (2)读取文本
  • (3)文本分割
  • (4)文本向量化
  • (5)问句向量化
  • (6)在文本向量中匹配出与问句向量最相似的 top k个
  • (7)匹配出的文本作为上下文和问题一起添加到 prompt中
  • (8)提交给 LLM生成回答。

匹配出的文本作为上下文和问题一起添加到 prompt中。从文档处理角度来看,实现流程如图所示。核心技术主要是向量 embedding,将用户知识库内容经过 embedding 存入向量知识库,然后用户每一次提问也会经过 embedding,利用向量相关性算法(例如余弦算法)找到最匹配的几个知识库片段,将这些知识库片段作为上下文,与用户问题一起作为 prompt 提交给 LLM 回答。
在这里插入图片描述

02、初始化openai环境

from langchain.chat_models import ChatOpenAI
import os
import openai
# 运行此API配置,需要将目录中的.env中api_key替换为自己的
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file
openai.api_key = os.environ['OPENAI_API_KEY']

03、本章内容采用以下两种方式实现


疑问点:
我们可以看到章节1中的index.query()的结果和第2章节中用检索问答链RetrievalQA的方法实现的结果是一样的,也许有读者会问,既然index.query()可以只用一行代码就完成了文档问答功能又何必要舍近求远搞一个RetrievalQA这样的对象来实现,并且增加很多繁琐的步骤(有5个步骤)来实现同样的效果呢?Langchain框架的作者Harrison Chase在课件视频中是这么解释的,通过index来进行文档问答,只需一行代码,但是这其中其实隐藏了很多的实现细节,如果我们使用的是RetrievalQA对象来实现文档问答功能,那么我们就可以了解其中的细节比如Embeddings,向量数据库等内容,反正各有各的好处吧。

一、方式1:直接使用向量存储查询

1.1 导入数据

from langchain.chains import RetrievalQA  #检索QA链,在文档上进行检索
from langchain.chat_models import ChatOpenAI  #openai模型
from langchain.document_loaders import CSVLoader #文档加载器,采用csv格式存储
from langchain.vectorstores import DocArrayInMemorySearch  #向量存储
from IPython.display import display, Markdown #在jupyter显示信息的工具
import pandas as pd# 某平台电商数据库
file = './data/kg.csv'# 使用pandas导入数据,用以查看
data = pd.read_csv(file, encoding='gbk')
data.head()

在这里插入图片描述

1.2 基于文档加载器创建向量存储

# 使用langchain文档加载器对数据进行导入
loader = CSVLoader(file_path=file)

创建了文档加载器loder以后,我们需要创建一个用于检索文档内容的索引器,这里我们需要指定指定一个向量数据库,我们使用DocArrayInMemorySearch作为向量数据库,DocArrayInMemorySearch是由Docarray提供的文档索引,它将会整个文档以向量的形式存储在内存中,对于小型数据集来说使用DocArrayInMemorySearch会非常方便,接下来我们还要指定一个数据源loder。
这里我们需要说明的是当加载文档后将执行三个主要步骤:

  • 1、将文档分割成块
  • 2、为每个文档创建embeddings
  • 3、将文档和embeddings存储到向量数据库中
#导入向量存储索引创建器
from langchain.indexes import VectorstoreIndexCreator # 创建指定向量存储类, 创建完成后,从加载器中调用, 通过文档加载器列表加载
# VectorstoreIndexCreator可以设置embedding参数,指定embedding的方式
index = VectorstoreIndexCreator(vectorstore_cls=DocArrayInMemorySearch).from_loaders([loader])

1.3 查询创建的向量存储

query ="请用markdown表格的方式列出所有手机品牌,并对其描述进行总结。"#使用索引查询创建一个响应,并传入这个查询
response = index.query(query)
# ' \n\n| 手机品牌 | 描述 |\n| -------- | ---- |\n| 小米14pro | 超乎你想象 |\n| 华为mate60pro | 遥遥领先 |'#查看查询返回的内容
display(Markdown(response))

在这里插入图片描述

二、 方式2:结合表征模型和向量存储

这种方式主要为了方便学习其内部细节组成

2.1 导入数据

由于语言模型的上下文长度限制,直接处理长文档具有困难。为实现对长文档的问答,我们可以引入向量嵌入(Embeddings)和向量存储(Vector Store)等技术:

首先,使用文本嵌入(Embeddings)算法对文档进行向量化,使语义相似的文本片段具有接近的向量表示。其次,将向量化的文档切分为小块,存入向量数据库,这个流程正是创建索引(index)的过程。向量数据库对各文档片段进行索引,支持快速检索。这样,当用户提出问题时,可以先将问题转换为向量,在数据库中快速找到语义最相关的文档片段。然后将这些文档片段与问题一起传递给语言模型,生成回答。

通过嵌入向量化和索引技术,我们实现了对长文档的切片检索和问答。这种流程克服了语言模型的上下文限制,可以构建处理大规模文档的问答系统。

#创建一个文档加载器,通过csv格式加载
file = './data/kg.csv'
loader = CSVLoader(file_path=file)
docs = loader.load()#查看单个文档,每个文档对应于CSV中的一行数据
docs
[Document(page_content='name: 耐克跑鞋\ndescription: 男子运动鞋为鞋款匠心融入经典设计,打造复古潮鞋佳选。', metadata={'source': './data/kg.csv', 'row': 0}),Document(page_content='name: chanel 可可小姐香水\ndescription: 清新感性的东方香调,清新活力的柑橘瞬间唤醒感官。', metadata={'source': './data/kg.csv', 'row': 1}),Document(page_content='name: 安踏运动跑鞋鞋\ndescription: 安踏星云轻质慢跑鞋,精心调教的中底材料搭配四大设计亮点,轻松解锁解锁软弹脚感。', metadata={'source': './data/kg.csv', 'row': 2}),Document(page_content='name: 华为mate60pro手机\ndescription: 遥遥领先的华为手机。', metadata={'source': './data/kg.csv', 'row': 3}),Document(page_content='name: 小罐茶彩多泡特级茉莉花茶\ndescription: 一口茶汤落喉间茉莉开,馥郁的花香扑鼻而来,像是沐浴在夏日的茉莉花田瞬间感到清新凉爽。', metadata={'source': './data/kg.csv', 'row': 4}),Document(page_content='name: 小米14pro手机\ndescription: 小米14手机超乎你想象。', metadata={'source': './data/kg.csv', 'row': 5})]

2.2 文本向量表征模型

看一看embedding向量的样子

# 使用OpenAIEmbedding类
from langchain.embeddings import OpenAIEmbeddings embeddings = OpenAIEmbeddings() #因为文档比较短了,所以这里不需要进行任何分块,可以直接进行向量表征
#使用初始化OpenAIEmbedding实例上的查询方法embed_query为文本创建向量表征
embed = embeddings.embed_query("你好呀,我的名字叫小可爱")#查看得到向量表征的长度
print("\n\033[32m向量表征的长度: \033[0m \n", len(embed))#每个元素都是不同的数字值,组合起来就是文本的向量表征
print("\n\033[32m向量表征前5个元素: \033[0m \n", embed[:5])
向量表征的长度:  1536向量表征前5个元素:  [-0.01954011514905696, -0.006576854850604859, -0.007268821433052672, -0.024199778786441622, -0.02676449759650871]

2.3 基于向量表征创建并查询向量存储

# 将刚才创建文本向量表征(embeddings)存储在向量存储(vector store)中
# 使用DocArrayInMemorySearch类的from_documents方法来实现
# 该方法接受文档列表以及向量表征模型作为输入
db = DocArrayInMemorySearch.from_documents(docs, embeddings)query = "请推荐一部华为手机"
#使用上面的向量存储来查找与传入查询类似的文本,得到一个相似文档列表
docs = db.similarity_search(query, k=3)
print("\n\033[32m返回文档的个数: \033[0m \n", len(docs))
print("\n\033[32m第一个文档: \033[0m \n", docs[0])
返回文档的个数:  4第一个文档:  page_content='name: 华为mate60pro手机\ndescription: 遥遥领先的华为手机。' metadata={'source': './data/kg.csv', 'row': 3}

2.4 使用查询结果构造提示来回答问题


llm = ChatOpenAI(temperature = 0.0) #合并获得的相似文档内容
qdocs = "".join([docs[i].page_content for i in range(len(docs))])  #将合并的相似文档内容后加上问题(question)输入到 `llm.call_as_llm`中
#这里问题是:以Markdown表格的方式列出所有具有防晒功能的衬衫并总结 
response = llm.call_as_llm(f"{qdocs} 问题:请用markdown表格的方式列出所有手机,并对每种手机的描述进行总结。") display(Markdown(response))

在这里插入图片描述

2.5 使用检索问答链 RetrievalQA 来回答问题

通过LangChain创建一个检索问答链,对检索到的文档进行问题回答。检索问答链的输入包含以下:

1、llm: 语言模型,进行文本生成。
2、chain_type: 传入链类型,这里使用stuff,将所有查询得到的文档组合成一个文档传入下一步。其他的方式包括:

  • Map Reduce: 将所有块与问题一起传递给语言模型,获取回复,使用另一个语言模型调用将所有单独的回复总结成最终答案,它可以在任意数量的文档上运行。可以并行处理单个问题,同时也需要更多的调用。它将所有文档视为独立的
  • Refine: 用于循环许多文档,际上是迭代的,建立在先前文档的答案之上,非常适合前后因果信息并随时间逐步构建答案,依赖于先前调用的结果。它通常需要更长的时间,并且基本上需要与Map Reduce一样多的调用
  • Map Re-rank: 对每个文档进行单个语言模型调用,要求它返回一个分数,选择最高分,这依赖于语言模型知道分数应该是什么,需要告诉它,如果它与文档相关,则应该是高分,并在那里精细调整说明,可以批量处理它们相对较快,但是更加昂贵。

3、retriever: 检索器

在这里插入图片描述

# 以下方法和上面方法一样,这里一步到位了,检索出来后组合在一起和query一起输入llm。
# 基于向量储存,创建检索器
retriever = db.as_retriever() qa_stuff = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever, verbose=True
)#创建一个查询并在此查询上运行链
query =  "请用markdown表格的方式列出所有手机,并对每种手机的描述进行总结。"response = qa_stuff.run(query)display(Markdown(response)) 

在这里插入图片描述

Reference

  • [1] 吴恩达老师的教程
  • [2] DataWhale组织

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

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

相关文章

Java JSON字符串替换其中对应的值

代码: public static void main(String[] args) { // String theData crmScene.getData();String theData "[{\"type\":1,\"values\":[\"审批中\",\"未交付\"],\"name\":\"status\"}]"…

实战项目:VB龟兔赛跑游戏+猜数字游戏

文章目录: 一:效果演示 二:实现思路 三:代码实现 form1 效果图 代码 form2 效果图 代码 form3 效果图 代码 一:效果演示 效果图◕‿◕✌✌✌ 代码下载 二:实现思路 窗口1:龟兔赛…

Mybatis-Plus 自定义SQL注入器,实现真正的批量插入![MyBatis-Plus系列]

导读 Hi,大家好,我是悟纤。过着爱谁谁的生活,活出不设限的人生。 在使用MyBatis-Plus时,dao层都会去继承BaseMapper接口,这样就可以用BaseMapper接口所有的方法CRUD。 在Mybatis-Plus中调用updateById方法进行数据更新默认情况下是不能更新空值字段的。

使用契约的链上限价订单

我们开发了链上限价订单。 它基于一种称为契约的智能合约,只有在花费输出的交易满足特定条件时才可以花费输出。 为了演示其工作原理,我们实施了以比特币支付的 Ordinals 代币买卖限价订单,无需托管人。 它可以运行在任何比特币协议链上&…

网络层——IP协议

文章目录 一.IP协议二.基本概念三.IP协议格式四.分片与组装五.网段划分六.特殊的IP地址七.IP地址的数量限制八.私网IP地址和公网IP地址九.路由十.路由表生成算法 一.IP协议 IP协议全称为“网际互连协议(Internet Protocol)”,IP协议是TCP/IP…

[uni-app]记录APP端跳转页面自动滚动到底部的bug

文章目录 bug描述原因分析: 处理方案 bug描述 1.点击的A页面, 跳转到了B页面, 第一次页面正常显示 2.从B页面返回A页面 3.A页面不进行任何操作,再次点击A页面进入B页面 4.B页面自动滚动到底部. 原因 看一段A页面代码 let that thisthis.defaultScrollTop uni.getStorageSy…

Zookeeper中的Watch机制的原理?

前言 Zookeeper是一个分布式协调组件,为分布式架构下的多个应用组件提供了顺序访问控制能力。它的数据存储采用了类似于文件系统的树形结构,以节点的方式来管理存储在Zookeeper上的数据 Zookeeper提供了一个Watch机制,可以让客户端感知到Zook…

启动dubbo消费端过程提示No provider available for the service的问题定位与解决

文/朱季谦 某次在启动dubbo消费端时,发现无法从zookeeper注册中心获取到所依赖的消费者API,启动日志一直出现这样的异常提示 Failed to check the status of the service com.fte.zhu.api.testService. No provider available for the service com.fte…

【Vue】Vue3 超简单拖拽条动态修改容器宽度

demo 代码 const leftBoxWidth ref(200); // 默认宽度 const leftResize (e: MouseEvent) > {const startX e.clientX;const startWidth leftBoxWidth.value;const mouseMove (documentE: MouseEvent) > {// 80 是左侧菜单宽度leftBoxWidth.value startWidth docu…

卷积神经网络(VGG-16)海贼王人物识别

文章目录 前期工作1. 设置GPU(如果使用的是CPU可以忽略这步)我的环境: 2. 导入数据3. 查看数据 二、数据预处理1. 加载数据2. 可视化数据3. 再次检查数据4. 配置数据集5. 归一化 三、构建VGG-16网络1. 官方模型(已打包好&#xff…

笔记56:深度循环神经网络

本地笔记地址:D:\work_file\DeepLearning_Learning\03_个人笔记\3.循环神经网络\第9章:动手学深度学习~现代循环神经网络 a a a a a a a a

vue动态配置路由

文章目录 前言定义项目页面格式一、vite 配置动态路由新建 /router/utils.ts引入 /router/utils.ts 二、webpack 配置动态路由总结如有启发,可点赞收藏哟~ 前言 项目中动态配置路由可以减少路由配置时间,并可减少配置路由出现的一些奇奇怪怪的问题 路由…

为什么选择B+树作为数据库索引结构?

背景 首先,来谈谈B树。为什么要使用B树?我们需要明白以下两个事实: 【事实1】 不同容量的存储器,访问速度差异悬殊。以磁盘和内存为例,访问磁盘的时间大概是ms级的,访问内存的时间大概是ns级的。有个形象…

抖音运营的必备10个工具,开启智能拓客引流新时代!

先来看实操成果,↑↑需要的同学可看我名字↖↖↖↖↖,或评论888无偿分享 一、引言 亲爱的知友们,您们是否对抖音运营有浓厚的兴趣和独特的见解?今天,我将为您介绍一些抖音运营必备的工具,帮助您在抖音上脱颖…

windows通过命令给文件夹或文件增加权限

给Demo001追加everyone权限 D:\cmd>cacls Demo001 /p everyone:f /e 处理的目录: D:\cmd\Demo001D:\cmd> 给Demo001下的所有文件追加everyone权限 D:\cmd>cacls Demo001 /p everyone:f /e /t 处理的目录: D:\cmd\Demo001 处理的目录: D:\cmd\Demo001\A 处理的文件:…

【文末送书】计算机网络 | IO多路转接技术 | poll/epoll详解

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和…

前端对用户名密码加密处理,后端解密

一. 正常表单提交如图&#xff0c;可以看见输入的用户名密码等 二. 使用crypto-js.min.js进行前端加密处理 js资源地址链接&#xff1a;https://pan.baidu.com/s/1kfQZ1SzP6DUz50D–g_ziQ 提取码&#xff1a;1234 前端代码 <script type"text/javascript" src&q…

kettle创建数据库资源库kettle repository manager

数据库资源库是将作业和转换相关的信息存储在数据库中&#xff0c;执行的时候直接去数据库读取信息&#xff0c;很容易跨平台使用。 创建数据库资源库&#xff0c;如图 1.点击Connect 2.点击Repository Manager 3.点击Other Repository 4.点击Database Repository 在选择Ot…

AI监管规则:各国为科技监管开辟了不同的道路

AI监管规则&#xff1a;各国为科技监管开辟了不同的道路 一份关于中国、欧盟和美国如何控制AI的指南。 编译 李升伟 茅 矛 &#xff08;特趣生物科技有限公司&#xff0c;广东深圳&#xff09; 插图&#xff1a;《自然》尼克斯宾塞 今年5月&#xff0c;科技公司OpenAI首席…

深兰科技成功入选《2023年度国家知识产权优势企业名单》

2023年11月13日&#xff0c;国家知识产权局正式公布了《2023年度国家知识产权优势企业的名单》(以下简称“《名单》”)。深兰人工智能科技(上海)股份有限公司成功入选&#xff0c;荣获“国家知识产权优势企业”称号。 “国家知识产权优势企业”是指企业经营范围属于国家重点发展…