使用 LangChain 和 Elasticsearch 对私人数据进行人工智能搜索

关于本博文的所有代码可以在地址下载:GitHub - liu-xiao-guo/python-vector-private

我将在本博文中其中深入研究人工智能和向量嵌入的深水区。 ChatGPT 令人大开眼界,但有一个主要问题。 这是一个封闭的托管系统。 在一个被大型网络公司改变的世界里生活了二十年之后,我们作为人们担心我们的私人信息甚至我们的知识仅仅因为我们使用互联网就成为他人的财产。 作为建立在竞争基础上的经济的参与者,我们对知识和数据集中在有反竞争行为历史的公司手中抱有强烈的不信任。

因此,眼前的问题是:我能否获得本地大型语言模型,并在不使用云服务的情况下在我的笔记本电脑上运行生成式人工智能聊天? 本文将展示如何在本地部署大模型,并使用 Elasticsearch 进行向量搜索。

我要建造什么?

简而言之:我将构建一个人工智能聊天机器人,通过将 LLM 与向量存储相结合,它 “知道” 其预先训练的神经网络中没有的东西。

我将从一个经常辅导的项目开始,最好将其描述为 “与我的书交谈”。 我没有发明这个,快速搜索发现其他一些通常使用付费 OpenAI API 的方法。 示例,视频示例

我将从我用来搜索的第一部分私人数据开始。一本从网上可以直接进行下载的一部书。 我将其转换为简单的 .txt 文件,并保存于项目中的 data/sample.txt 文件中。

这将如何运作

关键步骤

  • 文本被提取成小段落大小的块(chunks),足以容纳有关书的问题问题的所有答案。
  • 每个文本块都被传递给句子转换器,它生成一个密集向量,以向量嵌入的形式表示其语义含义
  • 这些块及其向量嵌入存储在 Elasticsearch 中
  • 当提出问题时,系统会为问题文本创建一个向量,然后查询 Elasticsearch 以查找语义上最接近问题的文本块; 想必有些文字会有答案。
  • 为 LLM 编写提示,将检索到的文本块作为额外的上下文知识 “填充”。
  • LLM 创建问题的答案

有关为什么需要把文本分成不同大小的 chunks,原因如下:

在本示例中,我将使用 sentence-transformers/all-mpnet-base-v2 模型。根据模型的描述,该模型的最大 token 长度为 384:

也就是说,我们需要把书分成最多不超过 384 的 chunks。

Langchain 让一切变得简单

有一个很棒的 Python 库,名为 Langchain,它不仅包含实用程序库,使变压器和向量存储的使用变得简单,而且在某种程度上可以互换。 Langchain 拥有比我在这里使用的更高级的与 LLM 合作的模式,但这是一个很好的第一个测试。

许多 Langchain 教程都需要使用付费 OpenAI 帐户。 OpenAI 很棒,并且目前可能在 LLM 质量竞赛中处于领先地位,但出于上述所有原因,我将使用免费的 HuggingFace 模型和 Elasticsearch。

获取一些离线模型

必须在 Huggingface 中创建一个帐户并获取 API 密钥。 之后,你可以使用 Huggingface_hub Python 或 Langchain 库以编程方式下拉模型。在运行代码的 terminal 中,你必须先打入如下的命令:

export HUGGINGFACEHUB_API_TOKENs="YOUR TOKEN"

我们在示例中使用如下的模型:

  • Sentence-transformers/all-mpnet-base-v2- 作为我的向量嵌入生成器
  • google/flan-t5-large - 作为我用于对话交互的大型语言模型

安装

如果你还没有安装好自己的 Elasticsearch 及 Kibana 的话,那么请参考如下的链接:

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

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

在安装的时候,我们选择 Elastic Stack 9.x 的安装指南来进行安装。在默认的情况下,Elasticsearch 集群的访问具有 HTTPS 的安全访问。

生成证书

为了能使得 python 应用能够正常访问 Elasticsearch,我们使用如下的命令来生成 pem 证书:

$ pwd
/Users/liuxg/elastic/elasticsearch-8.10.0
$ ./bin/elasticsearch-keystore list
keystore.seed
xpack.security.http.ssl.keystore.secure_password
xpack.security.transport.ssl.keystore.secure_password
xpack.security.transport.ssl.truststore.secure_password
$ ./bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
GcOUL8b2RxKooxJU-VymFg
$ openssl pkcs12 -in ./config/certs/http.p12 -cacerts -out ./python_es_client.pem
Enter Import Password:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
$ ls
LICENSE.txt          bin                  jdk.app              modules
NOTICE.txt           config               lib                  plugins
README.asciidoc      data                 logs                 python_es_client.pem

