大模型調用數據庫表實踐:基于自然語言的SQL生成與數據查詢系統

# 大模型調用數據庫表實踐:基于自然語言的SQL生成與數據查詢系統

## 一、背景與目標

在企業數據管理場景中,非技術人員(如業務人員、管理人員)常常需要通過數據庫查詢獲取關鍵信息,但直接編寫SQL語句存在技術門檻。傳統的數據庫交互方式依賴專業IT人員,效率較低且響應滯后。本系統通過集成大語言模型(LLM)與數據庫技術,實現**自然語言到SQL語句的自動轉換**,降低數據查詢的技術門檻,提升企業數據利用效率。

## 二、核心技術原理與實現

### 2.1 大模型驅動的SQL生成

系統選用`deepseek-r1:7b`大語言模型作為SQL生成引擎,核心邏輯封裝在`generate_sql`函數中(<mcsymbol name="generate_sql" filename="01.py" path="e:\source\traeproj\test01\ui界面\01.py" startline="29" type="function"></mcsymbol>)。其技術要點包括:

#### (1)Prompt工程設計

通過嚴格的`system prompt`約束模型行為:

- 僅輸出完整SQL語句(以分號結尾),禁止自然語言解釋;

- 強制對齊輸入的表結構(字段名、表名必須與`TABLE_SCHEMA`完全一致);

- 支持中文表名/字段名(如示例中的"員工表""姓名")。

用戶側通過`user prompt`傳遞具體需求,包含表結構描述、查詢需求及示例(如:"查詢研發部門中工資高于15000元的員工姓名,入職日期,薪資,按入職日期降序排列"),確保生成的SQL符合業務邏輯。

#### (2)生成結果清洗

