本地大模型編程實戰(23)用智能體(Agent)實現基于SQL數據構建問答系統(2)

本文將用 智能體(Agent) 實現對 SQLite 數據庫的查詢:用戶用自然語言提出問題,智能體也用自然語言根據數據庫的查詢結果回答問題。

本次將分別在英文、中文環境下,使用 qwen2.5MFDoom/deepseek-r1-tool-calling:7b 以及 llama3.1 做實驗。

準備

您可以按下面的步驟準備本地編程環境。

  1. 計算機
    本文涉及的代碼可以在沒有顯存的環境中執行。建議最低配置為:
  • CPU: Intel i5-8400 2.80GHz
  • 內存: 16GB
  1. Visual Studio Code 和 venv
    Visual Studio Code 是很受歡迎的開發工具,建議用 venv 創建虛擬環境, 詳見:
    在Visual Studio Code中配置venv。

  2. Ollama
    基于 Ollama 平臺,我們可以在本地方便的使用 llama3.1qwen2.5deepseek 等各種 LLM(大語言模型)。詳見:
    在langchian中使用本地部署的llama3.1大模型 。

創建 SQLite

我們直接使用之前創建好的 SQLite 數據庫:

# 獲取當前執行的程序文件的文件夾路徑
current_folder = os.path.dirname(os.path.abspath(__file__))db_file_path = os.path.join(current_folder, 'assert/Chinook.db')from langchain_community.utilities import SQLDatabasedb = SQLDatabase.from_uri(f"sqlite:///{db_file_path}")

智能體(Agent)

LangChain 有一個 SQL智能體,它提供了一種比鏈更靈活的與 SQL 數據庫交互的方式。使用 SQL智能體 的主要優點是:

  • 它可以根據數據庫的架構以及數據庫的內容(如描述特定表)回答問題
  • 它可以通過運行生成的查詢、捕獲執行棧并正確地重新生成它來從錯誤中恢復
  • 它可以根據需要多次查詢數據庫以回答用戶問題
    … 等等

創建 SQLite 工具

為了初始化智能體,我們將使用 SQLDatabaseToolkit 創建一組工具:

  • 創建和執行查詢
  • 檢查查詢語法
  • 檢索表描述
    … 等等
def create_tools(llm_model_name):"""創建工具"""llm = ChatOllama(model=llm_model_name,temperature=0, verbose=True)toolkit = SQLDatabaseToolkit(db=db, llm=llm)tools = toolkit.get_tools()print(tools)return tools

系統提示詞

我們來創建指導智能體的中英文提示詞。

  • 英文版
system = """You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct SQLite 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 5 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 given tools. Only use the information returned by the 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.You have access to the following tables: {table_names}
""".format(table_names=db.get_usable_table_names()
)system_message = SystemMessage(content=system)
  • 中文版
system = """您是設計用于與 SQL 數據庫交互的代理。用中文回答問題。
給定一個輸入問題,創建一個語法正確的 SQLite 查詢來運行,然后查看查詢結果并返回答案。
除非用戶指定他們希望獲得的特定數量的示例,否則請始終將查詢限制為最多 5 個結果。
您可以按相關列對結果進行排序,以返回數據庫中最有趣的示例。
切勿查詢特定表中的所有列,僅詢問給定問題的相關列。
您可以使用與數據庫交互的工具。
僅使用給定的工具。僅使用工具返回的信息來構建最終答案。
在執行查詢之前,您必須仔細檢查查詢。如果在執行查詢時出現錯誤,請重寫查詢并重試。請勿對數據庫執行任何 DML 語句(INSERT、UPDATE、DELETE、DROP 等)。您有權訪問以下數據庫表: {table_names}
""".format(table_names=db.get_usable_table_names()
)system_message = SystemMessage(content=system)

上述提示詞對大模型生成SQL語句的行為做了比較嚴格的限制,以防止生成錯誤的SQL破壞數據庫。

初始化智能體

使用 create_react_agent 方法初始化智能體,定義問答方法。

