文心ERNIE Bot SDK+LangChain:基于文档、网页的个性化问答系统

现在各行各业纷纷选择接入大模型,其中最火且可行性最高的形式无异于智能文档问答助手,而LangChain是其中主流技术实现工具,能够轻松让大语言模型与外部数据相结合,从而构建智能问答系统。ERNIE Bot SDK已接入文心大模型4.0能力,同时支持对话补全、函数调用、语义向量等功能。

本教程是基于文心一言ERNIE Bot SDK与LangChain构建基于Embedding Vector方式的文本问答系统, 整体可以解构为三部分。

1、基于ERNIE Bot与LangChain结合的Embedding,获取向量矩阵并保存

2、基于用户问题,在向量矩阵库中搜寻相近的原文句子

3、基于检索到的原文与Prompt结合,从LLM获取答案

图片

背景介绍

问答系统处理流程

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

技术工具
ERNIE Bot SDK

ERNIE Bot SDK 提供便捷易用的接口,可以调用文心大模型的能力,包含文本创作、通用对话、语义向量、AI作图等。

图片

LangChain

LangChain 是一个强大的框架,旨在帮助开发人员使用语言模型构建端到端的应用程序。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,并集成额外的资源,例如API和数据库。

项目代码

环境准备
安装相关库
!pip install -qr requirements.txt
读取 access_token

在星河社区的控制台访问令牌中找到自己的access_token,替换access_token.txt或下面代码中的access_token。

图片

fileName='access_token.txt'
access_token=''
if len(access_token)==0:with open(fileName,'r') as f:#逐行读取文件内容lines = f.readlines()for line in lines:if line[:13]=='access_token=':access_token=line[13:]
assert len(access_token)>10
print('access_token:',access_token)
LangChain及Embedding部分
获取文档载入器

使用GetLoader(source)获取LangChain中的Loader,GetLoader会根据source类型,调用对应的LangChain文本载入器。

创建或载入向量库

引入Embeddings函数并切分文本,chunk_size按ERNIE Bot SDK要求设为384

text_splitter = RecursiveCharacterTextSplitter(chunk_size=ernieChunkSize, chunk_overlap=0)
splits = text_splitter.split_documents(documents) 

获取整个文档或网页的Embedding向量并保存。

  embeddings=ErnieEmbeddings(access_token=access_token)# vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())vectorstore = Chroma.from_documents(persist_directory=persist_directory,documents=splits, embedding=embeddings)

根据用户问题获取文档中最相近的原文片段

使用了LangChain中的similarity_search_with_score就可以获取所需的top_k个文案片段,并且返回其score。结果显示score差别不是很大。

def searchSimDocs(query,vectorstore,top_k=3,scoreThershold=5):packs=vectorstore.similarity_search_with_score(query,k=top_k)contentList=[]for pack in packs:doc,score=packif score<scoreThershold:##好像设置5,基本都会返回contentList.append(doc.page_content)# print('content',contentList)return contentList

具体Embedding代码见下方:

import osos.environ['access_token']=access_token
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain_embedding_ErnieBotSDK import ErnieEmbeddings# Load documentsfrom langchain.document_loaders import WebBaseLoader
from langchain.document_loaders.text import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
import erniebot## https://python.langchain.com/docs/integrations/chat/ernie# loader = WebBaseLoader("https://cloud.tencent.com/developer/article/2329879")## 创建新的chroma向量库
def createDB(loader,persist_directory='./chromaDB'):#loader = TextLoader(file_path=file_path,encoding='utf8')documents=loader.load()# Split documentsernieChunkSize=384text_splitter = RecursiveCharacterTextSplitter(chunk_size=ernieChunkSize, chunk_overlap=0)splits = text_splitter.split_documents(documents)print('splits len:',len(splits))#,splits[:5])# Embed and store splitsembeddings=ErnieEmbeddings(access_token=access_token)# vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())vectorstore = Chroma.from_documents(persist_directory=persist_directory,documents=splits, embedding=embeddings)#https://juejin.cn/post/7236028062873550908# 持久化 会结合之前保存下来的 vectorstore#vectorstore.persist()return vectorstore
## 读取已保存的chroma向量库
def readDB(persist_directory="./chromaDB"):assert os.path.isdir(persist_directory)# # Embed and store splitsembeddings=ErnieEmbeddings(access_token=access_token)vectorstore = Chroma(persist_directory=persist_directory, embedding_function=embeddings)return vectorstore
## 基于用户的query去搜索库中相近的文档
def searchSimDocs(query,vectorstore,top_k=3,scoreThershold=5):packs=vectorstore.similarity_search_with_score(query,k=top_k)contentList=[]for pack in packs:doc,score=packif score<scoreThershold:##好像设置5,基本都会返回contentList.append(doc.page_content)# print('content',contentList)return contentListdef getLoader(source):if source[-4:]=='.txt':#file_path='doupo.txt'assert os.path.isfile(file_path)loader = TextLoader(file_path=file_path,encoding='utf8')elif source[:4]=='http':#url='https://zhuanlan.zhihu.com/p/657210829'loader= WebBaseLoader(source)return loader#######################################
new=True ##新建向量库,注意如果拿几百万字的小说embedding
source='https://zhuanlan.zhihu.com/p/657210829'
loader=getLoader(source)
if new:vectorstore=createDB(loader)
else:vectorstore=readDB()
# 初始化 prompt 对象
query = "大模型长文本建模的难点是什么?"
contentList=searchSimDocs(query,vectorstore,top_k=5)
print('contentList',contentList)
LLM根据相关文档片段回答问题

