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

news2024/11/27 16:47:35

现在各行各业纷纷选择接入大模型,其中最火且可行性最高的形式无异于智能文档问答助手,而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

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

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

相关文章

2023-12-10 LeetCode每日一题(爬楼梯)

2023-12-10每日一题 一、题目编号 70. 爬楼梯二、题目链接 点击跳转到题目位置 三、题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 示例 2&#xff1a; 提…

【vim】常用操作

用的时候看看&#xff0c;记太多也没用&#xff0c;下面都是最常用的&#xff0c;更多去查文档vim指令集。 以下均为正常模式下面操作&#xff0c;正在编辑的&#xff0c;先etc一下. 1/拷贝当前行 yy&#xff0c;5yy为拷贝包含当前行往下五行 2/p将拷贝的东西粘贴到当前行下…

(第一部分1-3 / 13)PMBOK 6

项目管理协会 PMI 价值观 责任、尊重、公正、诚实 法约尔 亨利法约尔_百度百科 管理的5项职能 计划组织指挥协调控制管理的14项原则&#xff08;该原则的提出&#xff0c;标志着法约尔管理理论的形成&#xff09; 【劳动分工】劳动分工是合理使用个人力量和集体力量的最好…

36 括号匹配问题

import java.util.HashMap; import java.util.LinkedList; import java.util.Scanner;public class Main {// 输入获取public static void main(String[] args) {Scanner sc new Scanner(System.in);String s sc.nextLine();System.out.println(getResult(s));}// 算法入口pu…

EdgeYOLO: anchor-free,边缘部署友好

简体中文 1 Intro 2 Updates 3 Coming Soon 4 Models 5 Quick Start \quad 5.1 setup

Cpolar配置外网访问和Dashy

Dashy是一个开源的自托管的导航页配置服务,具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一些网站聚合起来放在一起,形成自己的导航页。一款功能超强大,颜值爆表的可定制专属导航页工具 结合cpolar内网工具,我们实现无需部署到公网服务器…

详解异常 ! !(对异常有一个全面的认识)

【本章目标】 1. 异常概念与体系结构 2. 异常的处理方式 3. 异常的处理流程 4. 自定义异常类 1. 异常的概念与体系结构 1.1 异常的概念 在生活中&#xff0c;一个人表情痛苦&#xff0c;出于关心&#xff0c;可能会问&#xff1a;你是不是生病了&#xff0c;需要我陪你去看医…

T曲线速度控制与S曲线速度控制

梯形速度控制曲线&#xff08;T曲线&#xff09; 所谓梯形速度曲线&#xff0c;也称为直线加减速或T型加减速。 其算法十分简易&#xff0c;规划周期耗时短&#xff0c;有利于缩减系统的连续运行时间&#xff0c;从而提高系统的运动控制速度&#xff0c;实施起来比较易&#x…

构建linux系统的强有力工具buildroot

目录 01. buildroot简介 1.1简介 1.2 源码下载 1.3 buildroot版本更新介绍 02. 实操演示 2.1 buildroot源码目录层级的简介 2.2 实操演示 03. 结语 01. buildroot简介 1.1简介 Buildroot是一个嵌入式Linux系统的工具链&#xff0c;它用于构建嵌入式设备的根文件系统。…

利用pycharm进行python代码的debug各功能解释

利用pycharm进行python代码的debug各功能解释 利用pycharm进行python代码的debug各功能解释 一 进入debug 1 左键点击代码文件目标行&#xff0c;确定debug节点&#xff08;可一次选择多个debug节点&#xff09; 2 鼠标右键&#xff0c;选择debug 二 各功能解读 debug调试…

第九天:信息打点-CDN绕过篇amp;漏洞回链amp;接口探针amp;全网扫描amp;反向邮件

信息打点-CDN绕过篇 cdn绕过文章&#xff1a;https://www.cnblogs.com/qiudabai/p/9763739.html 一、CDN-知识点 1、常见访问过程 1、没有CDN情况下传统访问&#xff1a;用户访问域名-解析服务器IP–>访问目标主机 2.普通CDN&#xff1a;用户访问域名–>CDN节点–>…

鸿蒙OS应用开发之语句

在程序开发中&#xff0c;已经有上面的运算符和数据类型了&#xff0c;可以满足了大部的需求&#xff0c;但是这些程序还是比较简单的计算和逻辑运算&#xff0c;如果需要复杂的计算和逻辑处理&#xff0c;就需要采用复杂逻辑程序块来处理了&#xff0c;也就是复杂条件语句才能…

Kubernetes里的DNS;API资源对象ingress;Kubernetes调度;节点选择器NodeSelector;节点亲和性NodeAffinity

Kubernetes里的DNS K8s集群内有一个DNS服务&#xff1a; kubectl get svc -n kube-system |grep dns测试&#xff1a; 在tang3上安装bind-utils,目的是安装dig命令 yum install -y bind-utils apt install dnsutils #ubuntu上 解析外网域名 dig 10.15.0.10 www.baidu.com…

C语言笔试例题_指针专练30题(附答案解析)

C语言笔试例题_指针专练30题(附答案解析) 指针一直是C语言的灵魂所在&#xff0c;是掌握C语言的必经之路&#xff0c;收集30道C语言指针题目分享给大家&#xff0c;测试环境位64位ubuntu18.04环境&#xff0c;如有错误&#xff0c;恳请指出&#xff0c;文明讨论&#xff01;&am…

OpenGLES:glReadPixels()获取相机GLSurfaceView预览数据并保存

Android现行的Camera API2机制可以通过onImageAvailable(ImageReader reader)回调从底层获取到Jpeg、Yuv和Raw三种格式的Image&#xff0c;然后通过保存Image实现拍照功能&#xff0c;但是却并没有Api能直接在上层直接拿到实时预览的数据。 Android Camera预览的实现是上层下发…

飞天使-linux操作的一些技巧与知识点

命令行光标移动到行首行尾 ctrl a 跳到首 ctrl e 跳到尾/etc/passwd rpm 包格式 RPM&#xff08;Red Hat Package Manager&#xff09;是一种常用的Linux软件包管理系统&#xff0c;它使用特定的命名规则来标识和命名软件包。RPM包的名称格式通常遵循以下规则&#xff1a;…

angular route guards

它的作用 有5种guard 1.先创建一个services的typescript class 这个sivices 实现了 canActive 这个interface &#xff08;接口&#xff09; 返回true可以继续执行&#xff0c; 返回false中断执行 2. 在app.module的providers中使用这个services 3.最后在路由文件中使用 路…

一张图解释maxHistory、fileNamePattern、totalSizeCap、maxFileSize之间的关系

文中结合配置和坐标轴的关系进行案例讲解&#xff0c;文中知识针对每个案例情况进行解释&#xff0c;当然也存在其他案例&#xff0c;对比理解即可。 配置案例 <rollingPolicy class"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNam…

配电房无人值守管理系统

配电房无人值守管理系统是一种基于物联网、云计算、大数据等技术的智能化管理系统&#xff0c;依托电易云-智慧电力物联网&#xff0c;旨在实现对配电房的远程实时监控、自动化运行、故障预警和处理等功能&#xff0c;从而实现配电房的无人值守。 实时监测&#xff1a;通过安装…

MATLAB | 官方举办的动图绘制大赛 | 第四周(收官周)赛情回顾

MATHWORKS官方举办的迷你黑客大赛第三期(MATLAB Flipbook Mini Hack)圆满结束&#xff0c;虽然我的水平和很多大佬还有比较大的差距&#xff0c;但所有奖也算是拿满了&#xff1a; 专家评选前三名&#xff0c;以及投票榜前十&#xff1a;~ 每周的阶段性获奖者&#xff1a; 下面…