def ask(llm_model_name,question):"""詢問智能體"""tools = create_tools(llm_model_name)llm = ChatOllama(model=llm_model_name,temperature=0, verbose=True)agent_executor = create_react_agent(llm, tools, state_modifier=system_message)for s in agent_executor.stream({"messages": [HumanMessage(content=question)]}):print(s)print("----")

React智能體React Agent)指的是一種能自主決策和執行任務的AI智能體,它結合了大語言模型(LLM)和工具調用,可以根據環境和任務需求動態調整自己的行為。
簡單理解:

  1. React = 解釋 + 計算(Reason + Act)
    • 先分析當前的任務和數據(Reason)
    • 然后做出相應的行動(Act)
  2. 如何工作?
    • 先閱讀輸入信息
    • 決定是否調用某個工具(如數據庫查詢、API 調用)
    • 處理返回的結果,再次分析,繼續執行任務
  3. 示例:
    • 您輸入:“明天的天氣如何?”
    • 智能體會先思考:“這個問題需要調用天氣 API。”
    • 然后它調用天氣 API,獲取數據后再回復你:“明天是晴天,氣溫 20°C。”

見證效果

下面我們出3個同樣的中文、英文問題,看看這三款大模型的表現如何。

當用中文提問時,系統提示詞也用中文版;反之亦然。

英文問題

    questions = ["How many Employees are there?","Which country's customers spent the most?","Describe the PlaylistTrack table"]

我們先看看 qwen2.5 是如何思考回答 “How many Employees are there?” 的:

[QuerySQLDatabaseTool(description="Input to this tool is a detailed and correct SQL query, output is a result from the database. If the query is not correct, an error message will be returned. If an error is returned, rewrite the query, check the query, and try again. If you encounter an issue with Unknown column 'xxxx' in 'field list', use sql_db_schema to query the correct table fields.", ...)]
{'agent': {'messages': [AIMessage(content='',..., tool_calls=[{'name': 'sql_db_schema', 'args': {'table_names': 'Employee'}, ..., 'type': 'tool_call'}], ...)]}}
----
{'tools': {'messages': [ToolMessage(content='\nCREATE TABLE "Employee" (\n\t"EmployeeId" INTEGER NOT NULL, \n\t"LastName" NVARCHAR(20) NOT NULL, \n\t"FirstName" NVARCHAR(20) NOT NULL, \n\t"Title" NVARCHAR(30), \n\t"ReportsTo" INTEGER, \n\t"BirthDate" DATETIME, \n\t"HireDate" DATETIME, \n\t"Address" NVARCHAR(70), \n\t"City" NVARCHAR(40), \n\t"State" NVARCHAR(40), \n\t"Country" NVARCHAR(40), \n\t"PostalCode" NVARCHAR(10), \n\t"Phone" NVARCHAR(24), \n\t"Fax" NVARCHAR(24), \n\t"Email" NVARCHAR(60), \n\tPRIMARY KEY ("EmployeeId"), \n\tFOREIGN KEY("ReportsTo") REFERENCES "Employee" ("EmployeeId")\n)\n\n/*\n3 rows from Employee table:\nEmployeeId\tLastName\tFirstName\tTitle\tReportsTo\tBirthDate\tHireDate\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\n1\tAdams\tAndrew\tGeneral Manager\tNone\t1962-02-18 00:00:00\t2002-08-14 00:00:00\t11120 Jasper Ave NW\tEdmonton\tAB\tCanada\tT5K 2N1\t+1 (780) 428-9482\t+1 (780) 428-3457\tandrew@chinookcorp.com\n2\tEdwards\tNancy\tSales Manager\t1\t1958-12-08 00:00:00\t2002-05-01 00:00:00\t825 8 Ave SW\tCalgary\tAB\tCanada\tT2P 2T3\t+1 (403) 262-3443\t+1 (403) 262-3322\tnancy@chinookcorp.com\n3\tPeacock\tJane\tSales Support Agent\t2\t1973-08-29 00:00:00\t2002-04-01 00:00:00\t1111 6 Ave SW\tCalgary\tAB\tCanada\tT2P 5M5\t+1 (403) 262-3443\t+1 (403) 262-6712\tjane@chinookcorp.com\n*/', name='sql_db_schema',...)]}}
----
{'agent': {'messages': [AIMessage(content='', ..., tool_calls=[{'name': 'sql_db_query_checker', 'args': {'query': 'SELECT COUNT(*) FROM Employee'}, ..., 'type': 'tool_call'}], ...)]}}
----
{'tools': {'messages': [ToolMessage(content='The provided SQL query is:\n\n```sql\nSELECT COUNT(*) FROM Employee\n```\n\nThis query appears to be correct and does not contain any of the common mistakes listed. It simply counts all rows in the `Employee` table.\n\nTherefore, the final SQL query remains:\n\n```sql\nSELECT COUNT(*) FROM Employee\n```', name='sql_db_query_checker', ...)]}}
----
{'agent': {'messages': [AIMessage(content='', ..., tool_calls=[{'name': 'sql_db_query', 'args': {'query': 'SELECT COUNT(*) FROM Employee'}, ..., 'type': 'tool_call'}], ...)]}}
----
{'tools': {'messages': [ToolMessage(content='[(8,)]', name='sql_db_query', ...)]}}
----
{'agent': {'messages': [AIMessage(content='There are 8 employees in the database.', ...)]}}
----

