首页 > 后端开发 > Python教程 > 检索增强生成 (RAG) 的终极指南

检索增强生成 (RAG) 的终极指南

Barbara Streisand
发布: 2024-12-21 18:55:10
原创
839 人浏览过

像 OpenAI 的 ChatGPT 这样的生成式 AI 模型的快速发展彻底改变了自然语言处理,使这些系统能够生成连贯且上下文相关的响应。然而,即使是最先进的模型在处理特定领域的查询或提供高度准确的信息时也面临局限性。这通常会导致诸如幻觉之类的挑战——模型产生不准确或捏造的细节的情况。

检索增强生成(RAG),一个旨在弥合这一差距的创新框架。通过无缝集成外部数据源,RAG 使生成模型能够检索实时、利基信息,从而显着提高其准确性和可靠性。

在本文中,我们将深入研究 RAG 的机制,探索其架构,并讨论激发其创作灵感的传统生成模型的局限性。我们还将重点介绍实际实现、先进技术和评估方法,展示 RAG 如何改变人工智能与专业数据交互的方式。

入门

目录

  • 什么是RAG
  • RAG 的架构
  • RAG 流程
  • RAG 与微调
  • RAG 的类型
  • RAG 的应用
  • 使用 RAG 构建 PDF 聊天系统
  • 资源

什么是RAG

检索增强生成(RAG)是一种先进的框架,通过集成外部数据的实时检索来增强生成式人工智能模型的能力。虽然生成模型擅长生成连贯的、类似人类的文本,但当要求提供准确、最新或特定领域的信息时,它们可能会犹豫不决。这就是 RAG 介入的地方,确保回复不仅具有创意,而且基于可靠且相关的来源。

RAG 通过将生成模型与检索机制连接起来进行操作,通常由向量数据库或搜索系统提供支持。当收到查询时,检索组件会搜索大量外部数据集以获取相关信息。然后,生成模型综合这些数据,产生既准确又具有上下文洞察力的输出。

通过解决幻觉和有限领域知识等关键挑战,RAG 释放了生成模型在专业领域脱颖而出的潜力。其应用涵盖各个行业,从提供精确答案的自动化客户支持,到使研究人员能够按需获取精选知识。 RAG 代表着在使 AI 系统在现实场景中更加智能、值得信赖和有用方面向前迈出了重要一步。

RAG的架构

清楚地了解 RAG 架构对于释放其全部潜力和优势至关重要。该框架的核心是建立在两个主要组件之上:检索器和生成器,它们在无缝的信息处理流程中协同工作。

整个过程如下图所示:
The ultimate guide to Retrieval-Augmented Generation (RAG)
来源:https://weaviate.io/blog/introduction-to-rag

  • 检索 - RAG 中的推理阶段从检索开始,其中从外部知识源获取与用户查询相关的数据。在基本的 RAG 设置中,通常使用相似性搜索,将查询和外部数据嵌入到同一向量空间中以识别最接近的匹配。检索器在获取文档方面发挥着关键作用,采用稀疏检索和密集检索等方法。稀疏检索使用 TF-IDF 或 BM25 等技术,依赖于精确的单词匹配,但在同义词和释义方面遇到困难,而密集检索则利用 BERT 或 RoBERTa 等转换器模型来创建语义向量表示,从而实现更准确和细致的匹配。
  • 增强 - 从外部源检索最相关的数据点后,增强过程通过将其嵌入到预定义的提示模板中来合并此信息。
  • 生成 - 在生成阶段,模型使用增强提示,通过将其内部语言理解与检索到的外部数据相结合来制作连贯的、上下文准确的响应。虽然增强集成了外部事实,但生成将这些丰富的信息转换为根据用户查询定制的自然的、类似人类的文本。

RAG工艺流程

RAG 流程的所有阶段和基本组成部分,如下图所示。

The ultimate guide to Retrieval-Augmented Generation (RAG)
来源:https://www.griddynamics.com/blog/retrieval-augmented- Generation-llm

  • 文档加载:RAG 过程的第一步涉及数据准备,包括从存储中加载文档、提取、解析、清理和格式化文本以进行文档拆分。文本数据可以采用多种格式,例如纯文本、PDF、Word 文档、CSV、JSON、HTML、Markdown 或编程代码。为法学硕士准备这些不同的来源通常需要通过提取、解析和清理将它们转换为纯文本。
  • 文档拆分:通过文本拆分或分块将文档分为更小的、可管理的片段,这对于处理大型文档和遵守 LLM 中的令牌限制(例如 GPT-3 的 2048 个令牌)至关重要。策略包括固定大小或内容感知分块,其方法取决于数据的结构和要求。 The ultimate guide to Retrieval-Augmented Generation (RAG)

