首页 > 其他分享 >RAG原理、应用与开发实战指南

RAG原理、应用与开发实战指南

时间:2024-11-16 18:45:22浏览次数:3  
标签:指南 RAG 检索 splitter 模型 langchain 实战 import 向量

RAG概述

为了更好的解决大模型幻觉的问题,业界提出了基于知识检索与大模型生成相结合的技术:RAG(Retrieval - Augmented Generation)即检索增强生成。
在当前大模型应用开发中,RAG为解决通用大模型知识有限和知识更新不及时等问题提供了有效方案,也得到了广泛的应用。

RAG的工作原理

通用大模型的能力在完成训练后其知识就固定了,而RAG则能够为大模型补充外部知识库检索的能力,从而使生成的内容更加准确和具有针对性。它的核心思想是在回答用户问题时,不局限于大模型训练所用的知识库,还能动态的从企业私有数据库中获取最新的相关数据来增强回答。

RAG流程

  1. 数据准备
    首先,我们需要有一个知识库,这个知识库可以是非结构化的文档集合、数据库中的结构化数据等等。但我们需要提前对这批数据进行处理,如数据清洗、去除噪声、格式转换等操作,使其成为适合后续向量化处理的格式。
  2. 嵌入(Embedding)
    接下来需要将知识库中的数据通过嵌入模型转化为向量表示,嵌入模型也都可以为预训练模型,如智源开源的BAAI/BGE系列模型。在此之前还有一个重要工作:chunk,需要将数据切分成一定大小的chunk块再进行向量化存储;切分过程可能会有以下问题:
    ● 切块过大:切块过大可能会导致内容检索效率低以及语义表示不精确等问题;
    ● 切块过小:切块过小可能会导致上下文信息丢失以及增加检索开销等问题。
    这些问题大家可根据自己数据集特征进行动态调整即可,后续我也会更新更深度文章介绍解决之道~
  3. 向量存储
    向量存储直接存储到向量数据库即可,常用的数据库如:
    ● Faiss:由 Facebook 开发并维护,一个用于快速搜索相似性和密集向量的聚类的开源库;
    ● Chroma:开源的嵌入式向量数据库,具有轻量级、易用的特点;
    ● Milvus:由 Zilliz 开源的向量数据库,专为处理超大规模向量数据而设计;
    ● PGVector:PostgreSQL 的开源扩展,建立在 Faiss 库之上,适用于基于 PostgreSQL 数据库的应用程序需要进行向量搜索和分析的场景。
  4. 向量检索
    当收到用户的查询问题时,同样将问题通过嵌入模型转换为向量。然后在向量空间中,利用向量相似性搜索算法(如余弦相似度等)在知识库的向量表示中查找与问题向量最相似的几个文本向量。这些最相似的文本片段就是与问题相关的知识。
  5. 内容生成
    使用提示词模版将检索到的相关知识片段和用户问题一起输入到语言生成模型中,大模型将基于这些信息生成与之相关的回答。
    这个生成模型可以是基于 Transformer 架构的各种模型,如 GPT 系列等;也可以使用各大厂商的模型API。至此生成的回答不仅利用了模型本身的知识,还融合了从知识库中检索到的外部知识。

RAG开发示例

