spRAG框架学习小结

 spRAG是什么

  spRAG是一个针对非结构化数据的检索引擎。它特别擅长处理对密集文本的复杂查询,比如财务报告、法律文件和学术论文。有两种关键方法用于提高性能,超越了普通的RAG系统:

自动上下文(AutoContext):自动上下文的实现相当直接,首先生成文档的1-2句话摘要,将文件名添加进去,然后在嵌入之前将这些内容添加到每个文本块的前面。
相关段落提取(Relevant Segment Extraction, RSE):相关段落提取(RSE)是一个后处理步骤,它将相关文本块的集群智能地组合成长文本段落,我们称之为段落。这些段落比任何单独的文本块都能为LLM提供更好的上下文。对于简单的事实问题,答案通常包含在单个文本块中;但对于更复杂的问题,答案通常跨越更长的文本段落。RSE的目标是智能地识别提供最相关信息的文本段落,而不受固定长度文本块的限制。

spRAG使用

  spRAG的使用非常简单,安装sprag后,只需下面简单的几行代码,即可基于pdf文档内容进行问题检索。

from sprag.create_kb import create_kb_from_filefile_path = "spRAG/tests/data/levels_of_agi.pdf"
kb_id = "levels_of_agi"
kb = create_kb_from_file(kb_id, file_path)
search_queries = ["What are the levels of AGI?", "What is the highest level of AGI?"]
results = kb.query(search_queries)
for segment in results:print(segment)

    默认情况下,spRAG使用OpenAI进行嵌入,使用Claude 3 Haiku进行自动上下文处理,并使用Cohere进行重新排序。所以,如果要使用spRAG需要同时申请这三种大模型的key。如果只用OpenAI需要编写更多的代码,具体如下所示:下面的代码中通过OpenAIChatAPI来设置自动文本提取的llm使用openAI,重新排序这里,设置的NoReranker,经过下面的修改,即便只有OPENAI的key,也能正常使用spRAG了。

from sprag.llm import OpenAIChatAPI
from sprag.reranker import NoRerankerllm = OpenAIChatAPI(model='gpt-3.5-turbo')
reranker = NoReranker()kb = KnowledgeBase(kb_id="levels_of_agi", reranker=reranker, auto_context_model=llm)

spRAG实现原理

  实际spRAG的source code如下图所示,并不复杂,首先看vector_db部分,vector_db_connectors文件夹里面是直接使用第三方vectorDB工具weavite,对文档进行向量存储,添加,删除,以及查询等操作。外面的vector_db.py也定义了增加,删除文档,检索内容等方法,这个module会被vector_db_connectors中的python文件继承。

    在vector_db.py问中,封装了两种search方法,第一种是使用余玄相识度来进行内容检索,方法二是调用knn中的exhuastive_search方法来进行检索。

  以上就是向量存储方法的内容,接着看Ebedding的source code,这里没有啥复杂度,直接调用的各个LLM提供的SDK,生成向量即可。以下图为例,这里调用OpenAI提供的SDK来对输入的内容生成向量。

class OpenAIEmbedding(Embedding):def __init__(self, model: str = "text-embedding-3-small", dimension: int = 768):"""Only v3 models are supported."""super().__init__(dimension)self.model = modelself.client = OpenAI()def get_embeddings(self, text, input_type=None):response = self.client.embeddings.create(input=text, model=self.model, dimensions=int(self.dimension))embeddings = [embedding_item.embedding for embedding_item in response.data]return embeddings[0] if isinstance(text, str) else embeddingsdef to_dict(self):base_dict = super().to_dict()base_dict.update({'model': self.model})return base_dict

  接着来看看比较关键的自动上下文提取是如何实现的。下面的代码就是auto_context的source code,这段代码使用LLM生成简明扼要的文档描述,描述包含文档的标题和内容概要,并确保处理大文档时内容不会超出限制。具体代码内容,如下所示:

from sprag.llm import LLM
import tiktokenPROMPT = """
INSTRUCTIONS
What is the following document, and what is it about? Your response should be a single sentence, and it shouldn't be an excessively long sentence. DO NOT respond with anything else.You MUST include the name of the document in your response (if available), as that is a critical piece of information. Be as specific and detailed as possible in your document name. You can even include things like the author's name or the date of publication if that information is available. DO NOT just use the filename as the document name. It needs to be a descriptive and human-readable name.Your response should take the form of "This document is: X, and is about: Y". For example, if the document is a book about the history of the United States called A People's History of the United States, your response might be "This document is: A People's History of the United States, and is about the history of the United States, covering the period from 1776 to the present day." If the document is the 2023 Form 10-K for Apple Inc., your response might be "This document is: Apple Inc. FY2023 Form 10-K, and is about: the financial performance and operations of Apple Inc. during the fiscal year 2023."{auto_context_guidance}{truncation_message}DOCUMENT
filename: {document_title}{document}
""".strip()TRUNCATION_MESSAGE = """
Also note that the document text provided below is just the first ~4500 words of the document. Your response should still pertain to the entire document, not just the text provided below.
""".strip()def truncate_content(content: str, max_tokens: int):TOKEN_ENCODER = tiktoken.encoding_for_model('gpt-3.5-turbo')tokens = TOKEN_ENCODER.encode(content, disallowed_special=())truncated_tokens = tokens[:max_tokens]return TOKEN_ENCODER.decode(truncated_tokens), min(len(tokens), max_tokens)def get_document_context(auto_context_model: LLM, text: str, document_title: str, auto_context_guidance: str = ""):# truncate the content if it's too longmax_content_tokens = 6000 # if this number changes, also update the truncation message abovetext, num_tokens = truncate_content(text, max_content_tokens)if num_tokens < max_content_tokens:truncation_message = ""else:truncation_message = TRUNCATION_MESSAGE# get document contextprompt = PROMPT.format(auto_context_guidance=auto_context_guidance, document=text, document_title=document_title, truncation_message=truncation_message)chat_messages = [{"role": "user", "content": prompt}]document_context = auto_context_model.make_llm_call(chat_messages)return document_contextdef get_chunk_header(file_name, document_context):chunk_header = f"Document context: the following excerpt is from {file_name}. {document_context}"return chunk_header

    以上是一些比较关键的source code简要说明,接下来看看如何从调用入口开始,看看加载文件后,如何完成对文档的检索的。代码的source code封装的方法create_kb_from_file,就是使用spRAG的入口方法。可看到这个方法中,根据文件的后缀进行了不同的处理,总体而言,通过这样的处理,让spRAG可以支持多种文件格式。kb这个对象实际就是KnowlegeBase这个class的实例化。

def create_kb_from_file(kb_id: str, file_path: str, title: str = None, description: str = "", language: str = 'en', auto_context: bool = True, auto_context_guidance: str = ""):"""- kb_id is the name of the knowledge base- file_path is the absolute path to the file containing the documentsSupported file types: .docx, .md, .txt, .pdf"""if not title:title = kb_id# create a new KBkb = KnowledgeBase(kb_id, title=title, description=description, language=language, exists_ok=False)print (f'Creating KB with id {kb_id}...')file_name = os.path.basename(file_path)# add documentif file_path.endswith(('.docx', '.md', '.txt', '.pdf')):# define clean file path as just the file name here since we're not using a directoryclean_file_path = file_nameif file_path.endswith('.docx'):text = extract_text_from_docx(file_path)elif file_name.endswith('.pdf'):text = extract_text_from_pdf(file_path)elif file_path.endswith('.md') or file_path.endswith('.txt'):with open(file_path, 'r') as f:text = f.read()kb.add_document(clean_file_path, text, auto_context=auto_context, auto_context_guidance=auto_context_guidance)else:print (f"Unsupported file type: {file_name}")returnreturn kb

KnowlegeBase中包含两个重要方法

  add_document方法是将一个新文档添加到知识库中。首先验证参数的有效性,确保auto_context和chunk_header不同时设置,并检查文档ID的唯一性。如果启用了自动上下文生成,会通过LLM生成文档上下文描述并设置小块头信息。接着,它将文档文本拆分为小块,添加头信息后生成嵌入向量,然后将小块及其嵌入向量添加到数据库中,最后保存数据库以确保数据持久化。也就是前面提到的很关键的自动化上下文能力,具体的source code如下所示:

def add_document(self, doc_id: str, text: str, auto_context: bool = True, chunk_header: str = None, auto_context_guidance: str = ""):# verify that only one of auto_context and chunk_header is settry:assert auto_context != (chunk_header is not None)except:print ("Error in add_document: only one of auto_context and chunk_header can be set")# verify that the document does not already exist in the KBif doc_id in self.chunk_db.get_all_doc_ids():print (f"Document with ID {doc_id} already exists in the KB. Skipping...")return# AutoContextif auto_context:document_context = get_document_context(self.auto_context_model, text, document_title=doc_id, auto_context_guidance=auto_context_guidance)chunk_header = get_chunk_header(file_name=doc_id, document_context=document_context)elif chunk_header:passelse:chunk_header = ""chunks = self.split_into_chunks(text)print (f'Adding {len(chunks)} chunks to the database')# add chunk headers to the chunks before embedding themchunks_to_embed = []for i, chunk in enumerate(chunks):chunk_to_embed = f'[{chunk_header}]\n{chunk}'chunks_to_embed.append(chunk_to_embed)# embed the chunksif len(chunks) <= 50:# if the document is short, we can get all the embeddings at oncechunk_embeddings = self.get_embeddings(chunks_to_embed, input_type="document")else:# if the document is long, we need to get the embeddings in chunkschunk_embeddings = []for i in range(0, len(chunks), 50):chunk_embeddings += self.get_embeddings(chunks_to_embed[i:i+50], input_type="document")assert len(chunks) == len(chunk_embeddings) == len(chunks_to_embed)self.chunk_db.add_document(doc_id, {i: {'chunk_text': chunk, 'chunk_header': chunk_header} for i, chunk in enumerate(chunks)})# create metadata listmetadata = []for i, chunk in enumerate(chunks):metadata.append({'doc_id': doc_id, 'chunk_index': i, 'chunk_header': chunk_header, 'chunk_text': chunk})# add the vectors and metadata to the vector databaseself.vector_db.add_vectors(vectors=chunk_embeddings, metadata=metadata)self.save() # save the database to disk after adding a document

  再来看看search方法,search方法总体比较简单,首先就是调用常规的vector_db.search进行查询,获取到多个结果,再将问题和首次查询到的结果传递给rerank_search,进行二次查询,从而提高查询的准确率。

def search(self, query: str, top_k: int) -> list:"""Get top k most relevant chunks for a given query. This is where we interface with the vector database.- returns a list of dictionaries, where each dictionary has the following keys: `metadata` (which contains 'doc_id', 'chunk_index', 'chunk_text', and 'chunk_header') and `similarity`"""query_vector = self.get_embeddings(query, input_type="query") # embed the querysearch_results = self.vector_db.search(query_vector, top_k) # do a vector database searchsearch_results = self.reranker.rerank_search_results(query, search_results) # rerank search results using a rerankerreturn search_results

  以上就是对开源框架spRAG的学习小结。更多内容可查看官网。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

SQLServer Manager Studio扩展开发从入门到弃坑

Visualstudio的已经开发好了&#xff0c;可这个就是不行&#xff0c;直接运行点这些按钮加载失败&#xff0c;而我直接不调试模式&#xff0c;则直接什么都没有&#xff0c;调试 发现是根本没触发逻辑的。 文档资料太少&#xff0c; 我换了几个ssms.exe都不行&#xff0c;18-20…

【电路笔记】-AB类放大器

AB类放大器 文章目录 AB类放大器1、概述2、AB类放大器介绍3、AB类放大器效率4、偏置方法4.1 电压偏置4.2 分压网络4.3 电位器偏置4.4 二极管偏置5、二极管网络和电流源6、AB类放大器的电源分配7、总结1、概述 A类放大器提供非常好的输出线性度,这意味着可以忠实地再现信号,但…

Nacos架构设计

Nacos1.X架构设计 Nacos2.X架构修改

[240707] X-CMD v0.3.14: cb gh fjo zig 模块增强;新增 lsio 和 pixi 模块

目录 X-CMD 发布 v0.3.14✨ advise&#xff1a;Bash 环境下自动补全时&#xff0c;提供命令的描述信息✨ cb:支持下载指定版本的附件资源✨ gh:支持下载指定版本的附件资源✨ fjo:支持下载指定版本的附件资源✨ zig&#xff1a;新增 pm 和 zon 子命令✨ lsio&#xff1a;用于查…

Raylib 坐标系

draftx 符号调整为正数 发现采样坐标系原点0&#xff0c;0 在左上角&#xff0c;正方向 右&#xff0c;下 绘制坐标系 原点0&#xff0c;0 在左下角&#xff0c;正方向 右&#xff0c;上 拖拽可得 #include <raylib.h> // 重整原因&#xff1a;解决新函数放大缩小之下…

华媒舍:8种网站构建推广方法全揭密!

网站构建成为了推广宣传和宣传品牌的关键一环。对于新手&#xff0c;搭建和营销推广网站有可能是一项全新的挑战。下面我们就为大家介绍8种网站搭建和营销推广技巧&#xff0c;帮助你在这些方面取得成功。 1.选择适合自己的网站构建平台选择合适的网站构建平台针对构建一个成功…

阿里云ecs服务器,nginx多域名多项目部署教程,含本地部署教程

nginx多域名部署项目 本地部署线上部署 一、本地部署 第一步&#xff1a; winr 输入drivers 打开hosts文件&#xff0c;编辑 加行 127.0.0.1 自定义域名 … 第二步&#xff1a; 下载 nginx 安装好以后 打开ngin安装目录&#xff0c;选择nginx.conf 打开 #user Administ…

【Transformer】transformer模型结构学习笔记

