logo
Loading...

正課第七節 (應用) SQL RAG - RAG技術: 智能助手開發實戰 - Cupoy

這個程式整個工作流包括使用 Streamlit 建立一個前端介面,讓用戶透過自然語言查詢 SQL 資料庫中的數據。後端則使用 LangChain 來將用戶的自然語言查詢轉換為 SQL 語句,並利用語言...

這個程式整個工作流包括使用 Streamlit 建立一個前端介面,讓用戶透過自然語言查詢 SQL 資料庫中的數據。後端則使用 LangChain 來將用戶的自然語言查詢轉換為 SQL 語句,並利用語言模型(如 Groq 的 ChatGroq)來生成結果,最後通過 Streamlit 顯示查詢結果。 主要工作流程 啟動應用(Streamlit):當應用啟動時,Streamlit 會生成一個網頁界面,允許用戶選擇是使用 SQLite 資料庫還是 MySQL 資料庫,並在側邊欄輸入 MySQL 的連接信息(如果選擇 MySQL)。 資料庫連接配置: 如果用戶選擇使用本地的 SQLite 資料庫,系統會讀取 student.db 文件並打開該資料庫。 如果用戶選擇 MySQL 資料庫,系統會根據用戶輸入的 MySQL 連接參數(如主機、使用者名、密碼和資料庫名稱)連接 MySQL 資料庫。 語言模型初始化:根據 Groq 的 API 金鑰,應用初始化語言模型(LLM)ChatGroq,用於將自然語言查詢轉換成 SQL 查詢並從資料庫中獲取數據。 用戶查詢處理:用戶在界面上輸入查詢(如「查詢學生的成績」),這個查詢會通過 LangChain 的 SQL Agent 轉換為具體的 SQL 語句並查詢資料庫。 結果回應:SQL 查詢結果會通過語言模型生成的回應被流式顯示到 Streamlit 的聊天窗口中,展示給用戶。 互動式更新:訊息歷史會保存在 st.session_state 中,允許用戶進行多輪查詢,並且可以隨時清除訊息歷史。 建立虛擬環境及步驟 1. 安裝 Python 與虛擬環境工具: 確認已經安裝 Python 3.7 或更新版本。 安裝 venv 模組來管理虛擬環境(Python 內建)。 2. 建立虛擬環境: 打開終端或命令提示字元。 進入專案目錄,執行以下命令來建立虛擬環境: python -m venv env        3 .啟動虛擬環境:     Windows: .\env\Scripts\activate macOS/Linux: source env/bin/activate 4.安裝必要的依賴包: 在虛擬環境啟動後,使用 pip 安裝所有所需的套件。可以先創建一個 requirements.txt 檔案,內容如下: langchain python-dotenv ipykernel langchain-community pypdf bs4 arxiv pymupdf wikipedia langchain-text-splitters langchain-openai chromadb sentence_transformers langchain_huggingface faiss-cpu langchain_chroma duckdb pandas openai langchain-groq duckduckgo_search==5.3.1b1 pymupdf arxiv wikipedia mysql-connector-python SQLAlchemy validators==0.28.1 youtube_transcript_api unstructured pytube numexpr huggingface_hub #運行來安裝依賴 pip install -r requirements.txt 5.創建或確認資料庫文件: 如果使用的是 SQLite 資料庫,確認 student.db 文件位於專案根目錄中。 如果使用 MySQL,請準備好 MySQL 資料庫及其連接信息。 6. 運行應用: 使用 Streamlit 啟動應用: streamlit run your_script.py 這會啟動應用,並在瀏覽器中打開介面。 工作流總結 建立並啟動虛擬環境。 配置資料庫連接和語言模型。 用戶透過 Streamlit 介面輸入查詢。 語言模型將查詢轉換為 SQL 查詢,並查詢資料庫。 返回結果並顯示在界面上。 這樣的工作流幫助用戶從自然語言到資料庫查詢進行自動化處理,並提供流式的互動界面。 詳細解釋主程式: Streamlit 設定與應用標題:設置頁面配置,設定標題和圖標,並展示應用的標題。 資料庫選擇與連接:通過側邊欄,讓用戶選擇要連接的資料庫(SQLite 或 MySQL)。如果用戶選擇 MySQL,將會顯示 MySQL 的連接詳細信息表單。SQLite 是本地的 student.db 文件。 語言模型(LLM)設置:使用 Groq 的 ChatGroq 模型處理用戶的自然語言輸入,該模型會在對話中執行任務。使用 streaming=True 可以在輸出時逐步顯示結果。 資料庫配置函數:該函數根據用戶的選擇,配置並返回資料庫連接。SQLite 是本地文件資料庫,MySQL 則需要用戶輸入的連接信息。 SQL Agent 創建:SQL Agent 使用 LangChain 庫創建,負責將用戶的查詢轉換為 SQL 查詢,並與資料庫交互獲取數據。SQL Agent 通過 ZERO_SHOT_REACT_DESCRIPTION 策略,基於自然語言輸入生成 SQL 語句。 訊息記錄與用戶互動:應用保存用戶與助手之間的對話歷史,並通過聊天界面顯示。用戶輸入的查詢會被傳遞給 SQL Agent,該代理會將查詢結果流式輸出。 流式輸出回調處理:當 SQL Agent 執行查詢時,StreamlitCallbackHandler 將結果逐步展示到前端,提升用戶體驗。 可以問啥? 除了基本的數據查詢之外,你還可以進行更進階的查詢和操作,例如更新資料、刪除資料、進行數據分析或查詢結合。以下是一些進階查詢和操作的範例: ### 1. **更新學生的分數** 將學生 `Jacob` 的分數更新為 60: ```sql UPDATE STUDENT SET MARKS = 60 WHERE NAME = 'Jacob'; ``` **解釋**:這個查詢會將 `Jacob` 的分數從 50 更新為 60。 ### 2. **刪除特定學生記錄** 刪除分數低於 40 的學生記錄: ```sql DELETE FROM STUDENT WHERE MARKS ###draft_code_symbol_lessthen### 40; ``` **解釋**:這個查詢會刪除所有分數低於 40 的學生。 ### 3. **查詢每個分組的最高分數學生** 查詢每個分組中分數最高的學生: ```sql SELECT NAME, CLASS, SECTION, MAX(MARKS) FROM STUDENT GROUP BY SECTION; ``` **解釋**:這個查詢會根據分組(`SECTION`)分組,並返回每個分組中分數最高的學生。 ### 4. **查詢特定班級中有多少學生** 計算 `DEVOPS` 班級的學生數: ```sql SELECT COUNT(*) FROM STUDENT WHERE CLASS = 'DEVOPS'; ``` **解釋**:這個查詢會返回 `DEVOPS` 班級中的學生總數。 ### 5. **查詢學生的分數統計(最大值、最小值、平均值)** ```sql SELECT MAX(MARKS) as Max_Marks, MIN(MARKS) as Min_Marks, AVG(MARKS) as Average_Marks FROM STUDENT; ``` **解釋**:這個查詢會返回學生分數的最大值、最小值和平均值。 ### 6. **按分數區間統計學生數** 統計分數在不同區間內的學生數: ```sql SELECT CASE WHEN MARKS >= 90 THEN '90-100' WHEN MARKS >= 80 THEN '80-89' WHEN MARKS >= 70 THEN '70-79' ELSE '###draft_code_symbol_lessthen###70' END AS Score_Range, COUNT(*) as Student_Count FROM STUDENT GROUP BY Score_Range; ``` **解釋**:這個查詢會將學生的分數分為不同的區間(如 90-100、80-89 等),並統計每個區間內的學生數量。 ### 7. **查詢每個班級分數最高的學生** 查詢每個班級中分數最高的學生: ```sql SELECT NAME, CLASS, MAX(MARKS) FROM STUDENT GROUP BY CLASS; ``` **解釋**:這個查詢會返回每個班級中分數最高的學生。 ### 8. **計算分數超過 60 且位於特定班級的學生比例** ```sql SELECT (SELECT COUNT(*) FROM STUDENT WHERE MARKS > 60 AND CLASS = 'Data Science') * 100.0 / (SELECT COUNT(*) FROM STUDENT WHERE CLASS = 'Data Science') AS Percentage ``` **解釋**:這個查詢會計算在 `Data Science` 班級中,分數超過 60 的學生比例。 ### 9. **查詢學生的分數排名** 查詢所有學生,並根據分數進行排名: ```sql SELECT NAME, CLASS, SECTION, MARKS, RANK() OVER (ORDER BY MARKS DESC) AS Rank FROM STUDENT; ``` **解釋**:這個查詢會根據學生的分數進行排名,分數最高的學生排名靠前。 ### 10. **按班級和分組進行細分類別的分數統計** 計算每個班級和分組的學生平均分數: ```sql SELECT CLASS, SECTION, AVG(MARKS) AS Average_Marks FROM STUDENT GROUP BY CLASS, SECTION; ``` **解釋**:這個查詢會根據班級和分組分組,並計算每個組別的平均分數。 ### 11. **查詢學生的分數是否及格** 新增一個欄位來顯示學生是否及格(以 60 分為及格標準): ```sql SELECT NAME, CLASS, SECTION, MARKS, CASE WHEN MARKS >= 60 THEN 'Pass' ELSE 'Fail' END AS Result FROM STUDENT; ``` **解釋**:這個查詢會新增一個結果欄位,顯示學生的成績是否達到 60 分及格。 ### 12. **查詢某班級分數超過班級平均分的學生** 查詢 `Data Science` 班級中,分數超過該班級平均分數的學生: ```sql SELECT * FROM STUDENT WHERE CLASS = 'Data Science' AND MARKS > (SELECT AVG(MARKS) FROM STUDENT WHERE CLASS = 'Data Science'); ``` **解釋**:這個查詢會查詢 `Data Science` 班級中,分數超過該班級平均分數的學生。 --- ### 進階查詢與分析操作: - **資料表結合查詢(JOIN)**:如果你有多個資料表,可以使用 `JOIN` 來查詢不同表中的相關數據。 - **索引和效能優化**:當你的資料表變得更大時,考慮使用索引來加速查詢。 - **複雜的分析查詢**:如使用 `GROUP BY`、`HAVING`、`WITH`(Common Table Expressions, CTEs)等進行高階資料分析。 這些進階查詢讓你可以進行更精細的資料操作和分析,並進一步擴展你在 `STUDENT` 資料庫上的應用。你可以根據具體需求進行修改或組合查詢來滿足不同的應用情景。 import streamlit as st from pathlib import Path from langchain.agents import create_sql_agent from langchain.sql_database import SQLDatabase from langchain.agents.agent_types import AgentType from langchain.callbacks import StreamlitCallbackHandler from langchain.agents.agent_toolkits import SQLDatabaseToolkit from sqlalchemy import create_engine import sqlite3 from langchain_groq import ChatGroq st.set_page_config(page_title="LangChain: Chat with SQL DB", page_icon="🦜") st.title("🦜 LangChain: Chat with SQL DB") LOCALDB="USE_LOCALDB" MYSQL="USE_MYSQL" radio_opt=["Use SQLLite 3 Database- Student.db","Connect to you MySQL Database"] selected_opt=st.sidebar.radio(label="Choose the DB which you want to chat",options=radio_opt) if radio_opt.index(selected_opt)==1: db_uri=MYSQL mysql_host=st.sidebar.text_input("Provide MySQL Host") mysql_user=st.sidebar.text_input("MYSQL User") mysql_password=st.sidebar.text_input("MYSQL password",type="password") mysql_db=st.sidebar.text_input("MySQL database") else: db_uri=LOCALDB api_key=st.sidebar.text_input(label="GRoq API Key",type="password") if not db_uri: st.info("Please enter the database information and uri") if not api_key: st.info("Please add the groq api key") ## LLM model llm=ChatGroq(groq_api_key=api_key,model_name="Llama3-8b-8192",streaming=True) @st.cache_resource(ttl="2h") def configure_db(db_uri,mysql_host=None,mysql_user=None,mysql_password=None,mysql_db=None): if db_uri==LOCALDB: dbfilepath=(Path(__file__).parent/"student.db").absolute() print(dbfilepath) creator = lambda: sqlite3.connect(f"file:{dbfilepath}?mode=ro", uri=True) return SQLDatabase(create_engine("sqlite:///", creator=creator)) elif db_uri==MYSQL: if not (mysql_host and mysql_user and mysql_password and mysql_db): st.error("Please provide all MySQL connection details.") st.stop() return SQLDatabase(create_engine(f"mysql+mysqlconnector://{mysql_user}:{mysql_password}@{mysql_host}/{mysql_db}")) if db_uri==MYSQL: db=configure_db(db_uri,mysql_host,mysql_user,mysql_password,mysql_db) else: db=configure_db(db_uri) ## toolkit toolkit=SQLDatabaseToolkit(db=db,llm=llm) agent=create_sql_agent( llm=llm, toolkit=toolkit, verbose=True, agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION ) if "messages" not in st.session_state or st.sidebar.button("Clear message history"): st.session_state["messages"] = [{"role": "assistant", "content": "How can I help you?"}] for msg in st.session_state.messages: st.chat_message(msg["role"]).write(msg["content"]) user_query=st.chat_input(placeholder="Ask anything from the database") if user_query: st.session_state.messages.append({"role": "user", "content": user_query}) st.chat_message("user").write(user_query) with st.chat_message("assistant"): streamlit_callback=StreamlitCallbackHandler(st.container()) response=agent.run(user_query,callbacks=[streamlit_callback]) st.session_state.messages.append({"role":"assistant","content":response}) st.write(response) 程式功能概述: 這段 Python 程式使用 SQLite 資料庫,建立了一個 STUDENT 表,並插入了幾條學生記錄,最後顯示了所有插入的記錄。這個範例展示了如何使用 SQLite 來操作本地資料庫。 import sqlite3 # 導入 SQLite 模組,用於操作本地 SQLite 資料庫 # 1. 與 SQLite 資料庫建立連接。如果 "student.db" 文件不存在,SQLite 會自動創建該文件。 connection = sqlite3.connect("student.db") # 2. 創建一個游標對象 (cursor),用於執行 SQL 查詢 cursor = connection.cursor() # 3. 建立 STUDENT 資料表,資料表包含四個欄位:NAME(學生姓名)、CLASS(班級)、SECTION(分組)和 MARKS(分數) table_info = """ CREATE TABLE IF NOT EXISTS STUDENT ( NAME VARCHAR(25), CLASS VARCHAR(25), SECTION VARCHAR(25), MARKS INT ) """ # 4. 執行資料表的創建語句。如果表已存在,則跳過創建 cursor.execute(table_info) # 5. 插入記錄:插入五條學生的記錄,包含學生姓名、班級、分組和分數 cursor.execute('''INSERT INTO STUDENT VALUES ('Krish', 'Data Science', 'A', 90)''') cursor.execute('''INSERT INTO STUDENT VALUES ('John', 'Data Science', 'B', 100)''') cursor.execute('''INSERT INTO STUDENT VALUES ('Mukesh', 'Data Science', 'A', 86)''') cursor.execute('''INSERT INTO STUDENT VALUES ('Jacob', 'DEVOPS', 'A', 50)''') cursor.execute('''INSERT INTO STUDENT VALUES ('Dipesh', 'DEVOPS', 'A', 35)''') # 6. 顯示所有插入的記錄 print("The inserted records are:") # 執行 SQL 查詢,選取 STUDENT 表中的所有記錄 data = cursor.execute('''SELECT * FROM STUDENT''') # 迭代查詢結果,並逐行列印出來 for row in data: print(row) # 7. 提交對資料庫所做的變更(包括插入和表的創建) connection.commit() # 8. 關閉資料庫連接,釋放資源 connection.close() 詳細解釋步驟: 與 SQLite 資料庫建立連接: sqlite3.connect("student.db"):如果 student.db 資料庫文件存在,則打開它;如果不存在,則創建一個新的資料庫文件。這是一個本地的 SQLite 資料庫,位於程式的當前目錄中。 創建游標對象: cursor = connection.cursor():游標用於執行 SQL 語句並返回查詢結果。它是與資料庫進行互動的主要接口。 建立 STUDENT 資料表: CREATE TABLE IF NOT EXISTS STUDENT (...):這段 SQL 語句定義了 STUDENT 表結構,包括四個欄位: NAME:儲存學生姓名的欄位,字串類型,長度最多 25。 CLASS:儲存班級名稱,字串類型,長度最多 25。 SECTION:儲存分組名稱,字串類型,長度最多 25。 MARKS:儲存學生分數,整數類型。 IF NOT EXISTS:這個語句確保只有當表不存在時才會創建表。 插入學生記錄: INSERT INTO STUDENT VALUES (...):這些 SQL 語句插入五條學生記錄到 STUDENT 表中。每條記錄包含學生的姓名、班級、分組和分數。 查詢並顯示所有學生記錄: SELECT * FROM STUDENT:這段 SQL 語句選取 STUDENT 表中的所有欄位和記錄。 for row in data::迭代查詢結果,並逐行列印每個學生的資訊(姓名、班級、分組、分數)。 提交變更: connection.commit():將對資料庫的變更(例如表的創建和記錄的插入)提交到資料庫。如果不調用這個方法,變更將不會永久儲存在資料庫中。 關閉資料庫連接: connection.close():關閉與資料庫的連接,釋放相關資源。這是良好的程式習慣,以確保不會佔用系統資源。 工作流程總結: 建立資料庫連接。 創建資料表(如果尚未存在)。 插入多筆學生記錄。 查詢並顯示所有學生記錄。 提交資料庫變更。 關閉連接。 這個工作流程展示了如何使用 SQLite 管理一個本地資料庫,從創建表到插入數據並顯示結果,最後提交並保存數據。 總結: 這個應用程序通過 Streamlit 介面實現了一個與 SQL 資料庫互動的聊天系統,結合語言模型,將用戶的自然語言查詢轉換為 SQL 查詢並返回結果。