来自工业界的知识库 RAG 服务(五),模块化知识库 GoMate 实现方案详解

背景介绍

很早以前就看过一篇介绍 RAG 的综述性文章 Retrieval-Augmented Generation for Large Language Models: A Survey, 其中介绍了 RAG 的模块化架构:

但是一直没有看到对应的实现方案,以前也没有理解此框架的优势之处。随着在相关领域的持续实践,逐渐理解到模块化 RAG 的优势。模块化 RAG 可以方便地进行服务的迭代升级,另外模块可以自由组合,灵活性更好。

最近注意到来自中科院的 RAG 服务 GoMate 开源了,核心亮点就是模块化 RAG 设计,本文就深入介绍来 GoMate 的框架设计与实现细节。

框架设计

之前介绍的 RAG 框架存在着不同的侧重点,来自有道的 QAnything 强调其 Rerank 设计,RagFlow 强调其精细的文件处理。而 GoMate 则主要强调其模块化设计。

GoMate 的框架设计图如下所示:

可以看到,框架中将 RAG 流程拆分为不同模块,熟悉 RAG 服务还是比较容易理解的,一些核心模块如下所示:

  • Retrieval 对应的就是知识库的检索
  • Rerank&Judge 对应的就是检索内容的重排序与过滤
  • Generation 对应的就是大模型内容生成
  • Citation 对应的就是检索内容引用的处理

每个模块可以存在多种不同的实现形式,比如 Retrieval 图中包含如下所示的实现:

  • Sparse Retriever 对应的是稀疏检索,目前常见的 BM25 的检索;
  • Dense Retriever 对应的密集检索,RAG 中最常见的是向量检索;
  • Ensemble Retriever 对应的应该是混合检索;

从架构图可以看到 GoMate 就是包含了多个基础的功能模块,通过功能模块的的组合实现具体的应用。

实现细节

GoMate 是从 2024 年 2 月开始开发的,截止目前经过了 4 个月的开发,虽然功能还不够完善,但是已经可以看到模块化的完整设计思想了。

项目主要包含两部分:

  • modules 包含的就是基础模块, 与上面架构图中的模块可以对应起来
  • applications 表示的是模块组合生成的应用,实现业务所需的功能
功能模块

每个模块对应的职责比较明确,以 RAG 中核心的检索模块为例,深入查看对应的实现:

基础的检索接口在 gomate/modules/retrieval/base.py 中定义,只包含一个 retrieve() 方法:

python 复制代码
class BaseRetriever(ABC):
    @abstractmethod
    def retrieve(self, query: str) -> str:
        pass

BM25 检索算法在 gomate/modules/retrieval/bm25_retriever.py 实现,其中实现了 BM25Okapi, BM25LBM25Plus 版本的算法,具体如下所示:

python 复制代码
class BM25Retriever(BaseRetriever):
    # 实现不同的 BM25 算法

    def build_from_texts(self, corpus):
        self.corpus=corpus
        if self.algorithm == 'Okapi':
            self.bm25 = BM25Okapi(corpus=corpus, tokenizer=self.tokenizer, k1=self.k1, b=self.b, epsilon=self.epsilon)
        elif self.algorithm == 'BM25L':
            self.bm25 = BM25L(corpus=corpus, tokenizer=self.tokenizer, k1=self.k1, b=self.b, delta=self.delta)
        elif self.algorithm == 'BM25Plus':
            self.bm25 = BM25Plus(corpus=corpus, tokenizer=self.tokenizer, k1=self.k1, b=self.b, delta=self.delta)
        else:
            raise ValueError('Algorithm not supported')

    # 检索接口的实现

    def retrieve(self, query: str='',top_k:int=3) -> List[Dict]:
        tokenized_query = " ".join(self.tokenizer(query))
        search_docs = self.bm25.get_top_n(tokenized_query, self.corpus, n=top_k)
        return search_docs

向量检索算法是基于 Faiss 实现的,简化后实现如下所示:

python 复制代码
class DenseRetriever(BaseRetriever):
    # 初始化 Faiss 向量检索

    def __init__(self, config):
        self.config = config
        self.tokenizer = AutoTokenizer.from_pretrained(config.model_name)
        self.model = AutoModel.from_pretrained(config.model_name)
        self.index = faiss.IndexFlatIP(config.dim)

    # 检索接口实现

    def retrieve(self, query):
        D, I = self.index.search(self.get_embedding([query]), self.top_k)
        return [{self.doc_map[idx]: score} for idx, score in zip(I[0], D[0]) if idx in self.doc_map]

