使用 Milvus、vLLM 和 Llama 3.1 搭建 RAG 应用

6462cc77060ce4b6c28954945d4c2b3e.png

68643a4d7c934ec5ea89118c51aa7190.png

vLLM 是一个简单易用的 LLM 推理服务库。加州大学伯克利分校于 2024 年 7 月将 vLLM 作为孵化项目正式捐赠给 LF AI & Data Foundation 基金会。欢迎 vLLM 加入 LF AI & Data 大家庭!🎉

在主流的 AI 应用架构中,大语言模型(LLM)通常与向量数据库配套使用,用于构建检索增强生成(RAG)应用,从而解决 AI 幻觉问题。本文将介绍如何使用 Milvus、vLLM 和 Llama 3.1 构建并运行RAG 应用。我们将详细展示如何将文本信息转换为 Embedding 向量并存储到 Milvus 向量数据库中、如何将 Milvus 作为知识库有效检索与用户问题相关的文本块。最后,我们将通过 vLLM 使用 Meta的Llama 3.1-8B 模型生成答案。

01

Milvus、vLLM 和 Llama 3.1 简介

Milvus 向量数据库

Milvus 是一款开源的分布式向量数据库,可用于存储、索引和搜索向量数据,适用于生成式 AI(GenAI)应用。Milvus 支持 hybrid search、元数据过滤、重排(Reranking),能够高效处理万亿规模的向量,助力开发者搭建 AI 和 ML 应用。您可以在本地运行 Milvus standalone 或 cluster 版本,或者使用全托管的 Milvus 服务——Zilliz Cloud。

vLLM

vLLM 是加州大学伯克利分校 SkyLab 推出的一个开源项目,专注于优化 LLM 服务性能。通过高效的内存管理技术,如 PagedAttention、持续批处理和优化 CUDA 内核,vLLm 与传统方法相比将服务性能提高了多达 24 倍,同时将 GPU 内存用量减少了一半。

根据论文《Efficient Memory Management for Large Language Model Serving with PagedAttention》,KV 缓存使用约 30% 的 GPU 内存,可能会导致内存问题。KV 缓存存储在连续内存(contiguous memory)中,但内存变化可能导致内存碎片化,不利于计算效率。

d680b206e72f6685b07999eec68eec9b.png

通过使用虚拟内存缓存 KV,vLLM 只需要在必要时分配物理 GPU 内存,有效避免了内存碎片化和内存预分配。在测试中,vLLM 的吞吐量比 HuggingFace Transformers (HF) 高出多达 24 倍,比基于NVIDIA A10G 和 A100 GPU 的 Text Generation Inference (TGI) 高出 3.5 倍。

e8e77e8390e9fbbee05becd0ee9799cf.jpeg

Meta Llama 3.1

Meta 于 2024 年 7 月 23 日宣布推出 Llama 3.1,允许用于多种商业用途。其 405B 模型(4050 亿参数)在多个公开的性能测试中均展示出了最出色的性能,并支持 128,000 个输入 Token 的上下文窗口。除了 405B 模型外,Meta 还发布了 Llama3.1 70B(700 亿参数)和 8B(80 亿参数)模型。您可以通过 Meta 官网下载模型权重(model weight)。

需要注意微调生成的数据可以提高模型性能,但低质量的数据可能会降低模型性能。Llama 团队已不断识别和去除这些低质量的数据,使用模型本身及其他辅助模型和工具,进一步优化模型。

02

使用 Milvus 搭建 RAG-Retrieval部分

准备数据

本教程将使用 Milvus 文档作为数据集。我们需要先下载并本地保存 Milvus 文档。

from langchain.document_loaders import DirectoryLoader# Load HTML files already saved in a local directorypath = "../../RAG/rtdocs_new/"global_pattern = '*.html'loader = DirectoryLoader(path=path, glob=global_pattern)docs = loader.load()# Print num documents and a preview.print(f"loaded {len(docs)} documents")print(docs[0].page_content)pprint.pprint(docs[0].metadata)

3545032b6f53a0850df8888c7549ae12.png