文章目录 1. transformer架构2. transformer子层解析3. transformer注意力机制4. transformer部分释疑 图1 transformer模型架构 图2 transformer主要模块简介 图3 encoder-decoder示意图N6 图4 encoder-decoder子层示意图 1. transformer架构 encoder-decoder框架是一种处理NL…

ZYNQ-LINUX环境C语言利用Curl库实现HTTP通讯

前言 在Zynq-Linux环境中&#xff0c;需要使用C语言来编写APP时&#xff0c;访问HTTP一般可以使用Curl库来实现&#xff0c;但是在Zynq的SDK中&#xff0c;并没有集成该库&#xff0c;在寻找了很多资料后找到了一种使用很方便的额办法。这篇文章主要记录一下移植Curl的过程。 …

一招解决找不到d3dcompiler43.dll,无法继续执行代码问题

当您的电脑遇到d3dcompiler43.dll缺失问题时&#xff0c;首先需要了解d3dcompiler43.dll文件及其可能导致问题的原因&#xff0c;之后便可以选择合适的解决方案。在此&#xff0c;我们将会为您提供寻找d3dcompiler43.dll文件的多种处理方法。 一、d3dcompiler43.dll文件分析 d…

C++入门7——string类详解

目录 1.什么是string类&#xff1f; 2.string类对象的常见构造 2.1 string(); 2.2 string (const char* s); 2.3 string (const string& str); 2.4 string (const string& str, size_t pos, size_t len npos); 2.5 string (const char* s, size_t n); 2.7 验证…

绝区肆--2024 年AI安全状况

前言 随着人工智能系统变得越来越强大和普及&#xff0c;与之相关的安全问题也越来越多。让我们来看看 2024 年人工智能安全的现状——评估威胁、分析漏洞、审查有前景的防御策略&#xff0c;并推测这一关键领域的未来可能如何。 主要的人工智能安全威胁 人工智能系统和应用程…

Java里的Arrary详解

DK 中提供了一个专门用于操作数组的工具类&#xff0c;即Arrays 类&#xff0c;位于java.util 包中。该类提供了一些列方法来操作数组&#xff0c;如排序、复制、比较、填充等&#xff0c;用户直接调用这些方法即可不需要自己编码实现&#xff0c;降低了开发难度。 java.util.…

Python爬虫系列-让爬虫自己写爬虫(半自动化,代替人工写爬虫)

现在的PC、手机客户端等终端设备大量使用了网页前后端技术&#xff0c;另外主流的网站也会经常会更新&#xff0c;导致以前一个月更新一次爬虫代码&#xff0c;变成了天天需要更新代码&#xff0c;所以自动化爬虫技术在当前就显得特别重要&#xff0c;最近我也是在多次更新某个…

赋值运算符重载和const成员函数和 const函数

文章目录 1.运算符重载(1)(2)运算符重载的语法&#xff1a;(3)运算符重载的注意事项&#xff1a;(4)前置和后置重载区别 2.const成员函数3.取地址及const取地址操作符重载4.总结 1.运算符重载 (1) 我们知道内置类型(整形&#xff0c;字符型&#xff0c;浮点型…)可以进行一系…

TB作品】51单片机 Proteus仿真 51单片机SPI显示OLED字符驱动

// GND 电源地 // VCC 接5V或3.3v电源 // D0 P1^4&#xff08;SCL&#xff09; // D1 P1^3&#xff08;SDA&#xff09; // RES 接P12 // DC 接P11 // CS 接P10 OLED显示接口与控制实验报告 背景 OLED&#xff08;有机发光二极管&#xff09;显示器由于其高对比度、低功耗和…

最新版Python安装教程

一、安装Python 1.下载Python 访问Python官网&#xff1a; https:/www.oython.orgl 点击downloads按钮&#xff0c;在下拉框中选择系统类型(windows/Mac OS./Linux等) 选择下载最新稳定版本的Python 以下内容以演示安装Windows操作系统64位的python 左边是稳定发布版本Stabl…

Linux权限概述

一、权限概述 1.权限的基本概念 2.为什么要设置权限 3.linux用户的身份类别 4.user文件的拥有者 5.group文件所属组内用户 6.other其他用户 7.特殊用户root 二、普通权限管理 1.ls -l查看文件权限 2.文件类型以及权限解析 3.文件或文件夹的权限设置 4.通过数字给文件…

CSRF verification failed. Request aborted.

最近在学习django&#xff0c;遇到这个问题。CSRF verification failed. Request aborted. 解决方案&#xff1a; 1、在Html template中加入csrf_token 2、在view.py中对应的view函数上加上装饰器 再启动运行&#xff0c;报错就解决了。

网页生成二维码、在线演示

https://andi.cn/page/621504.html