使用UMAP降维可视化RAG嵌入

大型语言模型(LLMs)如 GPT-4 已经展示了出色的文本理解和生成能力。但它们在处理领域特定信息方面面临挑战,比如当查询超出训练数据范围时,它们会产生错误的答案。LLMs 的推理过程也缺乏透明度,使用户难以理解达成结论的方式。

检索增强生成(RAG)在 LLMS 的工作流程中添加了一个检索步骤,使其能够在响应查询时从其他来源(如私人文本文档)中查询相关数据。这些文档事先分成小段,然后使用embedding的 ML 模型生成嵌入。具有相似内容的段将具有相似的嵌入。当 RAG 应用程序收到一个问题时,它使用查询检索相关文档片段。然后 LLMS 使用这些文档片段作为上下文来回答问题。这种方法可以提供回答查询所需的信息,并通过展示使用的片段来增加回答的透明度。

对于RAG来说,可视化嵌入空间是一个非常重要的方法,因为RAG应用程序使用该空间来查找相关信息。查询的结果与文档片空间息息相关,所以可以使用像UMAP这样的可视化方法,将高维嵌入减少到更易于展示的2D进行可视化。虽然高维嵌入被简化为两个分量,但问题及其相关文档片段在嵌入空间中形成簇,仍然是可以被识别出来,尤其是这时肉眼可见的,所以这有助于深入了解数据的本质。

在本文中,我们将使用HTML格式的Wikipedia中的f1数据集,使用嵌入模型将它们转换为紧凑的矢量表示,并存储到ChromaDB中。使用LangChain构建RAG应用,并在2D中可视化嵌入,分析查询和文档片段之间的关系和接近度。

首先我们安装需要的库

 !pip install langchain langchain-openai chromadb renumics-spotlight

我们使用了Renumics-Spotlight python包,Renumics-Spotlight是一个交互式探索非结构化ML数据集的可视化工具。

而获得嵌入我们则直接使用了OpenAI的embedding-ada-002,所以这里要设置API的Key

 %env OPENAI_API_KEY=<your-api-key>

准备文件

对于数据集是使用wikipedia-api和BeautifulSoup创建的。

本数据集基于维基百科的文章,并在知识共享署名-相同方式共享许可下获得许可。原始文章和作者名单可以在各自的维基百科页面上找到。

将提取的html放到docs/子文件夹中,或者可以通过创建docs/子文件夹的方式将你自己的文件复制到其中来使用自己的Dataset。

创建嵌入

要创建嵌入,首先需要设置嵌入模型和vectorstore。这里我们使用OpenAIEmbeddings中的text- embeddings -ada-002和使用ChromaDB的vectorstore:

 from langchain_openai import OpenAIEmbeddingsfrom langchain.vectorstores.chroma import Chromaembeddings_model = OpenAIEmbeddings(model="text-embedding-ada-002")docs_vectorstore = Chroma(collection_name="docs_store",embedding_function=embeddings_model,persist_directory="docs-db",)

vectorstore将持久化到docs-db 文件夹中。然后使用BSHTMLLoader加载html文档:

 from langchain_community.document_loaders import BSHTMLLoader, DirectoryLoaderloader = DirectoryLoader("docs",glob="*.html",loader_cls=BSHTMLLoader,loader_kwargs={"open_encoding": "utf-8"},recursive=True,show_progress=True,)docs = loader.load()

将文档分成小块

 from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200, add_start_index=True)splits = text_splitter.split_documents(docs)

从元数据重建的id,这样可以在数据库中查找嵌入。

 import hashlibimport jsonfrom langchain_core.documents import Documentdef stable_hash(doc: Document) -> str:"""Stable hash document based on its metadata."""return hashlib.sha1(json.dumps(doc.metadata, sort_keys=True).encode()).hexdigest()split_ids = list(map(stable_hash, splits))docs_vectorstore.add_documents(splits, ids=split_ids)docs_vectorstore.persist()

LangChain