從上面的輸出來看,智能體是一步一步推理出最終的答案的:

  • QuerySQLDatabaseTool
    給出提示:此工具的輸入是詳細且正確的 SQL 查詢,輸出是數據庫的結果。如果查詢不正確,將返回錯誤消息。如果返回錯誤,請重寫查詢,檢查查詢,然后重試。如果您遇到“字段列表”中未知列“xxxx”的問題,請使用 sql_db_schema 查詢正確的表字段。
  • agent
    生成名為 sql_db_schematool_call ,確定表名為 Employee
  • tools
    執行前面tool_call,生成名為 sql_db_schemaToolMessage ,找出了表 EmployeeDML ,并成功查詢出3條信息。
  • agent
    生成名為 sql_db_query_checkertool_call,其中包含 SQL語句。
  • tools
    驗證前面 tool_call 中的SQL是否正確。生成名為 sql_db_query_checkerToolMessage,其內容顯示最終確定了正確的SQL語句。
  • agent
    生成名為 sql_db_querytool_call,其中包含SQL語句:SELECT COUNT(*) FROM Employee
  • tools
    執行前面的 tool_call ,生成名為 sql_db_queryToolMessage ,其中已經包含了 SQLite的返回值。
  • agent
    基于前面的結果生成了最終回答。

通過上述的推理過程顯示:智能體與工具進行了多輪交互后才給出最終回答。

下表直接列出各個大模型針對這3個問題的處理結果:

How many Employees are there?Which country’s customers spent the most?Describe the PlaylistTrack table
qwen2.5There are 8 employees in the database.The country with the highest spending by customers is USA, followed by Canada, France, Brazil, and Germany.\n\nHere are the top 5 countries based on total invoice amount:\n\n1. USA - $523.06\n…The PlaylistTrack table has two columns: PlaylistId and TrackId. It is a junction table used to establish a many-to-many relationship between the Playlist and Track tables…
llama3.1There are 8 Employees.The country’s customers that spent the most are from the USA, with a total spend of $523.06.The PlaylistTrack table contains information about the tracks in each playlist. It has two columns: PlaylistId and TrackId,…
MFDoom/deepseek-r1-tool-calling:7bThere are \boxed{8} Employees in the database.未推理出正確的的SQLAlright, …, it looks like this table has two main columns: PlaylistId and TrackId…

從上述結果來看,qwen2.5給出的回答最清晰全面,llama3.1也不錯,MFDoom/deepseek-r1-tool-calling:7b 未能正確回答第2個問題。

中文問題

    questions = ["有多少名員工?","哪個國家的顧客花費最多?","描述 PlaylistTrack 表" ]
