基于LLM的文档搜索引擎开发【Ray+LangChain】

Ray 是一个非常强大的 ML 编排框架,但强大的功能伴随着大量的文档。 事实上120兆字节。 我们如何才能使该文档更易于访问?

答案:使其可搜索! 过去,创建自己的高质量搜索结果很困难。 但通过使用 LangChain,我们可以用大约 100 行代码来构建它。

这就是 LangChain 的用武之地。LangChain 为LLM相关的一切提供了一套令人惊叹的工具。 它有点像 HuggingFace,但专门针对LLM。 有用于提示、索引、生成和总结文本的工具(链)。 Ray虽然是一个令人惊叹的工具,但与它配合使用可以让LangChain变得更加强大。 特别是,它可以:

  • 简单快速地帮助你部署LangChain服务。
  • 允许 Chains 与 LLM 本身共同运行并自动扩展,而不是依赖远程 API 调用。 这带来了我们在之前的博客文章中讨论的所有优势:更低的成本、更低的延迟以及对数据的控制。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包

1、建立LangChain索引

首先,我们将通过以下步骤构建索引。

  • 下载我们想要在本地建立索引的内容。
  • 阅读内容并将其切成小块(每块大约一个句子)。 这是因为将查询与页面的各个部分而不是整个页面进行匹配更容易。
  • 使用 HuggingFace 的 Sentence Transformers 库生成每个句子的向量表示。
  • 将这些向量嵌入到向量数据库中(我们使用 FAISS,但您可以使用您喜欢的任何内容)。

这段代码的神奇之处在于它非常简单 - 请参阅此处。 正如您将看到的,感谢浪链,所有繁重的工作都为我们完成了。 我们来摘录几段吧。

假设我们已经下载了 Ray 文档,那么我们只需执行以下操作即可阅读以下位置的所有文档:

loader = ReadTheDocsLoader("docs.ray.io/en/master/")
docs = loader.load() 

下一步是将每个文档分成小块。 LangChain 使用分割器来做到这一点。 所以我们所要做的就是:

chunks = text_splitter.create_documents(
    [doc.page_content for doc in docs], 
    metadatas=[doc.metadata for doc in docs])

我们希望保留原始 URL 的元数据,因此我们确保将元数据与这些文档一起保留。

现在我们有了块,我们可以将它们嵌入为向量。 LLM 提供商确实提供了用于远程执行此操作的 API(这就是大多数人使用 LangChain 的方式)。 但是,只需一点点胶水,我们就可以从 HuggingFace 下载 Sentence Transformers 并在本地运行它们(受到 LangChain 对 llama.cpp 支持的启发)。 这是胶水代码。

通过这样做,我们可以减少延迟,继续使用开源技术,并且不需要 HuggingFace 密钥或支付 API 使用费用。

最后,我们有了嵌入,现在我们可以使用向量数据库(在本例中为 FAISS)来存储嵌入。 矢量数据库经过优化,可以在高维空间中进行快速搜索。 LangChain 再次让这一切变得毫不费力。

from langchain.vectorstores import FAISS

db = FAISS.from_documents(chunks, embeddings)
db.save_local(FAISS_INDEX_PATH)

就是这样。 代码在这里。 现在我们可以建立存储库了。

% python build_vector_store.py

执行此操作大约需要 8 分钟。 大部分时间都花在嵌入上。 当然,在这种情况下这不是什么大问题,但想象一下,如果您要索引数百 GB 而不是数百兆字节。

2、使用 Ray 加速索引

[注意:这是一个稍微高级的主题,第一次阅读时可以跳过。 它只是展示了我们如何更快地做到这一点 – 速度提高 4 倍到 8 倍]

我们怎样才能加快索引速度呢? 伟大的事情是嵌入很容易并行化。 如果我们:

  • 将块列表切成 8 个分片。
  • 分别嵌入 8 个分片。
  • 合并分片。

需要意识到的一件关键事情是嵌入是 GPU 加速的,所以如果我们想做到这一点,我们需要 8 个 GPU。 感谢 Ray,这 8 个 GPU 不必位于同一台机器上。 但即使在单台机器上,使用 Ray 也有显着的优势。 而且不必考虑设置 Ray 集群的复杂性,您所需要做的就是 pip install ray[default],然后导入 ray。