下载 Embedding 模型

接着,从 HuggingFace 上下载一个免费的开源 Embedding 模型。

import torchfrom sentence_transformers import SentenceTransformer# Initialize torch settings for device-agnostic code.N_GPU = torch.cuda.device_count()DEVICE = torch.device('cuda:N_GPU' if torch.cuda.is_available() else 'cpu')# Download the model from huggingface model hub.model_name = "BAAI/bge-large-en-v1.5"encoder = SentenceTransformer(model_name, device=DEVICE)# Get the model parameters and save for later.EMBEDDING_DIM = encoder.get_sentence_embedding_dimension()MAX_SEQ_LENGTH_IN_TOKENS = encoder.get_max_seq_length()# Inspect model parameters.print(f"model_name: {model_name}")print(f"EMBEDDING_DIM: {EMBEDDING_DIM}")print(f"MAX_SEQ_LENGTH: {MAX_SEQ_LENGTH}")

d0513a10245cb2df47a3a967fcddea62.png

切分数据并编码为向量

将文档数据切分成固定长度(512 个字符)的文本块,并将切分 overlap 设置为 10%。

from langchain.text_splitter import RecursiveCharacterTextSplitterCHUNK_SIZE = 512chunk_overlap = np.round(CHUNK_SIZE * 0.10, 0)print(f"chunk_size: {CHUNK_SIZE}, chunk_overlap: {chunk_overlap}")# Define the splitter.child_splitter = RecursiveCharacterTextSplitter(chunk_size=CHUNK_SIZE,chunk_overlap=chunk_overlap)# Chunk the docs.chunks = child_splitter.split_documents(docs)print(f"{len(docs)} docs split into {len(chunks)} child documents.")# Encoder input is doc.page_content as strings.list_of_strings = [doc.page_content for doc in chunks if hasattr(doc, 'page_content')]# Embedding inference using HuggingFace encoder.embeddings = torch.tensor(encoder.encode(list_of_strings))# Normalize the embeddings.embeddings = np.array(embeddings / np.linalg.norm(embeddings))# Milvus expects a list of `numpy.ndarray` of `numpy.float32` numbers.converted_values = list(map(np.float32, embeddings))# Create dict_list for Milvus insertion.dict_list = []for chunk, vector in zip(chunks, converted_values):# Assemble embedding vector, original text chunk, metadata.chunk_dict = {'chunk': chunk.page_content,'source': chunk.metadata.get('source', ""),'vector': vector,}dict_list.append(chunk_dict)

235b31787284e54aac9392de962b3b1e.png

将向量数据存储在 Milvus 中

将向量存储到 Milvus 向量数据库中。

# Connect a client to the Milvus Lite server.from pymilvus import MilvusClientmc = MilvusClient("milvus_demo.db")# Create a collection with flexible schema and AUTOINDEX.COLLECTION_NAME = "MilvusDocs"mc.create_collection(COLLECTION_NAME,EMBEDDING_DIM,consistency_level="Eventually",auto_id=True, overwrite=True)# Insert data into the Milvus collection.print("Start inserting entities")start_time = time.time()mc.insert(COLLECTION_NAME,data=dict_list,progress_bar=True)end_time = time.time()print(f"Milvus insert time for {len(dict_list)} vectors: ", end="")print(f"{round(end_time - start_time, 2)} seconds")

5f42e2174c532e9c36b5f09c9df7946f.png

进行向量搜索

输入问题,并在 Milvus 知识库中搜索与问题最相似的文本块。

SAMPLE_QUESTION = "What do the parameters for HNSW mean?"# Embed the question using the same encoder.query_embeddings = torch.tensor(encoder.encode(SAMPLE_QUESTION))# Normalize embeddings to unit length.query_embeddings = F.normalize(query_embeddings, p=2, dim=1)# Convert the embeddings to list of list of np.float32.query_embeddings = list(map(np.float32, query_embeddings))# Define metadata fields you can filter on.OUTPUT_FIELDS = list(dict_list[0].keys())OUTPUT_FIELDS.remove('vector')# Define how many top-k results you want to retrieve.TOP_K = 2# Run semantic vector search using your query and the vector database.results = mc.search(COLLECTION_NAME,data=query_embeddings,output_fields=OUTPUT_FIELDS,limit=TOP_K,consistency_level="Eventually")