预置Prompt设定LLM角色,该Prompt将与向量计算中相关文档片段进行结合,作为query输入给大模型。

prompt=
"你是善于总结归纳并结合文本回答问题的文本助理。请使用以下检索到的上下文来回答问题。如果你不知道答案,就说你不知道。最多使用三句话,并保持答案简洁。问题为:\n"+query+" \n上下文:\n"+'\n'.join(contentList) +" \n 答案:"

以下为response解析代码:

def packPrompt(query,contentList):prompt="你是善于总结归纳并结合文本回答问题的文本助理。请使用以下检索到的上下文来回答问题。如果你不知道答案,就说你不知道。最多使用三句话,并保持答案简洁。问题为:\n"+query+" \n上下文:\n"+'\n'.join(contentList) +" \n 答案:"return promptdef singleQuery(prompt,model='ernie-bot'):response = erniebot.ChatCompletion.create(model=model,messages=[{'role': 'user','content': prompt}])print('response',response)try:resFlag=response['rcode']except:        resFlag=response['code']if resFlag==200:try:data=response['body']except:data=responseresult=response['result']usedToken=data['usage']['total_tokens']else:result=""usedToken=-1return result,usedTokenprompt=packPrompt(query,contentList)
res,usedToken=singleQuery(prompt,model='ernie-bot-4')
print(res)

该教程支持直接一键fork运行,点击下方链接查看。
https://aistudio.baidu.com/projectdetail/7051316

该教程项目来源于飞桨星河社区五周年开发精品教程征集,更多教程或有投稿需求请点击底部下方链接查看。

https://aistudio.baidu.com/topic/tutorial

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

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

相关文章

如何使用Imagewheel本地搭建一个简单的的私人图床公网可访问?

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

Java:字符流 文件输出 与 读入 方法

Java&#xff1a;字节流 文件输出与读入方法 并 实现文件拷贝 文章目录 字符流FileReaderFileWrite 字符流 字符流底层就是字节流。 字符流 字节流 字符集 特点&#xff1a; 输入流&#xff1a;一次读入一个字节&#xff0c;遇到中文时&#xff0c;一次读多个字节。 输出流…

POJ-2777 Count Color

经典区间染色板子题 #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N 1e610; struct Segment{int l,r,id; }tr[N<<2]; int n,color,m;void pushdown(int u){if(tr[u].id){tr[u<<1].id tr[u<&l…

计算机视觉之手势、面部、姿势捕捉以Python Mediapipe为工具

计算机视觉之手势、面部、姿势捕捉以 Python Mediapipe为工具 文章目录 1.Mediapipe库概述2.手势捕捉(hands)3.面部捕捉(face)4.姿势捕捉(pose) 1.Mediapipe库概述 Mediapipe是一个开源且强大的Python库&#xff0c;由Google开发和维护。它提供了丰富的工具和功能&#xff0c…

stm32学习总结:3、Proteus8+STM32CubeMX+MDK很有搞头

stm32学习总结&#xff1a;3、Proteus8STM32CubeMXMDK很有搞头 文章目录 stm32学习总结&#xff1a;3、Proteus8STM32CubeMXMDK很有搞头一、前言二、资料收集三、实际案例-点灯1、Proteus8安装2、Proteus创建stm32F013C6项目并添加外围LED电路3、STM32CubeMX配置F103C6引脚生成…

12.10_黑马数据结构与算法笔记Java

目录 058 链表 e10 判环算法1 thinking&#xff1a;什么是空指针&#xff1f; 058 链表 e10 判环算法2 059 数组 e01 合并有序数组1 059 数组 e01 合并有序数组2 060 队列 链表实现1 061 队列 链表实现2 062 队列 环形数组实现 方法1-1 063 队列 环形数组实现 方法1-2…

带有 RaspiCam 的 Raspberry Pi 监控和延时摄影摄像机

一、说明 一段时间以来&#xff0c;我一直想构建一个运动激活且具有延时功能的树莓派相机&#xff0c;但从未真正找到我喜欢的案例。我在thingiverse上找到了这个适合树莓派和相机的好案例。它是为特定的鱼眼相机设计的&#xff0c;但从模型来看&#xff0c;我拥有的廉价中国鱼…

