使用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.mzph.cn/news/678900.shtml

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

相关文章

指针的基本含义及其用法

1.前言 在学习C语言的时候&#xff0c;我们会经常接触一个概念&#xff0c;指针和地址&#xff0c;关于这两个概念很多人并不能理解地十分透彻&#xff0c;接下来我将详细介绍一下这两者的概念 2.地址 我们知道计算机的上CPU&#xff08;中央处理器&#xff09;在处理数据的时…

C++重新入门-循环

目录 1.循环类型 while循环&#xff1a; for循环 基于范围的for循环(C11) do...while 循环 2.循环控制语句 3.无限循环 有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着…

AI:126-基于深度学习的人体情绪识别与分析

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

react函数组件中使用context

效果 1.在父组件中创建一个createcontext并将他导出 import React, { createContext } from react import Bpp from ./Bpp import Cpp from ./Cpp export let MyContext createContext(我是组件B) export let Ccontext createContext(我是组件C)export default function App…

使用client-only 解决组件不兼容SSR问题

目录 前言 一、解决方案 1.基于Nuxt 框架的SSR应用 2.基于vue2框架的应用 3.基于vue3框架的应用 二、总结 往期回顾 前言 最近在我的单页面SSR应用上开发JSON编辑器功能&#xff0c;在引入组件后直接客户端跳转OK&#xff0c;但是在直接加载服务端渲染的时候一直报这…

Netty应用(六) 之 异步 Channel

目录 12.Netty异步的相关概念 12.1 异步编程的概念 12.2 方式1&#xff1a;主线程阻塞&#xff0c;等待异步线程完成调用&#xff0c;然后主线程发起请求IO 12.3 方式2&#xff1a;主线程注册异步线程&#xff0c;异步线程去回调发起请求IO 12.4 细节注释 12.5 异步的好处…

HiveSQL——用户行为路径分析

注&#xff1a;参考文档&#xff1a; SQL之用户行为路径分析--HQL面试题46【拼多多面试题】_路径分析 sql-CSDN博客文章浏览阅读2k次&#xff0c;点赞6次&#xff0c;收藏19次。目录0 问题描述1 数据分析2 小结0 问题描述已知用户行为表 tracking_log&#xff0c; 大概字段有&…

2.12作业

程序代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h>//递归实现n! int n(int element) {if(0element)return 1;return element*n(element-1); }//递归实现0-n的和 int sub_sum(int element) {if(0element)return 0;return eleme…

计算机二级C语言备考学习记录

一、C语言程序的结构 1.程序的构成&#xff0c;main函数和其他函数。 程序是由main函数和其他函数构成main作为主函数&#xff0c;一个C程序里只有一个main函数其他函数可以分为系统函数和用户函数&#xff0c;系统函数为编译系统提供&#xff0c;用户函数由用户自行编写 2.…

《动手学深度学习(PyTorch版)》笔记7.7

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

重温阿里云宝塔面板部署前后端项目

首先祝大家新年快乐啊&#xff01; 回到老家&#xff0c;便打算趁这一段空闲时间提升一下自己&#xff0c;重点是学习实践一下echarts相关内容&#xff0c;很多公司项目都需要实现可视化&#xff0c;所以在bilibili上找了黑马的一个教程开始学习&#xff0c;不同的是&#xff…

电子电器架构 —— 区域控制器是未来架构的正解吗?

电子电器架构 —— 区域控制器是未来架构的正解吗? 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶…

Linux(Ubuntu) 环境搭建:远程终端软件(MobeXterm)

一、MobaXterm下载地址 服务器的远程终端软件我选择的是&#xff1a;MobaXtermMobaXterm 官方网站下载地址&#xff1a;https://mobaxterm.mobatek.net/download.htmlMobaXterm 汉化版下载地址&#xff1a;https://github.com/RipplePiam/MobaXterm-Chinese-Simplified 二、官…

C# 字体大小的相关问题

设置字体大小无法这么写&#xff0c; button1.Font.Size 20&#xff1b; 这个是只读属性&#xff1b; 把字体大小改为16&#xff0c; button2.Font new Font(button2.Font.Name, 16); 程序运行的时候先看一下窗体和控件的默认字体尺寸&#xff0c;都是9&#xff1b;然后点b…

汽车出租管理系统

文章目录 汽车出租管理系统一、系统演示二、项目介绍三、系统部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 汽车出租管理系统 一、系统演示 汽车租赁系统 二、项目介绍 语言&#xff1a;java 框架&#xff1a;SpringBoot、…

Zabbix报警机制、配置钉钉机器人、自动发现、主动监控概述、配置主动监控、zabbix拓扑图、nginx监控实例

目录 配置告警 用户数超过50&#xff0c;发送告警邮件 实施 验证告警配置 配置钉钉机器人告警 创建钉钉机器人 编写脚本并测试 添加报警媒介类型 为用户添加报警媒介 创建触发器 创建动作 验证 自动发现 配置自动发现 主动监控 配置web2使用主动监控 修改配置文…

《统计学简易速速上手小册》第5章:回归分析(2024 最新版)

文章目录 5.1 线性回归基础5.1.1 基础知识5.1.2 主要案例&#xff1a;员工薪资预测5.1.3 拓展案例 1&#xff1a;广告支出与销售额关系5.1.4 拓展案例 2&#xff1a;房价与多个因素的关系 5.2 多元回归分析5.2.1 基础知识5.2.2 主要案例&#xff1a;企业收益与多因素关系分析5.…

Linux上MySQL安装部署

准备工作 在/opt/software目录下创建mysql目录用来存放MySQL安装包: 链接&#xff1a;https://pan.baidu.com/s/1pjc-w6MSNlpptUjsZXNEdQ?pwd6666 cd /opt/softwaremkdir mysql 将安装包上传到mysql目录 安装部署 &#xff08;1&#xff09;卸载MySQL依赖&#xff0c;虽…

Java图形化界面编程——弹球游戏 笔记

Java也可用于开发一些动画。所谓动画&#xff0c;就是间隔一定的时间(通常小于0 . 1秒 )重新绘制新的图像&#xff0c;两次绘制的图像之间差异较小&#xff0c;肉眼看起来就成了所谓的动画 。 ​ 为了实现间隔一定的时间就重新调用组件的 repaint()方法&#xff0c;可以借助于…

C++ 贪心 区间问题 区间分组

给定 N 个闭区间 [ai,bi] &#xff0c;请你将这些区间分成若干组&#xff0c;使得每组内部的区间两两之间&#xff08;包括端点&#xff09;没有交集&#xff0c;并使得组数尽可能小。 输出最小组数。 输入格式 第一行包含整数 N &#xff0c;表示区间数。 接下来 N 行&…