跳过导航
跳过mega-menu

基于LangChain的ElasticSearch Agent

在这个故事中,我们将关注如何构建一个 ElasticSearch 代理 Python 提供的基础设施 LangChain. 这个代理应该允许用户用自然语言就数据库中的数据提出问题 ElasticSearch 集群.

ElasticSearch 是一个强大的搜索引擎,支持词法和向量搜索. ElasticSearch 可以在RAG(检索增强生成)的上下文中使用,但这不是我们本文的主题. 所以我们没有使用 ElasticSearch 检索文档以创建在提示符中注入的上下文. 相反,我们使用 ElasticSearch 在Agent的上下文中,i.e. 我们正在构建一个用自然语言交流的代理 ElasticSearch 执行搜索和聚合查询,并解释这些查询.

ElasticSearch Agent在运行

我们已经在Youtube上上传了ElasticSearch Agent的演示:

这里有一些 截图 我们用Chainlit制作的UI:

交互1

交互2

互动3

交互4

构建代理的配方

如果我们从代理如何被“煮熟”的角度来看bot,我们将拥有以下成分:

  • LLM (大型语言模型):我们使用了ChatGPT 4 8K模型. 我们还尝试了ChatGPT 3.5个16K模型,但结果不是那么好.
  • 4 .自制代理工具:
    - 弹性列表索引一个获取所有可用ElasticSearch索引的工具
    - 弹性指数显示细节一个获取单个ElasticSearch索引信息的工具
    - 弹性指数显示数据一个从ElasticSearch索引中获取条目列表的工具, 有助于找出可用的数据.
    - 弹性搜索工具:该工具对ElastiSearch索引执行特定查询,并返回所有命中或聚合结果
  • 特别提示我们使用了一些特殊的说明来使代理正常工作. 提示符指示代理首先获取索引的名称,然后获取索引字段的名称. 没有内存相关指令的主提示符是:

f"""

确保首先查询ElasticSearch数据库中的索引.

确保在查询索引之后查询字段名.                    

然后回答这个问题:

{问题}

"""

座席流程

ElasticSearch Agent工作流

工作流有两个部分:

  • 设置 -执行三个步骤:
    -初始化工具
    -设置LLM模型
     -安装代理包括提示
  • 执行流程 -这些是工作流程步骤:
    -用户提出问题
    -法学硕士分析问题
    —网关:选择使用哪种工具. 在某些情况下,可能没有任何工具用于该任务.
    —网关案例1:tool found—执行了一个工具,并且收到了它的观察结果. 在我们的示例中,这是一个JSON响应.
    —网关案例2:未找到工具—工作流以错误消息结束.
    —在发现工具的情况下:将工具的观察结果发送回LLM.
     -网关:决定使用哪个工具,或者没有找到工具,流是否终止,或者我们是否有最终的答案. 如果决定使用工具,我们将再次循环相同的步骤.

执行流程循环进行,直到找到最终答案. 这意味着对于一个问题,代理可以访问多个工具,甚至可以多次访问同一个工具.

通常,工作流在与LLM交互15次后停止,并出现错误.

实现

我们将代码分成了两个Github存储库. 第一个只包含代理代码,第二个包含我们在演示中使用的UI,你可以在视频中看到.

代理代码

这里是Github仓库:

http://github.com/onepointconsulting/elasticsearch-agent

设置要求您使用 Conda诗歌 (依赖项管理器),但在本项目的 自述文件.

在我的测试和视频演示中使用的数据可以在这个目录中找到,并从 全球社会经济 & 环境指标Kaggle数据集.

我们使用了与二氧化碳排放量和国民总收入相关的CSV.

大部分实际代码都在以下文件夹中:

http://github.com/onepointconsulting/elasticsearch-agent/tree/main/elasticsearch_agent

代码包含三个逻辑单元:

  • 配置
  • 代理工具
  • 代理工厂

配置参数都列在项目的 自述 并且是从 .Env文件,您需要在本地创建它.

配置文件 包含所有工具使用的ElasticSearch集群的实际连接对象.

代理工具都是基于LangChain的,它们都有通过扩展指定的输入模式 Pydantic的basmodel类. 指定输入模式的原因是基于OPENAI_FUNCTIONS的代理类型.

