在本文中,我們將開始使用一個名為Chinook的範例資料函式庫,這將是我們DBCopilot的基礎。Chinook資料函式庫代表一個虛構的數位媒體商店,包含有關藝術家、專輯、媒體軌道、發票等的資訊。我們將檢查這個資料函式庫並探索如何使用Python連線到資料表。

設定環境

首先,我們需要安裝必要的Python套件:

# 安裝所需套件
pip install langchain python-dotenv huggingface_hub streamlit sqlite3

連線到Chinook資料函式庫

以下是連線到SQLite版本的Chinook資料函式庫的基本程式碼:

import sqlite3
import pandas as pd

# 連線到Chinook資料函式庫
conn = sqlite3.connect('chinook.db')

# 建立一個遊標物件
cursor = conn.cursor()

# 執行簡單查詢來檢查連線
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()

print("資料函式庫中的表格:")
for table in tables:
    print(table[0])

這段程式碼展示瞭如何使用Python的sqlite3模組連線到SQLite資料函式庫。首先我們匯入必要的模組:sqlite3用於資料函式庫連線,pandas用於資料處理。然後建立與chinook.db資料函式庫檔案的連線,並建立一個遊標物件來執行SQL命令。

接著執行一個SQL查詢,從sqlite_master系統表中取得所有表格的名稱。這是檢查資料函式庫結構的常用方法。最後,我們迭代查詢結果並列印每個表格的名稱,這有助於我們瞭解資料函式庫的整體結構。

探索Chinook資料函式庫結構

讓我們進一步探索Chinook資料函式庫的結構:

# 檢查特定表格的結構
def explore_table(table_name):
    cursor.execute(f"PRAGMA table_info({table_name});")
    columns = cursor.fetchall()
    
    print(f"\n{table_name}表格的結構:")
    for col in columns:
        print(f"欄位名稱: {col[1]}, 型別: {col[2]}, 是否為主鍵: {col[5]}")
    
    # 取得表格中的前5條記錄
    cursor.execute(f"SELECT * FROM {table_name} LIMIT 5;")
    rows = cursor.fetchall()
    
    print(f"\n{table_name}表格的前5條記錄:")
    for row in rows:
        print(row)

# 探索幾個關鍵表格
explore_table("Artist")
explore_table("Album")
explore_table("Track")
explore_table("Customer")
explore_table("Invoice")

這段程式碼定義了一個名為explore_table的函式,用來檢查資料函式庫中特定表格的結構和內容。函式首先執行PRAGMA table_info命令來取得表格的列訊息,包括列名、資料型別和主鍵標記。然後列印這些訊息,幫助我們理解表格的結構。

接著,函式執行一個簡單的SELECT查詢,取得表格中的前5條記錄並列印出來,這讓我們能夠快速瞭解表格中實際儲存的資料型別和格式。最後,我們針對Chinook資料函式庫中的幾個關鍵表格(Artist、Album、Track、Customer和Invoice)呼叫這個函式,全面瞭解資料函式庫的結構和內容。

瞭解表格間的關係

理解表格之間的關係對於構建有效的查詢

關聯式資料函式庫中的資料關係:深入理解與實踐

關聯式資料函式庫的核心優勢在於其嚴謹的資料結構和表格間的關聯性。在實際開發中,理解這些關聯對於有效處理資料至關重要。讓我們透過一個具體例子來理解:

在典型的資料函式庫設計中,「作者」與「書籍」通常是兩個獨立但相關的實體。作者資料表包含作者ID、姓名和出生年份等資訊;而書籍資料表則包含書籍ID、標題,以及一個外部索引鍵「AuthorID」,這個外部索引鍵參照作者資料表中的主鍵。

這種設計允許我們使用SQL查詢來取得各種有用的資訊,例如:

  • 查詢特定作者撰寫的所有書籍
  • 根據書籍反查作者的出生年份
  • 分析某作者的出版趨勢

關聯式結構使資料管理和檢索變得系統化與高效,這也是為什麼在企業級應用中,關聯式資料函式庫仍然佔據主導地位。

市場主流資料函式庫系統概覽

資料函式庫市場提供了多種選擇,每種都有其獨特的優勢和適用場景:

傳統SQL資料函式庫