这需要对代码进行一些小改动。 这是我们必须做的。

首先,创建一个任务来创建嵌入,然后使用它来索引分片。 请注意 Ray 注释,我们告诉我们每个任务都需要整个 GPU。

@ray.remote(num_gpus=1)
def process_shard(shard): 
    embeddings = LocalHuggingFaceEmbeddings('multi-qa-mpnet-base-dot-v1')
    result = FAISS.from_documents(shard, embeddings)
    return result

接下来,将工作负载拆分到分片中。 NumPy 来救援! 这是一行:

shards = np.array_split(chunks, db_shards)

然后为每个分片创建一个任务并等待结果:

futures = [process_shard.remote(shards[i]) for i in range(db_shards)]
results = ray.get(futures)

最后,让我们将分片合并在一起。我们使用简单的线性合并来做到这一点。

db = results[0]
for i in range(1,db_shards):
    db.merge_from(results[i])

你可能想知道,这真的有效吗?我们在具有 8 个 GPU 的 g4dn.metal 实例上运行了一些测试。原始代码需要 313 秒才能创建嵌入,新代码需要 70 秒,大约提高了 4.5 倍。创建任务、设置 GPU 等仍然有一些一次性开销。随着数据的增加,这种情况会减少。例如,我们用 4 倍的数据做了一个简单的测试,它大约是理论最大性能的 80%(即 6.5 倍快,而 8 个 GPU 的理论最大速度快 8 倍)。

我们可以使用 Ray Dashboard 来查看这些 GPU 的工作强度。果然,它们都接近 100% 运行我们刚刚编写的 process_shard 方法。

事实证明,合并向量数据库的速度非常快,只需 0.3 秒即可合并所有 8 个分片。

3、服务提供

服务是LangChain和Ray Serve结合的另一个领域。这只是皮毛:我们将在本系列的下一篇文章中探讨独立自动扩展和请求批处理等惊人功能。

执行此操作所需的步骤如下:

  • 加载我们创建的 FAISS 数据库并实例化嵌入
  • 开始使用 FAISS 进行相似性搜索。

Ray Serve 让这一切变得神奇地简单。Ray 使用“部署”来包装一个简单的 python 类。 __init__方法执行加载,然后 __call__实际执行工作。Ray 负责将其连接到互联网,启动服务、http 等。

下面是代码的简化版本:

@serve.deployment
class VectorSearchDeployment:
    def __init__(self):
        self.embeddings = … 
        self.db = FAISS.load_local(FAISS_INDEX_PATH, self.embeddings)

    def search(self,query): 
        results = self.db.max_marginal_relevance_search(query)
        retval = <some string processing of the results>
        return retval

    async def __call__(self, request: Request) -> List[str]:
        return self.search(request.query_params["query"])

deployment = VectorSearchDeployment.bind()

就是这样!

现在让我们使用命令行启动此服务(当然 Serve 的部署选项比这更多,但这是一种简单的方法):

% serve run serve_vector_store:deployment

现在我们可以编写一个简单的 python 脚本来查询服务以获取相关向量(它只是一个运行在端口 8000 上的 Web 服务器)。

import requests
import sys
query = sys.argv[1]
response = requests.post(f'http://localhost:8000/?query={query}')
print(response.content.decode())

现在让我们试试看:

$ python query.py 'Does Ray Serve support batching?'
From http://docs.ray.io/en/master/serve/performance.html

You can check out our microbenchmark instructions
to benchmark Ray Serve on your hardware.
Request Batching#
====

From http://docs.ray.io/en/master/serve/performance.html

You can enable batching by using the ray.serve.batch decorator. Let’s take a look at a simple example by modifying the MyModel class to accept a batch.
from ray import serve
import ray
@serve.deployment
class Model:
    def __call__(self, single_sample: int) -> int:
        return single_sample * 2
====

From http://docs.ray.io/en/master/ray-air/api/doc/ray.train.lightgbm.LightGBMPredictor.preferred_batch_format.html

