文心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=pack
       if score<scoreThershold:##好像设置5,基本都会返回
           contentList.append(doc.page_content)

   # print('content',contentList)
   return contentList

具体Embedding代码见下方:

import os

os.environ['access_token']=access_token
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain_embedding_ErnieBotSDK import ErnieEmbeddings# Load documents

from 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 documents

    ernieChunkSize=384
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=ernieChunkSize, chunk_overlap=0)
    splits = text_splitter.split_documents(documents)
    print('splits len:',len(splits))#,splits[:5])
    # Embed and store splits
    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)
    #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 splits
    embeddings=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=pack
        if score<scoreThershold:##好像设置5,基本都会返回
            contentList.append(doc.page_content)

    # print('content',contentList)
    return contentList

def 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 prompt

def 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=response

        result=response['result']

        usedToken=data['usage']['total_tokens']
    else:
        result=""
        usedToken=-1
    return result,usedToken

prompt=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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

平衡二叉树

AVL简称平衡二叉树&#xff0c;缩写为BBST&#xff0c;由苏联数学家 Adelse-Velskil 和 Landis 在 1962 年提出。 二叉树是动态查找的典范&#xff0c;但在极限情况下&#xff0c;二叉树的查找效果等同于链表&#xff0c;而平衡二叉树可以完美的达到 log ⁡ 2 n \log_2 n log2…

JVM 内存分析工具 Memory Analyzer Tool(MAT)的深度讲解

目录 一. 前言 二. MAT 使用场景及主要解决问题 三. MAT 基础概念 3.1. Heap Dump 3.2. Shallow Heap 3.3. Retained Set 3.4. Retained Heap 3.5. Dominator Tree 3.6. OQL 3.7. references 四. MAT 功能概述 4.1. 内存分布 4.2. 对象间依赖 4.3. 对象状态 4.4…

docker容器配置MySQL与远程连接设置(纯步骤)

以下为ubuntu20.04环境&#xff0c;默认已安装docker&#xff0c;没安装的网上随便找个教程就好了 拉去mysql镜像 docker pull mysql这样是默认拉取最新的版本latest 这样是指定版本拉取 docker pull mysql:5.7查看已安装的mysql镜像 docker images通过镜像生成容器 docke…

Git的安装以及SSH配置

前言 近期工作需要&#xff0c;所以版本管理工具要用到Git&#xff0c;某些操作需要ssh进行操作&#xff0c;在某次操作中遇到&#xff1a;git bash报错&#xff1a;Permission denied, please try again。经排查是ssh没有配置我的key&#xff0c;所以就借着这篇文章整理了一下…

典型的ETL使用场景