搜索结果如下所示:

b5815f45bcb446e84e704b253b0799be.png

03

使用 vLLM 和 Llama 3.1-8B 搭建 RAG-Generation 部分

安装 vLLM 与 HuggingFace 模型

vLLM 默认从 HuggingFace 下载大语言模型。通常情况下,如果您想使用 HuggingFace 上的新模型,需要执行 pip install --update 或 -U。此外,我们还需要 GPU 通过 vLLM 来运行 Meta 的 Llama 3.1 推理模型。

# (Recommended) Create a new conda environment.conda create -n myenv python=3.11 -yconda activate myenv# Install vLLM with CUDA 12.1.pip install -U vllm transformers torch
import vllm, torchfrom vllm import LLM, SamplingParams# Clear the GPU memory cache.torch.cuda.empty_cache()# Check the GPU.!nvidia-smi

获取 HuggingFace token

HuggingFace 上的部分模型(如 Meta Llama 3.1)要求用户在下载前接受其许可证。因此,您必须先创建一个 HuggingFace 帐户,接受模型的许可证,并生成一个 Token。

在 HuggingFace 的 Llama3.1 页上,您会收到一条消息要求您同意条款。单击"Accept License"以接受 Meta 条款,然后再下载模型权重。审批流程通常可以在一天内完成。

审批通过后,需要生成一个新的 HuggingFace token。旧 Token 无法使用。

在安装 vLLM 之前,请使用您的新 Token 登录 HuggingFace。以下示例代码中使用 Colab Secrets 来存储 Token。

# Login to HuggingFace using your new token.from huggingface_hub import loginfrom google.colab import userdatahf_token = userdata.get('HF_TOKEN')login(token = hf_token, add_to_git_credential=True)

运行 RAG-Generation 部分

我们需要 GPU 和较大的内存来运行 Llama-3.1-8B 模型。以下示例是在 Google Colab Pro上使用 A100 GPU 运行的。

# 1. Choose a modelMODELTORUN = "meta-llama/Meta-Llama-3.1-8B-Instruct"# 2. Clear the GPU memory cache, you're going to need it all!torch.cuda.empty_cache()# 3. Instantiate a vLLM model instance.llm = LLM(model=MODELTORUN,enforce_eager=True,dtype=torch.bfloat16,gpu_memory_utilization=0.5,max_model_len=1000,seed=415,max_num_batched_tokens=3000)

17e4ea8d96a1028f0180c0da3ac65bff.png

# Separate all the context together by space.contexts_combined = ' '.join(contexts)# Lance Martin, LangChain, says put the best contexts at the end.contexts_combined = ' '.join(reversed(contexts))# Separate all the unique sources together by comma.source_combined = ' '.join(reversed(list(dict.fromkeys(sources))))SYSTEM_PROMPT = f"""First, check if the provided Context is relevant tothe user's question.  Second, only if the provided Context is strongly relevant, answer the question using the Context.  Otherwise, if the Context is not strongly relevant, answer the question without using the Context. Be clear, concise, relevant.  Answer clearly, in fewer than 2 sentences.Grounding sources: {source_combined}Context: {contexts_combined}User's question: {SAMPLE_QUESTION}"""prompts = [SYSTEM_PROMPT]

使用从 Milvus 中检索获得的上下文和原始提问来编写提示,并生成回答。

# Sampling parameterssampling_params = SamplingParams(temperature=0.2, top_p=0.95)# Invoke the vLLM model.outputs = llm.generate(prompts, sampling_params)# Print the outputs.for output in outputs:prompt = output.promptgenerated_text = output.outputs[0].text# !r calls repr(), which prints a string inside quotes.print()print(f"Question: {SAMPLE_QUESTION!r}")pprint.pprint(f"Generated text: {generated_text!r}")

32c91276542560b35797fd5d449a33ee.png

