使用 Elasticsearch 和 OpenAI 构建生成式 AI 应用程序

本笔记本演示了如何:

  • 将 OpenAI Wikipedia 向量数据集索引到 Elasticsearch 中
  • 使用 Streamlit 构建一个简单的 Gen AI 应用程序,该应用程序使用 Elasticsearch 检索上下文并使用 OpenAI 制定答案

 安装

安装 Elasticsearch 及 Kibana

如果你还没有安装好自己的 Elasticsearch 及 Kibana,那么请参考一下的文章来进行安装:

  • 如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch

  • Kibana:如何在 Linux,MacOS 及 Windows 上安装 Elastic 栈中的 Kibana

在安装的时候,请选择 Elastic Stack 8.x 进行安装。在安装的时候,我们可以看到如下的安装信息:

环境变量

在启动 Jupyter 之前,我们设置如下的环境变量:

export ES_USER="elastic"
export ES_PASSWORD="xnLj56lTrH98Lf_6n76y"
export ES_ENDPOINT="localhost"
export OPENAI_API_KEY="YourOpenAiKey"

请在上面修改相应的变量的值。这个需要在启动 jupyter 之前运行。

拷贝 Elasticsearch 证书

我们把 Elasticsearch 的证书拷贝到当前的目录下:

$ pwd
/Users/liuxg/python/elser
$ cp ~/elastic/elasticsearch-8.12.0/config/certs/http_ca.crt .
$ ls http_ca.crt 
http_ca.crt

安装 Python 依赖包

python3 -m pip install -qU openai pandas==1.5.3 wget elasticsearch streamlit tqdm load_dotenv

准备数据

我们可以使用如下的命令来下载数据:

wget https://cdn.openai.com/API/examples/data/vector_database_wikipedia_articles_embedded.zip
$ pwd
/Users/liuxg/python/elser
$ wget https://cdn.openai.com/API/examples/data/vector_database_wikipedia_articles_embedded.zip
--2024-02-09 12:06:36--  https://cdn.openai.com/API/examples/data/vector_database_wikipedia_articles_embedded.zip
Resolving cdn.openai.com (cdn.openai.com)... 13.107.213.69
Connecting to cdn.openai.com (cdn.openai.com)|13.107.213.69|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 698933052 (667M) [application/zip]
Saving to: ‘vector_database_wikipedia_articles_embedded.zip’vector_database_wikipedi 100%[==================================>] 666.55M  1.73MB/s    in 3m 2s   2024-02-09 12:09:40 (3.66 MB/s) - ‘vector_database_wikipedia_articles_embedded.zip’ saved [698933052/698933052]

创建应用并展示

我们在当前的目录下打入如下的命令来创建 notebook:

$ pwd
/Users/liuxg/python/elser
$ jupyter notebook

导入包及连接到 Elasticsearch

import os
from getpass import getpass
from elasticsearch import Elasticsearch, helpers
import wget, zipfile, pandas as pd, json, openai
import streamlit as st
from tqdm.notebook import tqdm
from dotenv import load_dotenvload_dotenv()openai_api_key=os.getenv('OPENAI_API_KEY')
elastic_user=os.getenv('ES_USER')
elastic_password=os.getenv('ES_PASSWORD')
elastic_endpoint=os.getenv("ES_ENDPOINT")url = f"https://{elastic_user}:{elastic_password}@{elastic_endpoint}:9200"
client = Elasticsearch(url, ca_certs = "./http_ca.crt", verify_certs = True)print(client.info())

配置 OpenAI 连接

我们的示例将使用 OpenAI 来制定答案,因此请在此处提供有效的 OpenAI Api 密钥。

你可以按照本指南检索你的 API 密钥。然后测试与OpenAI的连接,检查该笔记本使用的型号是否可用。

from openai import OpenAIopenai = OpenAI()
openai.models.retrieve("text-embedding-ada-002")
$ pip3 list | grep openai
langchain-openai                         0.0.5
openai                                   1.12.0

下载数据集

with zipfile.ZipFile("vector_database_wikipedia_articles_embedded.zip",
"r") as zip_ref:zip_ref.extractall("data")

运行上面的代码后,我们可以在如下地址找到解压缩的文件 vector_database_wikipedia_articles_embedded.csv:

$ pwd
/Users/liuxg/python/elser
$ ls ./data
__MACOSX                                        vector_database_wikipedia_articles_embedded.csv
paul_graham

将 CSV 文件读入 Pandas DataFrame

接下来,我们使用 Pandas 库将解压的 CSV 文件读入 DataFrame。 此步骤可以更轻松地将数据批量索引到 Elasticsearch 中。

wikipedia_dataframe = pd.read_csv("data/vector_database_wikipedia_articles_embedded.csv")

使用映射创建索引

现在我们需要使用必要的映射创建一个 Elasticsearch 索引。 这将使我们能够将数据索引到 Elasticsearch 中。

我们对 title_vector 和 content_vector 字段使用密集向量字段类型。 这是一种特殊的字段类型,允许我们在 Elasticsearch 中存储密集向量。

稍后,我们需要以密集向量字段为目标进行 kNN 搜索。

index_mapping= {"properties": {"title_vector": {"type": "dense_vector","dims": 1536,"index": "true","similarity": "cosine"},"content_vector": {"type": "dense_vector","dims": 1536,"index": "true","similarity": "cosine"},"text": {"type": "text"},"title": {"type": "text"},"url": { "type": "keyword"},"vector_id": {"type": "long"}}
}
client.indices.create(index="wikipedia_vector_index", mappings=index_mapping)

请注意 title_vector 及 content_vector 两个字段已经是以向量的形式来存储的。我们不需要额外的工作来对字段进行向量化。

将数据索引到 Elasticsearch

以下函数生成所需的批量操作,这些操作可以传递到 Elasticsearch 的 bulk API,因此我们可以在单个请求中有效地索引多个文档。

对于 DataFrame 中的每一行,该函数都会生成一个字典,表示要索引的单个文档。

def dataframe_to_bulk_actions(df):for index, row in df.iterrows():yield {"_index": 'wikipedia_vector_index',"_id": row['id'],"_source": {'url' : row["url"],'title' : row["title"],'text' : row["text"],'title_vector' : json.loads(row["title_vector"]),'content_vector' : json.loads(row["content_vector"]),'vector_id' : row["vector_id"]}}

由于数据帧很大,我们将以 100 个为一组对数据进行索引。我们使用 Python 客户端的 bulk API 帮助程序将数据索引到 Elasticsearch 中。

total_documents = len(wikipedia_dataframe)progress_bar = tqdm(total=total_documents, unit="documents")
success_count = 0for ok, info in helpers.streaming_bulk(client, actions=dataframe_to_bulk_actions(wikipedia_dataframe), raise_on_error=False, chunk_size=100):if ok:success_count += 1else:print(f"Unable to index {info['index']['_id']}: {info['index']['error']}")progress_bar.update(1)progress_bar.set_postfix(success=success_count)

等上面的代码运行完毕后,我们可以在 Kibana 中进行查看:

使用 Streamlit 构建应用程序

在下一节中, 你将使用 Streamlit 构建一个简单的界面。

该应用程序将显示一个简单的搜索栏,用户可以在其中提出问题。 Elasticsearch 用于检索与问题匹配的相关文档(上下文),然后 OpenAI 使用上下文制定答案。

安装依赖项以在运行后访问应用程序。

!npm install localtunnel
%%writefile app.pyimport os
import streamlit as st
import openai
from elasticsearch import Elasticsearch
from dotenv import load_dotenvfrom openai import OpenAIopenai = OpenAI()load_dotenv()openai_api_key=os.getenv('OPENAI_API_KEY')
elastic_user=os.getenv('ES_USER')
elastic_password=os.getenv('ES_PASSWORD')
elastic_endpoint=os.getenv("ES_ENDPOINT")url = f"https://{elastic_user}:{elastic_password}@{elastic_endpoint}:9200"
client = Elasticsearch(url, ca_certs = "./http_ca.crt", verify_certs = True)# Define model
EMBEDDING_MODEL = "text-embedding-ada-002"def openai_summarize(query, response):context = response['hits']['hits'][0]['_source']['text']summary = openai.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "Answer the following question:" + query + "by using the following text: " + context},])print(summary)return summary.choices[0].message.contentdef search_es(query):# Create embeddingquestion_embedding = openai.embeddings.create(input=query, model=EMBEDDING_MODEL)# Define Elasticsearch queryresponse = client.search(index = "wikipedia_vector_index",knn={"field": "content_vector","query_vector":  question_embedding.data[0].embedding,"k": 10,"num_candidates": 100})return responsedef main():st.title("Gen AI Application")# Input for user search queryuser_query = st.text_input("Enter your question:")if st.button("Search"):if user_query:st.write(f"Searching for: {user_query}")result = search_es(user_query)# print(result)openai_summary = openai_summarize(user_query, result)st.write(f"OpenAI Summary: {openai_summary}")# Display search resultsif result['hits']['total']['value'] > 0:st.write("Search Results:")for hit in result['hits']['hits']:st.write(hit['_source']['title'])st.write(hit['_source']['text'])else:st.write("No results found.")if __name__ == "__main__":main()