native batch format.
DeveloperAPI: This API may change across minor Ray releases.
====

From http://docs.ray.io/en/master/serve/performance.html

Machine Learning (ML) frameworks such as Tensorflow, PyTorch, and Scikit-Learn support evaluating multiple samples at the same time.
Ray Serve allows you to take advantage of this feature via dynamic request batching.
====

4、结束语

我们在上面的代码中展示了构建基于 LLM 的搜索引擎的关键组件并通过结合 LangChain 和 Ray Serve 的强大功能向整个世界提供响应是多么容易。而且我们不必处理一个讨厌的 API 密钥!


原文链接:LLM搜索引擎开发教程 - BimAnt

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Open CASCADE学习|拓扑变换

目录 平移变换 旋转变换 组合变换 通用变换 平移变换 TopoDS_Shape out;gp_Trsf theTransformation;gp_Vec theVectorOfTranslation(0., 0.125 / 2, 0.);theTransformation.SetTranslation(theVectorOfTranslation);BRepBuilderAPI_Transform myBRepTransformation(out, th…

EAK厚膜功率电阻成功在eVTOL大量使用

eVTOL操作的特点是更高的放电曲线&#xff0c;特别是在起飞和着陆期间。 “传统上&#xff0c;电池要么被设计成提供大量能量&#xff0c;要么被设计成高功率&#xff0c;”Cuberg创始人兼首席执行官Richard Wang说。“对于eVTOL电池来说&#xff0c;在能量和功率之间保持良好…

Acwing---826.单链表

单链表 1.题目2.基本思想3.代码实现 1.题目 实现一个单链表&#xff0c;链表初始为空&#xff0c;支持三种操作&#xff1a; 向链表头插入一个数&#xff1b;删除第 k k k 个插入的数后面的数&#xff1b;在第 k k k 个插入的数后插入一个数。现在要对该链表进行 M M M 次…

中科大计网学习记录笔记(五):协议层次和服务模型

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

如何计算两个指定日期相差几年几月几日

一、题目要求 假定给出两个日期&#xff0c;让你计算两个日期之间相差多少年&#xff0c;多少月&#xff0c;多少天&#xff0c;应该如何操作呢&#xff1f; 本文提供网页、ChatGPT法、VBA法和Python法等四种不同的解法。 二、解决办法 1. 网页计算法 这种方法是利用网站给…

69.请描述Spring MVC的工作流程?描述一下 DispatcherServlet 的工作流程?

69.请描述Spring MVC的工作流程&#xff1f;描述一下 DispatcherServlet 的工作流程&#xff1f; 核心架构的具体流程步骤如下&#xff1a; 首先用户发送请求——>DispatcherServlet&#xff0c;前端控制器收到请求后自己不进行处理&#xff0c;而是委托给其他的解析器进行…

day30 window对象——BOM、定时器setTimeout

目录 JavaScript的组成BOM定时器——延时函数两种定时器对比&#xff1a;执行的次数 JavaScript的组成 ECMAScript: 规定了js基础语法核心知识。比如&#xff1a;变量、分支语句、循环语句、对象等等 Web APIs : DOM 文档对象模型&#xff0c; 定义了一套操作HTML文档的APIBOM…

【Iot】什么是串口?什么是串口通信?串口通信(串口通讯)原理,常见的串口通信方式有哪些?

串口通信原理 1. 串口2. 串口通信4. 波特率与比特率5. 帧格式3. 串口通讯的通讯协议3.1. RS2323.2. RS485 总结 1. 串口 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方式的扩展接口。 串口可…

CICD注册和使用gitlab-runner常见问题

1、现象 fatal: unable to access https://github.com/homebrew/brew/: 2、解决 git config --global --unset http.proxy git config --global --unset https.proxy 查看gitlab-runner是否成功&#xff1a; userusers-MacBook-Pro ~ % gitlab-runner -h 查看gitlab-run…

Vue.js设计与实现(霍春阳)

Vue.js设计与实现 (霍春阳) 电子版获取链接&#xff1a;Vue.js设计与实现(霍春阳) 编辑推荐 适读人群 &#xff1a;1.对Vue.js 2/3具有上手经验&#xff0c;且希望进一步理解Vue.js框架设计原理的开发人员&#xff1b; 2.没有使用过Vue.js&#xff0c;但对Vue.js框架设计感兴趣…

Loki使用指南

转载至我的博客 https://www.infrastack.cn &#xff0c;公众号&#xff1a;架构成长指南 与其他日志系统相比&#xff0c; Loki 的使用方式是有一定差异性的&#xff0c;需要用不同的思维方式。本文分享一下这些差异以及我们应该如何使用 作为 Loki 用户或操作人员&#xff0…

Leetcode—37. 解数独【困难】

2024每日刷题&#xff08;111&#xff09; Leetcode—37. 解数独 实现代码 class Solution { public:bool isValid(vector<vector<char>>& board, int row, int col, char c) {for(int i 0; i < 9; i) {if(board[row][i] c || board[i][col] c || boar…

最新GPT4.0使用教程,AI绘画,GPT语音对话使用,DALL-E3文生图

一、前言 ChatGPT3.5、GPT4.0、GPT语音对话、Midjourney绘画&#xff0c;文档对话总结DALL-E3文生图&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和…

界面控件DevExpress ASP.NET Spreadsheet组件 - 轻松集成电子表格功能!(一)

DevExpress ASP. NET Spreadsheet组件允许您轻松地将电子表格功能合并到任意ASP. NET应用程序&#xff0c;它可以加载、转换和保存工作簿到XLS-XLSx二进制文件格式&#xff0c;还可以导出和导入XLSX、CSV和TXT文件。 P.S&#xff1a;DevExpress ASP.NET Web Forms Controls拥有…

STM32--SPI通信协议(1)SPI基础知识总结

前言 I2C (Inter-Integrated Circuit)和SPI (Serial Peripheral Interface)是两种常见的串行通信协议&#xff0c;用于连接集成电路芯片之间的通信&#xff0c;选择I2C或SPI取决于具体的应用需求。如果需要较高的传输速度和简单的接口&#xff0c;可以选择SPI。如果需要连接多…

开关电源学习之Buck电路

一、引言 观察上方的电路&#xff0c;当开关闭合到A点时&#xff0c;电流流过电感线圈&#xff0c;形成阻碍电流流过的磁场&#xff0c;即产生相反的电动势&#xff1b;电感L被充磁&#xff0c;流经电感的电流线性增加&#xff0c;在电感未饱和前&#xff0c;电流线性增加&…

零基础Vue框架上手;git,node,yarn安装

项目搭建环境&#xff1a; git安装&#xff1a;Git - 安装 Git (git-scm.com)&#xff08;官网&#xff09; 下载路径&#xff1a;Git - Downloading Package (git-scm.com)&#xff1b;根据自己电脑下载相对应的安装包 ​ 点next ​ 点next&#xff0c;点到最后安装就行。…

航母编队反无人机蜂群作战能力需求分析

源自&#xff1a;指挥控制与仿真 作者&#xff1a;樊辉锦、巫银花、毕月、苏泽亚 “人工智能技术与咨询” 发布 声明:公众号转载的文章及图片出于非商业性的教育和科研目的供大家参考和探讨&#xff0c;并不意味着支持其观点或证实其内容的真实性。版权归原作者所有&#xf…

【DBF格式转换器.exe】

一、概要 DBF文件是一种数据库文件格式&#xff0c;通常用于存储表格数据。这种文件格式曾经被广泛使用&#xff0c;尤其是在一些较旧的数据库系统中。然而&#xff0c;随着时间的推移&#xff0c;其他更现代的文件格式&#xff0c;如XLS&#xff08;Excel&#xff09;、CSV、D…

红日靶场1搭建渗透

环境搭建 下载好镜像文件并解压&#xff0c;启动vmware 这里我用自己的win7 sp1虚拟机作为攻击机&#xff0c;设置为双网卡NAT&#xff0c;vm2 其中用ipconfig查看攻击机ip地址 设置win7 x64为双网卡&#xff0c;vm1&#xff0c;vm2 设置win08单网卡vm1&#xff0c;win2k3为单…
最新文章