将文档分成更小的块可能看起来很简单,但需要仔细考虑语义,以避免不恰当地分割句子,这可能会影响后续步骤,例如回答问题。简单的固定大小分块方法可能会导致每个块中的信息不完整。大多数文档分段算法使用块大小和重叠,其中块大小由字符、单词或标记计数确定,而重叠通过在相邻块之间共享文本来确保连续性。该策略保留了跨块的语义上下文。

  • 文本嵌入:文本块被转换为向量嵌入,它以一种可以轻松比较语义相似性的方式表示每个块。向量嵌入将复杂数据(例如文本)映射到相似数据点聚集在一起的数学空间中。此过程捕获文本的语义,因此具有相似含义的句子,即使措辞不同,也会在向量空间中紧密映射在一起。例如,“猫追老鼠”和“猫追啮齿动物”将被映射到附近的点,尽管它们的措辞不同。

The ultimate guide to Retrieval-Augmented Generation (RAG)
来源:https://www.griddynamics.com/blog/retrieval-augmented- Generation-llm

  • 向量存储:文档被分割并转换为向量嵌入后,它们被存储在向量存储中,这是一个用于存储和管理向量的专用数据库。向量存储可以有效搜索相似向量,这对于 RAG 模型的执行至关重要。矢量存储的选择取决于数据规模和可用计算资源等因素。

一些重要的矢量数据库是:

  • FAISS:FAISS 由 Facebook AI 开发,可有效管理大量高维向量集合,并在高维环境中执行相似性搜索和聚类。它优化了内存使用和查询持续时间,使其适合处理数十亿个向量。
  • Chroma:Chroma 是一个开源内存向量数据库,专为法学硕士应用程序而设计,为向量存储、搜索和检索提供可扩展的平台。它支持云端和本地部署,并且能够处理各种数据类型和格式。
  • Weaviate:一个可以自托管或完全管理的开源矢量数据库。它专注于高性能、可扩展性和灵活性,支持广泛的数据类型和应用程序。它允许存储向量和对象,从而实现基于向量和基于关键字的搜索技术的组合。
  • Pinecone:基于云的托管矢量数据库,旨在简化大规模机器学习应用程序的开发和部署。与许多矢量数据库不同,Pinecone 使用专有的封闭源代码。它擅长处理高维向量,适用于相似性搜索、推荐系统、个性化和语义搜索等应用。 Pinecone 还具有单级过滤功能。
  • 文档检索:信息检索系统中的检索过程(例如文档搜索或问答)从接收到查询并使用与文档索引相同的嵌入模型转换为向量时开始。目标是通过将查询向量与索引(向量存储)中存储的块向量进行比较来返回相关文档块。检索器的作用是识别并返回相关文档块的 ID,而不存储文档。可以使用各种搜索方法,例如相似性搜索(基于余弦相似性)和基于阈值的检索,仅返回超过特定相似性分数的文档。此外,LLM 辅助检索对于涉及内容和元数据过滤的查询非常有用。

The ultimate guide to Retrieval-Augmented Generation (RAG)
来源:https://www.griddynamics.com/blog/retrieval-augmented- Generation-llm

  • 答案生成:在检索过程中,相关文档块与用户查询相结合,生成LLM的上下文和提示。最简单的方法,在 LangChain 中被称为“Stuff”方法,涉及将所有块集中到同一个上下文窗口中,以获得直接、直接的答案。然而,由于上下文窗口的限制,这种方法难以应对大文档量和复杂查询。为了解决这个问题,可以使用 Map-reduce、Refine 和 Map-rerank 等替代方法。 Map-reduce 将文档单独发送给 LLM,然后合并响应。 Refine 会迭代更新提示以完善答案,而 Map-rerank 根据相关性对文档进行排名,非常适合多个令人信服的答案。

The ultimate guide to Retrieval-Augmented Generation (RAG)

