写点什么

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

  • 2023-12-08
    北京
  • 本文字数:3653 字

    阅读完需:约 12 分钟

现在各行各业纷纷选择接入大模型,其中最火且可行性最高的形式无异于智能文档问答助手,而 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)>10print('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_tokenfrom langchain.vectorstores import Chromafrom langchain.chains import RetrievalQAfrom langchain_embedding_ErnieBotSDK import ErnieEmbeddings# Load documents
from langchain.document_loaders import WebBaseLoaderfrom langchain.document_loaders.text import TextLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.vectorstores import Chromaimport 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 ##新建向量库,注意如果拿几百万字的小说embeddingsource='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

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2022-12-26 加入

还未添加个人简介

评论

发布
暂无评论
文心ERNIE Bot SDK+LangChain:基于文档、网页的个性化问答系统_人工智能_飞桨PaddlePaddle_InfoQ写作社区