使用【Ernie Bot SDK与向量数据库等】构建Agent实现规章信息查询

一、使用【Ernie Bot SDK与向量数据库等】构建Agent实现D章信息查询

1.ERNIE Bot Agent介绍

github.com/PaddlePaddl...

ERNIE Bot Agent 旨在为开发者提供快速搭建大模型Agent和应用的框架。该项目还在积极研发中,敬请期待我们后续的正式发版。

2.主要功能

2.1大模型 Agent 框架

ERNIE Bot Agent 将结合飞桨星河AI Studio社区,为开发者提供一站式的大模型Agent和应用搭建框架和平台。该项目还在积极研发中,敬请期待我们后续的正式发版。

2.2文心 LangChain 插件

为了让大家更加高效、便捷地结合文心大模型与LangChain进行开发,ERNIE Bot AgentLangChain框架进行了功能扩展,提供了基于文心大模型的大语言模型(LLM)组件、聊天模型(ChatModel)组件以及文本嵌入模型(Text Embedding Model)组件。

3.项目简介

这是一款名为'D建法规小助手'的演示应用,它展示了如何利用LangChain的工具以及ERNIEBot的functional agent来汇聚D建知识。通过利用ERNIE Bot SDK的functional agent,我们可以根据对话的上下文以及用户提出的具体问题,让大型模型在回答问题时灵活选择是否采用检索增强方式,或是直接给出答案。这种设计思路不仅丰富了大模型的领域知识,同时也保留了大模型在领域知识之外的通用对话能力。

二、环境准备

1.erniebot sdk安装

github.com/PaddlePaddl...

python 复制代码
# 使用最新版的 ERNIE-Bot-SDK ,该版本为我从github同步下来的。
!git clone https://gitee.com/livingbody/ERNIE-Bot-SDK --depth=1
sql 复制代码
fatal: destination path 'ERNIE-Bot-SDK' already exists and is not an empty directory.
python 复制代码
%%capture
%cd ~/ERNIE-Bot-SDK
!pip install -r requirements.txt
!pip install -e ./

2.Ernie Bot Agent安装

python 复制代码
%%capture
!pip install -r erniebot-agent/requirements.txt
!pip install -e erniebot-agent/

3.pypdf/faiss安装

python 复制代码
%%capture
!pip install pypdf
!pip install faiss-cpu
# !pip install faiss-gpu # 如果用GPU的话

注意:安装完erniebot-agent后需要重启notebook

三、项目建设

1. 导入第三方库

主要是在导入一些必要的Python库和模块,以便实现Construction Assistant的功能。

  • os: Python的标准库,用于与操作系统进行交互,如读写文件、管理路径等。
  • Optional, List, Type, Dict: 这些是Python类型提示(typing模块的一部分),用于增强代码的可读性和可维护性,同时也方便开发者进行静态类型检查。
  • BaseModel, Field: 这些都是来自Pydantic库的类,用于数据验证和设定数据模型。Field通常用于设定模型的字段。
  • SpacyTextSplitter: 一个文本分割工具,用于将文本分割为更小的部分,如句子或短语。
  • FAISS: 用于向量存储的模块,可能是用于存储和检索经过嵌入处理的文本或图像的向量表示。
  • PyPDFDirectoryLoader: 用于从PDF文件中加载数据的工具。
  • ErnieEmbeddings: 用于文本嵌入的工具,将文本转换为可以在模型中使用的向量表示。
  • Tool, ToolParameterView: 用于创建和管理工具的基类或工具参数视图的类。
  • FunctionalAgent: 这个类实现function calling功能的Agent的类,如问答、对话等。
  • WholeMemory: 用于存储和管理代理的记忆的类。
  • ERNIEBot: 实现ERNIE Bot的主要类,包含了实现对话功能的主要逻辑。
  • AIMessage, HumanMessage, Message: 用于实现消息传递和处理的类,如机器人和人类之间的消息交互。
  • erniebot: 这是导入erniebot模块的语句,erniebot可能是一个包含ERNIE Bot实现的主要代码库。
python 复制代码
import os
from typing import Optional, List, Type, Dict
from pydantic import BaseModel, Field
from langchain.text_splitter import SpacyTextSplitter
from langchain.vectorstores import FAISS
from langchain.document_loaders import PyPDFDirectoryLoader

from erniebot_agent.extensions.langchain.embeddings import ErnieEmbeddings
from erniebot_agent.tools.base import Tool, ToolParameterView
from erniebot_agent.agents.functional_agent import FunctionalAgent
from erniebot_agent.memory.whole_memory import WholeMemory
from erniebot_agent.chat_models.erniebot import ERNIEBot
from erniebot_agent.messages import AIMessage, HumanMessage, Message
import erniebot

2. 预处理

2.1 下载数据准备

打开D建网 www.12371.cn/special/dnf... ,另存页面为pdf,此处下载D章、D廉洁自律准则2016年、关于新形势下D内政治生活的若干准则 3个文件

