RAG技术下的文档智能检索

在数字化浪潮的推动下,信息检索已成为我们日常生活中不可或缺的一部分。然而,随着数据量的爆炸式增长,如何快速精准地从海量文档中检索出有价值的信息,成为了一个巨大的挑战。本文将带您走进 Pinecone 向量数据库的世界,探索如何利用这一前沿技术,结合检索增强生成(RAG)模型,实现对自定义文档的高效查询。这不仅是技术的飞跃,更是对传统检索方式的一次深刻革新。

向量数据库

向量数据库(Vector DB)现在非常流行。像 GPT-4o、Llama-3、Claude3.5 等大语言模型(LLMs)正基于专业使用案例和行业特定数据准备被行业采用。检索增强生成(RAG)—— 在推理期间将输入增强为与输入提示相关的数据,对于这些使用案例来说是一个令人兴奋的范式。

向量数据库提供了一种快速查询大量数据以找到最相关文档块的方法。与传统数据库相比,向量数据库在查询大维文本嵌入方面是高效的。

image.png

文档嵌入和标记化

首先处理文档的第一步是将其分成块,并获取每个块的嵌入。对于嵌入模型,我们使用的是北京智源人工智能研究院的嵌入模型“BGE-M3”,它是 1024 维的。

接下来,我们定义分块中允许的最大 Token。每个 Token 约为一个词的 3/4。通常,正确的数量是一个探索点,只能通过反复试验找到。如果预期答案遍布文档中的小文本部分,则较小的分块尺寸效果更好。较大的分块则更适合于更长、更详细的描述。较大的分块会倾向于从一个或几个较长的部分检索数据,而较短的部分则会偏向于具有有限上下文的较短文本片段。

python
复制代码
def get_embedding(text, model="BAAI/bge-m3"):# 替换换行符为空格text = text.replace("\n", " ")# 使用指定模型获取嵌入return client.embeddings.create(input=[text], model=model).data[0].embeddingdef tokenize(text, max_tokens) -> pd.DataFrame:""" 将文本拆分为最大令牌数的块 """# 加载适用于bge-m3模型的分词器tokenizer = tiktoken.get_encoding("cl100k_base")df = pd.DataFrame({'title': ['0'], 'text': [text]})# 对文本进行分词,并保存令牌数量到新列中df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))shortened = []# 遍历数据框for _, row in df.iterrows():# 如果文本为空,跳到下一行if row['text'] is None:continue# 如果令牌数大于最大令牌数,将文本拆分为多个块if row['n_tokens'] > max_tokens:shortened += split_into_many(row['text'], tokenizer, max_tokens)else:shortened.append(row['text'])df = pd.DataFrame(shortened, columns=['text'])df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))df['embeddings'] = df.text.apply(lambda x: get_embedding(x))return dfdef split_into_many(text: str, tokenizer: tiktoken.Encoding, max_tokens: int = 1024) -> list:""" 将字符串拆分为指定数量令牌的多个字符串 """# 将文本拆分为句子sentences = text.split(' ')# 获取每个句子的令牌数n_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]chunks = []tokens_so_far = 0chunk = []# 遍历句子和令牌数的元组for sentence, token in zip(sentences, n_tokens):chunk.append(sentence)tokens_so_far += token + 1# 如果令牌数加上当前句子的令牌数大于最大令牌数,将块添加到块列表中并重置if tokens_so_far + token > max_tokens:chunks.append(" ".join(chunk))chunk = []tokens_so_far = 0return chunksdf = tokenize(text, 100)

这里是一个最大块大小为 100 个标记的示例数据框架:

image.png

创建向量数据库索引并上传数据

创建了数据框架后,就可以为嵌入创建索引,并将它们上传到 Pinecone 数据库中。这里注意,因为 Pinecone 不允许一次性添加大量的块,所以意味着需要一些批处理过程。

python
复制代码def __init__(self, batch_size: int = 10) -> None:self.batch_size = batch_size# 从输入DataFrame中生成块def to_batches(self, df: pd.DataFrame) -> Iterator[pd.DataFrame]:splits = self.splits_num(df.shape[0])if splits <= 1:yield dfelse:for chunk in np.array_split(df, splits):yield chunk# 确定DataFrame包含多少块def splits_num(self, elements: int) -> int:return round(elements / self.batch_size)__call__ = to_batchesdf_batcher = BatchGenerator(300)index_name = 'overview-of-nvidia'# Check whether the index with the same name already exists - if so, delete it
if index_name in pc.list_indexes():pc.delete_index(index_name)pc.create_index(index_name, dimension=len(df['content_vector'][0]), spec=ServerlessSpec(cloud="aws",region="us-east-1"))index = pc.Index(name=index_name)# 上传内容向量
for batch_df in df_batcher(df):index.upsert(vectors=zip(batch_df.vector_id, batch_df.content_vector))