以下是工具列表:

  • 列表索引工具:此工具列出ElasticSearch索引,通常在每次代理回答任何问题时调用. 此工具接收分隔符作为输入,并输出由分隔符分隔的索引列表.
  • 索引详细信息工具:此工具列出特定索引的别名、映射和设置. 它接收一个ElasticSearch索引名作为输入.
  • 索引数据工具:该工具用于从ElasticSearch索引中获取条目列表, 有助于找出可用的数据. 根据我的测试,这是ChatGPT使用最少的工具.
  • 索引搜索工具:该工具是搜索工具,期望输入索引, 查询以及查询的开始和长度. 它解析查询并尝试找出查询是否为 搜索 或者一个 聚合 查询,并根据它返回命中(在搜索的情况下)或聚合(在聚合查询的情况下). 但是它也试图避免超过响应的令牌大小的某个阈值,因此可能会重试查询. 这是该工具的主要方法.
    在这个文件中,您可以找到输入模型(SearchToolInput)和该工具的运行方法(elastic_搜索):

http://github.com/onepointconsulting/elasticsearch-agent/blob/main/elasticsearch_agent/tools/index_search_tool.py#L13

最后,我们有 agent_factory 方法, 它负责初始化代理执行器,你可以在这个文件的第18行找到:

http://github.com/onepointconsulting/elasticsearch-agent/blob/main/elasticsearch_agent/agent/agent_factory.py#L18

我们上面提到的所有工具都是用来使用的 OpenAI功能,因此代理类型为OPENAI_FUNCTIONS . 初始化代码在代理中注入专门的系统消息.

但是,我们没有通过agent_factory函数注入任何专门的指令. 我尝试使用OpenAIFunctionsAgent的extra_prompt_messages参数.From_llm_和_tools函数,但这并没有很好地工作.

我每次都把问题用代理说明包装起来.

f"""

确保首先查询ElasticSearch数据库中的索引.

确保在查询索引之后查询字段名.                 

然后回答这个问题:

{问题}

"""

代理用户界面

http://github.com/onepointconsulting/elasticsearch-agent-chainlit

此项目依赖于代理代码项目. 的 自述文件 的实例说明如何构建此项目 Conda诗歌.

UI代码可以在这个文件中找到:

http://github.com/onepointconsulting/elasticsearch-agent-chainlit/blob/main/elasticsearch_chainlit/ui/agent_chainlit.py

最有趣的部分是处理传入消息的消息:

http://github.com/onepointconsulting/elasticsearch-agent-chainlit/blob/main/elasticsearch_chainlit/ui/agent_chainlit.py#L22

此功能中使用的提示符最多包含用户之前的5个问题. 这是一种简单的尝试,只通过问题来记忆. 它还包含从ElasticSearch获取每个问题的索引和详细信息的说明.

外卖

代理似乎工作得相当好,但它不是完美的. 有时,它无法以令人惊讶的方式交付预期的结果.

我也不能让它与ChatGPT 3很好地工作.5只与ChatGPT 4. 因此,运行它是相当昂贵的. 它还受到ChatGPT 4 (gpt-4-0613)的8K窗口大小的影响。, 因此,如果ElasticSearch答案有超过8K个令牌, 它被削减到大约6K个令牌,因此存在数据丢失.

这在某种程度上也是低效的. 每次运行代理时,它都会重复初始指令:

确保首先查询ElasticSearch数据库中的索引.

确保在查询索引之后查询字段名.

我们可以缓存这些指令,然后嵌入它们,以节省一些时间和金钱.

SQL Agent的LangChain实现——它给了我灵感——也会一次又一次地查询表和字段. 这既要花钱,又会拖慢整个代理的速度.

LangChain是一个非常完整的框架, 但有时我不能正确使用它的功能,选择一些快捷方式. 例如:我试过ConversationBufferMemory . 但结果不太好——代理人被弄糊涂了好多次 , 所以我决定自己用几行代码来管理内存. 这是一个hack,但很容易理解和控制.

澳门十大正规赌博娱乐平台

在这里注册