RAGMeUp核心组件探秘:PostgresHybridRetriever如何实现高效检索
【免费下载链接】RAGMeUpGeneric rag framework to apply the power of LLMs on any given dataset项目地址: https://gitcode.com/gh_mirrors/ra/RAGMeUp
RAGMeUp作为一款强大的通用RAG框架,能够将LLM的强大能力应用于任何给定数据集。而在其众多核心组件中,PostgresHybridRetriever扮演着至关重要的角色,它通过创新的混合检索技术,为整个系统提供了高效、精准的文档检索能力。本文将深入探讨PostgresHybridRetriever的工作原理、核心功能以及实现高效检索的关键技术。
什么是PostgresHybridRetriever?
PostgresHybridRetriever是RAGMeUp框架中的一个核心组件,它巧妙地结合了稀疏检索(BM25)和密集检索(向量搜索)两种技术,充分发挥了各自的优势,从而实现了更全面、更准确的文档检索。该组件通过PostgreSQL数据库来存储和管理文档数据,并利用PostgreSQL的强大功能来执行检索操作。
在RAGHelper类的初始化过程中,我们可以看到PostgresHybridRetriever的实例化和配置过程:
# Set up the PostgresHybridRetriever self.retriever = PostgresHybridRetriever(self.db_pool) self.retriever.setup_database(self.embeddings.get_sentence_embedding_dimension())这表明PostgresHybridRetriever需要一个数据库连接池来与PostgreSQL进行交互,并且需要根据嵌入模型的维度来设置数据库表结构。
数据库表结构设计
PostgresHybridRetriever在PostgreSQL中创建了两个主要的表来存储文档数据:ragmeup_dense_embeddings和ragmeup_sparse_embeddings。
密集嵌入表(ragmeup_dense_embeddings)
该表用于存储文档的密集向量表示,其结构如下:
CREATE TABLE IF NOT EXISTS ragmeup_dense_embeddings ( id VARCHAR(32) PRIMARY KEY, embedding public.vector({embedding_dimension}) NOT NULL, content varchar NOT NULL, metadata jsonb NOT NULL ); CREATE INDEX IF NOT EXISTS ragmeup_dense_embedding_index ON ragmeup_dense_embeddings USING hnsw (embedding vector_cosine_ops) WITH (m='16', ef_construction='64');这里使用了PostgreSQL的vector扩展来存储向量数据,并创建了一个基于hnsw算法的索引,以加速向量相似度搜索。
稀疏嵌入表(ragmeup_sparse_embeddings)
该表用于存储文档的原始内容,以便进行BM25检索:
CREATE TABLE IF NOT EXISTS ragmeup_sparse_embeddings ( id VARCHAR(32) PRIMARY KEY, content TEXT, metadata JSONB ); CREATE INDEX ragmeup_sparse_embeddings_bm25 ON ragmeup_sparse_embeddings USING bm25 (id, content) WITH (key_field='id');这里创建了一个BM25索引,以加速基于关键词的检索。
此外,还为两个表创建了基于dataset元数据的索引,以支持按数据集进行过滤:
CREATE INDEX idx_metadata_dense_dataset ON ragmeup_dense_embeddings (((metadata::jsonb ->> 'dataset')::text)); CREATE INDEX idx_metadata_sparse_dataset ON ragmeup_sparse_embeddings (((metadata::jsonb->>'dataset')::text));文档添加流程
PostgresHybridRetriever提供了add_documents方法,用于将文档添加到数据库中。该方法会将文档同时添加到密集嵌入表和稀疏嵌入表中:
def add_documents(self, documents) -> List[str]: # Batch these documents into chunks of 1000, with TQDM with tqdm(total=len(documents), desc="Adding documents to Postgres") as pbar: for i in range(0, len(documents), 1000): chunk = documents[i:i+1000] # Add to the BM25 index # ... # Now the dense embeddings # ...这种批量处理的方式可以提高数据插入的效率,特别是当处理大量文档时。
高效检索的实现
PostgresHybridRetriever的核心功能是get_relevant_documents方法,该方法会根据查询和查询嵌入来检索相关文档。它支持两种检索模式:min-max归一化排序和Reciprocal Rank Fusion(RRF)排序。
Min-max归一化排序
在min-max归一化排序模式下,系统会分别执行BM25检索和向量检索,然后将两种检索结果进行归一化处理,并以50:50的权重进行组合:
SELECT id, content, metadata, score_bm25, distance, sources, ( 0.5 * COALESCE(score_bm25 / NULLIF(max_bm25, 0), 0) + 0.5 * COALESCE(1 - (distance - min_distance) / NULLIF((max_distance - min_distance), 0), 0) ) AS hybrid_score FROM scored ORDER BY hybrid_score DESC LIMIT %s;这种方法通过将BM25得分和向量距离都归一化到[0, 1]范围内,然后进行加权平均,从而得到最终的混合得分。
RRF排序
RRF(Reciprocal Rank Fusion)是一种基于排名的结果融合方法,它通过为每个结果分配一个得分(1/(k + rank),其中k是平滑常数,默认为60),然后将不同检索方法得到的得分相加,来得到最终的排序结果。
# Process BM25 results for rank, row in enumerate(bm25_rows): doc_id, content, metadata = row rrf_score = 1.0 / (rrf_k + rank + 1) # ... # Process vector results for rank, row in enumerate(vector_rows): doc_id, content, metadata, distance = row rrf_score = 1.0 / (rrf_k + rank + 1) # ... # Sort by combined RRF score descending, take top_k ranked = sorted(doc_map.values(), key=lambda d: d["rrf_score"], reverse=True)[:k]RRF方法的优势在于它对分数的绝对值不敏感,只关注结果的排名,这使得不同检索方法的结果可以更公平地进行融合。此外,RRF方法实现简单,不需要复杂的参数调优。
其他核心功能
除了上述主要功能外,PostgresHybridRetriever还提供了其他一些重要的功能:
数据存在性检查
has_data方法用于检查数据库中是否存在文档数据:
def has_data(self): conn = None try: conn = self.connection_pool.getconn() with conn.cursor() as cursor: cursor.execute("SELECT COUNT(*) FROM ragmeup_sparse_embeddings;") return cursor.fetchone()[0] > 0 # ...文档删除
delete方法用于根据文件名删除文档:
def delete(self, filenames: List[str]) -> None: # ... cursor.execute(f"DELETE FROM ragmeup_sparse_embeddings WHERE metadata->>'source' IN ({placeholders});", tuple(filenames)) # ... cursor.execute(f"DELETE FROM ragmeup_dense_embeddings WHERE metadata->>'source' IN ({placeholders});", tuple(filenames)) # ...查询处理
escape_query方法用于对查询进行预处理,包括分词和特殊字符过滤:
def escape_query(self, query): # Tokenize the query into words tokens = nltk.word_tokenize(query) # Use regex to keep alphanumeric characters and diacritics, remove all others tokens = [regex.sub(r'[^\p{L}\p{N}\s]', '', token) for token in tokens] # Rejoin tokens into a sanitized string sanitized_query = ' '.join(tokens) return sanitized_query总结
PostgresHybridRetriever作为RAGMeUp框架的核心组件,通过巧妙地结合BM25稀疏检索和向量密集检索,实现了高效、准确的文档检索。其主要优势包括:
- 混合检索:结合了稀疏检索和密集检索的优点,能够处理各种类型的查询。
- 灵活的结果融合:支持min-max归一化和RRF两种结果融合方法,可以根据实际需求选择合适的方法。
- 高效的数据库操作:通过批量处理、索引优化等手段,提高了数据插入和检索的效率。
- 丰富的功能:提供了文档添加、删除、查询处理等一系列功能,满足了RAG系统的各种需求。
通过深入了解PostgresHybridRetriever的实现细节,我们可以更好地理解RAGMeUp框架的工作原理,从而更好地使用和扩展该框架。无论是对于新手还是有经验的开发者,PostgresHybridRetriever都是一个值得深入研究的组件,它展示了如何在实际应用中有效地结合不同的检索技术,以提供更好的搜索体验。
要开始使用RAGMeUp框架,你可以通过以下命令克隆仓库:
git clone https://gitcode.com/gh_mirrors/ra/RAGMeUp然后按照项目文档中的说明进行安装和配置,体验PostgresHybridRetriever带来的高效检索能力。
【免费下载链接】RAGMeUpGeneric rag framework to apply the power of LLMs on any given dataset项目地址: https://gitcode.com/gh_mirrors/ra/RAGMeUp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考