gomate/modules/retrieval/tree_retriever.py 中还实现了 RAPTOR 检索,感兴趣的也可以深入查看实现细节。

可以看到检索模块包含的就是不同算法的实现,上层应用可以根据需要选择合适的检索算法。

其他的模块与检索模块类似,对应的就是单个功能的实现。

应用

目前实现的应用比较少,只有 Rerank,Rewrite 和 RAG ,目前只有 RAG 属于一个完整的应用,其他都是单个模块的测试,深入查看 RAG 应用的实现,具体如下所示:

python 复制代码
class RagApplication():
    # 初始化向量库

    def init_vector_store(self):
        docs=self.reader.get_content(max_token_len=600, cover_content=150)
        self.vector_store.document=docs
        self.vector_store.get_vector(EmbeddingModel=self.embedding_model)
        self.vector_store.persist(path='storage')
        self.vector_store.load_vector(path='storage')

    # 向量库中添加文件

    def add_document(self, file_path):
        docs = self.reader.get_content_by_file(file=file_path, max_token_len=512, cover_content=60)
        self.vector_store.add_documents(self.config.vector_store_path, docs, self.embedding_model)

    # RAG 对话

    def chat(self, question: str = '', topk: int = 5):
        # 向量检索

        contents = self.vector_store.query(question, EmbeddingModel=self.embedding_model, k=topk)
        content = '\n'.join(contents[:5])

        # 大模型聊天

        response, history = self.llm.chat(question, [], content)
        return response, history,contents

可以看到目前实现的 RAG 应用只是一个简单的向量库模块和大模型聊天的模块的组合,暂时看不到模块化的优势之处。

但是从目前的设计来看,模块化的设计存在一些明显的优势。基础模块可以独立进行迭代,上层应用可以根据需要组合所需的模块,比如大模型聊天只需要将下面的模块组合在一起:

  • Query Processing
  • Prompt Engineering
  • Generation

而 RAG 完整流程可以组合下面的模块:

  • Query Processing
  • Query Transformation
  • Retrieval
  • Rerank&Judge
  • Prompt Engineering
  • Generation
  • Prompt Engineering
  • Generation
  • Citation
  • Post Processing

应用中的各个模块可以独立测试和优化,组合的模块也可以根据需要进行替换升级,比如 RAG 的检索方案从 DenseRetriever 调整为 BM25Retriever 只需要简单的参数修改即可。

总结

本文介绍了中科院的模块化 RAG 项目 GoMate,项目目前还处于初始阶段,还有不少功能等待实现,但是可以看到的一个模块化 RAG 的实现思路,通过精细的模块拆分,模块的迭代升级可以变得更加便利,应用的实现也会演变成简单的模块组合。对 GoMate 项目感兴趣的可以前往官网深入了解。

相关推荐
厚德云2 分钟前
Runway开放Gen-3:比Sora更好的视频模型?
人工智能·ai·云计算·视频
新手村领路人14 分钟前
macos m2 百度paddleocr文字识别 python
开发语言·python·macos
JAMES费15 分钟前
python机器人编程——用pytorch实现六轴机械臂的正向和逆向数值解算,及python算法解析
pytorch·python·机器人
渡众机器人21 分钟前
自动驾驶水泥搅拌车在梁场的应用(下)
人工智能·科技·物联网·机器学习·机器人·自动驾驶·搅拌车
PythonFun23 分钟前
如何用Python向PPT中批量插入图片
服务器·python·powerpoint
yuanlulu25 分钟前
在昇腾服务器上使用llama-factory对baichuan2-13b模型进行lora微调
人工智能·深度学习·lora·nlp·大语言模型·llama
CoderIsArt34 分钟前
Python:一个挑选黑色棋盘的程序
python·计算机视觉
sagima_sdu1 小时前
Win11 Python3.10 安装pytorch3d
人工智能·pytorch·python
WHAT8161 小时前
【CUDA】 由GPGPU控制核心架构考虑CUDA编程中线程块的分配
开发语言·c++·人工智能·架构
小白白白又白cdllp1 小时前
Cube-Studio:开源大模型全链路一站式中台
人工智能·开源·大模型