傳統的關聯式資料函式倉管理系統(RDBMS)如MySQL、PostgreSQL和Microsoft SQL Server,都使用SQL進行資料操作和查詢。這些系統經過長期發展,穩定性和生態系統都相當成熟。

企業級解決方案

Oracle Database提供了高階功能和可擴充套件性,適用於大型企業應用;而IBM Db2則是IBM開發的資料管理產品家族,包含多種關聯式資料函式庫伺服器。

嵌入式和輕量級選項

SQLite作為一個自包含、無伺服器和零設定的SQL資料函式庫引擎,常用於嵌入式系統和移動應用程式。其輕量級特性和與Python的無縫整合使其成為學習和小型專案的理想選擇。

雲端服務

雲端服務提供商也提供了管理完善的資料函式庫服務:

  • Amazon Web Services (AWS) RDS提供多種資料函式庫選項如MySQL、PostgreSQL等
  • Google Cloud SQL支援MySQL、PostgreSQL和SQL Server

特殊用途資料函式庫

Redis作為開放原始碼的記憶體資料結構儲存,可作為資料函式庫、快取和訊息代理使用,適合需要高效能的場景。

在本文中,我們將使用SQLite資料函式庫,因為它與Python整合簡單,與無需額外設定伺服器,非常適合學習和實驗。

Chinook資料函式庫:實用的學習資源

在深入程式碼前,讓我先介紹一下我們將使用的Chinook資料函式庫。這是一個專為學習和練習SQL設計的範例資料函式庫,模擬了一個數位媒體商店的資料結構,包含藝術家、專輯、音軌、客戶和發票等資訊。

Chinook資料函式庫有幾個值得注意的特點:

  1. 使用真實的iTunes資料函式庫資料,使其更加真實和有趣
  2. 資料模型清晰簡單,容易理解和查詢
  3. 涵蓋SQL的多種功能,如子查詢、連線、檢視和觸發器
  4. 與多種資料函式庫伺服器相容,使其更加通用

Chinook資料函式庫包含11個相互關聯的資料表,全部透過主鍵和外部索引鍵相連。這種結構很好地展示了關聯式資料函式庫的核心概念,在接下來的內容中,我們會探討如何在這些資料表之間導航,捕捉它們之間的關係並收集相關資訊。

Python中操作關聯式資料函式庫的工具箱

要在Python中使用關聯式資料函式庫,需要使用可以連線資料函式庫並執行SQL查詢的程式函式庫。市場上有多種選擇,各有特點:

主要Python資料函式庫連線工具

  1. SQLAlchemy:這是一個開放原始碼的SQL工具包和物件關係對映器(ORM),允許使用Python物件和方法來建立、讀取、更新和刪除關聯式資料函式庫中的資料。它支援多種資料函式庫引擎,如SQLite、MySQL、PostgreSQL和Oracle。

  2. Psycopg:專為PostgreSQL設計的資料函式庫聯結器,讓你能從Python執行SQL查詢並存取PostgreSQL功能。它快速、可靠與執行緒安全。

  3. MySQLdb:專為MySQL設計的資料函式庫聯結器,允許使用DB-API 2.0規範從Python與MySQL資料函式庫互動。

  4. cx_Oracle:Oracle資料函式庫的聯結器,支援進階功能如物件型別、大型物件(LOBs)和陣列。

  5. sqlite3:SQLite3的資料函式庫聯結器,SQLite是一個廣泛使用、輕量級、無伺服器、自包含與開放原始碼的關聯式資料函式倉管理系統。

在本文中,我們將使用sqlite3模組,因為我們選擇了SQLite資料函式庫。讓我們看sqlite3的一些特點:

  • 遵循DB-API 2.0規範,為Python資料庫存取模組定義標準介面
  • 支援交易,允許將多個SQL陳述式作為單一工作單元執行,並在錯誤時回復
  • 允許使用Python物件作為SQL查詢的引數和結果
  • 支援使用者定義函式、聚合、排序和授權器,使你能夠用Python程式碼擴充套件SQLite的功能
  • 內建行工廠,可以將查詢結果作為命名元組或字典回傳

實戰:使用Python連線並操作Chinook資料函式庫

接下來,讓我們透過實際的程式碼範例來看如何使用Python與SQLite資料函式庫互動。

建立資料函式庫連線

首先,我們需要從SQLite教學網站下載Chinook資料函式庫。解壓後,我們就能使用chinook.db檔案了。

