Elasticsearch:和 LIamaIndex 的集成

news2024/11/26 12:49:48

LlamaIndex 是一个数据框架,供 LLM 应用程序摄取、构建和访问私有或特定领域的数据。

LlamaIndex 是开源的,可用于构建各种应用程序。 在 GitHub 上查看该项目。

安装

 在 Docker 上设置 Elasticsearch

使用以下 docker 命令启动单节点 Elasticsearch 实例。我们可以参考之前的文章 “Elasticsearch:如何在 Docker 上运行 Elasticsearch 8.x 进行本地开发”。我选择不使用安全配置。直接使用 docker compose 来启动 Elasticsearch 及 Kibana:

.env

$ pwd
/Users/liuxg/data/docker8
$ ls -al
total 16
drwxr-xr-x    4 liuxg  staff   128 Jan 16 13:00 .
drwxr-xr-x  193 liuxg  staff  6176 Jan 12 08:31 ..
-rw-r--r--    1 liuxg  staff    21 Jan 16 13:00 .env
-rw-r--r--    1 liuxg  staff   733 Mar 14  2023 docker-compose.yml
$ cat .env
STACK_VERSION=8.11.3

docker-compose.yml

version: "3.9"
services:
  elasticsearch:
    image: elasticsearch:${STACK_VERSION}
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
      - xpack.security.enabled=false
    volumes:
      - type: volume
        source: es_data
        target: /usr/share/elasticsearch/data
    ports:
      - target: 9200
        published: 9200
    networks:
      - elastic

  kibana:
    image: kibana:${STACK_VERSION}
    container_name: kibana
    ports:
      - target: 5601
        published: 5601
    depends_on:
      - elasticsearch
    networks:
      - elastic      

volumes:
  es_data:
    driver: local

networks:
  elastic:
    name: elastic
    driver: bridge

我们使用如下的命令来启动:

docker-compose up

这样我们就完成了 Elasticsearch 及 Kibana 的安装了。我们的 Elasticsearch 及 Kibana 都没有安全的设置。这个在生产环境中不被推荐使用。

应用设计 -  组装管道

我们将使用 Jupyter notebook 来进行设计。我们在命令行中打入:

jupyter notebook

安装依赖

我们使用如下的命令来安装 Python 的依赖包:

pip3 install llama-index openai elasticsearch load_dotenv

我们接下来在当前的工作目录中创建一个叫做 .env 的文件:

.env

OPENAI_API_KEY="YourOpenAIKey"

请在 .env 中创建如上所示的变量。你需要把自己的 openai key 写入到上面的文件里。

加载模块及读取环境变量

import logging
import sys
import os
from dotenv import load_dotenv

load_dotenv()

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

os.environ["OPENAI_API_KEY"] = os.getenv('OPENAI_API_KEY')

import openai

连接到 Elasticsearch

ElasticsearchStore 类用于连接到 Elasticsearch 实例。 它需要以下参数:

  • index_name:Elasticsearch 索引的名称。 必需的。
  • es_client:可选。 预先存在的 Elasticsearch 客户端。
  • es_url:可选。Elasticsearch 网址。
  • es_cloud_id:可选。 Elasticsearch 云 ID。
  • es_api_key:可选。 Elasticsearch API 密钥。
  • es_user:可选。 Elasticsearch 用户名。
  • es_password:可选。 弹性搜索密码。
  • text_field:可选。 存储文本的 Elasticsearch 字段的名称。
  • vector_field:可选。 存储 Elasticsearch 字段的名称嵌入。
  • batch_size:可选。 批量索引的批量大小。 默认为 200。
  • distance_strategy:可选。 用于相似性搜索的距离策略。默认为 “COSINE”。

针对,我们的情况,我们可以使用如下的示例方法来进行本地连接:

from llama_index.vector_stores import ElasticsearchStore

es = ElasticsearchStore(
    index_name="my_index",
    es_url="http://localhost:9200",
)

我们将在下面的代码中使用上述的方法来连接 Elasticsearch。