查询数据库

添加向量之后,只需要输入一个相同维度(1024)的查询向量,以找到具有最接近嵌入和相似度分数的行。下面的函数将这些行映射到原始数据框,并提供文本和余弦相似度。

ini
复制代码
content_mapped = dict(zip(df.vector_id,df.text))# 使用指定命名空间中的标题查询文章并打印结果。
def query_article(query, top_k=3):# 基于标题列创建向量嵌入embedded_query = client.embeddings.create(input = [query], model="BAAI/bge-m3").data[0].embedding# 使用标题向量作为参数传递的查询命名空间query_result = index.query(vector=embedded_query,top_k=3)# 查询结果print(f'\n查询结果: {query}')if not query_result.matches:print('没有查询结果')matches = query_result.matchesids = [res.id for res in matches]scores = [res.score for res in matches]df = pd.DataFrame({'id':ids,'score':scores,'content': [content_mapped[_id] for _id in ids],})counter = 0for k,v in df.iterrows():counter += 1print(f'{v.content} (score = {v.score})')print('\n')return df

查询及结果如下:

image.png

Pinecone 并非唯一的向量数据库提供者,还有如 Weviate、Chroma 等,它们都采用类似的架构来创建索引、上传和查询文档。像 Langchain 和 Llamaindex 这样的框架抽象了大部分样板代码,有助于简化对 RAG 的采用。

结语

跟随本文的介绍,我们见证了 Pinecone 向量数据库在文档检索领域的强大潜力。通过 RAG 技术,我们不仅提升了检索的速度和准确性,更开启了对文档深层次理解和应用的新视角。这项技术的运用,不仅限于信息检索,更可能成为推动各行各业智能化转型的关键力量。在未来,我们有理由相信,向量数据库和 RAG 技术将在构建更加智能、高效的信息生态系统中发挥更加重要的作用。

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

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

相关文章

AIGC到底如何改变创意设计?

在当今数字化时代&#xff0c;AIGC&#xff08;生成式人工智能&#xff09;技术的崛起对创意设计领域产生了深远的影响。AIGC不仅为设计师提供了新的工具和方法&#xff0c;还改变了传统的设计流程和思维方式。 传统的设计过程中&#xff0c;设计师需要耗费大量时间在绘图、修…

npm install puppeteer 报错 npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated解决办法

npm install puppeteer 报错如下&#xff1a; npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated. Use PUPPETEER_DOWNLOAD_BASE_URL instead. npm ERR! Error: ERROR: Failed to set up Chrome v126.0.6478.126! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to sk…

【Linux进程】僵尸进程与孤儿进程

前言 僵尸进程和孤儿进程是Linux中极为重要的两个种进程状态, 本文将会围绕这三个问题: 是什么? 为什么? 如何产生的? 详细的介绍这两种进程; 以及一些使用场景. 僵尸进程 在了解孤儿进程之前, 需要先引入僵尸进程的概念; 什么是僵尸进程? 僵尸进程: 就是处于僵死状态的进…

揭秘代理IP:原理、优势与应用场景全面解析

随着数字化进程的加速&#xff0c;网络安全已经成为现代社会不可或缺的一环。无论是政府机构、企业还是个人用户&#xff0c;都面临着越来越多的网络威胁。本文将深入探讨网络安全的重要性、面临的主要威胁以及应对策略&#xff0c;旨在为读者提供一个全面的网络安全视角。 1.…

黑马点评学习过程汇总——Cookie \ Session \ Token的区别

1. Cookie \ Session \ Token的区别 10分钟助你弄懂cookie、session、token 区别、用途&#xff01;&#xff01;&#xff01;_哔哩哔哩_bilibili &#xff08;1&#xff09;为什么要使用Cookie 在客户端和服务端之间维持用户登录状态 &#xff08;2&#xff09;为什么不能只…

类似Jira的在线项目管理软件有哪些?10 个主流的Jira替代方案

10 个 Jira 替代方案&#xff1a;PingCode、Worktile、Teambition、Redmine、Asana、monday.com、Zoho Projects、思码逸、Notion、Airtable。 Jira 是一款流行的项目管理工具&#xff0c;专为产品开发团队而设计。虽然它是一种多功能解决方案&#xff0c;几乎适用于任何类型的…

Git 操作补充:变基

变基 在 Git 中&#xff0c;整合来自不同分支的修改&#xff0c;除了 merge&#xff0c;还有一种方法&#xff0c;变基 rebase。git rebase 命令基本是是一个自动化的 cherry-pick 命令&#xff0c;它计算出一系列的提交&#xff0c;然后在其他地方以同样的顺序一个一个的 che…

流程表单设计器开源优势多 助力实现流程化!