以下是一个使用 Python 和一些常见库实现的简单 RAG 示例。我们使用一个简单的文本文件作为知识库,并结合大模型的回答为大家演示一下整个RAG的流程。

  1. 准备工作
    首先,我们需要安装必要的库。主要使用Chroma作为向量数据库以及使用LangChain作为开发框架,使用以下命令即可完成安装:

    pip install chromadb
    pip install langchain
    

    安装完成后,将用到的相关依赖库导入到代码文件中即可:

    import os
    from langchain_community.embeddings import HuggingFaceBgeEmbeddings
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    from langchain.retrievers import ParentDocumentRetriever
    from langchain.storage import InMemoryStore
    from langchain_chroma import Chroma
    from langchain_community.document_loaders import TextLoader
    
  2. 定义大模型
    这里用月之暗面的API作为演示,大家可根据项目需要自行切换基础模型;

    from openai import OpenAI
    
    class LLM_Moon:
        def __init__(self):
            self.client = OpenAI(
                api_key='sk-xxxxxx',
                base_url='https://api.moonshot.cn/v1',
            )
    
        def request(self, question):
            completion = self.client.chat.completions.create(
                model='moonshot-v1-8k',
                messages=[
                    {'role': 'user', 'content': question}
                ],
                temperature=0.3
            )
            return completion.choices[0].message.content
    
  3. 初始化向量模型和数据库
    这里我们使用智源开源的向量模型:bge-large-zh-v1.5,首先定义BGE模型的位置和文件路径。然后,我们初始化HuggingFaceBgeEmbeddings模型,该模型将用于生成文档的嵌入。接着,我们创建了一个Chroma向量数据库实例,用于存储和检索这些嵌入。

    BGE_MODEL_PATH = "bge-large-zh-v1.5"
    FILE_PATH = "data.txt"
    
    embeddings = HuggingFaceBgeEmbeddings(
        model_name=BGE_MODEL_PATH,
        model_kwargs={'device': 'cpu'},
        encode_kwargs={'normalize_embeddings': True},
        query_instruction="为这个句子生成表示以用于检索相关文章:"
    )
    
    vectorstore = Chroma(
        collection_name='digital-administration-v1',
        embedding_function=embeddings,
        persist_directory='./vectorstore_2'
    )
    
  4. 定义检索器
    为了有效地检索文档,我们需要定义父块和子块的切分大小。这里我们使用了RecursiveCharacterTextSplitter来切分文档。chunk块的大小大家根据实际文档特征和调试表现灵活调整即可,我们设置父块的大小为500、子块的大小为200。

    
    # 定义父块切分大小
    parent_splitter = RecursiveCharacterTextSplitter(chunk_size=500)
    
    # 定义子块切分大小
    child_splitter = RecursiveCharacterTextSplitter(chunk_size=250)
    
    store = InMemoryStore()
    
    search_kwargs = {
        "k": 5
    }
    
    # 定义文档检索对象
    retriever = ParentDocumentRetriever(
            vectorstore=vectorstore,
            docstore=store,
            child_splitter=child_splitter,
            parent_splitter=parent_splitter,
            search_kwargs=search_kwargs
        )
    
    
  5. 加载和存储文档
    使用LangChain提供的TextLoader文本加载器来加载文件中的文本内容,并将这些文档添加到检索器中。

    # 文件读取
    docs = []
    loader = TextLoader("data.txt", encoding='utf-8')
    docs.extend(loader.load())
    retriever.add_documents(docs)
    
  6. 构造对话函数
    最后,我们定义了一个chat函数,该函数接受一个问题作为输入,使用检索器获取相关的文档,并使用提示词模版封装向量数据库检索出来的内容。然后,我们使用一个LLM模型(例如LLM_Moon)来生成回答。

    def chat(question):
        retriever_res = retriever.get_relevant_documents(question)
        searchdocs = []
        for x in retriever_res:
            searchdocs.append(x.page_content)
        req_prompt = generate_prompt(question, searchdocs)
        return model.request(req_prompt)
    
  7. 对话
    直接调用chat函数即可完成RAG检索和对话的结果生成:

    print(chat("介绍下你自己"))
    

    大模型会结合提示词中给出的问题相关文档以及问题,给出更合理的回答。
    响应内容

  8. 示例代码

    import os
    from langchain_community.embeddings import HuggingFaceBgeEmbeddings
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    from langchain.retrievers import ParentDocumentRetriever
    from langchain.storage import InMemoryStore
    from langchain_chroma import Chroma
    from langchain_community.document_loaders import TextLoader
    from prompt_utils import generate_prompt
    from llm_base import LLM_Moon
    
    
    model = LLM_Moon()
    
    # 定义bge模型位置
    BGE_MODEL_PATH = "bge-large-zh-v1.5"
    FILE_PATH = "data.txt"
    
    # 初始化向量模型
    embeddings = HuggingFaceBgeEmbeddings(
        model_name=BGE_MODEL_PATH,
        model_kwargs={'device': 'cpu'},
        encode_kwargs={'normalize_embeddings': True},
        query_instruction="为这个句子生成表示以用于检索相关文章:"
    )
    
    # 初始化向量数据库
    vectorstore = Chroma(
        collection_name='digital-administration-v1',
        embedding_function=embeddings,
        persist_directory='./vectorstore_2'
    )
    
    # 定义父块切分大小
    parent_splitter = RecursiveCharacterTextSplitter(chunk_size=500)
    
    # 定义子块切分大小
    child_splitter = RecursiveCharacterTextSplitter(chunk_size=250)
    
    store = InMemoryStore()
    
    search_kwargs = {
        "k": 5
    }
    
    
    # 定义文档检索对象
    retriever = ParentDocumentRetriever(
            vectorstore=vectorstore,
            docstore=store,
            child_splitter=child_splitter,
            parent_splitter=parent_splitter,
            search_kwargs=search_kwargs
        )
    
    
    # 加载文件夹中的文件内容
    def extract_file_dirs(directory):
        file_paths = []
        for root, dirs, filelist in os.walk(directory):
    
            for file in filelist:
                fp = os.path.join(root, file)
                file_paths.append(fp)
        return file_paths
    
    
    # 文件读取
    docs = []
    loader = TextLoader("data.txt", encoding='utf-8')
    docs.extend(loader.load())
    retriever.add_documents(docs)
    
    
    def chat(question):
        retriever_res = retriever.get_relevant_documents(question)
        searchdocs = []
        for x in retriever_res:
            searchdocs.append(x.page_content)
        req_prompt = generate_prompt(question, searchdocs)
        return model.request(req_prompt)
    
    
    print(chat("介绍下你自己"))
    
    