RAG 与微调

RAG(检索增强生成)和微调是扩展LLM能力的两种关键方法,每种方法适合不同的场景。微调涉及对特定领域数据的法学硕士进行再培训,以执行专门的任务,非常适合静态、狭窄的用例,例如需要特定语气或风格的品牌或创意写作。然而,它成本高昂、耗时,并且不适合动态、频繁更新的数据。

另一方面,RAG 通过动态检索外部数据而不修改模型权重来增强 LLM,使其具有成本效益,非常适合法律、财务或客户服务应用程序等实时数据驱动环境。 RAG 使法学硕士能够处理大型、非结构化的内部文档语料库,与导航混乱的数据存储库的传统方法相比,具有显着的优势。

微调擅长创建细致入微、一致的输出,而 RAG 通过利用外部知识库提供最新、准确的信息。在实践中,RAG 通常是需要实时、适应性响应的应用程序的首选,特别是在管理大量非结构化数据的企业中。

RAG 的类型

检索增强生成 (RAG) 方法有多种类型,每种方法都针对特定用例和目标量身定制。主要类型包括:

The ultimate guide to Retrieval-Augmented Generation (RAG)
来源:https://x.com/weaviate_io/status/1866528335884325070

  • 原生 RAG:指的是一种紧密集成的方法,其中检索增强生成系统的检索和生成组件被设计为在同一架构中无缝工作。与依赖外部工具或 API 的传统实现不同,原生 RAG 优化了检索机制和生成模型之间的交互,从而实现更快的处理并提高上下文相关性。这种方法通常使用内存处理或高度优化的本地数据库,从而减少延迟和资源开销。原生 RAG 系统通常针对特定用例量身定制,通过消除对第三方服务的依赖来提高效率、准确性和成本效益。
  • 检索和重新排名 RAG:专注于改进检索过程以提高准确性和相关性。在此方法中,根据查询的语义相似性检索初始文档或块集,通常由嵌入空间中的余弦相似性确定。随后,重新排序模型根据检索到的文档与查询的上下文相关性对它们进行重新排序。此重新排名步骤通常利用深度学习模型或转换器,从而允许在基本相似性指标之外进行更细致的排名。通过优先考虑最相关的文档,这种方法可确保生成模型接收上下文丰富的输入,从而显着提高响应质量。
  • 多模态 RAG:通过将文本、图像、音频或视频等多种数据模态合并到检索增强生成管道中,扩展了传统的 RAG 范式。它允许系统检索并生成集成不同形式数据的响应。例如,在涉及基于图像的查询的场景中,系统可能会检索相关图像以及文本内容,以创建更全面的答案。多模态 RAG 在电子商务、医学成像和多媒体内容分析等领域特别有用,这些领域的见解通常依赖于文本和视觉信息的组合。
  • Graph RAG:利用基于图的数据结构根据实体之间的关系和连接来建模和检索信息。在这种方法中,知识被组织为一个图,其中节点表示实体(例如概念、文档或对象),边捕获它们的关系(例如语义、层次或时间)。处理查询以识别与输入相关的子图或路径,然后将这些子图输入生成模型。这种方法在科学研究、社交网络和知识管理等领域尤其有价值,这些领域的关系洞察力至关重要。
  • 混合 RAG:结合多种检索技术,例如密集检索和稀疏检索,以增强不同查询类型的性能。密集检索使用向量嵌入来捕获语义相似性,而稀疏检索则依赖基于关键字的方法(例如 BM25)来实现精确匹配。通过集成这些方法,混合 RAG 平衡了精度和召回率,使其在查询可能高度具体或抽象的场景中具有通用性。它在异构数据环境中特别有效,确保在检索过程中同时考虑高级语义和特定关键字。
  • 代理 RAG(路由器):采用决策层根据查询的特征动态地将查询路由到适当的检索和生成模块。路由器分析传入的查询以确定最佳处理路径,这可能涉及不同的检索方法、数据源,甚至专门的生成模型。这种方法确保系统根据每个查询的特定需求定制其操作,从而提高不同应用程序的效率和准确性。
  • 代理 RAG(多代理 RAG):多代理 RAG 涉及一个协作框架,其中多个专门代理处理检索和生成过程的不同方面。每个代理负责特定的任务,例如从特定域检索数据、对结果重新排序或以特定样式生成响应。这些代理进行沟通和协作以提供有凝聚力的输出。多代理 RAG 对于复杂的多域查询特别强大,因为它使系统能够利用不同代理的专业知识来提供全面且细致入微的响应。

