logo
Loading...

補充: 使用 Streamlit 建立多模態 RAG 應用程式:詳細教學 - RAG技術: 智能助手開發實戰 - Cupoy

在這篇教學中,我們將詳細介紹如何使用 Streamlit 來建立一個多模態的 RAG(Retrieval-Augmented Generation)應用程式。本應用程式允許使用者上傳 PDF 檔案,並...

在這篇教學中,我們將詳細介紹如何使用 Streamlit 來建立一個多模態的 RAG(Retrieval-Augmented Generation)應用程式。本應用程式允許使用者上傳 PDF 檔案,並透過結合文本、表格和圖像等多種資料,實現智能的問答和評估功能。 目錄 環境準備 程式碼導覽 導入必要的函式庫 初始化 Session State 設定 Streamlit 應用程式 文件處理流程 PDF 元素提取 內容分塊 元素分類 摘要生成 圖像摘要生成 建立向量儲存和檢索器 建立 RAG 鏈 使用者介面說明 上傳 PDF 檔案 查詢回應和評估 結論 環境準備 在開始之前,請確保已安裝以下工具和函式庫: Python 3.7 以上版本 Streamlit Unstructured NLTK LangChain OpenAI API Chroma Pydantic 其他相關函式庫 請確保已經設定好 OpenAI API 的金鑰,並且可以順利連線至所需的服務。 程式碼導覽 接下來,我們將逐步解析程式碼,並說明每個部分的功能。 導入必要的函式庫 import streamlit as st from unstructured.partition.pdf import partition_pdf from unstructured.chunking.title import chunk_by_title from typing import Any from pydantic import BaseModel from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_chroma import Chroma from langchain_openai import OpenAIEmbeddings from utils.image_processing import generate_img_summaries from utils.retriever import create_multi_vector_retriever from utils.rag_chain import multi_modal_rag_chain, plt_img_base64 from utils.rag_evaluation import LLM_Metric from io import BytesIO import nltk import ssl import os from dotenv import load_dotenv 首先,我們導入了所需的函式庫,包括 Streamlit、Unstructured、LangChain 等,以及自定義的工具模組,例如 image_processing、retriever、rag_chain 和 rag_evaluation。 # Initialize session state if 'processed' not in st.session_state: st.session_state.processed = False if 'retriever' not in st.session_state: st.session_state.retriever = None if 'chain' not in st.session_state: st.session_state.chain = None 為了在應用程式中保持狀態,我們使用了 st.session_state。這可以讓我們在不同的使用者互動之間保存變數的值,例如檔案是否已處理、檢索器和 RAG 鏈的狀態。 設定 Streamlit 應用程式 st.set_page_config( page_title='Multi-Modal RAG Application', page_icon='random', layout='wide', initial_sidebar_state='auto' ) 這部分設定了 Streamlit 應用程式的頁面配置,包括標題、圖標、佈局和側邊欄的狀態。 文件處理流程 PDF 元素提取 def process_document(uploaded_file): # Process PDF with st.spinner('Processing PDF...'): st.sidebar.info('Extracting elements from PDF...') pdf_bytes = uploaded_file.read() elements = partition_pdf( file=BytesIO(pdf_bytes), strategy="hi_res", extract_images_in_pdf=True, extract_image_block_types=["Image", "Table"], extract_image_block_to_payload=False, extract_image_block_output_dir="docs/saved_images", ) st.sidebar.success('PDF elements extracted successfully!') 當使用者上傳 PDF 檔案後,應用程式會讀取檔案並使用 partition_pdf 函式提取其中的元素。我們設定了高解析度策略,並提取圖像和表格等元素,將圖像儲存到指定的目錄。 內容分塊 # Create chunks by title with st.spinner('Chunking content...'): st.sidebar.info('Creating chunks by title...') chunks = chunk_by_title(elements) st.sidebar.success('Chunking completed successfully!') 提取元素後,我們使用 chunk_by_title 函式根據標題將內容分塊,方便後續的處理和分析。 元素分類 # Categorize Elements class Element(BaseModel): type: str text: Any categorized_elements = [] for element in chunks: if "unstructured.documents.elements.CompositeElement" in str(type(element)): categorized_elements.append(Element(type="text", text=str(element))) elif "unstructured.documents.elements.Table" in str(type(element)): categorized_elements.append(Element(type="table", text=str(element))) text_elements = [e for e in categorized_elements if e.type == "text"] table_elements = [e for e in categorized_elements if e.type == "table"] 我們定義了一個 Element 類別,並將分塊的內容分類為文本或表格。這有助於我們在後續針對不同類型的內容進行特定的處理。 摘要生成 # Prompt prompt_text = """You are an expert Research Assistant tasked with summarizing tables and texts from research articles. \ Give a concise summary of the text. text chunk: {element} """ prompt = ChatPromptTemplate.from_template(prompt_text) # Summary chain model = ChatOpenAI(temperature=0, model="gpt-4o", max_tokens=1024) summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser() texts = [i.text for i in text_elements] text_summaries = summarize_chain.batch(texts, {"max_concurrency": 5}) tables = [i.text for i in table_elements] table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5}) 我們使用了 OpenAI 的模型(如 gpt-4o)來生成文本和表格的摘要。首先,定義了一個提示模板,然後建立了一個摘要鏈,最後批量處理文本和表格,生成對應的摘要。 圖像摘要生成 # Image summaries fpath = "docs/saved_images" img_base64_list, image_summaries = generate_img_summaries(fpath) 這部分使用自定義的 generate_img_summaries 函式,對提取的圖像進行摘要生成。函式會返回圖像的 Base64 編碼列表和對應的摘要。 建立向量儲存和檢索器 # Vectorstore vectorstore = Chroma( collection_name="mm_tagiv_paper", embedding_function=OpenAIEmbeddings() ) # Create retriever st.session_state.retriever = create_multi_vector_retriever( vectorstore, text_summaries, texts, table_summaries, tables, image_summaries, img_base64_list, ) 我們使用了 Chroma 來建立向量儲存,並使用 OpenAI 的嵌入函式。接著,利用 create_multi_vector_retriever 函式建立了一個多向量的檢索器,將文本、表格和圖像的摘要和原始內容整合在一起。 建立 RAG 鏈 # Create RAG chain st.session_state.chain = multi_modal_rag_chain(retriever=st.session_state.retriever) st.session_state.processed = True 最後,使用 multi_modal_rag_chain 函式建立了一個多模態的 RAG 鏈,並將檔案處理的狀態設定為 True,表示已完成處理。 使用者介面說明 上傳 PDF 檔案 with st.sidebar: # File upload st.subheader('Add your PDF') uploaded_file = st.file_uploader("Upload a PDF file", type=["pdf"]) if st.button('Submit'): if uploaded_file is not None: process_document(uploaded_file) st.success('Document processed successfully!') else: st.error('Please upload a PDF file first.') 在側邊欄中,使用者可以上傳 PDF 檔案。按下「Submit」按鈕後,若有上傳檔案,將呼叫 process_document 函式進行處理,否則提示請先上傳檔案。 查詢回應和評估 # Main page for query response and evaluation st.subheader("RAG Assistant") query = st.text_input("Enter your query:") if query and st.session_state.processed: # Execution retrieval_context = st.session_state.retriever.invoke(query, limit=1) actual_output = st.session_state.chain(query) # Evaluation llm_metric = LLM_Metric(query, retrieval_context, actual_output) faith_score, faith_reason = llm_metric.get_faithfulness_metric() relevancy_score, relevancy_reason = llm_metric.get_contextual_relevancy_metric() answer_relevancy_score, answer_relevancy_reason = llm_metric.get_answer_relevancy_metric() hallucination_score, hallucination_reason = llm_metric.get_hallucination_metric() # Display results st.subheader("Query Response") st.write(actual_output) st.subheader("Evaluation Metrics") st.write(f"Faithfulness Score: {faith_score}, Reason: {faith_reason}") st.write(f"Contextual Relevancy Score: {relevancy_score}, Reason: {relevancy_reason}") st.write(f"Answer Relevancy Score: {answer_relevancy_score}, Reason: {answer_relevancy_reason}") st.write(f"Hallucination Score: {hallucination_score}, Reason: {hallucination_reason}") elif query and not st.session_state.processed: st.warning("Please upload and process a document first.") 在主頁面中,使用者可以輸入查詢。若已處理檔案,應用程式將: 使用檢索器取得相關內容。 使用 RAG 鏈生成回應。 利用 LLM_Metric 進行評估,包括真實性、上下文相關性、答案相關性和幻覺分數。 顯示生成的回應和評估結果。 若未處理檔案,則提示使用者先上傳並處理文件。 結論 透過本教學,我們詳細介紹了如何使用 Streamlit 和相關的 AI 工具,建立一個多模態的 RAG 應用程式。我們涵蓋了從檔案上傳、內容處理、摘要生成到查詢回應和評估的完整流程。希望這篇文章能夠幫助您理解並實現類似的應用程式。 實作工作流: 從建立虛擬環境到完整執行應用程式的詳細指南 在這篇文章中,我將指導您從建立 Python 虛擬環境(venv)到完整執行我們的多模態 RAG 應用程式。並且,我會幫您整理所需安裝的套件,並提供 requirements.txt 檔案的內容,以方便您安裝。 目錄 建立虛擬環境 啟動虛擬環境 創建 requirements.txt 檔案 安裝所需的套件 設定環境變數 執行應用程式 可能遇到的問題與解決方法 結論 建立虛擬環境 首先,我們需要在您的專案目錄中建立一個虛擬環境,以隔離專案的依賴關係。 步驟: 開啟終端機(Terminal)或命令提示字元(Command Prompt)。 導航到您的專案目錄: bash 複製程式碼 cd /path/to/your/project  建立虛擬環境: 如果您使用 Python 內建的 venv 模組: python3 -m venv venv  如果您的系統上有多個 Python 版本,請確保使用正確的版本: python3.8 -m venv venv  # 假設您使用 Python 3.8  啟動虛擬環境 步驟: 在 macOS/Linux 上: bash source venv/bin/activate  在 Windows 上: bash venv\Scripts\activate  啟動後,您會看到終端機提示符前面有 (venv),表示虛擬環境已啟動。 創建 requirements.txt 檔案 在您的專案目錄中,創建一個名為 requirements.txt 的檔案,並將以下內容複製貼上到該檔案中。 requirements.txt 內容: #txt streamlit==1.25.0 unstructured==0.8.3 nltk==3.8.1 langchain==0.0.308 openai==0.28.1 chromadb==0.4.13 pydantic==1.10.13 Pillow==10.0.0 python-dotenv==1.0.0 sentence-transformers==2.2.2 注意: 為了確保套件之間的兼容性,我已經為每個套件指定了版本號。如果您需要調整版本,請務必確認相容性。 安裝所需的套件 在啟動虛擬環境的狀態下,執行以下命令來安裝 requirements.txt 中列出的套件。 步驟: bash pip install --upgrade pip  # 先升級 pip install -r requirements.txt 這將自動安裝所有列出的套件及其依賴項。 其他需要的安裝和設定 NLTK 資料下載: 在您的程式碼中,已經有以下代碼來下載 NLTK 資料: python nltk.download('averaged_perceptron_tagger_eng')  如果您在執行時遇到 SSL 認證的問題,程式碼中已經處理了 SSL 認證繞過: python import ssl ssl._create_default_https_context = ssl._create_unverified_context  OpenAI API 金鑰設定: 您需要在專案目錄中創建一個 .env 檔案,並添加您的 OpenAI API 金鑰: env 複製程式碼 OPENAI_API_KEY=your_openai_api_key_here  請確保不要將 .env 檔案提交到版本控制系統中,以保護您的金鑰安全。 創建必要的目錄: 如果您的程式碼中使用了特定的目錄來保存圖像或其他資料,請確保這些目錄已經存在。例如: bash mkdir -p docs/saved_images  下載其他 NLTK 資料: 根據您的需求,您可能需要下載其他的 NLTK 資料集,例如: python nltk.download('punkt')  nltk.download('averaged_perceptron_tagger')  nltk.download('stopwords')  設定環境變數 在您的 .env 檔案中,除了 OPENAI_API_KEY,如果有其他環境變數需要設定,也可以在此添加。例如,如果您使用 Hugging Face Hub: env HUGGINGFACEHUB_API_TOKEN=your_huggingface_api_token_here 執行應用程式 在安裝完所有套件後,您可以使用 Streamlit 來執行應用程式。 步驟: 啟動虛擬環境(如果尚未啟動): bash 複製程式碼 source venv/bin/activate  # macOS/Linux  venv\Scripts\activate     # Windows  執行應用程式: 假設您的主程式碼文件名為 app.py,執行以下命令: streamlit run app.py  在瀏覽器中查看應用程式: Streamlit 會自動在您的預設瀏覽器中打開應用程式。如果沒有,您可以在終端機中看到一個類似以下的 URL,手動複製並在瀏覽器中打開: http://localhost:8501  可能遇到的問題與解決方法 套件版本不兼容: 如果您在安裝或執行時遇到套件版本不兼容的問題,請嘗試調整 requirements.txt 中的套件版本,並重新安裝。 缺少套件或模組: 如果在執行時提示缺少某個套件或模組,請手動安裝該套件。例如: pip install package_name  OpenAI 模型名稱錯誤: 確保您在程式碼中使用的 OpenAI 模型名稱是有效的。例如,gpt-4o 可能不是有效的模型名稱,請確認並使用正確的模型名稱,例如 gpt-4 或 gpt-3.5-turbo。 model = ChatOpenAI(temperature=0, model="gpt-4", max_tokens=1024)  SSL 認證問題: 如果在下載 NLTK 資料時遇到 SSL 認證問題,程式碼中已經添加了繞過 SSL 認證的解決方案。 路徑問題: 確保所有使用的路徑都是正確的,並且文件和目錄實際存在。 環境變數未正確讀取: 確保您已經安裝 python-dotenv,並在程式碼中正確載入環境變數: python 複製程式碼 from dotenv import load_dotenv load_dotenv()  結論 通過以上步驟,您應該能夠從建立虛擬環境到完整執行應用程式。如果在過程中遇到任何問題,請仔細檢查錯誤訊息,並根據提示進行調整。祝您順利完成應用程式的部署與運行! 備註: 請確保您的 Python 版本與套件的需求相匹配,並且始終在虛擬環境中操作,以避免影響全域的 Python 環境。