從自然語言輸入生成查詢緩慢且效率低下,是決策制定的瓶頸。這迫使分析師和業務用戶嚴重依賴數據團隊,從而延遲洞察并限制敏捷性。
Text-to-SQL 正在改變我們與數據交互的方式,使用戶能夠以自然語言查詢結構化數據庫。在為專業行業部署特定領域的模型時,這尤其有用。然而,大規模使用這些模型進行分析工作負載推理會帶來延遲和性能挑戰。
在本教程中,我們將展示如何使用 NVIDIA NIM 優化 Vanna 的文本轉 SQL 解決方案。Vanna 的開源文本轉 SQL 解決方案因其靈活性、安全性和適應性而在組織中備受關注。
您會學習:
- 將預處理數據插入數據庫并連接 Vanna。
- 對 Vanna 進行業務術語或定義培訓。
- 利用 NVIDIA NeMo Retriever 嵌入模型檢索上下文以生成 SQL。
- 使用適用于 LLM 的 NVIDIA NIM 端點加速推理。
在演示中,我們使用了 Kaggle 中的兩個開源 Steam 游戲數據集,這是一個豐富的游戲元數據集,非常適合分析查詢。
預備知識
- 已安裝 Python 3.10 或更高版本
- 適用于 NVIDIA NeMo Retriever 嵌入模型的 NVIDIA 支持 LangChain 軟件包
- 訪問 NVIDIA NIM 端點
- 熟悉已安裝的 SQLiteVanna 庫
- Steam 數據集 數據集 1 數據集 2
程序
1. 下載并預處理 Steam 數據集
為此,請克隆位于/ NVIDIA/ GenerativeAIExamples 的存儲庫,并在社區部分打開 Vanna_with_NVIDIA notebook。
關鍵預處理步驟包括:
- 過濾所需列
- 將具有范圍的列解壓縮為單獨的列
- 為每款游戲添加游戲長度
預處理步驟結束時,我們會得到三個 CSV:
tableau_games.csv
tableau_categories.csv
tableau_tags.csv
2. 使用 NVIDIA NIM 和 NeMo Retriever 初始化 Vanna
Vanna 實例需要連接到向量數據庫、嵌入器和 LLM 端點。我們使用 Milvus 向量數據庫,因為它具有 GPU 加速功能、NVIDIA 檢索器嵌入模型 (llama-3.2-nv-embedqa-1b-v2) 和 Llama 3.1 70B NIM 微服務。
借助 NIM 微服務,您的推理模型可在 NVIDIA 加速基礎設施上運行,從而為生產部署提供更快的響應時間和成本效益。NVIDIA NIM 包含在 NVIDIA AI Enterprise 軟件許可證中,可在任何地方運行,讓您擁有自定義設置的所有權,并完全控制您的知識產權 (IP) 和 AI 應用。
有關 NIM 端點的設置說明,請參閱 NVIDIA NIM 文檔。