RAG的应用

检索增强生成(RAG)框架由于其能够将外部知识动态集成到生成语言模型中,因此在各个行业具有广泛的应用。以下是一些突出的应用:

  • 客户支持和服务:RAG 系统广泛用于客户支持,以创建能够通过从产品手册、知识库和公司政策文档中检索相关数据来回答复杂查询的智能聊天机器人。这可确保客户收到准确且最新的信息,从而增强他们的体验。
  • 法律文档分析:在法律领域,RAG 可以从大量判例法、合同和法律文档中解析、检索并生成摘要或答案。它对于进行法律研究、起草合同和确保遵守法规特别有用。
  • 财务分析:RAG 在金融服务中用于分析收益报告、市场趋势和监管文件。通过检索相关财务数据,它可以帮助分析师生成见解、报告,甚至对有关市场表现的查询提供实时答案。
  • 医疗保健和医疗诊断:在医疗保健中,RAG 用于检索和综合来自医学文献、患者记录和治疗指南的信息。它有助于诊断支持、药物发现和个性化治疗建议,确保临床医生能够获得最新、最相关的数据。
  • 教育和电子学习:RAG 驱动的工具通过检索课程材料并生成量身定制的答案或学习指南来协助个性化教育。他们可以根据用户查询提供上下文解释和动态内容来增强学习平台。
  • 电子商务和零售:在电子商务中,RAG 系统通过从目录和客户评论中检索数据来改进产品搜索和推荐引擎。它们还支持对话式购物助理,根据用户偏好提供个性化的产品建议。
  • 智能虚拟助理:RAG 通过提供准确且与上下文相关的响应来增强 Alexa 或 Siri 等虚拟助理,特别是对于需要外部知识的查询,例如实时天气更新或本地商业信息。

使用RAG构建PDF聊天系统

在本节中,我们将开发一个 Streamlit 应用程序,能够理解 PDF 的内容并使用检索增强生成 (RAG) 根据该内容响应用户查询。该实施利用 LangChain 平台来促进与法学硕士和向量商店的交互。我们将利用 OpenAI 的 LLM 及其嵌入模型构建 FAISS 矢量存储,以实现高效的信息检索。

安装依赖项

  • 通过执行以下命令创建并激活虚拟环境。
python -m venv venv
source venv/bin/activate #for ubuntu
venv/Scripts/activate #for windows
登录后复制
  • 使用 pip 安装 langchain、langchain_community、openai、faiss-cpu、PyPDF2、streamlit、python-dotenv、tiktoken 库。
pip install langchain langchain_community openai faiss-cpu PyPDF2 streamlit python-dotenv tiktoken
登录后复制

设置环境和凭据

  • 创建一个名为 .env 的文件。该文件将存储您的环境变量,包括 OpenAI 密钥、模型和嵌入。
  • 打开 .env 文件并添加以下代码以指定您的 OpenAI 凭据:
OPENAI_API_KEY=sk-proj-xcQxBf5LslO62At...
OPENAI_MODEL_NAME=gpt-3.5-turbo
OPENAI_EMBEDDING_MODEL_NAME=text-embedding-3-small
登录后复制

导入环境变量

  • 创建一个名为app.py的文件。
  • 将 OpenAI 凭据添加到环境变量中。
from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME")
OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME")
登录后复制

导入所需的库

导入用于构建应用程序、处理 PDF 的基本库,例如 langchain、streamlit、pyPDF。

import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_models import ChatOpenAI
from htmlTemplates import bot_template, user_template, css
登录后复制

定义从 PDF 中提取文本的函数

  • 使用 PyPDF2 从上传的 PDF 文件中提取文本。
def get_pdf_text(pdf_files):
    text = ""
    for pdf_file in pdf_files:
        reader = PdfReader(pdf_file)
        for page in reader.pages:
            text += page.extract_text()
    return text
登录后复制

将提取的文本分割成块

使用 LangChain 的 CharacterTextSplitter 将大文本分成更小的、可管理的块。