结论

通过使用RAG外挂知识库的方式,我们可以构建一个强大的大模型应用,该应用能利用检索到的相关信息来生成更准确、更相关的回答。这种方法在问答系统、聊天机器人和其他需要结合私有知识库来生成内容的应用中非常有用。

标签:指南,RAG,检索,splitter,模型,langchain,实战,import,向量
From: https://blog.csdn.net/qq_25893567/article/details/143821251

相关文章

  • 全面指南 | 知识库管理系统在零售行业中的作用是什么?
    中国的零售行业在2023年展现出了稳健的增长态势。根据国家统计局的数据,2023年国内社会消费品零售总额为47.15万亿元,同比增长7.2%。有一点是明确的——零售行业只会继续蓬勃发展。在这个不断壮大的巨大行业中,要想在竞争激烈的市场中脱颖而出绝非易事。问题是,如何才能成为顾......
  • 书生·共学大模型实战营第4期 L1G4000任务提交
    基于LlamaIndex构建自己的RAG知识库,寻找一个问题A在使用LlamaIndex之前浦语API不会回答,借助LlamaIndex后浦语API具备回答A的能力我们选择了一个名为wereader的Github小众项目,这是一个Chrome/Firefox扩展,主要用于微信读书做笔记,对常使用Markdown做笔记的读者比较有帮助。可以发现......
  • 大模型实战项目:基于大模型+知识图谱的知识库问答 (附项目)
    今天给大家介绍一个git开源的宝藏项目—基于大模型+知识图谱的知识库问答,这里还搭配了一个演示dome给大家,如需要此项目练手的,我已经打包好了放在文末~基于大模型+知识图谱的知识库问答系统项目整体流程介绍项目整体包含5个部分:数据重构、图谱构建、图谱补全、对话......
  • 上交出品《动手学大模型》LLM 实战课,课件+实战教程(教程分享)
    来了来了!上海交通大学的大模型超超超级牛掰的大模型编程实战课公开了,课件+教程,本套实战教程旨在提供大模型相关的入门编程参考。通过简单实践,帮助同学快速入门大模型,更好地开展课程设计或学术研究。上海交大大模型实验室整了一份针对入门阶段的大模型教程,已经看完了非常不......
  • 大模型开源入门教程:《开源大模型食用指南》全网发布,轻松助你速通大模型!
    前言《开源大模型食用指南》是一个围绕开源大模型、针对国内初学者、基于AutoDL平台的中国宝宝专属大模型教程,针对各类开源大模型提供包括环境配置、本地部署、高效微调等技能在内的全流程指导,简化开源大模型的部署、使用和应用流程,让更多的普通学生、研究者更好地使用......
  • localStorage和sessionStorage存储封装
    constcreateStorageProxy=(target={},type:'local'|'session')=>{conststorage=type==='local'?localStorage:sessionStorage;returnnewProxy(target,{get(obj:Record<string,any>,prop:string......
  • 【GraphRAG】本地部署全流程!超详细介绍!
    1、GraphRAG是什么?GraphRAG(Graph-basedRelation-AwareGrouping)是一种基于图的关系感知分组方法,通常用于计算机视觉和机器学习领域。它的核心思想是利用图结构来表示和处理实体之间的关系,从而更有效地进行分组和识别任务。2、本地部署在autodl上进行运行,4090单显卡+24GB内......
  • 如何快速开发一款AI小程序?基于微信云开发的实战指南
    如何快速开发一款AI小程序?基于微信云开发的实战指南引言微信小程序凭借其轻便、易推广等特点,已成为应用开发的重要方式之一。而AI技术的快速发展让智能化应用成为可能。通过微信云开发(CloudBase)与小程序结合,开发者可以实现从前端到后端的一站式AI应用开发。本文将深入讲解......
  • 大模型微调实战营-精通+指令微调+开源大模型微调+对齐+垂直领域应用
    ‌大模型微调实战营是一个专注于大模型微调技术的训练营,涵盖指令微调、开源大模型微调、对齐以及垂直领域应用等多个方面。‌‌指令微调‌:通过添加特定的指令或模板,对大模型进行微调,使其能够生成更符合期望的回答。‌开源大模型微调‌:利用开源的大模型资源,进行微调训练,以适应特......
  • AI大模型实战:打造银行智能营销助手:大模型助力精准营销的8大优势
    在金融科技快速发展的时代,银行的业务模式和客户需求都发生了巨大变化。为了应对日益激烈的市场竞争,银行必须依托先进技术,提升客户服务水平和营销效率。银行智能营销助手应运而生,它通过结合知识图谱和大模型(LLM),帮助银行精确获取客户信息、分析市场需求、定制个性化营销方案,为......