首先,你需要选择一个LLM模型。我们使用GPT-4

 from langchain_openai import ChatOpenAIllm = ChatOpenAI(model="gpt-4", temperature=0.0)retriever = docs_vectorstore.as_retriever(search_kwargs={"k": 20})

在初始化ChatOpenAI模型时,将temperature参数设置为0.0可确保确定性输出。

我们使用下面的提示:

 from langchain_core.prompts import ChatPromptTemplatetemplate = """You are an assistant for question-answering tasks.Given the following extracted parts of a long document and a question, create a final answer with references ("SOURCES").If you don't know the answer, just say that you don't know. Don't try to make up an answer.ALWAYS return a "SOURCES" part in your answer.QUESTION: {question}========={source_documents}=========FINAL ANSWER: """prompt = ChatPromptTemplate.from_template(template)

然后对检索到的文档进行格式化,使其包含页面内容和源文件路径,将这个格式化的输入输入到语言模型(LLM),模型就可以根据合并的用户问题和文档上下文生成答案。

 from typing import Listfrom langchain_core.runnables import RunnableParallel, RunnablePassthroughfrom langchain_core.output_parsers import StrOutputParserdef format_docs(docs: List[Document]) -> str:return "\n\n".join(f"Content: {doc.page_content}\nSource: {doc.metadata['source']}" for doc in docs)rag_chain_from_docs = (RunnablePassthrough.assign(source_documents=(lambda x: format_docs(x["source_documents"])))| prompt| llm| StrOutputParser())rag_chain = RunnableParallel({"source_documents": retriever,"question": RunnablePassthrough(),}).assign(answer=rag_chain_from_docs)

RAG的为问题回答

RAG应用程序现在已经准备好回答问题了:

 question = "Who built the nuerburgring"response = rag_chain.invoke(question)response["answer"]

回答如下:

 'The Nürburgring was built in the 1920s, with the construction of the track beginning in September 1925. The track was designed by the Eichler Architekturbüro from Ravensburg, led by architect Gustav Eichler. The original Nürburgring was intended to be a showcase for German automotive engineering and racing talent (SOURCES: data/docs/Nürburgring.html).'

这个问题也将在下一步中用于进一步得到确认。

可视化

为了进行可视化,我们使用Pandas DataFrame来组织数据。从从矢量存储中提取文本片段及其嵌入。我们还要标出正确的答案:

 import pandas as pdresponse = docs_vectorstore.get(include=["metadatas", "documents", "embeddings"])df = pd.DataFrame({"id": response["ids"],"source": [metadata.get("source") for metadata in response["metadatas"]],"page": [metadata.get("page", -1) for metadata in response["metadatas"]],"document": response["documents"],"embedding": response["embeddings"],})df["contains_answer"] = df["document"].apply(lambda x: "Eichler" in x)df["contains_answer"].to_numpy().nonzero()

问题和相关的答案也被投影到嵌入空间中。它们的处理方式与文本片段相同:

 question_row = pd.DataFrame({"id": "question","question": question,"embedding": embeddings_model.embed_query(question),})answer_row = pd.DataFrame({"id": "answer","answer": answer,"embedding": embeddings_model.embed_query(answer),})df = pd.concat([question_row, answer_row, df])

首先打印问题与文档片段之间的距离:

 import numpy as npquestion_embedding = embeddings_model.embed_query(question)df["dist"] = df.apply(lambda row: np.linalg.norm(np.array(row["embedding"]) - question_embedding),axis=1,)

这个距离还可以用于可视化:

 from renumics import spotlightspotlight.show(df)

上面的语句会打开一个新的浏览器窗口。左上角的表格部分显示数据集的所有字段。右上方的相似性图中突出显示它们。

可以看到,包含正确答案的单个文档片段和最相关的文件离问题和答案很近。

总结

使用降维技术可以使用户和开发人员访问嵌入空间。在可视化空间中,可以通过浏览相邻的数据点来进行检索增强的检查。降维可视化虽然有助于理解数据,但也可能存在信息损失,因为它将高维数据映射到一个较低维度的空间中。因此,在进行检查时,需要权衡信息丢失和效果提升之间的关系。