模型返回內容可能包含Markdown代碼塊(如```sql)或中間思考過程(如`<answer>...`),系統通過正則表達式(`re.sub`)清理冗余信息,最終輸出純凈的SQL語句。具體步驟包括:

- 移除`</answer>...`標簽及內容;

- 清理開頭的```sql標記和結尾的```標記;

- 去除首尾換行符,確保輸出為嚴格SQL語句。

### 2.2 數據庫交互與數據管理

系統基于`SQLAlchemy`實現數據庫操作,支持SQLite輕量級數據庫(<mcsymbol name="initialize_database" filename="01.py" path="e:\source\traeproj\test01\ui界面\01.py" startline="167" type="function"></mcsymbol>),核心功能包括:

#### (1)數據庫初始化

- 檢查`employee.db`是否存在,若不存在則自動創建`員工表`(字段包含`id`、`姓名`、`部門`、`入職日期`、`工資`);

- 首次初始化時調用`insert_test_data`(<mcsymbol name="insert_test_data" filename="01.py" path="e:\source\traeproj\test01\ui界面\01.py" startline="101" type="function"></mcsymbol>)插入20條模擬數據(使用`Faker`生成中文姓名、部門等信息),并通過`assert`進行類型校驗(如姓名必須為字符串、工資必須為浮點數)。

#### (2)數據查詢執行

`query_database`函數(<mcsymbol name="query_database" filename="01.py" path="e:\source\traeproj\test01\ui界面\01.py" startline="201" type="function"></mcsymbol>)接收生成的SQL語句,通過`pd.read_sql`執行查詢并返回結果(`pandas DataFrame`格式),支持異常捕獲與日志記錄(如SQL為空、數據庫連接失敗等場景)。

## 三、可靠性設計與異常處理

### 3.1 數據質量保障

- **測試數據校驗**:在`insert_test_data`中,每條模擬數據生成時均通過`assert`校驗類型(如`assert isinstance(name, str)`),確保入庫數據符合表結構定義;

- **SQL合法性約束**:通過大模型的`system prompt`強制生成符合表結構的SQL,避免字段名/表名錯誤導致的查詢失敗。

### 3.2 運行時監控與日志

系統集成`logging`模塊(配置于文件頂部),記錄關鍵操作日志:

- 數據插入成功時輸出`INFO`級日志(如"已成功插入20條測試數據");

- 數據庫操作異常(如`OperationalError`)、數據類型錯誤(如`AssertionError`)時輸出`ERROR`級日志,并記錄堆棧信息(`exc_info=True`),便于問題定位。

## 四、應用場景與示例演示

### 4.1 典型應用場景

- **企業員工管理**:業務人員通過自然語言查詢"研發部中工資高于15000元的員工",系統自動生成SQL并返回結果,無需IT人員介入;

- **數據分析輔助**:管理人員通過"近一年入職的市場部員工數量"等自然語言需求,快速獲取統計數據,支撐決策分析。

### 4.2 完整流程示例

以`NATURAL_QUERY`("查詢研發部門中工資高于15000元的員工姓名,入職日期,薪資,按入職日期降序排列")為例:

1. **生成SQL**:`generate_sql`函數調用大模型生成SQL(示例輸出:`SELECT 姓名, 入職日期, 工資 FROM 員工表 WHERE 部門 = '研發部' AND 工資 > 15000 ORDER BY 入職日期 DESC;`);

2. **執行查詢**:`query_database`函數執行上述SQL,返回符合條件的員工數據;

3. **結果輸出**:通過`pandas.to_markdown`以表格形式展示結果(如無數據則提示"無符合條件的數據")。

# 導入 requests 庫,用于發送 HTTP 請求
import requests
# 從 sqlalchemy 庫導入 create_engine 函數,用于創建數據庫連接引擎
from sqlalchemy import create_engine
# 導入 pandas 庫,用于數據處理和分析
import pandas as pd
# 導入 os 模塊,用于與操作系統進行交互
import os
# 從 sqlalchemy.exc 導入 OperationalError 異常,用于處理數據庫操作錯誤
from sqlalchemy.exc import OperationalError
# 導入 Faker 類,用于生成模擬數據
from faker import Faker  # 新增:用于生成模擬數據
# 導入 random 模塊,用于生成隨機數
import random
# 從 datetime 模塊導入 datetime 和 timedelta 類,用于處理日期和時間
from datetime import datetime, timedelta
# 從 sqlalchemy 導入 text 函數,用于處理 SQL 語句
from sqlalchemy import text  # 新增導入 text 函數
# 導入 logging 模塊,用于日志記錄
import logging  # 新增:日志記錄模塊
# 從 tenacity 庫導入重試相關的類和函數,用于實現重試機制
from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type
# 從 ollama 庫導入 chat 函數,用于與大語言模型進行交互
from ollama import chat
# 從 ollama 庫導入 ChatResponse 類,用于處理聊天響應
from ollama import ChatResponse# 定義 generate_sql 函數,用于根據自然語言查詢和表結構生成 SQL 語句
def generate_sql(query, table_schema, model="deepseek-r1:7b"):# 調用 chat 函數與大語言模型進行交互,獲取生成的 SQL 語句response: ChatResponse = chat(model, messages=[{"role": "system","content": "你是一個純粹的SQL生成工具,必須嚴格遵循以下規則:\n""1. 僅返回完整的SQL語句(以分號結尾),禁止輸出任何解釋、說明或自然語言文本;\n""2. 嚴格根據輸入的表結構生成語句,字段名和表名必須與表結構完全一致;\n""3. 若輸入中包含中文表名/字段名,直接使用中文,無需翻譯或轉義。"},{'role': 'user','content': f"""1. 表結構:{table_schema}2. 查詢需求:{query}3. 示例:"SELECT 姓名, 入職日期 FROM 員工表 WHERE 部門 = '研發部' AND 工資 > 15000 ORDER BY 入職日期 DESC;" (注意:部門字段的值必須為'研發部',包含'部'字,禁止使用簡寫'研發')4. 僅輸出sql語句,不允許輸出解釋或說明。條件要與表中的內容保持一致,保證能查出5. 注意初始字段要依據表結構名稱中的字段名一致,不要使用英文字段名"""},],)# 導入 re 模塊,用于正則表達式處理import re# 獲取大語言模型返回的消息內容answer = response['message']['content']# 使用正則表達式移除 <think> 標簽及其內容cleaned = re.sub(r'<think>.*?</think>', '', answer, flags=re.DOTALL)# 清理開頭的 ```sql 標記cleaned = re.sub(r'^\s*```sql\s*', '', cleaned, flags=re.DOTALL)# 清理結尾的 ``` 標記cleaned = re.sub(r'\s*```\s*$', '', cleaned, flags=re.DOTALL)# 移除開頭和結尾的換行符sql = re.sub(r'^\n+|\n+$', '', cleaned)# 打印生成的 SQL 語句print("sql:" + sql)# 返回生成的 SQL 語句return sql# print(response['message']['content'])# or access fields directly from the response object# print(response.message.content)# return response['message']['content']# 配置日志(建議添加在文件頂部)
logging.basicConfig(# 設置日志級別為 INFOlevel=logging.INFO,# 設置日志格式format='%(asctime)s - %(levelname)s - %(message)s',# 設置日志輸出到文件和控制臺handlers=[logging.FileHandler('app.log'), logging.StreamHandler()]
)# 定義 send_messages 函數,用于向大語言模型發送消息并獲取 SQL 語句
def send_messages(messages):# 調用 chat 函數與大語言模型進行交互,獲取生成的 SQL 語句response: ChatResponse = chat(model="deepseek-r1:7b", messages=[{'role': 'user','content': f"""內容:{messages}獲取:返回SQL語句1. 僅返回嚴格的SQL語句(以分號結尾,無任何其他文本)。2. 結果不顯示思考過程文字,僅返回SQL語句。""",},])# 返回聊天響應中的第一條消息return response.choices[0].message# 定義 insert_test_data 函數,用于向數據庫中插入模擬員工數據
def insert_test_data():"""插入20條模擬員工數據(增強版:命名參數綁定+類型校驗)"""# 創建 Faker 實例,用于生成中文模擬數據fake = Faker("zh_CN")# 定義部門列表departments = ["研發部", "市場部", "財務部", "人力資源部"]# 初始化一個空列表,用于存儲模擬數據test_data = []  # 將存儲字典列表(命名參數格式)# 生成數據時增加類型校驗for _ in range(20):# 判斷是否為研發部門數據is_rd = _ < 5# 生成員工姓名并校驗類型name = fake.name()assert isinstance(name, str), "姓名必須為字符串類型"# 生成員工部門并校驗類型department = "研發部" if is_rd else random.choice(departments[1:])assert isinstance(department, str), "部門必須為字符串類型"# 生成員工入職日期并校驗類型hire_date = (datetime.now() - timedelta(days=random.randint(365, 3650))).strftime("%Y-%m-%d")assert isinstance(hire_date, str), "入職日期必須為字符串類型"# 生成員工工資并校驗類型salary = round(random.uniform(12000, 25000) if is_rd else random.uniform(8000, 14000), 2)assert isinstance(salary, float), "工資必須為浮點數類型"# 存儲為字典(命名參數格式)test_data.append({"name": name,"department": department,"hire_date": hire_date,"salary": salary})# 執行插入(改用命名參數綁定)# 創建數據庫連接引擎engine = create_engine(f"sqlite:///employee.db")# 定義插入數據的 SQL 語句,使用命名占位符insert_sql = """INSERT INTO 員工表 (姓名, 部門, 入職日期, 工資) VALUES (:name, :department, :hire_date, :salary)"""try:# 連接數據庫with engine.connect() as conn:# 使用命名參數無需排序,避免類型比較錯誤conn.execute(text(insert_sql), test_data)# 提交事務conn.commit()# 記錄日志,表示數據插入成功logging.info(f"已成功插入{len(test_data)}條測試數據")except OperationalError as e:# 記錄數據庫操作異常日志logging.error(f"數據庫操作異常:{str(e)},請檢查SQL語句或表結構")except AssertionError as e:# 記錄測試數據類型錯誤日志logging.error(f"測試數據類型錯誤:{str(e)},請檢查數據生成邏輯")except Exception as e:# 記錄插入測試數據失敗日志,并記錄堆棧信息logging.error(f"插入測試數據失敗:{str(e)}", exc_info=True)# 定義 initialize_database 函數,用于初始化數據庫
def initialize_database():"""檢查數據庫是否存在,不存在則創建表并插入測試數據"""# 定義數據庫文件路徑db_path = "employee.db"  # 固定為當前目錄# 檢查數據庫文件是否存在if not os.path.exists(db_path):# 創建數據庫連接引擎engine = create_engine(f"sqlite:///{db_path}")# 定義創建表的 SQL 語句create_table_sql = f"""CREATE TABLE 員工表 (id INTEGER PRIMARY KEY AUTOINCREMENT,姓名 TEXT,部門 TEXT,入職日期 DATE,工資 REAL);"""try:# 連接數據庫with engine.connect() as conn:# 關鍵修復:使用 text() 包裝 SQL 語句conn.execute(text(create_table_sql))# 打印提示信息,表示數據庫和表已創建print(f"數據庫文件 {db_path} 不存在,已自動創建并初始化員工表")# 插入測試數據(僅首次創建時執行)insert_test_data()except Exception as e:# 打印初始化數據庫失敗的錯誤信息print(f"初始化數據庫失敗:{e}")# 定義 query_database 函數,用于執行 SQL 查詢
def query_database(sql):# 檢查傳入的 SQL 語句是否為空if not sql:# 記錄日志,表示傳入的 SQL 為空,無法執行查詢logging.error("錯誤:傳入的SQL為空,無法執行查詢")  # 替換print為日志return None# 定義數據庫文件路徑db_path = "employee.db"# 創建數據庫連接引擎engine = create_engine(f"sqlite:///{db_path}")try:# 連接數據庫并執行 SQL 查詢with engine.connect() as conn:result = pd.read_sql(sql, conn)# 返回查詢結果return resultexcept Exception as e:# 記錄數據庫查詢失敗的日志,并記錄堆棧信息logging.error(f"數據庫查詢失敗(具體錯誤):{str(e)}", exc_info=True)return None# 定義 getsql 函數,用于生成 SQL 語句
def getsql():# 調用 generate_sql 函數生成 SQL 語句并返回return generate_sql(NATURAL_QUERY, TABLE_SCHEMA)# 定義表結構
TABLE_SCHEMA = """
員工表(id INTEGER PRIMARY KEY AUTOINCREMENT,姓名 TEXT,部門 TEXT,入職日期 DATE,工資 REAL
)
"""# 自然語言查詢示例
# NATURAL_QUERY = "查詢研發部門中工資高于15000元的員工姓名,入職日期,薪資,按入職日期降序排列"
NATURAL_QUERY = "統計每個部門的工資的平均工資,按照平均工資從多到少排列,輸出部門,平均工資"# 主流程優化
if __name__ == "__main__":# 初始化數據庫initialize_database()# 1. 生成 SQL(增加失敗處理)generated_sql = generate_sql(NATURAL_QUERY, TABLE_SCHEMA)# 檢查生成的 SQL 語句是否為空if not generated_sql:print("生成SQL失敗,終止后續流程")exit(1)# 打印生成的 SQL 語句print("生成的 SQL:\n", generated_sql)# sql = send_messages(generated_sql)# print("sql==="+sql)# 2. 執行查詢result_df = query_database(generated_sql)# 3. 整理并輸出結果(明確錯誤類型)if result_df is None:print("查詢過程中出現錯誤")elif result_df.empty:print("無符合條件的數據。")else:print("\n查詢結果:")print(result_df.to_markdown())  # 以表格形式輸出

## 五、總結

本系統通過大模型與數據庫技術的結合,實現了自然語言到SQL的自動化轉換,降低了數據查詢的技術門檻。核心設計(如嚴格的prompt約束、數據類型校驗、日志監控)保障了系統的可靠性,適用于企業內部數據管理、業務分析等場景,為非技術人員提供了高效的數據交互方式。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85414.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85414.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85414.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

28 C 語言作用域詳解:作用域特性(全局、局部、塊級)、應用場景、注意事項

1 作用域簡介 作用域定義了代碼中標識符&#xff08;如變量、常量、數組、函數等&#xff09;的可見性與可訪問范圍&#xff0c;即標識符在程序的哪些位置能夠被引用或訪問。在 C 語言中&#xff0c;作用域主要分為三類&#xff1a; 全局作用域局部作用域塊級作用域 需注意&am…

Tomcat運行比較卡頓進行參數調優

在Tomcat conf/catalina.bat或catalina.sh中 的最上面增加參數 1. 初步調整參數&#xff08;緩解問題&#xff09; set JAVA_OPTS -Xms6g -Xmx6g -Xmn3g # 增大新生代&#xff0c;減少對象過早晉升到老年代 -XX:MetaspaceSize256m -XX:MaxMetaspaceS…

WSL2 安裝與Docker安裝

注意&#xff1a;如沒有科學上網請勿嘗試&#xff0c;無法判斷是否會因網絡錯誤導致的安裝失敗&#xff01;&#xff01;&#xff01; WSL2&#xff08;Windows Subsystem for Linux 2&#xff09; 功能簡介&#xff1a; WSL2 是微軟提供的在 Windows 上運行完整 Linux 內核的…

Redis的安裝與使用

網址&#xff1a;Spring Data Redis 安裝包&#xff1a;Releases tporadowski/redis GitHub 解壓后 在安裝目錄中打開cmd 打開服務&#xff08;注意&#xff1a;每次客戶端連接都有先打開服務&#xff01;&#xff01;&#xff01;&#xff09; 按ctrlC退出服務 客戶端連接…

springboot-響應接收與ioc容器控制反轉、Di依賴注入

1.想將服務器中的數據返回給客戶端&#xff0c;需要在controller類上加注解&#xff1a;ResponseBody; 這個注解其實在前面已經使用過&#xff0c;RestController其實就包含兩個注解&#xff1a; Controller ResponseBody 返回值如果是實體對象/集合&#xff0c;將會轉換為j…

將材質球中的紋理屬性對應的貼圖保存至本地

通過Texture2D的EncodeToPNG方法將紋理轉為圖片形式 material.GetTexture方法通過屬性名獲取紋理貼圖 material.SetTexture方法通過屬性名設置紋理貼圖 屬性名可在shader代碼中查看 using UnityEngine; using System.IO;public class TextureSaver : MonoBehaviour {public…

MySQL半同步復制配置和參數詳解

目錄 1 成功配置主從復制 2 加載插件 3 半同步復制監控 4 半同步復制參數 1 成功配置主從復制 操作步驟參考&#xff1a;https://blog.csdn.net/zyb378747350/article/details/148309545 2 加載插件 #主庫上 MySQL 8.0.26 之前版本: mysql>INSTALL PLUGIN rpl_semi_syn…

【筆記】Windows 成功部署 Suna 開源的通用人工智能代理項目部署日志

#工作記錄 本地部署運行截圖 kortix-ai/suna&#xff1a; Suna - 開源通用 AI 代理 項目概述 Suna 是一個完全開源的 AI 助手&#xff0c;通過自然對話幫助用戶輕松完成研究、數據分析等日常任務。它結合了強大的功能和直觀的界面&#xff0c;能夠理解用戶需求并提供結果。其強…

PCB制作入門

文章目錄 1 嘉立創使用旋轉 2元器件選擇MP2315SLM7815與LM7915 1 嘉立創使用 旋轉 空格旋轉 2元器件選擇 MP2315S MP2315S 是一款內置功率 MOSFET 的高效率同步整流降壓開關變換器。 其輸入電壓范圍為 4.5V 至 24V &#xff0c;能實現 3A 連續輸出電流&#xff0c;負載與…

2025——》NumPy中的np.logspace使用/在什么場景下適合使用np.logspace?NumPy中的np.logspace用法詳解

1.NumPy中的np.logspace使用: 在 NumPy 中,np.logspace函數用于生成對數尺度上等間距分布的數值序列,適用于科學計算、數據可視化等需要對數間隔數據的場景。以下是其核心用法和關鍵細節: 一、基礎語法與參數解析: numpy.logspace(start, stop, num=50, endpoint=True, ba…

Java實現中文姓名轉拼音生成用戶信息并寫入文件

中文姓名轉拼音 Java實現中文姓名轉拼音生成用戶信息并寫入文件&#xff08;shili域名版&#xff09;一、項目背景與功能簡介二、技術棧與核心組件2.1 主要技術2.2 功能模塊 三、核心代碼解析3.1 主函數邏輯&#xff08;流程控制&#xff09;3.2 拼音轉換模塊&#xff08;核心功…

Google car key:安全、便捷的汽車解鎖新選擇

有了兼容的汽車和 Android 手機&#xff0c;Google car key可讓您將Android 手機用作車鑰匙。您可以通過兼容的 Android 手機鎖定、解鎖、啟動汽車并執行更多功能。但是&#xff0c;Google car key安全嗎&#xff1f;它是如何工作的&#xff1f;如果我的手機電池沒電了怎么辦&a…

如何輕松將 iPhone 備份到外部硬盤

當您的iPhone和電腦上的存儲空間有限時&#xff0c;您可能希望將iPhone備份到外部硬盤上&#xff0c;這樣可以快速釋放iPhone上的存儲空間&#xff0c;而不占用電腦上的空間&#xff0c;并為您的數據提供額外的安全性。此外&#xff0c;我們還提供 4 種有效的解決方案&#xff…

AI煉丹日志-22 - MCP 自動操作 Figma+Cursor 自動設計原型

MCP 基本介紹 官方地址&#xff1a; https://modelcontextprotocol.io/introduction “MCP 是一種開放協議&#xff0c;旨在標準化應用程序向大型語言模型&#xff08;LLM&#xff09;提供上下文的方式。可以把 MCP 想象成 AI 應用程序的 USB-C 接口。就像 USB-C 提供了一種…

機器學習-線性回歸基礎

一、什么是回歸 依據輸入x寫出一個目標值y的計算方程&#xff0c;求回歸系數的過程就叫回歸。簡言之&#xff1a;根據題意列出方程&#xff0c;求出系數的過程就叫做回歸。 回歸的目的是預測數值型的目標值y&#xff0c;分類的目的預測標稱型的目標值y。 二、線性回歸 2.1線性…

解決RAGFlow(v0.19.0)有部分PDF無法解析成功的問題。

ragflow版本為&#xff1a;v0.19.0 1.解析的時候報錯&#xff1a;Internal server error while chunking: Coordinate lower is less than upper。 看報錯懷疑是分片的問題&#xff0c;于是把文檔的切片方法中的“建議文本塊大小”數值&#xff08;默認512&#xff09;調小&…

【前端】html2pdf實現用前端下載pdf

npm安裝完后&#xff0c;編寫代碼。 <template><div id"pdf-content">需要被捕獲為pdf的內容</div> </template><script> import html2pdf from html2pdf.js;export default {methods: {downloadPdf() {const element document.getE…

從零實現富文本編輯器#4-瀏覽器選區模型的核心交互策略

先前我們提到了&#xff0c;數據模型的設計是編輯器的基礎模塊&#xff0c;其直接影響了選區模塊的表示。選區模塊的設計同樣是編輯器的基礎部分&#xff0c;編輯器應用變更時操作范圍的表達&#xff0c;就需要基于選區模型來實現&#xff0c;也就是說選區代表的意義是編輯器需…

數論——質數和合數及求質數

質數、合數和質數篩 質數和合數及求質數試除法判斷質數Eratosthenes篩選法&#xff08;埃氏篩&#xff09;線性篩&#xff08;歐拉篩&#xff09; 質數有關OJ列舉P1835 素數密度 - 洛谷簡單的哥赫巴德猜想和cin優化 質數和合數及求質數 一個大于 1 的自然數&#xff0c;除了 1…

多商戶系統源碼性能調優實戰:從瓶頸定位到高并發架構設計!

在電商業務爆發式增長的今天&#xff0c;多商戶系統作為支撐平臺方、入駐商家和終端消費者的核心樞紐&#xff0c;其性能表現直接決定了商業變現效率。當你的商城在促銷期間崩潰&#xff0c;損失的不僅是訂單&#xff0c;更是用戶信任。 本文將深入剖析多商戶系統源碼性能優化的…