运行应用

运行应用程序并检查您的隧道 IP:

!streamlit run app.py

如果你想把网站供全网其它的电脑访问,你可以使用如下的命令:

npx localtunnel --port 8501

整个 notebook 的源码可以在地址下载:https://github.com/liu-xiao-guo/semantic_search_es/blob/main/openai_rag_streamlit.ipynb

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

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

相关文章

Python爬虫Xpath库详解#4

爬虫专栏:http://t.csdnimg.cn/WfCSx 前言 前面,我们实现了一个最基本的爬虫,但提取页面信息时使用的是正则表达式,这还是比较烦琐,而且万一有地方写错了,可能导致匹配失败,所以使用正则表达式…

1275.找出井字棋的获胜者(Java)

题目描述: A 和 B 在一个 3 x 3 的网格上玩井字棋。 井字棋游戏的规则如下: 玩家轮流将棋子放在空方格 (" ") 上。 第一个玩家 A 总是用 “X” 作为棋子,而第二个玩家 B 总是用 “O” 作为棋子。 “X” 和 “O” 只能放在空方格中&…

FPGA_简单工程_状态机

一 理论 fpga是并行执行的,当处理需要顺序解决的事时,就要引入状态机。 状态机: 简写FSM,也称同步有限状态机。 分为:more型状态机,mealy型状态机。 功能:执行该事件,然后跳转到下…

相机图像质量研究(11)常见问题总结:光学结构对成像的影响--像差

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结:光学结构对成…

Linux 36.2@Jetson Orin Nano之Hello AI World!

Linux 36.2Jetson Orin Nano之Hello AI World! 1. 源由2. Hello AI World!3. 步骤3.1 准备阶段3.2 获取代码3.3 Python环境3.4 重点环节3.5 软件配置3.6 PyTorch安装3.7 编译链接3.8 安装更新 4. 测试4.1 video-viewer4.2 detectnet4.3 演示命令 5. 参考…

【OrangePi Zero2 智能家居】阿里云人脸识别方案

一、接入阿里云 二、C语言调用阿里云人脸识别接口 三、System V消息队列和POSIX 消息队列 一、接入阿里云 在之前树莓派的人脸识别方案采用了翔云平台的方案去1V1上传比对两张人脸比对,这种方案是可行,可 以继续采用。但为了接触更多了云平台方案&…

互联网摸鱼日报(2024-02-09)

互联网摸鱼日报(2024-02-09) 博客园新闻 开启 LLMs 应用开发之门 | 新程序员 技术宅死磕云游戏,米哈游的10亿玩家梦 苹果发布开源 AI 模型 MGIE 全新宝马 5 系旅行车发布 iPhone 16 最新相机模组设计:垂直排列,凸起呈药丸形状 马斯克评…

课时19:全局变量_文件体系

2.3.2 文件体系 学习目标 这一节,我们从 变量文件、简单实践、小结 三个方面来学习。 变量文件 变量文件 在linux环境中,有很多目录下的文件都可以定制一些作用范围更广的变量,这些文件或文件所在的目录有:作用范围在制定的用…

跟着pink老师前端入门教程-day23

苏宁网首页案例制作 设置视口标签以及引入初始化样式 <meta name"viewport" content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0"> <link rel"stylesheet" href"css/normaliz…

Mybatis是否支持延迟加载?