我们把上面生成的 python_es_client.pem 文件拷贝到应用的根目录下。这样整个应用的目录架构如下:

$ tree -L 3
.
├── README.md
├── app-book.py
├── data
│   └── sample.txt
├── lib_book_parse.py
├── lib_embeddings.py
├── lib_llm.py
├── lib_vectordb.py
├── python_es_client.pem
├── requirements.txt
└── simple.cfg

配置项目

如上所示,我们有一个叫做 simple.cfg 的配置文件:

simple.cfg

ES_SERVER: "localhost" 
ES_PASSWORD: "vXDWYtL*my3vnKY9zCfL"
ES_FINGERPRINT: "e2c1512f617f432ddf242075d3af5177b28f6497fecaaa0eea11429369bb7b00"

我们需要根据自己的 Elasticsearch 服务器的地址来配置 ES_SERVER。我们也需要配置 elastic 超级用户的密码。这个密码可以在安装 Elasticsearch 时得到。当然你也可以使用其他用户的信息来进行练习。如果这样,你需要做相应的配置和代码改动。

你还可以在 Kibana 的配置文件 confgi/kibana.yml 文件中获得 fingerprint 的配置:

运行项目

在运行项目之前,你需要做一下安装的动作:

python3 -m venv env
source env/bin/activate
python3 -m pip install --upgrade pip
pip install -r requirements.txt

创建嵌入模型

lib_embedding.py

## for embeddings
from langchain.embeddings import HuggingFaceEmbeddingsdef setup_embeddings():# Huggingface embedding setupprint(">> Prep. Huggingface embedding setup")model_name = "sentence-transformers/all-mpnet-base-v2"return HuggingFaceEmbeddings(model_name=model_name)

创建向量存储

lib_vectordb.py

import os
from config import Config## for vector store
from langchain.vectorstores import ElasticVectorSearchdef setup_vectordb(hf,index_name):# Elasticsearch URL setupprint(">> Prep. Elasticsearch config setup")with open('simple.cfg') as f:cfg = Config(f)endpoint = cfg['ES_SERVER']username = "elastic"password = cfg['ES_PASSWORD']ssl_verify = {"verify_certs": True,"basic_auth": (username, password),"ca_certs": "./python_es_client.pem",}url = f"https://{username}:{password}@{endpoint}:9200"return ElasticVectorSearch( embedding = hf, elasticsearch_url = url, index_name = index_name, ssl_verify = ssl_verify), url

创建使用带有上下文和问题变量的提示模板的离线 LLM

lib_llm.py

## for conversation LLM
from langchain import PromptTemplate, HuggingFaceHub, LLMChain
from langchain.llms import HuggingFacePipeline
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, AutoModelForSeq2SeqLMdef make_the_llm():# Get Offline flan-t5-large ready to go, in CPU modeprint(">> Prep. Get Offline flan-t5-large ready to go, in CPU mode")model_id = 'google/flan-t5-large'# go for a smaller model if you dont have the VRAMtokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForSeq2SeqLM.from_pretrained(model_id) #load_in_8bit=True, device_map='auto'pipe = pipeline("text2text-generation",model=model, tokenizer=tokenizer, max_length=100)local_llm = HuggingFacePipeline(pipeline=pipe)# template_informed = """# I know the following: {context}# Question: {question}# Answer: """template_informed = """I know: {context}when asked: {question}my response is: """prompt_informed = PromptTemplate(template=template_informed, input_variables=["context", "question"])return LLMChain(prompt=prompt_informed, llm=local_llm)

装载书籍

以下是我的分块和向量存储代码。 它需要在 Elasticsearch 中准备好组成的 Elasticsearch url、huggingface 嵌入模型、向量数据库和目标索引名称

lib_book_parse.py