2.2 配置 ERNIE BOT API

这里使用aistudio的Access_token, 申请地址请参考accessToken

python 复制代码
erniebot.api_type = "aistudio"
aistudio_access_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
erniebot.access_token = aistudio_access_token

3. Tool 构建

3.1 构建Schema

定义了三个类:SearchToolInputView,SearchResponseDocument,和SearchToolOutputView,它们都是ToolParameterView的子类,用于处理和描述一种特定的工具参数。这些类利用了Python的typing模块来定义字段和它们的类型,以及字段的描述。

  • SearchToolInputView类定义了两个字段:query和retrieval_num。query字段是一个字符串,用于描述"规章查询语句",这可能是用户输入的查询参数。retrieval_num字段是一个整数,描述了"检索结果数目",默认值是5。
  • SearchResponseDocument类定义了三个字段:document,filename和page_num。这些字段可能用于描述一个特定的搜索结果。document字段是字符串,用于存储和查询相关的规章片段。filename字段也是字符串,用于存储规章的名称。page_num字段是整数,用于描述规章的页数。
  • SearchToolOutputView类定义了一个字段:documents,这是一个SearchResponseDocument对象的列表,用于描述搜索结果。这个字段的描述表明它包含的是"检索结果,内容为D章等法规中和query相关的片段"。
python 复制代码
class SearchToolInputView(ToolParameterView):
    query: str = Field(description='规章查询语句')
    retrieval_num: int = Field(description="检索结果数目", default=5)

class SearchResponseDocument(ToolParameterView):
    document: str = Field(description="和query相关的规章片段")
    filename: str = Field(description="规章名称")
    page_num: int = Field(description="规章页数")

class SearchToolOutputView(ToolParameterView):
    documents: List[SearchResponseDocument] = Field(description="检索结果,内容为D章等法规中和query相关的片段")

3.2 构建Faiss检索工具

这段代码定义了一个名为FaissSearchTool的类,它是Tool的子类。这个工具被设计用于在住房和城乡建设部规章中寻找和给定查询(query)最相关的片段。

    1. FaissSearchTool的类属性description描述了这个工具的功能,input_type和output_type则分别指定了输入和输出的类型。
    1. 在__init__方法中,这个工具初始化了一个数据库连接。
    1. __call__方法是这个工具的核心,它是一个异步方法,接受一个查询字符串和一个检索数量,返回一个包含检索到的文档的字典。这个方法首先使用数据库的similarity_search方法获取与查询相似的文档,然后构造检索结果,最后返回一个包含检索结果的字典。
    1. examples属性返回了一个示例列表,这个列表包含一个人类消息和一个AI消息。这些消息可以用来演示这个工具的使用方法。

总的来说,这个类是一个基于Faiss库的搜索工具,用于在特定的文档数据库中找到与给定查询最相关的文档。这在信息检索、问答系统等领域有广泛的应用。

python 复制代码
class FaissSearchTool(Tool):
    description: str = "在D的各项法规中寻找和query最相关的片段"
    input_type: Type[ToolParameterView] = SearchToolInputView
    ouptut_type: Type[ToolParameterView] = SearchToolOutputView

    def __init__(self, db):
        self.db = db

    async def __call__(self, query: str, retrieval_num: int = 5) -> Dict[str, float]:
        docs = self.db.similarity_search(query)
        retrieval_results = []
        for doc in docs:
            retrieval_results.append(
                dict(SearchResponseDocument(
                    document=doc.page_content,
                    filename=doc.metadata["source"],
                    page_num=doc.metadata["page"],
                ))
            )
        return {"documents": retrieval_results}

    @property
    def examples(self) -> List[Message]:
        return [
                HumanMessage("D员义务是什么?"),
                AIMessage(
                    "",
                    function_call={
                        "name": self.tool_name,
                        "thoughts": f"这是一个D章相关的问题,我们使用{self.tool_name}工具检索相关的信息,检索的query:'D员义务'。",
                        "arguments": '{"query": "D员义务", "retrieval_num": 3}',
                    },
                )
            ]

4.Assistant

4.1 建索引库

这段代码主要功能是用于创建或加载一个FAISS索引来进行文档相似度匹配。首先,创建一个ErnieEmbeddings对象,用于生成文档的嵌入向量。aistudio_access_token是访问AI Studio的令牌,chunk_size是用于嵌入的文档块的数量,sleep_time是在每次请求嵌入后的休眠时间,用于限制请求的频率。

python 复制代码
embeddings = ErnieEmbeddings(aistudio_access_token=aistudio_access_token, 
                             chunk_size=16,
                             sleep_time=20)