前言 随着互联网应用的不断发展&#xff0c;数据库访问成为了应用开发中的一个重要环节。在这个背景下&#xff0c;MyBatis作为一种优秀的持久层框架&#xff0c;提供了灵活的SQL映射配置和强大的功能&#xff0c;为开发者提供了便捷的数据库访问解决方案。本文将深入探讨MyBat…

(2024,街景生成,道路拓扑生成器,对象布局生成器,成分集成和天气生成)Text2Street:街景的可控文本到图像生成

公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; Text2Street: Controllable Text-to-image Generation for Street Views 目录 0. 摘要 2. 相关工作 3. 方法 3.1. 概述 3.2. 车道感知的道…

如何将 Hexo 部署到 GitHub Pages

引言 在数字时代&#xff0c;拥有个人博客是展示自己想法、分享知识和技能的绝佳方式。Hexo 是一个基于 Node.js 的静态博客生成器&#xff0c;它结合了简洁性和功能性&#xff0c;让我们可以轻松地建立并维护一个博客。而 GitHub Pages 提供了一个免费的平台来托管这些静态网站…

【java】简单的Java语言控制台程序

一、用于文本文件处理的Java语言控制台程序示例 以下是一份简单的Java语言控制台程序示例&#xff0c;用于文本文件的处理。本例中我们将会创建一个程序&#xff0c;它会读取一个文本文件&#xff0c;显示其内容&#xff0c;并且对内容进行计数&#xff0c;然后将结果输出到控…

vue3跨组件(多组件)通信:事件总线【Event Bus】

★推荐方案&#xff1a;使用 events npm库&#xff1b; 可用范围&#xff1a;vue、react、angular等任何框架都可使用&#xff1b;且使用方式完全一致&#xff1b; 本文仅介绍、讲解对web页面端项目的常用API&#xff1b;通过events实现事件总线功能&#xff1b; event库概述&a…

交易之路:从无知到有知的五个阶段

交易是易学的&#xff0c;它的操作很直观&#xff0c;也是复杂的&#xff0c;它的价格很玄妙。在金融行业日益壮大的背景下&#xff0c;新人辈出&#xff0c;而弱者则逐渐退出。市场生态在不断变化&#xff0c;我们每个人在交易之路上所经历的种种&#xff0c;既清晰可见又模糊…

Flask实现异步调用sqlalchemy的模型类

事情是这样的&#xff0c;我这边需要在一次请求里面&#xff0c;搞一个异步不阻碍的任务&#xff0c;来执行耗时的操作。 一开始&#xff0c;我准备写的代码是这样的&#xff1a; from flask import Flask import time from concurrent.futures import ThreadPoolExecutorexec…

基于opencv-python模板匹配的银行卡号识别(附源码)

目录 介绍 数字模板处理 银行卡图片处理 导入数字模板 模板匹配及结果 介绍 我们有若干个银行卡图片和一个数字模板图片&#xff0c;如下图 我们的目的就是通过对银行卡图片进行一系列图像操作使得我们可以用这个数字模板检测出银行卡号。 数字模板处理 首先我们先对数…

WPF DispatcherTimer用法

System.Windows.Threading.DispatcherTimer 类主要用于WPF应用程序中进行周期性任务调度&#xff0c;并且保证这些任务在UI线程上执行。 这对于需要更新界面或与UI元素交互的定时操作非常有用&#xff0c;因为WPF的所有UI操作都必须在主线程&#xff08;即Dispatcher线程&…

【开源】SpringBoot框架开发桃花峪滑雪场租赁系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设计3.1 教练表3.2 教练聘请表3.3 押金规则表3.4 器材表3.5 滑雪场表3.7 售票表3.8 器材损坏表 四、系统展示五、核心代码5.1 查询教练5.2 教练聘请5.3 查询滑雪场5.4 滑雪场预定5.5 新…

实践:微服务版本升级步骤以及maven仓库相关概念

进行微服务开发的时候&#xff0c;上层服务依赖于下层的服务的api&#xff0c;比如适配属于上层服务&#xff0c;用户属于下层服务。 例子: 上层服务 <!--订单管理微服务api依赖--> <dependency><groupId>com.jn.server</groupId><artifactId>…