完整代码:
https://avoid.overfit.cn/post/31e45d66ef1547e397bbbef2ebcf38c8

作者:Markus Stoll

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

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

相关文章

【Linux】make和Makefile

目录 make和Makefile make和Makefile 我们使用vim编辑器的时候&#xff0c;在一个文件里写完代码要进行编译&#xff0c;要自己输入编译的指令。有没有一种可以进行自动化编译的方法——makefile文件&#xff0c;它可以指定具体的编译操作&#xff0c;写好makefile文件&#x…

新零售的升维体验,摸索华为云GaussDB如何实现数据赋能

新零售商业模式 商业模式通常是由客户价值、企业资源和能力、盈利方式三个方面构成。其最主要的用途是为实现客户价值最大化。 商业模式通过把能使企业运行的内外各要素整合起来&#xff0c;从而形成一个完整的、高效率的、具有独特核心竞争力的运行系统&#xff0c;并通过最…

【el-tree 文字过长处理方案】

文字过长处理方案 一、示例代码二、关键代码三、效果图 一、示例代码 <divstyle"height: 600px;overflow: auto"class"text item"><el-treeref"tree":data"treeData":props"defaultProps"class"filter-tree&…

fast.ai 深度学习笔记(四)

深度学习 2&#xff1a;第 2 部分第 8 课 原文&#xff1a;medium.com/hiromi_suenaga/deep-learning-2-part-2-lesson-8-5ae195c49493 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 来自 fast.ai 课程的个人笔记。随着我继续复习课程以“真正”理解它&#xff0c;这…

6.0 Zookeeper session 基本原理详解教程

客户端与服务端之间的连接是基于 TCP 长连接&#xff0c;client 端连接 server 端默认的 2181 端口&#xff0c;也就 是 session 会话。 从第一次连接建立开始&#xff0c;客户端开始会话的生命周期&#xff0c;客户端向服务端的ping包请求&#xff0c;每个会话都可以设置一个…

数据分析基础之《pandas(6)—高级处理》

一、缺失值处理 1、如何处理nan 两种思路&#xff1a; &#xff08;1&#xff09;如果样本量很大&#xff0c;可以删除含有缺失值的样本 &#xff08;2&#xff09;如果要珍惜每一个样本&#xff0c;可以替换/插补&#xff08;计算平均值或中位数&#xff09; 2、判断数据是否…

爬虫练习——动态网页的爬取(股票和百度翻译)

动态网页也是字面意思&#xff1a;实时更新的那种 还有就是你在股票这个网站上&#xff0c;翻页。他的地址是不变的 是动态的加载&#xff0c;真正我不太清楚&#xff0c;只知道他是不变的。如果用静态网页的方法就不可行了。 静态网页的翻页&#xff0c;是网址是有规律的。 …

【正在更新】从零开始认识语音识别:DNN-HMM混合系统语音识别(ASR)原理

摘要 | Abstract TO-BE-FILLED 1.前言 | Introduction 近期想深入了解语音识别(ASR)中隐马尔可夫模型(HMM)和深度神经网络-隐马尔可夫(DNN-HMM)混合模型&#xff0c;但是尽管网络上有许多关于DNN-HMM的介绍&#xff0c;如李宏毅教授的《深度学习人类语言处理》[1]&#xff0c;…

office 2021安装教程(官方自动批量激活,无付费)

全程不需要第三方软件&#xff0c;所有用到的工具都是微软官方的&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 基于KMS的 GVLK&#xff1a;https://learn.microsoft.com/zh-cn/deployoffice/vlactivation/gvlks 首先我们需要去下载 office 软件部署工具&a…

二、数据结构

链表 单链表 https://www.acwing.com/problem/content/828/ #include<iostream> using namespace std; const int N 1e5 10; //head:头节点的指向 e[i]:当前节点i的值 ne[i]:当前节点i的next指针 idx:当前存储的点 int head, e[N], ne[N], idx;//初始化 void i…