from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import TextLoader## for vector store
from langchain.vectorstores import ElasticVectorSearch
from elasticsearch import Elasticsearch
from config import Configwith open('simple.cfg') as f:cfg = Config(f)fingerprint = cfg['ES_FINGERPRINT']
endpoint = cfg['ES_SERVER']
username = "elastic"
password = cfg['ES_PASSWORD']
ssl_verify = {"verify_certs": True,"basic_auth": (username, password),"ca_certs": "./python_es_client.pem",
}url = f"https://{username}:{password}@{endpoint}:9200"def parse_book(filepath):loader = TextLoader(filepath)documents = loader.load()text_splitter = RecursiveCharacterTextSplitter(chunk_size=384, chunk_overlap=0)docs = text_splitter.split_documents(documents)return docsdef loadBookBig(filepath, url, hf, db, index_name):    es = Elasticsearch( [ url ], basic_auth = ("elastic", cfg['ES_PASSWORD']), ssl_assert_fingerprint = fingerprint, http_compress = True  )## Parse the book if necessaryif not es.indices.exists(index=index_name):print(f'\tThe index: {index_name} does not exist')print(">> 1. Chunk up the Source document")docs = parse_book(filepath)# print(docs)print(">> 2. Index the chunks into Elasticsearch")elastic_vector_search= ElasticVectorSearch.from_documents( docs,embedding = hf, elasticsearch_url = url, index_name = index_name, ssl_verify = ssl_verify)   else:print("\tLooks like the book is already loaded, let's move on")

用问题循环将所有内容联系在一起

解析这本书后,主控制循环是这样的

# ## how to ask a question
def ask_a_question(question):# print("The Question at hand: "+question)## 3. get the relevant chunk from Elasticsearch for a question# print(">> 3. get the relevant chunk from Elasticsearch for a question")similar_docs = db.similarity_search(question)print(f'The most relevant passage: \n\t{similar_docs[0].page_content}')## 4. Ask Local LLM context informed prompt# print(">> 4. Asking The Book ... and its response is: ")informed_context= similar_docs[0].page_contentresponse = llm_chain_informed.run(context=informed_context,question=question)return response# # The conversational loopprint(f'I am the book, "{bookName}", ask me any question: ')while True:command = input("User Question>> ")response = ask_a_question(command)print(f"\n\n I think the answer is : {response}\n")

运行结果

我们可以通过如下的命令来运行应用:

python3 app-book.py 

上面的问题是:

when was it?Although it was not yet late, the sky was dark when I turned into Laundress Passage. 

我们来尝试其他的问题:

上面的问题是:

what will I send to meet you from the half past four arrival at Harrogate Station?

上面的问题是:

what do I make all the same and put a cup next to him on the desk?

上面的问题是:

How long did I sit on the stairs after reading the letter? 

Hooray! 我们完成了问答系统。它可以完美地回答我书里的内容。是不是觉得很神奇 :)

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

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

相关文章

iOS——present相关属性以及dismiss多级的方法

push和present 两者的区别 push: push由视图栈控制,每一个视图都入栈,调用之前的视图则需要出栈,可返回任意一层,一般用于同一业务不同界面之间的切换。 push是由UINavigationController管理的视图控制器堆栈,在wind…

MySQL学习笔记

目录 注释1、启动和关闭MYSQL服务2、库的增删改查3、表的增删改查3.1 创建表3.2 修改表3.3 删除 4、数据类型4.1 字符串:char(num) 与 varchar(num)的区别4.2 整型4.3 浮点型4.4 日期型4.5 枚举型 注释 单行注释:#注释文字(没空格&#xff09…

如何运用yolov5训练自己的数据(手把手教你学yolo)

在这篇博文中,我们对YOLOv5模型进行微调,用于自定义目标检测的训练和推理。 目录 引言: YOLOv5是什么? YOLOv5提供的模型 YOLOv5提供的功能 使用YOLOv5进行自定义目标检测训练 自定义训练的方法 自定义训练代码 准备数据集 …

对话ChatGPT:AIGC时代下,分布式存储的应用与前景

随着科技的飞速发展,我们正步入一个被称为AIGC时代的全新阶段,人工智能、物联网、大数据、云计算成为这个信息爆炸时代的主要特征。自2022年11月以来,ChatGPT的知名度迅速攀升,引发了全球科技爱好者的极大关注,其高超的…

【跟小嘉学习区块链】二、Hyperledger Fabric 架构详解

系列文章目录 【跟小嘉学习区块链】一、区块链基础知识与关键技术解析 【跟小嘉学习区块链】一、区块链基础知识与关键技术解析 文章目录 系列文章目录[TOC](文章目录) 前言一、Hyperledger 社区1.1、Hyperledger(面向企业的分布式账本)1.2、Hyperledger社区组织结构 二、Hype…

AI-Chat,一款集全网ai功能的应用(附下载链接)

AI-Chat是一款综合性的聊天机器人,集成了多种先进的模型和功能。它采用了GPT4.0、联网版GPT和清华模型等多种模型,使得其具备更强大的语言处理能力。同时,AI-Chat还融合了AI绘画模型,例如Stable Diffusion绘画、文生图、图生图、艺…

