使用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 OpenAIEmbeddings
 from langchain.vectorstores.chroma import Chroma
 
 embeddings_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, DirectoryLoader
 loader = 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 RecursiveCharacterTextSplitter
 text_splitter = RecursiveCharacterTextSplitter(
     chunk_size=1000, chunk_overlap=200, add_start_index=True
 )
 splits = text_splitter.split_documents(docs)

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

 import hashlib
 import json
 from langchain_core.documents import Document
 
 def 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 ChatOpenAI
 
 llm = 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 ChatPromptTemplate
 
 template = """
 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 List
 
 from langchain_core.runnables import RunnableParallel, RunnablePassthrough
 from langchain_core.output_parsers import StrOutputParser
 
 
 def 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 pd
 
 response = 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 np
 question_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 spotlight
 spotlight.show(df)

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

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

总结

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

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

作者:Markus Stoll

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

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

相关文章

Qt之条件变量QWaitCondition详解

QWaitCondition内部实现结构图&#xff1a; 相关系列文章 C之Pimpl惯用法 目录 1.简介 2.示例 2.1.全局配置 2.2.生产者Producer 2.3.消费者Consumer 2.4.测试例子 3.原理分析 3.1.辅助函数CreateEvent 3.2.辅助函数WaitForSingleObject 3.3.QWaitConditionEvent …

C++笔记1:操纵符输入输出

C操纵符用来控制输出控制&#xff0c;一是输出的形式&#xff0c;二是控制补白的数量和位置。本文记录一下&#xff0c;在一些笔试的ACM模式可能有用。其中1-4节的部分是关于格式化输入输出操作&#xff0c;5-6节的部分是关于未格式化输入输出操作。 1. 控制布尔值的格式 一般…

uniapp API文档地址 以及 HBuilder安装

uniapp API文档地址 以及 HBuilder安装 一、进入 当前网站 uni-app 官网 [uni-app](https://zh.uniapp.dcloud.io/quickstart-hx.html)二、点击截图下载文件 三、 进入 当前网站 &#xff08;https://www.dcloud.io/hbuilderx.html&#xff09; 浏览器会识别 也可以自行选择…

基于GIS、RS、VORS模型、CCDM模型、geodetecto、GWR模型集成的生态系统健康的耦合协调分析

详情点击公众号&#xff1a;技术科研吧 链接&#xff1a;基于GIS、RS、VORS模型、CCDM模型、geodetecto、GWR模型集成的生态系统健康的耦合协调分析 前沿 当空间大数据、云计算与人工智能发生碰撞,地理服务产业也不断发生变革与进步。ArcGIS Pro 是一个专业的桌面 GIS 应用程…

17 外排序

排序分为内排序和外排序&#xff0c;内排序是在内存中的排序。外排序指在磁盘中文件的排序&#xff0c;因为在磁盘中&#xff0c;不能进行下标访问&#xff0c;归并排序经常用于磁盘中文件的排序 假如有10亿个整形数据在磁盘中&#xff0c;要对它排序&#xff0c;内存中只有1G…

水果FL Studio21.2最新中文版功能特点介绍

FL Studio 21的特点和优势包括&#xff1a; 丰富的主题换肤&#xff1a;用户可以通过调整色调、饱和度、亮度、文本、仪表和步进序列器的颜色&#xff0c;来个性化定制FL Studio 21的外观&#xff0c;使其更符合个人审美或工作风格。更快的音频编辑&#xff1a;FL Studio 21集…

AI少女/HS2甜心选择2 仿剑三剑灵人物卡全合集打包

AI少女/HS2甜心选择2 仿剑三剑灵人物卡全合集打包 内含&#xff1a;菩提禅音[剑网3]明教晓天喵姐[剑3]明教晓天喵姐无帽版[剑3]茱莉亚[剑灵] 下载地址&#xff1a; https://www.changyouzuhao.cn/12492.html

软件价值12-射箭游戏

射箭游戏&#xff0c;按空格键发射&#xff0c;打击移动靶&#xff0c;左上角显示成绩状态。 代码&#xff1a; import pygame import sys import random# 初始化Pygame pygame.init()# 设置窗口大小 SCREEN_WIDTH 800 SCREEN_HEIGHT 600 screen pygame.display.set_mode((…

【开源】基于JAVA+Vue+SpringBoot的就医保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 科室档案模块2.2 医生档案模块2.3 预约挂号模块2.4 我的挂号模块 三、系统展示四、核心代码4.1 用户查询全部医生4.2 新增医生4.3 查询科室4.4 新增号源4.5 预约号源 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVue…

DS:树及二叉树的相关概念

创作不易&#xff0c;兄弟们来波三连吧&#xff01;&#xff01; 一、树的概念及结构 1.1 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c…

利用Cloudflare Workers实现网页状态监控

首先 Fork cf-workers-status-page 浏览器地址栏输入 https://deploy.workers.cloudflare.com/?urlhttps://github.com/$YourUserName/cf-workers-status-page 获取 Cloudflare 账户内的 Account ID 和 API Token 授权的 token 需要 workes 的编辑权限 在 Github actio…

LeetCode二叉树的垂序遍历

题目描述 给你二叉树的根结点 root &#xff0c;请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言&#xff0c;其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二叉树的 垂序遍历 从最左边的列开始直到…

DolphinScheduler安装与配置

DolphinScheduler概述 Apache DolphinScheduler是一个分布式、易扩展的可视化DAG工作流任务调度平台。致力于解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。 DolphinScheduler的主要角色如下&#xff1a; MasterServer采用分布式无…

CPython:表达式的求值顺序(evaluation order)

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 C中表达式的求值 C语言针对表达式的计算&#xff0c;设置了操作符的优先级和结合性这两个特性&#xff0c;优先级用于解析不同优先级的符号&#xff0c;结合性用于解析…

【基础】第K大与第K小数

说明 给定一个长度为N(0< n< 10000)的序列&#xff0c;保证每一个序列中的数字a[i]是正整数 &#xff0c;编程要求求出整个序列中第k大的数字减去第k小的数字的值m&#xff0c;并判断m是否为质数。(0< k< n) 输入数据 第一行为2个数n&#xff0c;k&#xff08;…

【北邮鲁鹏老师计算机视觉课程笔记】10 Classification 分类

【北邮鲁鹏老师计算机视觉课程笔记】10 Classification 分类 1 图像识别的基本范式 检测问题&#xff1a;不仅要知道有没有&#xff0c;还要知道在哪里 分类是整图级标签&#xff0c;检测是区域级标签&#xff0c;分割是像素级标签 2 检测任务的应用 3 单实例识别与类别识别…

《Linux 简易速速上手小册》第3章: 文件系统与权限(2024 最新版)

文章目录 3.1 Linux 文件系统结构3.1.1 重点基础知识3.1.2 重点案例&#xff1a;设置一个 Web 服务器3.1.3 拓展案例 1&#xff1a;日志文件分析3.1.3 拓展案例 2&#xff1a;备份用户数据 3.2 理解文件权限3.2.1 重点基础知识3.2.2 重点案例&#xff1a;共享项目文件夹3.2.3 拓…

java学习08---面向对象

一 类和对象 1 类和对象的理解 客观存在的事物皆为对象 &#xff0c;所以我们也常常说万物皆对象。 类 简单理解&#xff1a;类就是对现实事物的一种描述 类是对象的数据类型&#xff0c;类是具有相同属性和行为的一组对象的集合 类是对现实生活中一类具有共同属性和行为的事…

Python教程56:海龟画图turtle画kitty猫

---------------turtle源码集合--------------- Python教程91&#xff1a;关于海龟画图&#xff0c;Turtle模块需要学习的知识点 Python教程51&#xff1a;海龟画图turtle画&#xff08;三角形、正方形、五边形、六边形、圆、同心圆、边切圆&#xff0c;五角星&#xff0c;椭…

【python量化交易】qteasy使用教程02 - 获取和管理金融数据

qteasy教程2 - 获取并管理金融数据 qteasy教程2 - 获取并管理金融数据开始前的准备工作获取基础数据以及价格数据下载交易日历和基础数据查看股票和指数的基础数据下载沪市股票数据从本地获取股价数据生成K线图 数据类型的查找定期下载数据到本地回顾总结 qteasy教程2 - 获取并…