import sqlite3
import pandas as pd

# 建立資料函式庫連線
database = 'chinook.db'
conn = sqlite3.connect(database)

# 匯入資料表
tables = pd.read_sql("""
    SELECT name, type
    FROM sqlite_master
    WHERE type IN ("table", "view");
    """, conn)

這段程式碼做了兩件關鍵的事情:首先,我們使用sqlite3.connect()函式建立了與chinook.db資料函式庫的連線,這個連線被儲存在conn變數中。接著,我們使用pandas的read_sql函式執行SQL查詢,取得資料函式庫中所有表格和檢視的名稱。這個查詢從sqlite_master系統表中提取資訊,該表包含了SQLite資料函式庫結構的中繼資料。執行後,我們可以看到Chinook資料函式庫包含的所有表格名稱。

如果你需要檢視特定表格的列名和結構,可以使用以下命令:

pd.read_sql("PRAGMA table_info(customers);", conn)

執行基本SQL查詢

讓我們看如何執行一些實用的SQL查詢,例如找出銷售額最高的前五個國家:

pd.read_sql("""
    SELECT c.country AS Country, SUM(i.total) AS Sales
    FROM customer c
    JOIN invoice i ON c.customer_id = i.customer_id
    GROUP BY Country
    ORDER BY Sales DESC
    LIMIT 5;
    """, conn)

這段SQL查詢展示了關聯式資料函式庫的強大功能。我們連線了customerinvoice兩個表格,使用JOIN操作根據客戶ID建立關聯。然後,我們按國家分組(GROUP BY),計算每個國家的總銷售額(SUM),按銷售額降序排序(ORDER BY Sales DESC),並限制結果只顯示前5條記錄(LIMIT 5)。

這種查詢在資料分析中非常見,它能夠快速提供業務洞察,例如確定哪些市場表現最佳。使用pandas的read_sql函式,我們可以直接將結果轉換為DataFrame,這使得後續分析和視覺化變得簡單。

資料視覺化:使用matplotlib展示資料函式庫統計

除了基本查詢外,我們還可以結合Python的視覺化工具,將資料函式庫中的統計資料轉化為直觀的

import matplotlib.pyplot as plt

# 定義SQL查詢
sql = """
    SELECT g.Name AS Genre, COUNT(t.track_id) AS Tracks
    FROM genre g
    JOIN track t ON g.genre_id = t.genre_id
    GROUP BY Genre
    ORDER BY Tracks DESC;
    """

# 將資料讀入DataFrame
data = pd.read_sql(sql, conn)

# 繪製條形圖
plt.bar(data.Genre, data.Tracks)
plt.title("各音樂型別的曲目數量")
plt.xlabel("音樂型別")
plt.ylabel("曲目數量")
plt.xticks(rotation=90)
plt.show()

這段程式碼展示瞭如何將SQL查詢與Python視覺化工具結合。首先,我們執行一個SQL查詢,計算每種音樂型別(Genre)的曲目(Track)數量。這個查詢連線了genretrack兩個表格,按型別分組並計數。

然後,我們使用matplotlib的bar函式將這些資料視覺化為條形圖。plt.xticks(rotation=90)確保x軸標籤(音樂型別)垂直顯示,使圖表更易讀。這種視覺化能立即顯示哪些音樂型別在資料函式庫中最受歡迎,為業務決策提供直觀參考。

這個例子展示了SQL和Python結合的強大功能:SQL處理資料查詢和聚合,而Python提供了資料處理和視覺化的靈活工具。

資料函式庫查詢的未來:從SQL到自然語言

如你所見,為了從資料函式庫中取得相關資訊,我們需要使用SQL語法,這需要專業知識和學習成本。而隨著技術發展,我們正在朝向一個可以使用自然語言與資料函式庫互動的未來發展。

想像一下,如果你可以直接用自然語言提問:“哪個國家的銷售額最高?“或"各音樂型別的曲目數量是多少?",然後自動獲得相應的結果,而不需要編寫SQL查詢。這就是大模型語言(LLM)與結構化資料結合的潛力所在。

在後續內容中,我們將探討如何使用現代AI技術,特別是大模型語言,來實作這種自然語言到SQL的轉換,使資料函式庫查詢變得更加直觀和無障礙。

從結構到洞察:SQL與Python的協同效應