实现流程化办公是很多职场企业的发展目标。应用什么样的软件可以实现这一目的&#xff1f;低代码技术平台、流程表单设计器开源的优势特点多&#xff0c;在推动企业降本增效、流程化办公的过程中作用明显&#xff0c;是理想的软件平台。那么&#xff0c;流程表单设计器开源的优…

编译Open Cascade(OCC)并使用C#进行开发

说明&#xff1a; VS版本&#xff1a;Visual Studio Community 2022系统&#xff1a;Windows 11 专业版23H2Open CASCADE&#xff1a;v7.7.0&#xff08;链接&#xff1a;https://pan.baidu.com/s/1-o1s4z3cjpYf5XkwhSDspQ?pwdp9i5提取码&#xff1a;p9i5&#xff09; 下载和…

Julia精解【1】

文章目录 转换类型伴随矩阵 转换类型 在Julia中&#xff0c;可以使用内置函数来转换或者调整数据类型。以下是一些常用的数据类型转换方法&#xff1a; 转换类型 Int(): 将浮点数或字符串转换为整数。Float(): 将整数或字符串转换为浮点数。String(): 将其他类型转换为字符串…

阐述pandabuy淘宝代购集运系统在国外用户采购中国商品重要性丨类似淘宝代购集运系统搭建经验

Pandabuy淘宝代购集运系统在国外用户采购中国商品中的重要性&#xff0c;主要体现在以下几个方面&#xff1a; 一、满足多样化需求 Pandabuy系统为海外消费者提供了一个便捷的渠道&#xff0c;使他们能够轻松购买到来自中国电商平台的商品&#xff0c;如淘宝、天猫、京东等。…

python数据分析入门学习笔记

目录 一、 数据分析有关的python库简介 (一)numpy (二)pandas (三)matplotlib (四)scipy (五)statsmodels (六)scikit-learn 二、 数据的导入和导出 三、 数据筛选 四、 数据描述 五、 数据处理 六、 统计分析 七、 可视化 八、 其它![](https://…

windows电脑蓝屏解决方法(亲测有效)

如果不是硬件问题&#xff0c;打开终端尝试以下命令 sfc /scannow DISM /Online /Cleanup-Image /RestoreHealth

关于敏捷研发

文章目录 前言瀑布流和敏捷研发流程瀑布流研发流程缺点 敏捷研发流程 前言 关于敏捷研发。 瀑布流和敏捷研发流程 瀑布流研发流程 1.需求 2.设计 3.开发 4.测试 缺点 流程之间关联性很强&#xff0c;容易卡住风险不好预估&#xff0c;工时不好预估&#xff0c;如 2 个月的…

nodejs sqlite模块

SQLite 是一个轻量级的嵌入式数据库&#xff0c;它在 Node.js 中的使用通常是异步的。这意味着当你执行数据库操作时&#xff0c;例如创建表、插入数据或查询数据&#xff0c;这些操作会被放入事件队列中异步执行&#xff0c;而不会阻塞主线程。 安装sqlite3 npm install sql…

If you already have a 64-bit JDK installed ,defined a JAVA_HOME...的错误

今天感觉idea有点卡&#xff0c;修改了一下内存&#xff0c;结果就报这个错误了&#xff0c;网上的解决方案好多&#xff0c;都不行 以下是解决方案 打开 C:\Program Files\JetBrains\IntelliJ IDEA 2024.1.4\bin\jetbrains_client64.exe 把jihuo这个目录下所有的文件都删掉&…

通过easyexcel导入数据,添加表格参数的校验,同表格内校验以及和已有数据的校验

引入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.11</version><scope>compile</scope></dependency> 需要导入到某个目录下 如果产品名称相同&#xff0c…

Mybatis数据封装

目录 解决方案&#xff1a; 1.起别名&#xff1a; 2.手动结果映射&#xff1a; 3.开启驼峰命名(推荐)&#xff1a; 我们看到查询返回的结果中大部分字段是有值的&#xff0c;但是deptId&#xff0c;createTime&#xff0c;updateTime这几个字段是没有值的&#xff0c;而数据…

分析数据不要太老实,有BI方案就用起来——奥威BI软件

在当今数据驱动的时代&#xff0c;企业对于数据分析的需求日益迫切。然而&#xff0c;面对海量的数据和复杂的分析需求&#xff0c;许多企业仍停留在传统的手工分析模式&#xff0c;这不仅效率低下&#xff0c;还容易出错。幸运的是&#xff0c;像奥威BI这样的数据分析软件提供…

Linux——互斥与同步练习

用多线程程序设计一个火车票售票系统&#xff0c; 要求至少有两个售票窗口&#xff0c;每个售票窗口 不能重复买票&#xff0c;将100张车票均匀的从两个 窗口卖出即可。 ./a.out 窗口1 卖出车票 1 窗口2 卖出车票 2 窗口1 卖出车票 3 窗口2 卖出车票 4 ..... #include <std…