有多少名員工?哪個國家的顧客花費最多?描述 PlaylistTrack 表
qwen2.5數據庫中一共有 8 名員工。花費最多的國家及其總金額如下:\n\n1. 美國 (USA) - 總\金額: $523.06…\n\n因此,顧客花費最多的國家是美國。PlaylistTrack 表包含兩個列:PlaylistIdTrackId。這兩個列共同作為主鍵,表示播放列表和其中的歌曲之間的關系。…
llama3.1有 8 名員工。答案是:美國。根據工具的輸出,PlaylistTrack 表是一個連接表,它將Playlist和Track兩個表關聯起來。它有兩個列:PlaylistId和TrackId,…
MFDoom/deepseek-r1-tool-calling:7b未正確做答未正確做答未正確做答

總結

我們實現了用 智能體(Agent)SQlite 對話的功能,通過中英文環境的簡單對比實驗發現,qwen2.5 表現最穩健。

代碼

本文涉及的所有代碼以及相關資源都已經共享,參見:

  • github
  • gitee

為便于找到代碼,程序文件名稱最前面的編號與本系列文章的文檔編號相同。

參考

  • Build a Question/Answering system over SQL data

🪐感謝您觀看,祝好運🪐

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

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

相關文章

nodejs npm install、npm run dev運行的坎坷之路

1、前面的種種都不說了,好不容易運行起來oap-portal項目,運行idm-ui項目死活運行不起來,各種報錯,各種安裝,各種卸載nodejs,卸載nvm,重裝,都不好使。 2、甚至后來運行npm install會…

gotool在線工具集

1. 包含各種 sql 處理 2. 包含 json 處理 3. 包含 圖片處理 4. 跨平臺傳輸 gotool

猿大師播放器:智慧交通Web網頁低延遲播放監控RTSP H.265視頻解決方案

在智慧城市建設加速推進的今天,智慧交通作為城市"神經系統"正面臨前所未有的發展機遇。據統計,2023年全國交通視頻監控設備保有量已突破4500萬臺,日均產生的視頻數據量超50PB。但在這些龐大數字背后,行業卻普遍面臨著&q…

Web自動化之Selenium控制已經打開的瀏覽器(Chrome,Edge)

在使用selenium進行web自動化或爬蟲的時候,經常會面臨登錄的情況,對于這種情況,我們可以利用Selenium控制已經打開的瀏覽器,從而避免每次都需要重新打開瀏覽器并進行登錄的繁瑣步驟。 目錄 說明 啟動瀏覽器 注意 --user-data-dir說明 代碼設定 代碼 改進代…

【Alertmanager】Alertmanager告警路由,告警靜默,告警抑制,高可用的實現

?? 歡迎大家來到景天科技苑?? ???? 養成好習慣,先贊后看哦~???? ?? 作者簡介:景天科技苑 ??《頭銜》:大廠架構師,華為云開發者社區專家博主,阿里云開發者社區專家博主,CSDN全棧領域優質創作者,掘金優秀博主,51CTO博客專家等。 ??《博客》:Python全…

Vue3 + Vite + TS,使用 配置項目別名屬性:resolve

使用 resolve 配置全局項目路徑別名 1.優化了開發中單頁面引用其他模塊的路徑復雜性 2.妥妥解決了,組件復用當中提高開發效率 // 不使用配置 import { useStore } from ../../../stores // 使用配置 可根據開發者需求任意定義,較多 import { useStore…

Linux主機用戶登陸安全配置

Linux主機用戶登陸安全配置 在Linux主機上進行用戶登錄安全配置是一個重要的安全措施,可以防止未經授權的訪問。以下是如何創建用戶hbu、賦予其sudo權限,以及禁止root用戶SSH登錄,以及通過ssh key管理主機用戶登陸。 創建用戶hbu 使用具有…

基于 SpringBoot Vue 的生鮮商城系統設計和實現(源碼+文檔+部署講解)

技術范圍:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容:免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論…

設計模式-結構性模式

結構型模式主要關注類或對象的組合,旨在通過識別簡單的結構關系來設計更復雜的結構。以下是幾種常見的結構型設計模式: 1. 適配器模式(Adapter Pattern) 將一個類的接口轉換成客戶端所期望的另一個接口,使得原本由于接…

VantUI官網更新2025,移動端前端開發

