LLM之RAG实战(八)| 使用Neo4j和LlamaIndex实现多模态RAG

       人工智能和大型语言模型领域正在迅速发展。一年前,没有人使用LLM来提高生产力。时至今日,很难想象我们大多数人或多或少都在使用LLM提供服务,从个人助手到文生图场景。由于大量的研究和兴趣,LLM每天都在变得越来越好、越来越聪明。不仅如此,他们的理解也开始跨越多种模态。随着GPT-4-Vision和随后的其他LLM的引入,今天的LLM似乎可以很好地处理和理解图像。以下是ChatGPT描述图像中内容的一个示例。

       正如所观察到的,ChatGPT非常善于理解和描述图像。我们可以在RAG应用程序中使用其理解图像的能力,在该应用程序中,我们现在可以将文本和图片中的信息结合起来,生成比以往任何时候都更准确的答案,而不仅仅依靠文本来生成准确和最新的答案。使用LlamaIndex,实现多模态RAG pipeline非常容易。受(https://github.com/run-llama/llama_index/blob/main/docs/examples/multi_modal/gpt4v_multi_modal_retrieval.ipynb)的启发,来测试是否可以使用Neo4j作为数据库来实现多模态RAG应用程序。

       要使用LlamaIndex实现多模态RAG管道,只需实例化两个矢量存储,一个用于图像,另一个用于文本,然后查询这两个矢量,以便检索相关信息以生成最终答案。

       多模态RAG首先需要将数据分为图像和文本,然后分别进行embedding并单独构建索引。对于文本,我们将使用ada-002文本嵌入模型;而对于图像,我们将采用[双编码器模型CLIP](https://github.com/openai/CLIP),CLIP可以将文本和图像嵌入到同一嵌入空间中。当最终用户提出问题时,执行两个向量的相似性搜索:一个用于查找相关图像,另一个用于文档。结果被输入到多模态LLM中,该LLM为用户生成答案,展示了处理和利用混合媒体进行信息检索和响应生成的综合方法。

数据预处理

        我们将使用[Medium](https://github.com/tomasonjo/blog-datasets/blob/main/articles.zip)作为RAG应用程序的基础数据集。这些文章包含了关于Neo4j图形数据科学库以及将Neo4j与LLM框架相结合的大量信息。从Medium下载的文章是HTML格式。因此,我们需要使用一些编码来分别提取文本和图像。

def process_html_file(file_path):    with open(file_path, "r", encoding="utf-8") as file:        soup = BeautifulSoup(file, "html.parser")    # Find the required section    content_section = soup.find("section", {"data-field": "body", "class": "e-content"})    if not content_section:        return "Section not found."    sections = []    current_section = {"header": "", "content": "", "source": file_path.split("/")[-1]}    images = []    header_found = False    for element in content_section.find_all(recursive=True):        if element.name in ["h1", "h2", "h3", "h4"]:            if header_found and (current_section["content"].strip()):                sections.append(current_section)            current_section = {                "header": element.get_text(),                "content": "",                "source": file_path.split("/")[-1],            }            header_found = True        elif header_found:            if element.name == "pre":                current_section["content"] += f"```{element.get_text().strip()}```\n"            elif element.name == "img":                img_src = element.get("src")                img_caption = element.find_next("figcaption")                caption_text = img_caption.get_text().strip() if img_caption else ""                images.append(ImageDocument(image_url=img_src))            elif element.name in ["p", "span", "a"]:                current_section["content"] += element.get_text().strip() + "\n"    if current_section["content"].strip():        sections.append(current_section)    return images, sections

       不会详细介绍解析代码,但我们根据标题h1–h4分割文本并提取图像链接。然后,我们只需通过此函数运行所有文章,即可提取所有相关信息。

all_documents = []all_images = []# Directory to search in (current working directory)directory = os.getcwd()# Walking through the directoryfor root, dirs, files in os.walk(directory):    for file in files:        if file.endswith(".html"):            # Update the file path to be relative to the current directory            images, documents = process_html_file(os.path.join(root, file))            all_documents.extend(documents)            all_images.extend(images)text_docs = [Document(text=el.pop("content"), metadata=el) for el in all_documents]print(f"Text document count: {len(text_docs)}") # Text document count: 252print(f"Image document count: {len(all_images)}") # Image document count: 328

       总共得到252个文本块和328个图像。

对数据创建索引

       如前所述,我们必须实例化两个矢量存储,一个用于图像,另一个用于文本。CLIP嵌入模型的尺寸为512,而ada-002的尺寸为1536。

text_store = Neo4jVectorStore(    url=NEO4J_URI,    username=NEO4J_USERNAME,    password=NEO4J_PASSWORD,    index_name="text_collection",    node_label="Chunk",    embedding_dimension=1536)image_store = Neo4jVectorStore(    url=NEO4J_URI,    username=NEO4J_USERNAME,    password=NEO4J_PASSWORD,    index_name="image_collection",    node_label="Image",    embedding_dimension=512)storage_context = StorageContext.from_defaults(vector_store=text_store)

      现在向量索引已经创建好了,我们使用MultiModalVectorStoreIndex来索引这两种模态的信息。

# Takes 10 min without GPU / 1 min with GPU on Google collabindex = MultiModalVectorStoreIndex.from_documents(    text_docs + all_images, storage_context=storage_context, image_vector_store=image_store)

       MultiModalVectorStoreIndex使用文本和图像嵌入模型来计算嵌入,并在Neo4j中存储和索引结果。仅为图像存储URL,而不是实际的base64或图像的其他表示。

多模态RAG pipeline

       这段代码是直接从LlamaIndex多模式烹饪书中复制的。我们首先定义一个多模态LLM和prompt template,然后将所有内容组合为一个查询引擎。

openai_mm_llm = OpenAIMultiModal(    model="gpt-4-vision-preview", max_new_tokens=1500)qa_tmpl_str = (    "Context information is below.\n"    "---------------------\n"    "{context_str}\n"    "---------------------\n"    "Given the context information and not prior knowledge, "    "answer the query.\n"    "Query: {query_str}\n"    "Answer: ")qa_tmpl = PromptTemplate(qa_tmpl_str)query_engine = index.as_query_engine(    multi_modal_llm=openai_mm_llm, text_qa_template=qa_tmpl)

       现在我们可以继续测试它的性能了。

query_str = "How do vector RAG application work?"response = query_engine.query(query_str)print(response)

        我们还可以可视化检索提取的图像以及用于帮助提供最终答案的图像。

       LLM得到了两个相同的图像作为输入,说明数据集中有重复的图。然而,我对CLIP嵌入感到惊喜,因为他们能够检索到该系列中最相关的图像。在生产环境中,一般需要对数据做预处理,去除重复数据,本文不做此介绍。

结论

       LLM的发展速度比我们历史上习惯的要快,并且跨越了多种模态。我坚信,到明年年底,LLM将很快能够理解视频,因此能够在与你交谈时获得非语言提示。另一方面,我们可以使用图像作为RAG管道的输入,并增强传递给LLM的各种信息,使响应更好、更准确。使用LlamaIndex和Neo4j实现多模式RAG管道非常简单。

参考文献:

[1] https://blog.llamaindex.ai/multimodal-rag-pipeline-with-llamaindex-and-neo4j-a2c542eb0206

[2] https://github.com/tomasonjo/blogs/blob/master/llm/neo4j_llama_multimodal.ipynb

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

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

相关文章

[node]Node.js 模块系统

[node]模块系统 Node.js中的模块系统模块的使用模块的导入模块的导出导出多个值导出默认值导出可传参的函数 文件查找策略从文件模块缓存中加载从原生模块加载从文件加载 Node.js中的模块系统 为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。 …

【第七在线】数据分析与人工智能在商品计划中的应用

随着技术的不断进步,数据分析和人工智能(AI)已经成为了现代商品计划的关键组成部分。在服装行业,这两项技术正在帮助企业更好地理解市场需求、优化库存管理、提高生产效率和提供更好的客户体验。本文将深入探讨数据分析和人工智能…

华为---登录USG6000V防火墙---console、web、telnet、ssh方式登录

目录 一、环境搭建 二、第一次登录USG6000V防火墙,即通过console方式登录 三、用户配置 四、web登录USG6000V防火墙 1. 用web创建的用户通过web方式登录USG6000V防火墙 2. 命令行创建的用户通过web方式登录USG6000V防火墙 五、ssh方式登录USG6000V防火墙 1. 用…

从CTF中学习自增构造webshell

FLAG:那天晚上和你聊了很久,手机烫的和心脏一样 专研方向: 代码审计,Crypto 每日emo:天一亮,时间就不属于我了 从CTF中学习自增构造webshell 前言1.异或2.自增3.取反青少年CTF之ezbypass 前言 今天写了几道代码审计的…

Android MVI架构之UI状态的持有与保存

Android MVI架构之UI状态的持有与保存 我们将介绍状态持有者和其他与 UI 层相关的主题,例如在 Android 上提升状态和保存 UI 状态的位置。 状态持有者 状态持有者通过处理逻辑和/或公开 UI 状态来简化 UI。在本节中,我们将看到如何实现状态持有者以及…

Deepin更换仿Mac主题

上一篇博客说了要写一篇deepin系统的美化教程 先看效果图: 准备工作: 1.你自己 嘻嘻嘻 2.能上网的deepin15.11电脑 首先去下载主题 本次需要系统美化3部分:1.图标 2.光标 3.壁纸 开始之前,请先把你的窗口特效打开,…

深度解析LinkedList

LinkedList是Java集合框架中List接口的实现之一,它以双向链表的形式存储元素。与传统的数组相比,链表具有更高的灵活性,特别适用于频繁的插入和删除操作。让我们从底层实现开始深入了解这个强大的数据结构。 底层数据结构 LinkedList的底层数…

天猫数据分析(软件工具)-2023年11月天猫保健品行业分析报告:市场需求扩容,年轻人是主流群体

近年来,随着健康经济、颜值经济的兴起,越来越多的年轻人加入养生大军,成为保健食品市场上的一股新力量,带动市场扩容。根据鲸参谋电商数据分析平台的相关数据显示,今年11月份,天猫平台上保健食品的销量为24…

YOLOv8改进 | 主干篇 | 利用MobileNetV3替换Backbone(轻量化网络结构)

一、本文介绍 本文给大家带来的改进机制是MobileNetV3,其主要改进思想集中在结合硬件感知的网络架构搜索(NAS)和NetAdapt算法,以优化移动设备CPU上的性能。它采用了新颖的架构设计,包括反转残差结构和线性瓶颈层&…

Unity | HybridCLR 热更新(Windows端)

目录 一、准备工作 1.环境相关 2.Unity中配置 二、热更新 1.创建 HotUpdate 热更新模块 2.安装和配置HybridCLR 3.配置PlayerSettings 4.创建热更新相关脚本 5.打包dll 6.测试热更新 一、准备工作 1.环境相关 安装git环境。Win下需要安装visual studio 2019或更高版…

使用Aspose.Slides 控件,在线将 ODP 转换为 PPT

OpenOffice 等开源生产力工具有其用途。但如果您希望在线将 ODP 转换为 PPT,您很可能已经确定 Microsoft PowerPoint 的专有 PPT 格式和平台比 OpenOffice ODP 更适合您的需求。 本文的第一部分重点介绍在线将 ODP 转换为 PPT 的快速方法。第二部分探讨涉及C#应用程…

R语言中使用ggplot2绘制散点图箱线图,附加显著性检验

散点图可以直观反映数据的分布,箱线图可以展示均值等关键统计量,二者结合能够清晰呈现数据蕴含的信息。 本篇笔记主要内容:介绍R语言中绘制箱线图和散点图的方法,以及二者结合展示教程,添加差异比较显著性分析&#xf…

27.Java程序设计-基于Springboot的在线考试系统小程序设计与实现

1. 引言 随着数字化教育的发展,在线考试系统成为教育领域的一项重要工具。本论文旨在介绍一个基于Spring Boot框架的在线考试系统小程序的设计与实现。在线考试系统的开发旨在提高考试的效率,简化管理流程,并提供更好的用户体验。 2. 系统设…

UG阵列特征

阵列特征:将一个或多个特征,沿线性方向阵列复制图形 实体建模时建议草图尽可能简单,能特征阵列的别草图阵列 阵列特征命令在如下位置:菜单-插入-关联复制-阵列特征 当我们只需要选中的特征沿着一个或两个方向进行阵列的时候&…

Day68力扣打卡

打卡记录 得到山形数组的最少删除次数&#xff08;线性DP 前后缀分解&#xff09; 链接 class Solution:def minimumMountainRemovals(self, nums: List[int]) -> int:n len(nums)pre, suf [1] * n, [1] * nfor i in range(n):for j in range(i):if nums[j] < nums[…

Go 随机密码

一.Go实现随机密码 随机密码 package mainimport ("fmt""math/rand""os""strconv""time" )func RandomPassword(num int) {length : numif len(os.Args) > 1 {arg : os.Args[1]i, err : strconv.ParseInt(arg, 10, 6…

HarmonyOS - macOS 上搭建 鸿蒙开发环境

文章目录 安装 DevEco第一个 App1、工程基本信息设置2、安装设备3、运行工程 安装 DevEco 软件下载地址&#xff1a; https://developer.harmonyos.com/cn/develop/deveco-studio 今天我下载 DevEco Studio 3.1.1 Release - Mac 版本 解压后是一个 dmg 文件&#xff08;也不必…

Grafana高可用-LDAP

一. grafana高可用 1. 迁移之前的 grafana sqlitedump.sh #!/bin/bash DB$1 TABLES$(sqlite3 $DB .tables | sed -r s/(\S)\s(\S)/\1\n\2/g | grep -v migration_log) for t in $TABLES; doecho "TRUNCATE TABLE $t;" done for t in $TABLES; doecho -e ".mode…

Linux中vim中进行替换/批量替换

Linux中vim中进行替换/批量替换 一:在 Vim 中进行文本替换的操作是通过使用 :s&#xff08;substitute&#xff09;命令来实现的。这里是一些基本的替换命令 替换当前行的第一个匹配项: :s/old/new/这将替换当前行中第一个出现的 “old” 为 “new”。 替换当前行的所有匹配项…

Linux ContOS7 日志管理(rsyslog)

目录 01. rsyslog 记录日志程序 02.日志文件 03.日志等级 Linux 日志文件是记录 Linux 系统运行信息的文件。它们类似于人类的日记&#xff0c;记录了系统的各种活动&#xff0c;如用户登录、进程启动、错误消息等。 Linux 日志文件通常存储在 /var/log/ 目录中。该目录包含…