加载文档,使用 Elasticsearch 构建 VectorStoreIndex

from llama_index import VectorStoreIndex, SimpleDirectoryReader
from llama_index.vector_stores import ElasticsearchStore

!mkdir -p 'data/paul_graham/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'

运行完上面的命令后,我们可以在当前的目录下查看:

$ pwd
/Users/liuxg/python/elser
$ ls data/paul_graham/
paul_graham_essay.txt

我们可以看到一个叫做 pau_graham_essay.txt 的文件。它的内容如下:

What I Worked On

February 2021

Before college the two main things I worked on, outside of school, were writing and programming. I didn't write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep.

The first programs I tried writing were on the IBM 1401 that our school district used for what was then called "data processing." This was in 9th grade, so I was 13 or 14. The school district's 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain's lair down there, with all these alien-looking machines — CPU, disk drives, printer, card reader — sitting up on a raised floor under bright fluorescent lights.

...

The language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer.

I was puzzled by the 1401. I couldn't figure out what to do with it. And in retrospect there's not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn't have any data stored on punched cards. The only other option was to do things that didn't rely on any input, like calculate approximations of pi, but I didn't know enough math to do anything interesting of that type. So I'm not surprised I can't remember any programs I wrote, because they can't have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn't. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager's expression made clear.
...

Toward the end of the summer I got a big surprise: a letter from the Accademia, which had been delayed because they'd sent it to Cambridge England instead of Cambridge Massachusetts, inviting me to take the entrance exam in Florence that fall. This was now only weeks away. My nice landlady let me leave my stuff in her attic. I had some money saved from consulting work I'd done in grad school; there was probably enough to last a year if I lived cheaply. Now all I had to do was learn Italian.
...
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()

from llama_index.storage.storage_context import StorageContext

vector_store = ElasticsearchStore(
    es_url="http://localhost:9200",
    # Or with Elastic Cloud
    # es_cloud_id="my_cloud_id",
    # es_user="elastic",
    # es_password="my_password",
    index_name="paul_graham",
)

storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    documents, storage_context=storage_context
)

基本查询

我们将向查询引擎询问有关我们刚刚索引的数据的问题。

# set Logging to DEBUG for more detailed outputs
query_engine = index.as_query_engine()
response = query_engine.query("what were his investments in Y Combinator?")
print(response)

元数据过滤器

在这里,我们将使用元数据索引一些文档,以便我们可以将过滤器应用于查询引擎。

from llama_index.schema import TextNode

nodes = [
    TextNode(
        text="The Shawshank Redemption",
        metadata={
            "author": "Stephen King",
            "theme": "Friendship",
        },
    ),
    TextNode(
        text="The Godfather",
        metadata={
            "director": "Francis Ford Coppola",
            "theme": "Mafia",
        },
    ),
    TextNode(
        text="Beautiful weather",
        metadata={
            "director": "Mark shuttle",
            "theme": "Mafia",
        },
    ),    
    TextNode(
        text="Inception",
        metadata={
            "director": "Christopher Nolan",
        },
    ),
]

# initialize the vector store
vector_store_metadata_example = ElasticsearchStore(
    index_name="movies_metadata_example",
    es_url="http://localhost:9200",
)
storage_context = StorageContext.from_defaults(
    vector_store=vector_store_metadata_example
)
index1 = VectorStoreIndex(nodes, storage_context=storage_context)


# Metadata filter
from llama_index.vector_stores.types import ExactMatchFilter, MetadataFilters

filters = MetadataFilters(
    filters=[ExactMatchFilter(key="theme", value="Mafia")]
)

retriever = index1.as_retriever(filters=filters)

retriever.retrieve("weather is so beautiful")

在上面,我们搜索的是 “weather is so beautiful”,从而在两个 theme 为 Mafia 的 Texnode 里,Mark shuttle 位列第一。这个是因为 “weather is so beautiful” 更和 “Beautiful weather” 更为贴近。 如果我们使用如下的查询:

retriever.retrieve("The godfather is a nice person")

很显然,这次我们的搜索结果的排序颠倒过来了。

自定义过滤器和覆盖查询

llama-index 目前仅支持 ExactMatchFilters。 Elasticsearch 支持多种过滤器,包括范围过滤器、地理过滤器等。 要使用这些过滤器,你可以将它们作为字典列表传递给 es_filter 参数。

def custom_query(query, query_str):
    print("custom query", query)
    return query

query_engine = index.as_query_engine(
    vector_store_kwargs={
        "es_filter": [{"match": {"content": "growing up"}}],
        "custom_query": custom_query,
    }
)

response = query_engine.query("what were his investments in Y Combinator?")
print(response)

为了方便大家学习,我把所有的源码放到 github:https://github.com/liu-xiao-guo/semantic_search_es。其中相关的文件是:

  • https://github.com/liu-xiao-guo/semantic_search_es/blob/main/Elasticsearch%20integration%20-%20LIamaIndex%20.ipynb

更多阅读:使用 Elasticsearch 和 LlamaIndex 进行高级文本检索:句子窗口检索

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

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

相关文章

【创作活动】ChatGPT 和文心一言哪个更好用?

文章目录 文心一言优点缺点 ChatGPT优点缺点 Java编码能力比较对人工智能的看法 ChatGPT是由OpenAI开发的交互式AI大模型, 文心一言是由百度研发的知识增强大语言模型,本文从Java开发的角度对比一下哪个更好用(本文仅用于投稿CSDN创造活动&am…

【playwright】新一代自动化测试神器playwright+python系列课程15_playwright网页相关操作_网页截图

Playwright 网页截图 在做web自动化测试时,脚本执行时会出现执行失败的情况,这个时候就需要分析失败的原因,由于脚本执行时是不需要人工盯着执行的,这个时候就需要在脚本执行失败时保留某些信息方便脚本执行完成后来分析失败的原…

SpringMVC(全局异常处理.动态接收Ajax请求)

1.全局异常处理 1 异常处理器 基于AOP 用户发起请求, SpringMVC接受请求, SpringMVC加载静态资源问题说明 请求过去了,但没有处理 规则说明:静态资源进入SpringMVC框架之后,没有找到要怎样处理静态资源的方法,所以他们就不解决,也就不显示 解决方法:SpringMVC基于Servlet处理…

添加边界值分析测试用例

1.1创建项目成功后会自动生成封装好的函数,在这些封装好的函数上点击右键,添加边界值分析测试用例,如下图所示。 1.2生成的用例模版是不可以直接运行的,需要我们分别点击它们,让它们自动生成相应测试用例。如下图所示&…

华为路由器配置访问控制列表ACL用例

配置要求 如组网图所示,R3为服务器,R1为客户端,客户端与服务器 之间路由可达。其中R1和R2间互联物理接口地址分别为 10.1.2.1/24和10.1.2.2/24,R2和R3间互联物理接口地址分别 为10.1.3.2/24和10.1.3.1/24。另外,R1上创…

企业计算机服务器中了mkp勒索病毒如何处理,mkp勒索病毒解密

网络技术的不断发展,为企业的生产运营提供了非常有利条件,但也为企业的数据安全埋下隐患,近期,众多企业的服务器遭到了mkp勒索病毒攻击,导致企业计算机服务器瘫痪无法正常工作,严重影响了企业正常生活运营。…

统计学-R语言-5.3

文章目录 前言分位数统计量的标准误总结 前言 本篇文章即为概率与分布的最后一篇文章。 分位数 分位数函数是累积分布函数的反函数。 p-分位数是具有这样性质的一个值:小于或等于它的概率为p。 根据定义,中位数即50%分位数。 分位数通常用于置信区间的…

系统架构的演变:从单体到微服务的旅程

文章目录 前言一、单体架构简图 二、垂直架构简图 三、水平架构简图 四、面向服务架构(SOA)简图 五、微服务架构简图 总结 前言 随着信息技术的快速发展,系统架构也在不断演变。从早期的单体架构到现代的微服务架构,每一次的变革都…

Leetcode454四数相加Ⅱ(java实现)

今天,我们分享的题目是Leetcode454四数相加Ⅱ,我们先来看题目: 首先可以从题意中大体得知,也是从某个集合中找有没有符合条件的元素。遇见这种类型的题目我们可以考虑用哈希表,本题我们选取的是map集合,因…

Damicms漏洞挖掘

今天又是挖漏洞的一天,(寒假了也不能停下挖洞的步伐) “《学而不思则罔,不学不思则爽》” ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 1.存储型XSS XSS…

Spring MVC学习之——自定义日期转化器

日期转换器 在数据库中的日期数据是date类型,而如何我们想在页面自己添加数据,一般是使用年-月-日的形式,这种形式不仅date类型接收不到,而且传来的是String类型,此时,我们就可以自定义日期转换器来接收数…

React 基于Ant Degisn 实现table表格列表拖拽排序

效果图: 代码: myRow.js import { MenuOutlined } from ant-design/icons; import { DndContext } from dnd-kit/core; import { restrictToVerticalAxis } from dnd-kit/modifiers; import {arrayMove,SortableContext,useSortable,verticalListSorti…

C——语言内存函数

目录 一、memcpy的使用和模拟实现 1.memcpy函数原型 2.memcpy函数的使用 3.memcpy函数的模拟实现 二、memmove的使用和模拟实现 1.memmove函数原型 2.memmove函数的使用 3.memmove函数的模拟实现 三、memset的使用 1.memset函数原型 2.memset函数的使用 四、memcmp…

【话题】ChatGPT 和文心一言哪个更好用

星火说 ChatGPT 智能回复:ChatGPT能够根据上下文理解用户的问题,并给出相应的回答。它使用深度学习算法来理解和生成文本,因此可以处理各种复杂的问题和话题。语言准确性:ChatGPT的语言模型经过了大量的训练数据,因此…

vue项目本地开发完成后部署到服务器后报404是什么原因

文章目录 一、如何部署二、404问题为什么history模式下有问题为什么hash模式下没有问题解决方案 参考文献 一、如何部署 前后端分离开发模式下,前后端是独立布署的,前端只需要将最后的构建物上传至目标服务器的web容器指定的静态目录下即可 我们知道vu…

macOS系统下载安装IDEA 操作流程

目录 第一步 进入官网,选择箭头指向的版本 第二步 下载完成后打开,拖动安装包安装​编辑 第三步 点击" project",在JDK下拉框选择"Download JDK" 第四步 下载完成以后,点击右下角的Create按钮。 第一步 进…

【Docker】在Windows操作系统安装Docker前配置环境

欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是《Docker容器》序列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对…

PMP考试中常见的组织/人员/职位/角色的含义,以及典型真题分析3

华研荟继续为您分享在PMP考试中经常出现的一些组织、人员、职位和角色的含义,并且通过近年真题分析来给大家体会考试中如何理解,如何解答。 这篇文章来看客户和供应商/分包商,也是PMP考试中经常出现的两类人(角色)。 …

常见的设计模式(模板与方法,观察者模式,策略模式)

前言 随着时间的推移,软件代码越来越庞大,随着而来的就是如何维护日趋庞大的软件系统。在面向对象开发出现之前,使用的是面向过程开发来设计大型的软件程序,面向过程开发将软件分成一个个单独的模块,模块之间使用函数…

C语言通过MSXML6.0读写XML文件(同时支持char[]和wchar_t[]字符数组)

开发环境&#xff1a;Visual Studio 2010 运行环境&#xff1a;Windows XP SP3 第一节 读取XML文件&#xff08;使用wchar_t[]字符数组&#xff09; /* 这个程序只能在C编译器下编译成功, 请确保源文件的扩展名为c */ #define COBJMACROS #include <stdio.h> #include …