使用【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 Agent对LangChain框架进行了功能扩展,提供了基于文心大模型的大语言模型(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还未支持。
相关推荐
Jsundoku7 分钟前
第四章 深度学习 -- 训练技巧
人工智能·深度学习
HDU-Dade37 分钟前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
在所不辞兄1 小时前
【零基础学智能仿真-63】ABACUS作业工具与MCP接口
人工智能·深度学习·神经网络·机器学习·智能仿真
楚山之石1 小时前
【Medical Image Analysis】深度学习医学图像合成综述:伪CT、合成MRI与合成PET的架构、性能与临床边界
图像处理·人工智能·学习·mr·mri
blackappleD2 小时前
百度 Unlimited OCR 2 拆解:SR-SWA 如何让百页文档的 KV 缓存不再涨
人工智能·llm
数字新视界2 小时前
国产动环数据库在智能机房环境监控中的应用与优势分析
大数据·人工智能·数据中心·机房管理·模块化机房
holly就是我2 小时前
AI 编程助手为什么跑偏?用开源 ccglass 看清 Prompt、工具调用和 Token 消耗
人工智能·后端
雨中飘荡的记忆2 小时前
额度又见底了?这个开源项目,给 AI 编程助手接上 61 家"加油站"
人工智能
天远Date Lab2 小时前
零信任架构实战:基于天远企业年报信息核验构建自动化商业保理财务与社保穿透评估网关
人工智能·架构·自动化
EnCi Zheng2 小时前
后端怎么把AI接口稳定安全低成本接进业务:超时重试、密钥隔离与成本熔断清单
人工智能·后端·安全·架构·api