01动力云客之环境准备+前端Vite搭建VUE项目入门+引入Element PLUS

1. 技术选型 前端&#xff1a;Html、CSS、JavaScript、Vue、Axios、Element Plus 后端&#xff1a;Spring Boot、Spring Security、MyBatis、MySQL、Redis 相关组件&#xff1a;HiKariCP&#xff08;Spring Boot默认数据库连接池&#xff09;、Spring-Data-Redis&#xff08;S…

【多模态大模型】视觉大模型SAM:如何使模型能够处理任意图像的分割任务?

SAM&#xff1a;如何使模型能够处理任意图像的分割任务&#xff1f; 核心思想起始问题: 如何使模型能够处理任意图像的分割任务&#xff1f;5why分析5so分析 总结子问题1: 如何编码输入图像以适应分割任务&#xff1f;子问题2: 如何处理各种形式的分割提示&#xff1f;子问题3:…

43.1k star, 免费开源的 markdown 编辑器

简介 项目名&#xff1a; MarkText-- 简单而优雅的开源 Markdown 编辑器 Github 开源地址&#xff1a; https://github.com/marktext/marktext 官网&#xff1a; https://www.marktext.cc/ 支持平台&#xff1a; Linux, macOS 以及 Windows。 操作界面&#xff1a; 在操作界…

vueRouter中Hash模式和History模式有什么区别

VueRouter是Vue.js官方推荐的前端路由库&#xff0c;它提供了一种方便的方式来构建单页应用&#xff08;SPA&#xff09;。在使用VueRouter时&#xff0c;我们可以选择不同的路由模式&#xff0c;其中最常见的是Hash模式和History模式。本文将深入探讨这两种模式的区别&#xf…

资产管理系统技术架构设计与实现

资产管理系统在现代金融领域扮演着至关重要的角色。它不仅帮助机构有效管理和优化资产配置&#xff0c;还提供了风险控制、绩效评估等功能。本文将探讨资产管理系统的技术架构设计与实现&#xff0c;以帮助读者深入了解该系统&#xff0c;并为其开发和部署提供参考。 1. 概述资…

【算法与数据结构】496、503、LeetCode下一个更大元素I II

文章目录 一、496、下一个更大元素 I二、503、下一个更大元素II三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、496、下一个更大元素 I 思路分析&#xff1a;本题思路和【算法与数据结构】739、LeetCode每日温度类似…

spring boot和spring cloud项目中配置文件application和bootstrap中的值与对应的配置类绑定处理

在前面的文章基础上 https://blog.csdn.net/zlpzlpzyd/article/details/136065211 加载完文件转换为 Environment 中对应的值之后&#xff0c;接下来需要将对应的值与对应的配置类进行绑定&#xff0c;方便对应的组件取值处理接下来的操作。 对应的配置值与配置类绑定通过 Con…

排序算法---堆排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 堆排序&#xff08;Heap Sort&#xff09;是一种基于二叉堆数据结构的排序算法。它将待排序的元素构建成一个最大堆&#xff08;或最小堆&#xff09;&#xff0c;然后逐步将堆顶元素与堆的最后一个元素交换位置&#xff0c…

AI助力农作物自动采摘,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建作番茄采摘场景下番茄成熟度检测识别计数分析系统

去年十一那会无意间刷到一个视频展示的就是德国机械收割机非常高效自动化地24小时不间断地在超广阔的土地上采摘各种作物&#xff0c;专家设计出来了很多用于采摘不同农作物的大型机械&#xff0c;看着非常震撼&#xff0c;但是我们国内农业的发展还是相对比较滞后的&#xff0…

Mysql-数据库优化-客户端连接参数

客户端参数 原文地址 # 连接池配置 # 初始化连接数 spring.datasource.druid.initial-size1 # 最小空闲连接数&#xff0c;一般设置和initial-size一致 spring.datasource.druid.min-idle1 # 最大活动连接数&#xff0c;一个数据库能够支撑最大的连接数是多少呢&#xff1f; …