数据结构与算法基础-(2)

🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…

ElasticSearch - 分布式搜索引擎底层实现——倒排索引

目录 一、ElasticSearch 1.1、ElasticSearch 是什么? 1.2、ElasticStack 是什么? 1.3、正向索引和倒排索引 1.3.1、正向索引 1.3.2、倒排索引 a)倒排索引的创建过程: b)倒排索引的查询过程: c)分…

LeetCode讲解篇之347. 前 K 个高频元素

347. 前 K 个高频元素 文章目录 347. 前 K 个高频元素题目描述题解思路题解代码 题目描述 题解思路 根据数组频率倒序排序, 然后返回前k的个数据 题解代码 func topKFrequent(nums []int, k int) []int {m : make(map[int]int, 0)for i : len(nums) - 1; i > 0; i-- {m[n…

一拖三快充线(USB-C转三充)的解决方案--LDR6020P

DR6020P 是带有 3 组 6 路 DRP USB-C 及 PD 通信协议处理模块和 USB2.0 Device 功能的 16 位 RISC MCU,内置 8K16 位 MTP 程序存储器(可烧录 1000 次),512 字节的数据存储器(SRAM)。内置 LDO 5V 输出&#…

滑动窗口9.23

1876.长度为3且各字符不同的子字符串 1876. 长度为三且各字符不同的子字符串 - 力扣(LeetCode)https://leetcode.cn/problems/substrings-of-size-three-with-distinct-characters/?envTypelist&envId24zW97w8自写思路: 数组充当哈希表…

Mysql004:用户管理

前言:本章节讲解的是mysql中的用户管理,包括(管理数据用户)、(控制数据库的访问权限)。 目录 1. 查询用户 2. 创建用户 3. 修改用户密码 4. 删除用户 5. 权限控制 1. 查询用户 在mysql数据库中&#xff0…

数字IC设计系列----单端口RAM、双端口RAM

一、单端口RAM原理及实现 1.1、概念/原理 在内存空间中开辟出一段固定大小的内存用于存储数据,每一个数据所占的bit位称之为位宽,这段内存空间中数据的总数称之为深度。例如reg [7:0] mem [255:0],这段内存空间中每一个数据的位宽为8bit&am…

Nuxt 菜鸟入门学习笔记:路由

文章目录 路由 Routing页面 Pages导航 Navigation路由参数 Route Parameters路由中间件 Route Middleware路由验证 Route Validation Nuxt 官网地址: https://nuxt.com/ 路由 Routing Nuxt 的一个核心功能是文件系统路由器。pages/目录下的每个 Vue 文件都会创建一…

C语言数组和指针笔试题(四)(一定要看)

目录 二维数组例题一例题二例题三例题四例题五例题六例题七例题八例题九例题十例题十一 结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒个人主页 🥸🥸🥸C语言 🐿️…

【Unity3D赛车游戏制作】开始界面场景搭建

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:Uni…

大模型的最大bug,回答正确率几乎为零,GPT到Llama无一幸免

目录 前言 1.名字和描述颠倒一下,大模型就糊涂了 2.实验及结果 3.未来展望 前言 大模型的逻辑?不存在的。 我让 GPT-3 和 Llama 学会一个简单的知识:A 就是 B,然后反过来问 B 是什么,结果发现 AI 回答的正确率竟然是…

SpringCloud Alibaba - Sentinel

接上文SpringCloud Alibaba - Nacos 1.Sentinel 流量防卫兵 1.1 安装与部署 和Nacos一样,它是独立安装和部署的,下载地址https://github.com/alibaba/Sentinel/releases 下载后的jar放到目录 然后配置 启动并访问,用户名密码都是 sentinel 此时就…

2024年考研教育专业的教育综合考试大纲、样题和往年真题

根据教育部通知,2024年全国硕士研究生招生考试初试定于2023年12月23日至24日,即我们说的2024年考研时间为12月23-24日。距离现在只剩下3个月不到的时间,那么如何让我们在最后三个月内的复习和备考有效且高效呢? 结合很多清北复交研…

湖南麒麟两种修复硬盘方式

1、背景介绍 目前X86平台采用湖南麒麟3.3-3B系统,当遇到文件系统损坏时,可分下面两种情况进行文件系统修复 2、紧急模式下的修复 板子能进入系统,但是进入的是紧急模式,类似下面这种 此时可以直接输入修复命令进行系统修复 xf…