使用 Hugging Face 資料集檢視器 API 和 Motherduck DuckDB-NSQL-7B 實現 Text2SQL
如今,整合 AI 驅動的功能,尤其是利用大語言模型 (LLM) 的功能,在文字生成、分類、圖文轉換、影像到影像轉換等各種任務中變得越來越普遍。
開發者們越來越認識到這些應用的潛在好處,尤其是在增強核心任務方面,例如編寫指令碼、Web 開發,以及現在與資料互動。從歷史上看,為資料分析編寫富有洞察力的 SQL 查詢主要是資料分析師、SQL 開發人員、資料工程師或相關領域專業人士的領域,他們都需要處理 SQL 方言語法的細微差別。然而,隨著 AI 驅動解決方案的出現,情況正在發生變化。這些先進的模型為與資料互動提供了新的途徑,有可能簡化流程,並以更高的效率和深度揭示洞見。
如果你無需深入編碼就能從資料集中發掘出有趣的洞見,那會怎麼樣?要收集有價值的資訊,需要編寫一個專門的 SELECT
語句,考慮要顯示哪些列、源表、篩選所選行的條件、聚合方法以及排序偏好。這種傳統方法涉及一系列命令:SELECT
、FROM
、WHERE
、GROUP
和 ORDER
。
但如果你不是經驗豐富的開發者,但仍然想利用資料的力量呢?在這種情況下,尋求 SQL 專家的幫助就變得必要,這突顯了在可訪問性和可用性方面的差距。
這就是 AI 和 LLM 技術的突破性進展介入以彌合這一鴻溝的地方。想象一下,毫不費力地與你的資料對話,只需用簡單的語言陳述你的資訊需求,然後讓模型將你的請求翻譯成查詢。
最近幾個月,這一領域取得了重大進展。MotherDuck 和 Numbers Station 推出了他們最新的創新:DuckDB-NSQL-7B,這是一款專為 DuckDB SQL 設計的頂尖 LLM。這個模型的使命是什麼?讓使用者能夠毫不費力地從資料中發掘洞見。
DuckDB-NSQL-7B 最初是在 Meta 原版的 Llama-2–7b 模型基礎上,使用一個涵蓋通用 SQL 查詢的廣泛資料集進行微調的,之後又使用 DuckDB 的 text-to-SQL 對進行了進一步最佳化。值得注意的是,其功能超出了編寫 SELECT
語句的範疇;它可以生成各種有效的 DuckDB SQL 語句,包括官方文件和擴充套件,使其成為一個多功能的資料探索和分析工具。
在本文中,我們將學習如何使用 DuckDB-NSQL-7B 模型、用於 Parquet 檔案的 Hugging Face 資料集檢視器 API 以及用於資料檢索的 duckdb 來處理 text2sql 任務。
text2sql 流程
如何使用模型
- 使用 Hugging Face
transformers
流水線
from transformers import pipeline
pipe = pipeline("text-generation", model="motherduckdb/DuckDB-NSQL-7B-v0.1")
- 使用 transformers 的分詞器和模型
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("motherduckdb/DuckDB-NSQL-7B-v0.1")
model = AutoModelForCausalLM.from_pretrained("motherduckdb/DuckDB-NSQL-7B-v0.1")
- 使用
llama.cpp
載入GGUF
格式的模型
from llama_cpp import Llama
llama = Llama(
model_path="DuckDB-NSQL-7B-v0.1-q8_0.gguf", # Path to local model
n_gpu_layers=-1,
)
llama.cpp
的主要目標是實現 LLM 推理,只需最少的設定,並在各種硬體上(本地和雲端)實現最先進的效能。我們將使用這種方法。
適用於超過 12 萬個資料集的 Hugging Face 資料集檢視器 API
資料是任何機器學習工作中的關鍵組成部分。Hugging Face 是一個寶貴的資源,提供了超過 12 萬個免費開放的資料集,涵蓋了 CSV、Parquet、JSON、音訊和影像檔案等多種格式。
Hugging Face 上託管的每個資料集都配備了全面的資料集檢視器。該檢視器為使用者提供了基本功能,如統計洞察、資料大小評估、全文搜尋功能和高效的篩選選項。這個功能豐富的介面使使用者能夠輕鬆探索和評估資料集,從而在整個機器學習工作流程中促進明智的決策。
對於這個演示,我們將使用 world-cities-geo 資料集。
world-cities-geo 資料集的資料集檢視器
在幕後,Hub 中的每個資料集都由 Hugging Face 資料集檢視器 API 處理,該 API 獲取有用資訊並提供以下功能:
- 列出資料集的拆分、列名和資料型別
- 獲取資料集的大小(以行數或位元組為單位)
- 下載並檢視資料集中任意索引的行
- 在資料集中搜尋一個詞
- 根據查詢字串篩選行
- 獲取關於資料的富有洞察力的統計資訊
- 以 parquet 檔案的形式訪問資料集,以便在你喜歡的處理或分析框架中使用
在這個演示中,我們將使用最後一個功能,即自動轉換的 parquet 檔案。
從文字指令生成 SQL 查詢
首先,下載 DuckDB-NSQL-7B-v0.1 的量化模型版本
下載模型
或者,你可以執行以下程式碼
huggingface-cli download motherduckdb/DuckDB-NSQL-7B-v0.1-GGUF DuckDB-NSQL-7B-v0.1-q8_0.gguf --local-dir . --local-dir-use-symlinks False
現在,讓我們安裝所需的依賴項
pip install llama-cpp-python
pip install duckdb
對於 text-to-SQL 模型,我們將使用具有以下結構的提示
### Instruction:
Your task is to generate valid duckdb SQL to answer the following question.
### Input:
Here is the database schema that the SQL query will run on:
{ddl_create}
### Question:
{query_input}
### Response (use duckdb shorthand if possible):
- ddl_create 將是作為 SQL
CREATE
命令的資料集模式 - query_input 將是使用者指令,用自然語言表達
所以,我們需要告訴模型關於 Hugging Face 資料集的模式。為此,我們將獲取 jamescalam/world-cities-geo 資料集的第一個 parquet 檔案
GET https://huggingface.co/api/datasets/jamescalam/world-cities-geo/parquet
{
"default":{
"train":[
"https://huggingface.co/api/datasets/jamescalam/world-cities-geo/parquet/default/train/0.parquet"
]
}
}
這個 parquet 檔案託管在 Hugging Face 檢視器的 refs/convert/parquet
修訂版下
Parquet 檔案
- 從 parquet 檔案的第一行模擬一個 DuckDB 表的建立
import duckdb
con = duckdb.connect()
con.execute(f"CREATE TABLE data as SELECT * FROM '{first_parquet_url}' LIMIT 1;")
result = con.sql("SELECT sql FROM duckdb_tables() where table_name ='data';").df()
ddl_create = result.iloc[0,0]
con.close()
CREATE
模式 DDL 是
CREATE TABLE "data"(
city VARCHAR,
country VARCHAR,
region VARCHAR,
continent VARCHAR,
latitude DOUBLE,
longitude DOUBLE,
x DOUBLE,
y DOUBLE,
z DOUBLE
);
而且,如你所見,它與資料集檢視器中的列相匹配
資料集列
- 現在,我們可以用 ddl_create 和 query 輸入來構建提示
prompt = """### Instruction:
Your task is to generate valid duckdb SQL to answer the following question.
### Input:
Here is the database schema that the SQL query will run on:
{ddl_create}
### Question:
{query_input}
### Response (use duckdb shorthand if possible):
"""
如果使用者想知道來自阿爾巴尼亞國家的城市,提示將如下所示
query = "Cities from Albania country"
prompt = prompt.format(ddl_create=ddl_create, query_input=query)
因此,將傳送給 LLM 的擴充套件提示如下所示
### Instruction:
Your task is to generate valid duckdb SQL to answer the following question.
### Input:
Here is the database schema that the SQL query will run on:
CREATE TABLE "data"(city VARCHAR, country VARCHAR, region VARCHAR, continent VARCHAR, latitude DOUBLE, longitude DOUBLE, x DOUBLE, y DOUBLE, z DOUBLE);
### Question:
Cities from Albania country
### Response (use duckdb shorthand if possible):
- 是時候將提示傳送給模型了
from llama_cpp import Llama
llm = Llama(
model_path="DuckDB-NSQL-7B-v0.1-q8_0.gguf",
n_ctx=2048,
n_gpu_layers=50
)
pred = llm(prompt, temperature=0.1, max_tokens=1000)
sql_output = pred["choices"][0]["text"]
輸出的 SQL 命令將指向一個 data
表,但由於我們沒有一個真正的表,只有一個對 parquet 檔案的引用,我們將用 first_parquet_url
替換所有 data
的出現
sql_output = sql_output.replace("FROM data", f"FROM '{first_parquet_url}'")
最終的輸出將是
SELECT city FROM 'https://huggingface.co/api/datasets/jamescalam/world-cities-geo/parquet/default/train/0.parquet' WHERE country = 'Albania'
- 現在,是時候最終在資料集上直接執行我們生成的 SQL 了,所以,讓我們再次利用 DuckDB 的力量
con = duckdb.connect()
try:
query_result = con.sql(sql_output).df()
except Exception as error:
print(f"❌ Could not execute SQL query {error=}")
finally:
con.close()
這裡我們得到了結果(100 行)
執行結果(100 行)
讓我們將這個結果與使用“搜尋功能”搜尋阿爾巴尼亞國家的資料集檢視器進行比較,結果應該是一樣的
阿爾巴尼亞國家的搜尋結果
你也可以直接調用搜索或篩選 API 來獲得相同的結果
- 使用 /search API
import requests
API_URL = "https://datasets-server.huggingface.co/search?dataset=jamescalam/world-cities-geo&config=default&split=train&query=Albania"
def query():
response = requests.get(API_URL)
return response.json()
data = query()
- 使用 filter API
import requests
API_URL = "https://datasets-server.huggingface.co/filter?dataset=jamescalam/world-cities-geo&config=default&split=train&where=country='Albania'"
def query():
response = requests.get(API_URL)
return response.json()
data = query()
我們的最終演示將是一個看起來像這樣的 Hugging Face space
你可以在這裡檢視帶程式碼的 notebook。
以及這裡的 Hugging Face Space