答案十分准确!

如果您对文本内容感兴趣,欢迎上手亲自尝试和实践。同时,我们欢迎您加入 Milvus 社区,与所有 GenAI 开发者共同交流。

参考

vLLM 官方文档及模型页面

https://docs.vllm.ai/en/latest/getting_started/installation.html

https://docs.vllm.ai/en/latest/models/supported_models.html#supported-models

2023 vLLM 论文

https://arxiv.org/pdf/2309.06180

2023 Ray Summit vLLM 相关演讲

https://www.youtube.com/watch?v=80bIUggRJf4

vLLM 博客: vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention

https://blog.vllm.ai/2023/06/20/vllm.html

介绍如何运行 vLLM server 的博客文章: Deploying vLLM: a Step-by-Step Guide

https://ploomber.io/blog/vllm-deploy/

The Llama 3 Herd of Models | Research - AI at Meta

https://ai.meta.com/research/publications/the-llama-3-herd-of-models/

推荐阅读

d66b5ed0234240d64b2e99c1f2cfedb7.png

a6c5c7393bc5b250991bb7af5fe7ac2a.png

966b8dd21bf0430839de82e09ffd1077.png

cc1c130dbe560d05f6604ee4b5cfcd1d.png

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

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

相关文章

电离层闪烁

电离层闪烁,有的时候有有的时候无,但是经常出现,导致导航信号的振幅和相位发生变化,影响导航精度。使得载噪比降低。定位精度降低。 电离层闪烁的大小从几米到几百米,所以在使用RTK时,就算是相隔很近的基站…

OKHttp实现原理分享

前言介绍 大约在2年半之前,就想写一篇关于OKHttp原理的文章,一来深入了解一下其原理,二来希望能在了解原理之后进行更好的使用。但是因为种种原因,一直无限往后推迟,最近因为我们情景智能半个月一次的分享轮到我了&…

【鸿蒙】HarmonyOS NEXT星河入门到实战1-开发环境准备