透過本文的範例,我們看到了SQL與Python結合使用的強大功能。SQL提供了結構化查詢的能力,而Python則增加了資料處理和視覺化的靈活性。這種結合使我們能夠從資料函式庫中提取有價值的洞察,而不僅是原始資料。

關聯式資料函式庫的真正價值在於其結構化的特性,它使我們能夠根據業務邏輯建立實體之間的關係,並高效地查詢這些關係。而Python的生態系統則提供了豐富的工具來擴充套件這些能力,從基本的資料操作到高階的統計分析和機器學習。

當我們掌握了這些工具和技術,就能夠將原始資料轉化為實用的業務洞察,這正是資料驅動決策的核心。無論是分析銷售趨勢、瞭解客戶行為還是最佳化庫存管理,SQL和Python的結合都能提供強大的解決方案。

隨著技術的不斷發展,我們期待看到更多創新的方式來簡化資料函式庫操作和資料分析的流程,使其更加直觀和高效。而理解關聯式資料函式庫的基本原理和掌握SQL與Python的結合使用,將為這一旅程奠定堅實的基礎。

開發自然語言資料函式庫互動系統:DBCopilot實作詳解

在現代資料應用中,讓非技術人員也能輕鬆查詢資料函式庫一直是個挑戰。透過結合大模型語言(LLM)與資料函式庫技術,我們可以建立一個自然語言介面,讓使用者用日常語言與資料函式庫對話。這篇文章將探討如何使用LangChain框架中的SQL Agent元件實作這樣的系統。

LangChain代理機制與SQL Agent簡介

在開發智慧型資料函式庫互動系統前,需要理解LangChain的代理(Agent)機制。代理是LLM應用中的決策驅動器,它們能根據使用者輸入和上下文選擇使用哪些工具,並且具有動態適應能力,可以根據情境調整行動策略。

SQL Agent是一種專門設計用來與關聯式資料函式庫互動的代理。它利用以下LangChain元件:

  • create_sql_agent:專為資料函式庫互動設計的代理
  • SQLDatabaseToolkit:為代理提供必要的非引數化知識的工具集
  • OpenAI:作為代理背後的推理引擎及生成對話結果的LLM

實作DBCopilot的步驟

讓我們開始實際編寫程式碼,實作一個能與Chinook範例資料函式庫互動的自然語言介面。

1. 初始化元件與建立資料函式庫連線

首先,需要匯入必要的模組並建立與Chinook資料函式庫的連線:

from langchain.agents import create_sql_agent
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
from langchain.llms.openai import OpenAI
from langchain.agents import AgentExecutor
from langchain.agents.agent_types import AgentType
from langchain.chat_models import ChatOpenAI

# 初始化OpenAI語言模型
llm = OpenAI()

# 連線到Chinook SQLite資料函式庫
db = SQLDatabase.from_uri('sqlite:///chinook.db')

# 初始化SQL工具箱
toolkit = SQLDatabaseToolkit(db=db, llm=llm)

# 建立SQL代理執行器
agent_executor = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True,
    agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)

這段初始化程式碼設定了DBCopilot系統的基礎。我們首先匯入LangChain的關鍵元件,然後初始化OpenAI的語言模型作為系統的推理引擎。接著連線到SQLite格式的Chinook示範資料函式庫(這是一個模擬音樂商店的常用範例資料函式庫)。

SQLDatabaseToolkit為代理提供了與資料函式庫互動所需的工具集,而create_sql_agent則建立了一個專門處理SQL相關任務的代理。verbose=True引數讓我們能看到代理的思考過程,這對於除錯和理解代理決策非常有幫助。

2. 探索代理可用的工具

在執行代理前,讓我們先了解它可使用的工具:

[tool.name for tool in toolkit.get_tools()]

執行結果:

['sql_db_query', 'sql_db_schema', 'sql_db_list_tables', 'sql_db_query_checker']

這段程式碼列出了SQL工具箱中所有可用的工具。理解這些工具的功能對於掌握代理如何與資料函式庫互動至關重要。每個工具都有特定的功能:

  • sql_db_query:執行SQL查詢並回傳結果,若查詢有誤則回傳錯誤訊息
  • sql_db_schema:顯示指定表格的結構和樣本資料
  • sql_db_list_tables:列出資料函式庫中所有表格
  • sql_db_query_checker:在執行查詢前檢查SQL語法是否正確