在以下文本中,我們將介紹如何使用 NVIDIA 加速組件初始化 Vanna 實例。
- 將 Vanna 類定義如下。
from pymilvus import MilvusClient, model from vanna.milvus import Milvus_VectorStore from vanna.openai import OpenAI_Chat from openai import OpenAI # Set the nvidia api key nvidia_api_key = '...' # Define Vanna Class class VannaMilvus(Milvus_VectorStore, OpenAI_Chat): def __init__( self , llm_client, config = None ): Milvus_VectorStore.__init__( self , config = config) OpenAI_Chat.__init__( self , client = llm_client, config = config) |
- 接下來,使用 NVIDIA API 密鑰創建基于 OpenAI Wrapper 的 NIM 客戶端。
def get_openai_client(): client = OpenAI( api_key = nvidia_api_key ) return client llm_client = get_openai_client() |
- 通過 Milvus DB 為 NeMo Retriever 嵌入模型使用包裝器。您可以使用相同的
nvidia_api_key
。
class EmbeddingWrapper: def __init__( self , embedder): self .embedder = embedder def encode_documents( self , texts): result = self .embedder.embed_documents(texts) return [np.array(r) for r in result] def encode_queries( self , texts): embeddings = [] for text in texts: embeddings.append( self .embedder.embed_query(text)) return embeddings vanna_embedder = EmbeddingWrapper(nvidia_embedder) |
- 接下來,使用 NVIDIA API 密鑰創建基于 OpenAI Wrapper 的 NIM 客戶端。
def get_openai_client(): client = OpenAI( base_url = "https://integrate.api.nvidia.com/v1", api_key = nvidia_api_key ) return client llm_client = get_openai_client() |
- 使用本地 Milvus DB 實例。
milvus_uri = "./milvus_nvidia.db" milvus_client_nvidia = MilvusClient(uri = milvus_uri) |
- 使用之前定義的組件指定 Vanna 實例的配置。
# Specify the LLM used for SQL generation model_name = "nvidia/llama-3.1-70b-instruct" # Define the configuration for Vanna instance config_nvidia = { "model": model_name, "milvus_client": milvus_client_nvidia, "embedding_function": vanna_embedder, "n_results": 2, # The number of results to return from Milvus semantic search. } vn_nvidia = VannaMilvus(llm_client, config=config_nvidia) |
3. 創建并填充 SQLite 數據庫
- 在此演示中使用 SQLite 提供了一個輕量級、無服務器的數據庫,用于測試文本轉 SQL。您可以使用 Vanna 支持的任何數據庫。將預處理步驟中的三個 CSV 插入數據庫。
import sqlite3 import pandas as pd # Specify the path to the SQLite database sqlite_path = 'steam_data.db' # Connect to the SQLite database sql_connect = sqlite3.connect(sqlite_path) c = sql_connect.cursor() # Create tables init_sqls = """ CREATE TABLE IF NOT EXISTS games ( app_id INTEGER PRIMARY KEY, name TEXT, release_date TEXT, price REAL, short_description TEXT, positive INTEGER, negative INTEGER, min_owners INTEGER, max_owners INTEGER, hltb_single REAL ); CREATE TABLE IF NOT EXISTS categories ( app_id INTEGER, categories TEXT, FOREIGN KEY (app_id) REFERENCES games(app_id) ); CREATE TABLE IF NOT EXISTS tags ( app_id INTEGER, tags TEXT, tag_frequencies TEXT, FOREIGN KEY (app_id) REFERENCES games(app_id) ); """ for sql in init_sqls.split( ";" ): c.execute(sql) # Read the CSV files games_df = pd.read_csv( 'processed_dataset/games.csv' ) categories_df = pd.read_csv( 'processed_dataset/categories.csv' ) tags_df = pd.read_csv( 'processed_dataset/tags.csv' ) # Insert data into tables games_df.to_sql( 'games' , sql_connect, if_exists = 'append' , index = False ) categories_df.to_sql( 'categories' , sql_connect, if_exists = 'append' , index = False ) tags_df.to_sql( 'tags' , sql_connect, if_exists = 'append' , index = False ) sql_connect.commit() |
- 現在,將 SQL DB 連接到 Vanna。
# Connect to the SQLite database vn_nvidia.connect_to_sqlite(sqlite_path) |
4. 訓練數據
Vanna 在處理查詢數據和業務特定術語的上下文時表現最佳。
- 刪除現有訓練數據以避免重復數據,并使用數據庫數據定義語言 (DDL) 訓練 Vanna。
# Remove existing training data existing_training_data = vn_nvidia.get_training_data() if len(existing_training_data) > 0: for _, training_data in existing_training_data.iterrows(): vn_nvidia.remove_training_data(training_data["id"]) # Get the DDL of the SQLite database df_ddl = vn_nvidia.run_sql("SELECT type, sql FROM sqlite_master WHERE sql is not null") # Train the model on the DDL data for ddl in df_ddl["sql"].to_list(): vn_nvidia.train(ddl=ddl) |
- 接下來,添加有關數據庫模式
games
、tg_ 15 和 tg_ 16 中三個表的文檔。
# Add documentation about your business terminology or definitions. vn_nvidia.train( documentation = """ This dataset is used to answer questions about the game trends. """ ) # Add documentation about the tables vn_nvidia.train( documentation = """ The games table contains information about the games. The app_id is the unique identifier for the game.This is a primary key. The name is the name of the game. The release_date is the date the game was released. The price is the price of the game. Price in USD, 0.0 if its free. The short_description is a brief description of the game. The positive is the number of positive reviews or votes. The negative is the number of negative reviews or votes. The min_owners is the minimum number of owners. Used together with max_owners to get an estimate of the player base. The max_owners is the maximum number of owners. Used together with min_owners to get an estimate of the player base. The hltb_single is the average playtime of the game. This is an estimate. """ ) vn_nvidia.train( documentation = """ The categories table contains information about the categories of the games. The app_id is the unique identifier for the game. The categories is the categories of the game. The app_id is a foreign key to the games table. """ ) vn_nvidia.train( documentation = """ The tags table contains information about the tags of the games. The app_id is the unique identifier for the game. The tags is the tags of the game. These are user defined. The tag_frequencies is the frequencies of the tags. The app_id is a foreign key to the games table. """ ) |
- 然后,使用簡單的命令查看訓練數據。
training_data = vn_nvidia.get_training_data() training_data |
5. 生成 SQL
您已準備好開始使用由 NIM 提供支持的 Vanna 查詢數據庫。
- 從簡單查詢開始。生成的 SQL 也可以在執行之前打印出來。
sql = vn_nvidia.generate_sql( "Which 5 games have the most positive reviews and how many?" ) vn_nvidia.run_sql(sql) |
- Run a harder query now.
sql = vn_nvidia.generate_sql( "Which indie game has the biggest player base?" ) vn_nvidia.run_sql(sql) |
總結
在本教程中,您學習了如何使用 NVIDIA NIM 加速 Vanna 上的文本轉 SQL 推理。憑借清晰的數據庫架構、真實數據集和優化的推理端點,該系統能夠為用戶生成的查詢提供響應速度更快的分析。
進一步探索:
- 以此 Notebook 為起點,在您自己的數據集上試用 Vanna。
- 部署 NVIDIA NIM 端點進行生產級推理。
嘗試添加不同的訓練信息,以更好地生成 SQL。
?