典型的ETL使用场景 ETL( Extract&#xff0c;Transform&#xff0c;Load)是一种用于数据集成和数据转换的常用技术。它主要用于从多个数据源中提取数据&#xff0c;对数据进行清洗、转换和整合&#xff0c;最后加载到目标系统中。ETL 的使用场景非常广泛&#xff0c;下面将介绍…

Windows系统Java开发环境安装

总结一下Java软件开发工程师常见的环境的安装&#xff0c;仅限Windows环境。 以下下载链接均来自官网&#xff0c;网络条件自己克服。 目录 1. JDKJDK Oracle 官网下载地址配置系统环境变量 2. Mavenapache maven 官网地址本地仓库和中央仓库配置配置系统环境变量 3. GitGit 官…

【Docker一】Docker架构、镜像操作和容器操作

一、docker基本管理和概念 1、概念 docker&#xff1a;开源的应用容器引擎。基于go语言开发的。运行在Linux系统中的开源的轻量级的“虚拟机” docker的容器技术可用在一台主机上轻松到达为任何应用创建一个轻量级到的&#xff0c;可移植的&#xff0c;自给自足的容器 dock…

二维码智慧门牌管理系统:提升管理效率

文章目录 前言一、快速准确录入&#xff1a;提高工作效率二、多样化支付&#xff1a;提供高效支付功能三、智能化管理&#xff1a;提高效率与准确性 前言 科技时代的必备工具 在当今科技高速发展的时代&#xff0c;二维码智慧门牌管理系统已成为各行业提高管理效率和准确性的重…

智能仪表板DevExpress Dashboard v23.1 - 支持自定义样式创建

使用DevExpress Analytics Dashboard&#xff0c;再选择合适的UI元素&#xff08;图表、数据透视表、数据卡、计量器、地图和网格&#xff09;&#xff0c;删除相应参数、值和序列的数据字段&#xff0c;就可以轻松地为执行主管和商业用户创建有洞察力、信息丰富的、跨平台和设…

C语言——字符函数和字符串函数(一)

&#x1f4dd;前言&#xff1a; 这篇文章对我最近学习的有关字符串的函数做一个总结和整理&#xff0c;主要讲解字符函数和字符串函数&#xff08;strlen&#xff0c;strcpy和strncpy&#xff0c;strcat和strncat&#xff09;的使用方法&#xff0c;使用场景和一些注意事项&…

gin投票项目5

对应视频V3版本 1.优化用户注册的功能 增加扩展字段 1.增加一个UUID字段&#xff0c;vachar&#xff08;50&#xff09;。 2.增加一个UUID的唯一索引。 UUID具有全局唯一性&#xff1b; 方法&#xff1a;在数据库中新建一个列&#xff0c;名为uuid并移至主键下方&#xf…

CRM系统选择技巧,什么样的CRM系统好用?

SaaS行业发展迅速&#xff0c;更多的企业逐渐选择CRM管理系统。打开搜索引擎&#xff0c;有非常多的结果。怎样在数十万个搜索结果中选择适合您的CRM系统&#xff1f;下面我们将聊聊&#xff0c;怎样选择CRM系统。 第一步&#xff1a;明确自身需求 重要性&#xff1a;每家企业…

POJ1182 食物链(并查集)

题目展示 Description 动物王国中有三类动物A,B,C&#xff0c;这三类动物的食物链构成了有趣的环形。A吃B&#xff0c; B吃C&#xff0c;C吃A。 现有N个动物&#xff0c;以1&#xff0d;N编号。每个动物都是A,B,C中的一种&#xff0c;但是我们并不知道它到底是哪一种。 有人用…

【Linux】探索Linux进程状态 | 僵尸进程 | 孤儿进程

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 目录 一、进程状态1.1运行状态1.2阻塞状态1.3挂起状态 二、具体L…

在UE中使用Python设置枚举类属性值的问题

目标 在UE编辑器中使用Python设置枚举类属性值会遇到些问题&#xff0c;本篇记录了这些问题的解决方法。 1. 设置数值类属性值 先在编辑器中选择一个Actor&#xff0c;然后运行下面Python代码&#xff1a; actor unreal.EditorLevelLibrary.get_selected_level_actors()[0…

【JavaEE】线程池

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

2024年网络安全竞赛-Web安全应用

Web安全应用 (一)拓扑图 任务环境说明: 1.获取PHP的版本号作为Flag值提交;(例如:5.2.14) 2.获取MySQL数据库的版本号作为Flag值提交;(例如:5.0.22) 3.获取系统的内核版本号作为Flag值提交;(例如:2.6.18) 4.获取网站后台管理员admin用户的密码作为Flag值提交…

我的隐私计算学习——隐私集合求交(1)

笔记内容来自多本书籍、学术资料、白皮书及ChatGPT等工具&#xff0c;经由自己阅读后整理而成。 &#xff08;一&#xff09;PSI的介绍 隐私计算关键技术&#xff1a;隐私集合求交&#xff08;PSI&#xff09;原理介绍 隐私计算关键技术&#xff1a;隐私集合求交&#xff08…

【基于Flask、MySQL和Echarts的热门游戏数据可视化平台设计与实现】

基于Flask、MySQL和Echarts的热门游戏数据可视化平台设计与实现 前言数据获取与清洗数据集数据获取数据清洗 数据分析与可视化数据分析功能可视化功能 创新点结语 前言 随着游戏产业的蓬勃发展&#xff0c;了解游戏销售数据对于游戏从业者和游戏爱好者都至关重要。为了更好地分…

【Python数据结构与算法】—— 搜索算法 | 期末复习不挂科系列

​ &#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 数据结构与算法&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 这篇博客主要探索的是计算机科学常见问题---搜索算法 “时间紧&#xff0c;任务重&#xff01;” 话不多说&#xff0c;开始今天…