這些工具共同構成了代理的「技能集」,讓它能夠理解資料函式庫結構、執行查詢並驗證其正確性。

3. 執行簡單查詢測試代理功能

現在讓我們執行一個簡單的查詢,要求代理描述playlist_track表格:

agent_executor.run("Describe the playlisttrack table")

當執行這個命令時,代理會啟動一個思考鏈。首先,它會檢查資料函式庫中有哪些表格,然後找到目標表格playlist_track,查詢其結構,最後生成一個自然語言描述。

代理的思考過程大致如下:

  1. 查詢所有表格(使用sql_db_list_tables工具)
  2. 找到目標表格playlist_track
  3. 取得該表格的結構(使用sql_db_schema工具)
  4. 分析結果並生成自然語言回應

最終,代理會回傳類別似這樣的回應:「playlist_track表格包含playlist_id和track_id列。它有一個由playlist_id和track_id組成的主鍵,同時還有指向track和playlist表格的外部索引鍵參照。樣本行包括(1, 3402)、(1, 3389)和(1, 3390)。」

深入理解SQL Agent的工作原理

SQL Agent的強大能力來自於其預設的提示範本(prompt template)。這個範本指導代理如何解釋使用者查詢、生成SQL陳述式並格式化回應。讓我們看這個範本:

print(agent_executor.agent.llm_chain.prompt.template)

檢查提示範本能幫助我們理解代理的「思維模式」。這個範本定義了代理的角色、行為準則和工作流程。關鍵指令包括:

  1. 代理的身份:「你是一個設計用來與SQL資料函式庫互動的代理」
  2. 查詢限制:預設限制回傳最多10個結果
  3. 查詢最佳化:只查詢相關列,不要查詢整個表格
  4. 安全措施:禁止執行任何資料操作語言(DML)陳述式,如INSERT、UPDATE、DELETE等
  5. 錯誤處理:如果查詢出錯,重寫查詢並再次嘗試
  6. 思考框架:定義了代理的思考、行動和輸出格式

這個範本確保了代理能安全、高效地處理資料函式庫查詢,同時提供使用者友好的回應。

處理跨表查詢

SQL Agent不僅能處理單表查詢,還能處理涉及多個表的複雜查詢。例如:

agent_executor.run('what is the total number of tracks and the average length of tracks by genre?')

這個查詢要求代理計算每個音樂型別的曲目總數和平均長度。為了完成這個任務,代理需要:

  1. 理解查詢意圖(計算統計資料,按型別分組)
  2. 識別相關表格(至少需要track和genre表格)
  3. 確定表格間的關聯方式
  4. 生成正確的SQL查詢(包含JOIN、GROUP BY和聚合函式)
  5. 執行查詢並格式化結果

代理能夠自動完成這些步驟,從最初的自然語言問題直接得到結構化答案,這展示了LLM與資料函式庫結合的強大能力。

資料操作語言(DML)的安全限制

值得注意的是,SQL Agent被明確指示不能執行任何DML陳述式,這是一個重要的安全措施。DML陳述式包括:

  • SELECT:用於從一個或多個表格或檢視中檢索資料
  • INSERT:用於向表格插入新資料記錄或行
  • UPDATE:用於修改表格中現有資料記錄或行的值
  • DELETE:用於從表格中刪除一個或多個資料記錄或行
  • MERGE:用於根據共同列合併兩個表格的資料

在代理的提示範本中,明確禁止了除SELECT以外的所有DML操作,確保代理只能讀取資料而不能修改資料函式庫內容,這對於生產環境中的安全性至關重要。

DBCopilot的應用場景與優勢

實作這樣的自然語言資料函式庫介面有諸多優勢:

  1. 降低技術門檻:非技術人員無需學習SQL就能查詢資料
  2. 提高效率:使用自然語言描述需求比編寫複雜SQL更快速
  3. 錯誤減少:代理會檢查詢正確性,減少人為錯誤
  4. 自動最佳化:代理會自動最佳化查詢,如只選擇必要的列

擴充套件DBCopilot的功能

在基本功能之上,我們可以考慮以下擴充套件:

  1. 結果視覺化:將查詢結果自動生成為圖表或儀錶板
  2. 上下文記憶:讓代理記住對話歷史,支援後續查詢中的代詞參照
  3. 自定義提示:根據特定領域需求調整代理的提示範本
  4. 多資料源整合:連線多個資料函式庫,讓代理能夠跨資料源查詢