def get_chunk_text(text):
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    chunks = text_splitter.split_text(text)
    return chunks
登录后复制

为文本嵌入创建向量存储

生成文本块的嵌入并使用 FAISS 将它们存储在矢量数据库中。

def get_vector_store(text_chunks):
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY, model=OPENAI_EMBEDDING_MODEL_NAME)
    vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings)
    return vectorstore
登录后复制

构建会话检索链

定义一个从向量存储中检索信息并通过 LLM 与用户交互的链。

def get_conversation_chain(vector_store):
    llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model_name=OPENAI_MODEL_NAME, temperature=0)
    memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)
    system_template  =  """
    Use  the following pieces of context and chat history to answer the question at the end. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.

    Context: {context}

    Chat history: {chat_history}

    Question: {question}
    Helpful Answer:
    """
    prompt = PromptTemplate(
        template=system_template,
        input_variables=["context", "question",  "chat_history"],
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        verbose = True,
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt}
    )
    return conversation_chain
登录后复制

处理用户查询

处理用户输入,将其传递到对话链,并更新聊天记录。

def handle_user_input(question):
    try:
        response = st.session_state.conversation({'question': question})
        st.session_state.chat_history = response['chat_history']
    except Exception as e:
        st.error('Please select PDF and click on Process.')
登录后复制

为简化聊天创建自定义 HTML 模板

要使用 CSS 为用户和机器人消息创建自定义聊天界面,请设计自定义模板并使用 CSS 对其进行样式设置。

  • 创建一个名为 htmlTemplates.py 的文件并添加以下代码。
css = '''
<style>
.chat-message {
    padding: 1rem; border-radius: 0.5rem; margin-bottom: 1rem; display: flex
}
.chat-message.user {
    background-color: #2b313e
}
.chat-message.bot {
    background-color: #475063
}
.chat-message .avatar {
  width: 10%;
}
.chat-message .avatar img {
  max-width: 30px;
  max-height: 30px;
  border-radius: 50%;
  object-fit: cover;
}
.chat-message .message {
  width: 90%;
  padding: 0 1rem;
  color: #fff;
}
'''