接下来利用ErnieEmbeddings来抽取向量构建索引。

  • 如果FAISS索引文件已经存在,就使用FAISS.load_local方法加载这个索引,这个索引文件的名字就是定义的faiss_name。
  • 如果FAISS索引不存在,则需要建索引。
    • 第一步,使用PyPDFDirectoryLoader来从"mydata"这个文件夹中加载PDF文档。
    • 第二步,使用SpacyTextSplitter来将加载的文档分割成更小的部分,以便于生成嵌入向量。这个分割器主要用于中文文本,因为这里使用的pipeline是'zh_core_web_sm',如果是初次运行,需要安装spacy并运行python -m spacy download zh_core_web_sm来下载中文分句模型。
    • 第三步,通过分割后的文档创建一个新的FAISS索引,并将这个索引保存为之前定义的faiss_name。
python 复制代码
%%capture
%cd ~
!pip install spacy
# 由于是github下载太慢,手动下载安装
# !python -m spacy download zh_core_web_sm
!pip install zh_core_web_sm-3.7.0-py3-none-any.whl
python 复制代码
faiss_name = "faiss_index"
if os.path.exists(faiss_name):
    db = FAISS.load_local(faiss_name, embeddings)
else:
    loader = PyPDFDirectoryLoader("./mydata")
    documents = loader.load()
    text_splitter = SpacyTextSplitter(pipeline='zh_core_web_sm', chunk_size=320, chunk_overlap=0)
    docs = text_splitter.split_documents(documents)
    db = FAISS.from_documents(docs, embeddings)
    db.save_local(faiss_name)

以下代码是使用FaissSearchTool工具进行搜索的一个例子,流程大致如下:

    1. 创建FaissSearchTool对象,并传入数据库对象db。
    1. 使用await关键字对FaissSearchTool对象进行异步调用,并传入查询字符串"城市管理执法主管部门的职责是什么?"。
    1. 将搜索结果以格式化的形式进行打印,这里使用了pprint模块进行美化打印。最终的结果存储在变量res中。

备注: 目前有bug,多次访问会提示erniebot调用过于频繁,谁遇到

python 复制代码
tool = FaissSearchTool(db=db)
res = await tool(query="D员义务是什么?")
from pprint import pprint
pprint(res)

XXXXXXXXXXXXXXXXXXXXXXXXXX关键字屏蔽

4.2 构建 Assistant

Assistant可以自主决定什么时候选择调用工具,什么时候进行聊天,以下是一个自主调用工具的示例。

python 复制代码
# 创建一个ERNIEBot实例,使用"ernie-bot-8k"模型。
llm = ERNIEBot(model="ernie-bot-8k")
# 创建一个WholeMemory实例。这可能是一个用于存储对话历史和上下文信息的类,有助于模型理解和持续对话。  
memory = WholeMemory()
# 创建一个FunctionalAgent实例。这个代理将使用上面创建的ERNIEBot模型和WholeMemory,同时传入了一个名为tool的工具。
agent = FunctionalAgent(llm=llm, tools=[tool], memory=memory)
python 复制代码
query = "D员的权利有哪些?"
response = await agent.async_run(query)
# 使用agent的async_run方法来异步执行查询。由于这是异步操作,因此需要使用'await'关键字。 
messages = response.chat_history
for item in messages:
    print(item.to_dict())
python 复制代码
{'role': 'assistant', 'content': 'XXXXXXXXXXXXXXXXXXXXXXXXXX关键字屏蔽', 'function_call': None}

四、总结

1.ERNIE Bot Agent的LangChain插件

ERNIE Bot Agent的LangChain插件目前包含如下组件:

  • ErnieBot:大语言模型,用于完成文本补全任务。
  • ErnieBotChat:聊天模型,用于完成对话补全任务。
  • ErnieEmbeddings:文本嵌入模型,用于生成文本的向量表示。

2.ErnieEmbeddings 目前问题

  • 文件过大、或者多,会报访问 过于频繁错误。
  • 目前仅支持aistudio token认证,qianfan ak/sk还未支持。
相关推荐
Aileen_0v01 小时前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
阿正的梦工坊2 小时前
深入理解 PyTorch 的 view() 函数:以多头注意力机制(Multi-Head Attention)为例 (中英双语)
人工智能·pytorch·python
Ainnle2 小时前
GPT-O3:简单介绍
人工智能
OceanBase数据库官方博客2 小时前
向量检索+大语言模型,免费搭建基于专属知识库的 RAG 智能助手
人工智能·oceanbase·分布式数据库·向量数据库·rag
测试者家园2 小时前
ChatGPT助力数据可视化与数据分析效率的提升(一)
软件测试·人工智能·信息可视化·chatgpt·数据挖掘·数据分析·用chatgpt做软件测试
Loving_enjoy4 小时前
ChatGPT详解
人工智能·自然语言处理
人类群星闪耀时4 小时前
深度学习在灾难恢复中的作用:智能运维的新时代
运维·人工智能·深度学习
图王大胜4 小时前
模型 确认偏误(关键决策)
人工智能·职业发展·管理·心理·认知·决策
机器懒得学习5 小时前
从随机生成到深度学习:使用DCGAN和CycleGAN生成图像的实战教程
人工智能·深度学习