實作注意事項

在實際佈署DBCopilot時,需要注意以下幾點:

  1. 安全性:確保代理只能存取授權的資料,特別是在處理敏感資料時
  2. 效能最佳化:對於大型資料函式庫,需要監控查詢效能並設定超時機制
  3. 錯誤處理:完善錯誤處理機制,提供友好的錯誤訊息
  4. 使用者反饋:收集使用者反饋以不斷改進代理的回應品質

結合實際業務場景的應用範例

為了說明DBCopilot的實際價值,讓我們考慮一個業務分析場景。假設銷售經理想了解不同音樂型別的銷售表現,他可以直接詢問:

agent_executor.run("Which music genres generated the most revenue? Show me the top 5 genres with their total sales.")

代理會理解這個問題需要連線多個表格(至少包括invoice_line、track、genre和可能的invoice表格),生成適當的SQL查詢,執行它,然後以易於理解的方式呈現結果。

這種自然語言介面大簡化了資料分析流程,讓業務人員能夠自助取得洞見,而不需要依賴資料分析師或工程師。

透過LangChain的SQL Agent,我們成功實作了一個能夠理解自然語言並且資料函式庫互動的系統。這種系統打破了技術與業務之間的壁壘,讓資料的力量更加民主化,使各層級的使用者都能從資料中取得價值。隨著LLM技術的不斷進步,這類別系統的能力和應用範圍將會持續擴充套件,為企業和組織帶來更多資料驅動的機會。

開發全能型資料函式庫人工智慧助手

在資料驅動的時代,能夠快速分析資料函式庫並產生深入洞見的工具變得越來越重要。想像一下,你可以用自然語言向資料函式庫提問,並得到不只是查詢結果,還有視覺化圖表和詳細解釋的情境。這正是我們今天要探討的主題:如何結合LangChain、SQLite和Python開發一個功能強大的資料函式庫助手。

為何需要人工智慧資料函式庫助手?

傳統的資料函式庫查詢需要編寫SQL陳述式,這對非技術人員來說可能是個障礙。即使對於經驗豐富的開發者,在複雜資料函式庫中構建正確的查詢也可能耗時。人工智慧資料函式庫助手可以:

  1. 接受自然語言指令並轉換為SQL查詢
  2. 自動驗證查詢結果的正確性
  3. 生成視覺化圖表以增強理解
  4. 將結果儲存到檔案系統中
  5. 提供查詢背後的推理過程

本文將以Chinook音樂資料函式庫為例,展示如何實作這些功能。

基礎:探索資料函式庫結構

在開始構建人工智慧助手前,讓我們先了解一下Chinook資料函式庫的結構。這是一個模擬音樂商店的資料函式庫,包含了歌曲、專輯、藝術家、客戶和銷售資訊等。

透過LangChain的SQL工具,我們可以快速列出資料函式庫中的表格:

# 匯入必要的函式庫
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.sql_database import SQLDatabase
from langchain.llms import OpenAI

# 連線到SQLite資料函式庫
db = SQLDatabase.from_uri("sqlite:///chinook.db")
toolkit = SQLDatabaseToolkit(db=db)

# 建立SQL代理
llm = OpenAI(temperature=0)
agent_executor = create_sql_agent(
    llm=llm,
    toolkit=toolkit,
    verbose=True
)

這段程式碼設定了基本的SQL代理。我們首先匯入必要的函式庫,然後連線到Chinook SQLite資料函式庫。接著建立一個SQL工具包(toolkit),並使用OpenAI的語言模型(LLM)來初始化SQL代理。temperature=0引數讓模型產生更確定性的結果,而verbose=True則讓我們能看到代理的思考過程。

執行查詢後,我們發現Chinook資料函式庫包含以下表格:album, artist, customer, employee, genre, invoice, invoice_line, media_type, playlist, playlist_track, track。

深入瞭解音樂資料

讓我們進一步檢視音樂型別(genre)與曲目(track)的關係:

result = agent_executor.run("What are the top 10 genres by track count and average track length?")
print(result)

查詢結果顯示:

前10個音樂型別(按曲目數量和平均長度排序)是Rock(1297首,平均長度283910.04毫秒)、Latin(579首,平均長度232859.26毫秒)、Metal(374首,平均長度309749.44毫秒)、Alternative & Punk(332首,平均長度234353.85毫秒)、Jazz(130首,平均長度291755.38毫秒)、TV Shows(93首,平均長度2145041.02毫秒)、Blues(81首,平均長度270359.78毫秒)、Classical(74首,平均長度293867.57毫秒)、Drama(64首,平均長度2575283.78毫秒)和R&B/Soul(61首,平均長度220066.85毫秒)。

這個結果很有趣,但我們如何確保它是正確的?這就引出了下一個關鍵問題:如何讓AI助手提供更透明的推理過程?

提升透明度:最佳化提示工程

LangChain代理使用預設提示來引導其行為,但我們可以自訂這些提示以增強其功能。為了讓SQL代理更透明地展示其推理過程和使用的SQL查詢,我需要修改其預設提示。

自訂SQL代理提示

首先,我們需要了解SQL代理接受哪些提示引數。檢查create_sql_agent函式,我們發現它接受prompt_prefixformat_instructions兩個關鍵引數。

以下是我最佳化後的提示內容:

# 增加要求代理提供解釋的指令
prompt_prefix = """You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct {dialect} query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most {top_k} results.
You can order the results by a relevant column to return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the below tools. Only use the information returned by the below tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.

DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

If the question does not seem related to the database, just return "I don't know" as the answer.

As part of your final answer, ALWAYS include an explanation of how to got to the final answer, including the SQL query you run. Include the explanation and the SQL query in the section that starts with "Explanation:".
"""

# 增加解釋範例的格式指引
prompt_format_instructions = """Explanation:
<===Beginning of an Example of Explanation:
I joined the invoices and customers tables on the customer_id column, which is the common key between them. This will allowed me to access the Total and Country columns from both tables. Then I grouped the records by the country column and calculate the sum of the Total column for each country, ordered them in descending order and limited the SELECT to the top 5.
```sql
SELECT c.country AS Country, SUM(i.total) AS Sales
FROM customer c
JOIN invoice i ON c.customer_id = i.customer_id
GROUP BY Country
ORDER BY Sales DESC
LIMIT 5;

===>End of an Example of Explanation "””

使用自訂提示建立SQL代理

agent_executor = create_sql_agent( prefix=prompt_prefix, format_instructions=prompt_format_instructions, llm=llm, toolkit=toolkit, verbose=True, top_k=10 )



在這段程式碼中,我修改了SQL代理的提示,增加了兩個關鍵元素:
1. `prompt_prefix`中,我加入了要求代理在最終答案中包含解釋和SQL查詢的指令
2. `format_instructions`中,我提供了一個解釋的範例,使用少量範例學習(few-shot learning)技術引導模型產生類別似格式的回應。

這種提示工程技術能大幅提高代理輸出的透明度和可解釋性,對於需要驗證AI決策的場景尤為重要

### 測試最佳化後的代理

讓我們用最佳化後的代理來查詢銷售最好的專輯:

```python
result = agent_executor.run("What are the top 5 best-selling albums and their artists?")
print(result)

執行後,我們得到:

銷售最好的前5張專輯及其藝術家是:Iron Maiden的’A Matter of Life and Death’,Led Zeppelin的’BBC Sessions [Disc 1] [live]’,Deep Purple的’MK III The Final Concerts [Disc 1]’,Metallica的’Garage Inc. (Disc 1)‘和U2的’Achtung Baby’。

解釋:我將album和invoice表連線在album_id欄位上,並將album和artist表連線在artist_id欄位上。這讓我能夠存取album表中的title和artist欄位,以及invoice表中的total欄位。然後我按artist欄位對記錄進行分組,計算每個藝術家的Total欄位總和,按降序排列,並將SELECT限制在前5名。

SELECT al.title AS Album, ar.name AS Artist, SUM(i.total) AS Sales
FROM album al
JOIN invoice i ON al.album_id = i.invoice_id
JOIN artist ar ON al.artist_id = ar.artist_id
GROUP BY ar.name
ORDER BY Sales

現在,我們不僅得到了查詢結果,還能看到代理的推理過程和使用的SQL查詢。這對於驗證結果的正確性非常重要,也讓我們能夠理解代理是如何得出結論的。