Vant 2 - Mobile UI Components built on Vue https://vant-ui.github.io/vant/v2/#/zh-CN/quickstart Vant 4 - A lightweight, customizable Vue UI library for mobile web apps. https://vant-ui.github.io/vant/#/zh-CN Vant Weapp - 輕量、可靠的小程序 UI 組件庫,微…

《我的AUTOSAR之路》Det 解析

Det 解析 1. 引言和功能概述2. Errors2.1 開發錯誤(Development Errors)2.2 運行時錯誤(Runtime Errors)2.3 臨時故障(Transient Faults)3 錯誤查詢默認錯誤追蹤器(Default Error Tracer,DET) 1. 引言和功能概述 默認錯誤追蹤器(DET):該規范描述了默認錯誤追蹤器(…

電腦連接示波器顯示波形

通過網線連接示波器和電腦,將示波器波形顯示在電腦上直接復制圖片至報告中,以下是配置步驟。 一、設備 網線,Tektronix示波器,電腦 二、使用步驟 1.用網線連接電腦和示波器 2.電腦關掉WiFi,查看IPv4網關地址&#xf…

npm i 失敗權限問題

安裝完node之后, 測試全局安裝一個最常用的 express 模塊進行測試 失敗,但是用管理員權限打開cmd 安裝就成功。 報錯如下: npm ERR! If you believe this might be a permissions issue, please double-check the npm ERR! permissions of the file and …

上海創智學院(測試)算法筆試(ACM賽制)部分例題

1.第一個題,大概題目意思是求n句話中最長的單詞和最短的單詞 這個題目做的有點磕巴,好幾年沒有寫過c/c了,連string的復制都不會寫了,哈哈哈,太笨了 后面一點點撿起來,還是寫出來了,本身沒啥&…

編寫一個程序,輸出 “Hello, World!“(Python版)

編寫一個程序,輸出 "Hello, World!" 在 Python 中,輸出 “Hello, World!” 的程序非常簡單。你只需要使用 print 函數即可。以下是代碼示例: print("Hello, World!")將這段代碼保存為一個 .py 文件(例如 hel…

python實戰項目58:采集蜻蜓FM熱門音頻top排行榜

python實戰項目58:采集蜻蜓FM熱門音頻top排行榜 一、采集流程介紹二、數據接口采集三、使用xpath提取頁面數據1、抓包,找到數據接口2、發送請求,獲取數據3、提取數據4、保存數據一、采集流程介紹 蜻蜓FM熱門音頻top排行榜的鏈接為: https://m.qingting.fm/rank/,首頁如下圖…

【Matlab仿真】Matlab Function中如何使用靜態變量?

背景 根據Simulink的運行機制,每個采樣點會調用一次MATLAB Function的函數,兩次調用之間,同一個變量的前次計算的終值如何傳遞到當前計算周期來?其實可以使用persistent變量實現函數退出和進入時內部變量值的保持。 persistent變…

LaneATT環境配置步驟

本文介紹Ubuntu下配置車道線檢測算法LaneATT代碼運行環境,步驟如下。 1. 從LaneATT官方代碼倉庫下載源碼。也可git直接拉取。 2. 安裝Anaconda或miniconda 。 參考:https://docs.anaconda.com/miniconda/ 3. 創建conda虛擬環境LaneATT(環…

【AIGC】使用Python實現科大訊飛語音服務ASR轉錄功能:完整指南

文章目錄 訊飛ASR轉寫API完整指南1. 引言2. 訊飛ASR API介紹3. API參數說明3.1 認證參數3.2 上傳參數3.3 查詢結果參數3.4 orderResult 字段3.5 Lattice 字段3.6 json_1best 字段3.7 st 字段 4. Python代碼實現4.1 生成簽名4.2 上傳音頻文件4.3 獲取轉寫結果4.4 解析轉寫結果 5…

大學本科教務系統設計方案,涵蓋需求分析、架構設計、核心模塊和技術實現要點

以下是大學本科教務系統的設計方案,涵蓋需求分析、架構設計、核心模塊和技術實現要點: 大學本科教務系統設計方案 一、需求分析 1. 核心用戶角色 角色功能需求學生選課/退課、成績查詢、課表查看、學分統計、考試報名、學業預警教師成績錄入、課程大綱上傳、教學進度管理、…