目录 一、达成目标 二、鸿蒙开发环境准备 2.1 开发者工作下载 2.2 解压安装 2.3 运行配置安装node.js和SDK 2.4 开始创建第一个项目 2.5 预览 2.5.1 预览遇到的问题(报错) 2.5.2 修改内容查看预览 三、备用下载地址(如果下载是4.X版…

Prism库:详解其核心组件和使用方法

Prism库简介 Prism库是一个开源项目,由 Microsoft 社区开发和维护。它是一组用于创建 WPF、UWP 和 Xamarin 应用程序的工具和库,提供了一种基于模块化和依赖注入的架构模式,同时它提供了一系列的工具,帮助开发人员构建可扩展、可…

MATLAB、FPGA、STM32中调用FFT计算频率、幅值及相位差

系列文章目录 文章目录 系列文章目录前言MATLABSTM32调用DSPSTM32中实现FFT关于初相位 FPGA 前言 最近在学习如何在STM32中调用FFT MATLAB 首先对FFT进行一下说明,我们输入N个点的数据到FFT中,FFT会返回N个点的数据,这些数据都是复数&#…

ctfshow-PHP反序列化

web254 源码 <?php/* # -*- coding: utf-8 -*- # Author: h1xa # Date: 2020-12-02 17:44:47 # Last Modified by: h1xa # Last Modified time: 2020-12-02 19:29:02 # email: h1xactfer.com # link: https://ctfer.com //mytime 2023-12-4 0:22 */ error_reporting(0)…

MATLAB | R2024b更新了哪些好玩的东西?

Hey, 又到了一年两度的MATLAB更新时刻&#xff0c;MATLAB R2024b正式版发布啦&#xff01;&#xff0c;直接来看看有哪些我认为比较有意思的更新吧! 1 小提琴图 天塌了&#xff0c;我这两天才写了个半小提琴图咋画&#xff0c;MATLAB 官方就出了小提琴图绘制方法。 小提琴图…

鸿蒙读书笔记1:《鸿蒙操作系统设计原理与架构》

笔记来自新书&#xff1a;《鸿蒙操作系统设计原理与架构》 HarmonyOS采用分层架构&#xff0c;从下到 上依次分为内核层、系统服务层、框架层和应用层。 1. 内核层 内核层主要提供硬件资源抽象和常用软件资源&#xff0c;包括进程/线程管 理、内存管理、文件系统和IPC&#xff…

Unity教程(十五)敌人战斗状态的实现

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

react js 路由 Router

完整的项目,我已经上传了 资料链接 起因, 目的: 路由, 这部分很难。 原因是, 多个组件,进行交互,复杂度比较高。 我看的视频教程 1. 初步使用 安装: npm install react-router-dom 修改 index.js/ 或是 main.js 把 App, 用 BrowserRouter 包裹起来 2. Navigate 点击…

redis基本数据类型和常见命令

引言 Redis是典型的key-value&#xff08;键值型&#xff09;数据库&#xff0c;key一般是字符串&#xff0c;而value包含很多不同的数据类型&#xff1a; Redis为了方便我们学习&#xff0c;将操作不同数据类型的命令也做了分组&#xff0c;在官网&#xff08; Commands | Do…

TS 常用类型

我们经常说TypeScript是JavaScript的一个超级 TypeScript 常用类型 TypeScript 是 JS 的超集&#xff0c;TS 提供了 JS 的所有功能&#xff0c;并且额外的增加了&#xff1a;类型系统 所有的 JS 代码都是 TS 代码 JS 有类型&#xff08;比如&#xff0c;number/string 等&…

《JavaEE进阶》----14.<SpringMVC配置文件实践之【验证码项目】>

本篇博客介绍的是Google的开源项目Kaptcha来实现的验证码。 这种是最简单的验证码。 也是很常见的一种验证码。可以去看项目结果展示。就可以明白这个项目了。 前言&#xff1a; 随着安全性的要求越来越高、很多项目都使用了验证码。如今验证码的形式也是有许许多多、更复杂的图…

基于SpringBoot的古城墙景区管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的古城墙景区管理系…

2024数学建模国赛官方评阅标准发布!

​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑​↑…

C++类与对象(下)--最后的收尾

内部类 • 如果⼀个类定义在另⼀个类的内部&#xff0c;这个内部类就叫做内部类。内部类是⼀个独⽴的类&#xff0c;跟定义在 全局相⽐&#xff0c;他只是受外部类类域限制和访问限定符限制&#xff0c;所以外部类定义的对象中不包含内部类。 #include<iostream> using…

安装FTP服务器教程

一。安装vsftpd yum install vsftpd 二。修改配置文件&#xff0c;匿名账户具有访问&#xff0c;上传和创建目录的权限 vim /etc/vsftpd/vsftpd.conf &#xff08;红色进行设置放开YES&#xff09; local_enable&#xff1a;本地登陆控制&#xff0c;no表示禁止&#xff0c;ye…

3. 轴指令(omron 机器自动化控制器)——>MC_MoveAbsolute

机器自动化控制器——第三章 轴指令 4 MC_MoveAbsolute变量▶输入变量▶输入输出变量▶输入输出变量 功能说明▶指令详情▶时序图▶重启运动指令▶多重启动运动指令▶异常 示例程序1▶参数设定▶动作示例▶梯形图▶结构文本(ST) 示例程序2▶参数设定▶动作示例▶梯形图▶结构文…

RDMA应用场景及效果

GPU Direct 参考&#xff1a;网络架构如何支持超万卡的大规模 AI 训练&#xff1f;| AICon_芯片与网络_InfoQ精选文章 GPU 网络的情况已经发生了很大变化。每个 GPU 都有自己的内部互联&#xff0c;例如 NVIDIA 的 A100 或 H800&#xff0c;它们内部的 NVLink 互联可以达到 6…

单个 java 虚拟机 生产者消费者

一、通过 java.lang.Object#wait()&#xff0c;java.lang.Object#notify&#xff0c;java.lang.Object#notifyAll来实现 生产者&#xff0c;消费者 public abstract class Goods {protected String type;protected String goodName;protected int number;public abstract …