【Vulnhub 靶场】【Hackable: III】【简单 - 中等】【20210602】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/hackable-iii,720/ 靶场下载&#xff1a;https://download.vulnhub.com/hackable/hackable3.ova 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年06月02日 文件大小&#xff1a;1.6 GB 靶场作者&…

Docker | 自定义网络

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏:Docker系列 ✨特色专栏: MySQL学习 🥭本文内容: Docker | 自定义网络 📚个人知识库: 知识库,欢迎大家访问 1.前言 大家好,我是Leo哥…

当视觉遇到毫米波雷达:自动驾驶的三维目标感知基准

​ 文章&#xff1a;Vision meets mmWave Radar: 3D Object Perception Benchmark for Autonomous Driving 作者: Yizhou Wang, Jen-Hao Cheng, Jui-Te Huang , Sheng-Yao Kuan , Qiqian Fu , Chiming Ni 编辑&#xff1a;点云PCL 欢迎各位加入知识星球&#xff0c;获取PDF…

vector类

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟悉vector库 > 毒鸡汤&#xff1a;从人生低谷…

【面试总结】Java面试题目总结(一)

&#xff08;以下仅为个人见解&#xff0c;如果有误&#xff0c;欢迎大家批评并指出错误&#xff0c;谢谢大家&#xff09; 1.项目中的验证码功能是如何实现的&#xff1f; 第一步&#xff1a;在项目的pom.xml文件中导入 EasyCaptcha 的依赖&#xff1b; <dependency>…

20231207给NanoPC-T4(RK3399)开发板刷Android12的挖掘机方案的LOG

20231207给NanoPC-T4(RK3399)开发板刷Android12的挖掘机方案的LOG 2023/12/7 23:50 SDK&#xff1a;rk356x_android12_220722.tgz 只修改DTS的DTC部分就【直接】可以跑NanoPC-T4 参考资料&#xff1a; http://www.friendlyelec.com.cn/agent.asp http://www.friendlyelec.com.c…

实现安装“自由化”!在Windows 11中如何绕过“您尝试安装的应用程序未通过微软验证”

这篇文章描述了如果你不能安装应用程序,而是当你在Windows 11中看到消息“您尝试安装的应用程序未通过微软验证”时该怎么办。完成这些步骤将取消你安装的应用程序必须经过Microsoft验证的要求。 使用设置应用程序 “设置”应用程序提供了绕过此警告消息的最简单方法,以便你…

python简易学生管理 + MySQL

数据库表 Python代码部分 import pymysqlclass StMgmt(object):def tips(self):"""提示用户选择的操作"""print("""学生管理系统 1.01.查看所有信息2.查看学生信息3.修改学生信息4.增加学生信息5.退出学生系统"""…

【网络安全技术】传输层安全——SSL/TLS

一、TLS位置及架构 TLS建立在传输层TCP/UDP之上&#xff0c;应用层之下。 所以这可以解决一个问题&#xff0c;那就是为什么抓不到HTTP和SMTP包&#xff0c;因为这两个在TLS之上&#xff0c;消息封上应用层的头&#xff0c;下到TLS层&#xff0c;TLS层对上层消息整个做了加密&…

<JavaEE> 经典设计模式之 -- 单例模式(“饿汉模式”和“懒汉模式”实现单例模式)

目录 一、单例模式概述 二、“饿汉模式”实现单例模式 三、“懒汉模式”实现单例模式 3.1 单线程下的“懒汉模式” 3.2 多线程下的“懒汉模式” 一、单例模式概述 1&#xff09;什么是单例模式&#xff1f; 单例模式是一种设计模式。 单例模式可以保证某个类在程序中只存…

【Java数据结构 -- 顺序表】

List和ArrayList与顺序表 一. List1.1 List介绍2.1 常见接口介绍3.1 List的使用 二. ArrayList与顺序表1.线性表2.顺序表2.1 接口的实现2.2 顺序表的创建2.3 顺序表的打印2.4 顺序表的插入2.5 顺序表的按索引位置插入数据2.6 判断顺序表是否包含某个数2.7 返回顺序表某个数的索…

2023-12学习笔记

1.NonNull要手动写无参构造器 这是一个我今天研究了很久的问题&#xff0c;开始不知道原因是在这里&#xff0c;还在那想是不是Data覆盖了无参构造&#xff0c;结果当然不是。先说下解决历程 1.问题起因 通过RequestBody接收前端报文的时候报错&#xff0c;大致是说我构造方…

python中tkinter实现GUI程序:三个实例

python中tkinter实现GUI程序 写在最前面Python中使用Tkinter实现GUI程序的基本元素Tkinter简介基本元素1. 根窗口&#xff08;Root Window&#xff09;2. 小部件&#xff08;Widgets&#xff09;3. 布局管理4. 事件处理 1.用 tkinter实现一个简单的 GUI程序,单击“click”按钮&…