bot_template = '''
<div>



<h3>
  
  
  Displaying chat history
</h3>

<p>Show the user and AI conversation history in a reverse order with HTML templates for formatting.<br>
</p>

<pre class="brush:php;toolbar:false">def display_chat_history():
    if st.session_state.chat_history:
        reversed_history = st.session_state.chat_history[::-1]

        formatted_history = []
        for i in range(0, len(reversed_history), 2):
            chat_pair = {
                "AIMessage": reversed_history[i].content,
                "HumanMessage": reversed_history[i + 1].content
            }
            formatted_history.append(chat_pair)

        for i, message in enumerate(formatted_history):
            st.write(user_template.replace("{{MSG}}", message['HumanMessage']), unsafe_allow_html=True)
            st.write(bot_template.replace("{{MSG}}", message['AIMessage']), unsafe_allow_html=True)
登录后复制

构建 Streamlit 应用程序界面

设置应用程序主界面,用于文件上传、问题输入和聊天记录显示。

def main():
    st.set_page_config(page_title='Chat with PDFs', page_icon=':books:')
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header('Chat with PDFs :books:')

    question = st.text_input("Ask anything to your PDF:")
    if question:
        handle_user_input(question)

    if st.session_state.chat_history is not None:
        display_chat_history()

    with st.sidebar:
        st.subheader("Upload your Documents Here: ")
        pdf_files = st.file_uploader("Choose your PDF Files and Press Process button", type=['pdf'], accept_multiple_files=True)

        if pdf_files and st.button("Process"):
            with st.spinner("Processing your PDFs..."):
                try:
                    # Get PDF Text
                    raw_text = get_pdf_text(pdf_files)
                    # Get Text Chunks
                    text_chunks = get_chunk_text(raw_text)
                    # Create Vector Store
                    vector_store = get_vector_store(text_chunks)
                    st.success("Your PDFs have been processed successfully. You can ask questions now.")
                    # Create conversation chain
                    st.session_state.conversation = get_conversation_chain(vector_store)
                except Exception as e:
                    st.error(f"An error occurred: {e}")

if __name__ == '__main__':
    main()
登录后复制

PDF 聊天应用程序的完整代码

以下是 PDF 聊天应用程序的完整代码实现。它将环境变量设置、文本提取、矢量存储和 RAG 功能集成到简化的解决方案中:

from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME")
OPENAI_EMBEDDING_MODEL_NAME = os.getenv("OPENAI_EMBEDDING_MODEL_NAME")

import streamlit as st
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import PromptTemplate
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_models import ChatOpenAI
from htmlTemplates import bot_template, user_template, css

def get_pdf_text(pdf_files):
    text = ""
    for pdf_file in pdf_files:
        reader = PdfReader(pdf_file)
        for page in reader.pages:
            text += page.extract_text()
    return text

def get_chunk_text(text):
    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    chunks = text_splitter.split_text(text)
    return chunks

def get_vector_store(text_chunks):
    embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY, model=OPENAI_EMBEDDING_MODEL_NAME)
    vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings)
    return vectorstore

def get_conversation_chain(vector_store):
    llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model_name=OPENAI_MODEL_NAME, temperature=0)
    memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)
    system_template  =  """
    Use  the following pieces of context and chat history to answer the question at the end. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.

    Context: {context}

    Chat history: {chat_history}

    Question: {question}
    Helpful Answer:
    """
    prompt = PromptTemplate(
        template=system_template,
        input_variables=["context", "question",  "chat_history"],
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        verbose = True,
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt}
    )
    return conversation_chain

def handle_user_input(question):
    try: 
        response = st.session_state.conversation({'question': question})
        st.session_state.chat_history = response['chat_history']
    except Exception as e:
        st.error('Please select PDF and click on OK.')

def display_chat_history():
    if st.session_state.chat_history:
        reversed_history = st.session_state.chat_history[::-1]

        formatted_history = []
        for i in range(0, len(reversed_history), 2):
            chat_pair = {
                "AIMessage": reversed_history[i].content,
                "HumanMessage": reversed_history[i + 1].content
            }
            formatted_history.append(chat_pair)

        for i, message in enumerate(formatted_history):
            st.write(user_template.replace("{{MSG}}", message['HumanMessage']), unsafe_allow_html=True)
            st.write(bot_template.replace("{{MSG}}", message['AIMessage']), unsafe_allow_html=True)

def main():
    st.set_page_config(page_title='Chat with PDFs', page_icon=':books:')
    st.write(css, unsafe_allow_html=True)

    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None

    st.header('Chat with PDFs :books:')

    question = st.text_input("Ask anything to your PDF:")
    if question:
        handle_user_input(question)

    if st.session_state.chat_history is not None:
        display_chat_history()

    with st.sidebar:
        st.subheader("Upload your Documents Here: ")
        pdf_files = st.file_uploader("Choose your PDF Files and Press Process button", type=['pdf'], accept_multiple_files=True)

        if pdf_files and st.button("Process"):
            with st.spinner("Processing your PDFs..."):
                try:
                    # Get PDF Text
                    raw_text = get_pdf_text(pdf_files)
                    # Get Text Chunks
                    text_chunks = get_chunk_text(raw_text)
                    # Create Vector Store
                    vector_store = get_vector_store(text_chunks)
                    st.success("Your PDFs have been processed successfully. You can ask questions now.")
                    # Create conversation chain
                    st.session_state.conversation = get_conversation_chain(vector_store)
                except Exception as e:
                    st.error(f"An error occurred: {e}")

if __name__ == '__main__':
    main()

登录后复制

运行应用程序

使用以下命令通过 Streamlit 执行应用程序。

streamlit run app.py
登录后复制

您将得到如下输出,
The ultimate guide to Retrieval-Augmented Generation (RAG)

感谢您阅读这篇文章!!

感谢 Gowri M Bhatt 审阅内容。

如果您喜欢这篇文章,请点击心形按钮♥并分享以帮助其他人找到它!

本教程的完整源代码可以在这里找到,

codemaker2015/pdf-chat-using-RAG | github.com

资源

  • RAG 和 LLM 业务流程自动化:技术策略 - Grid Dynamics | www.griddynamics.com
  • 检索增强生成 (RAG) 简介 |维阿维
  • 增强语言模型的技术、挑战和未来 - 梯度流
  • 行星规模检索增强一代|弧形

以上是检索增强生成 (RAG) 的终极指南的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板