搜尋結果

×

LangChain 和 Ollama 進行 SQL 查詢和自動化答案生成:LLM 實作與教學

使用 LangChain 框架來構建一個能夠自動生成 SQL 查詢並基於查詢結果返回自然語言答案的應用

我們將學習如何使用 LangChain 框架來構建一個能夠自動生成 SQL 查詢並基於查詢結果返回自然語言答案的應用。這樣的工具可以大大提升與資料庫互動的效率,特別是在處理自然語言查詢並轉化為 SQL 查詢的過程中。

本文是使用到裡面的:

目標

我們的目標是實現一個系統,能夠:

  1. 接受用戶的自然語言問題。
  2. 根據資料庫的結構生成相應的 SQL 查詢。
  3. 執行 SQL 查詢並返回結果。
  4. 根據 SQL 查詢結果生成自然語言答案。

成果展示

  • 告訴我全部共有幾個人

      root@4be643ba6a94:/app# python3 langchain_sqlite.py
    
      >>> 告訴我全部共有幾個人
      SQL> SELECT COUNT(*) FROM Users;
      問題: 告訴我全部共有幾個人
      執行: SELECT COUNT(*) FROM Users;
      查詢結果: [(4,)]
      回答: 有 4 人。
    
  • 告訴我id2和id3的資訊

      root@4be643ba6a94:/app# python3 langchain_sqlite.py
    
      >>> 告訴我id2和id3的資訊
      SQL> SELECT * FROM Users WHERE id IN (2, 3);
      問題: 告訴我id2和id3的資訊
      執行: SELECT * FROM Users WHERE id IN (2, 3);
      查詢結果: [(2, 'cccc', 'cccc@cccc.com.tw'), (3, 'zzcx', 'zzxc@zzxc.com.tw')]
      回答: id2是'cccc',email是'cccc@cccc.com.tw'。id3是'zzcx',email是'zzxc@zzxc.com.tw'。>>>
    

設定環境

需要安裝一些必要的套件。這些套件來自 LangChain 和 SQLAlchemy,它們將幫助我們構建整個應用:

pip install langchain langchain-community sqlalchemy

崴寶創了一個DB名為 weibert.sqlite3 的SQLite 資料庫,我們將使用它來結合Langchain,裡面內容是我亂打的xD

id username email
1 aa aa@aaa.cc
2 cccc cccc@cccc.com.tw
3 zzcx zzxc@zzxc.com.tw
4 apple apple@qqqq.com.tw

Docker

步驟 1:Ollama LLM

這次的大語言模型和之前的教學都不同,崴寶是選用kenneth85/llama-3-taiwan:8b-instruct

llm = ChatOllama(model='kenneth85/llama-3-taiwan:8b-instruct', callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]))

步驟 2:初始化資料庫連接

首先,我們將建立一個 SQLite 資料庫的連接,並通過 SQLDatabase 類別來訪問資料庫。

from langchain_community.utilities import SQLDatabase

# 連接到 SQLite 資料庫
db = SQLDatabase.from_uri("sqlite:///./weibert.sqlite3")

步驟 3:創建 SQL 查詢生成的流程

創建一個模型提示模板來生成 SQL 查詢。這是通過 ChatPromptTemplate 完成的,該模板包含了用戶輸入的問題和資料庫的結構,模型將根據這些信息生成 SQL 查詢。

from langchain_core.prompts import ChatPromptTemplate

gen_sql_prompt = ChatPromptTemplate.from_messages([
    ('system', '根據下面的資料庫結構,編寫一個 SQL 查詢來回答使用者的問題:{db_schema}'),
    ('user', '請為以下問題生成一個 SQL 查詢:"{input}"。\
    查詢應該格式化為以下方式,並且不附加任何額外的解釋:\
    SQL> <sql_query>\
    '),
])

這段程式碼中的 systemuser 訊息將引導模型根據資料庫結構生成正確的 SQL 查詢。模型會根據用戶輸入的問題生成相應的 SQL 查詢,並以 SQL> 為標誌格式化返回的查詢。

步驟 4:創建 SQL 查詢解析器

為了處理模型生成的查詢,我們需要一個解析器來提取純粹的 SQL 查詢語句,並清除掉多餘的文字。

from langchain_core.output_parsers import StrOutputParser

class SqlQueryParser(StrOutputParser):
    def parse(self, s):
        r = s.split('SQL> ')
        if len(r) > 1:
            return r[1].strip()  # 提取出 SQL 查詢部分
        return s.strip()

這個 SqlQueryParser 類別將會提取從模型生成的文本中的 SQL 查詢部分。

步驟 5:執行 SQL 查詢

當我們得到 SQL 查詢後,需要執行它並獲取查詢結果。以下是執行 SQL 查詢並捕獲異常的代碼:

from sqlalchemy.exc import OperationalError

def run_query(query):
    try:
        return db.run(query)
    except (OperationalError, Exception) as e:
        return str(e)

這段代碼會執行 SQL 查詢並返回結果。如果有任何錯誤(例如 SQL 語法錯誤),則返回錯誤信息。

步驟 6:生成自然語言回答

當 SQL 查詢執行完畢後,我們需要生成一個自然語言的回答來解釋查詢結果。我們會使用另一個 ChatPromptTemplate,讓模型根據問題、SQL 查詢和查詢結果生成一個簡潔的回答。

gen_answer_prompt = ChatPromptTemplate.from_template("""
根據提供的問題、SQL 查詢和查詢結果,撰寫一個自然語言的回答。
不應包含任何額外的解釋。

回答應該格式化為以下形式:
'''
問題: {input}
執行: {query}
查詢結果: {result}
回答: <answer>
'''
""")

這個模板將指導模型根據提供的資料庫查詢結果,生成最終的自然語言回應。

步驟 7:整合流程

最後,我們將所有部分組合在一起,形成一個完整的流程。這個流程包括了生成 SQL 查詢、執行查詢和生成最終答案。

from langchain_core.runnables import RunnablePassthrough

gen_query_chain = (
    RunnablePassthrough.assign(db_schema=get_db_schema)
    | gen_sql_prompt
    | llm
    | SqlQueryParser()
)

chain = (
    RunnablePassthrough.assign(query=gen_query_chain).assign(
        result=lambda x: run_query(x["query"]),
    )
    | gen_answer_prompt
    | llm
)

在這裡,我們創建了一個 chain,這個 chain 包含了所有步驟的組合,從生成 SQL 查詢到最終的自然語言回應。

步驟 8:交互式使用

現在我們已經建立了完整的系統,接下來是創建一個簡單的命令行界面,用戶可以在其中輸入問題並獲得答案:

input_text = input('>>> ')
while input_text.lower() != 'bye':
    if input_text:
        response = chain.invoke({
            'input': input_text,
        })
        print(response)  # 顯示回答
    input_text = input('>>> ')

這段代碼讓用戶可以輸入問題,並根據模型生成的 SQL 查詢和資料庫結果來獲得回答。如果用戶輸入 “bye”,系統將終止。

root@4be643ba6a94:/app# python3 langchain_sqlite.py
first=RunnableAssign(mapper={
db_schema: RunnableLambda(get_db_schema)
}) middle=[ChatPromptTemplate(input_variables=['db_schema', 'input'], 
messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(
input_variables=['db_schema'], 
template='根據下面的資料庫結構,編寫一個 SQL 查詢來回答使用者的問題:{db_schema}')), 
HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], 
template='請為以下問題生成一個 SQL 查詢:"{input}"。     
查詢應該格式化為以下方式,並且不附加任何額外的解釋:     SQL> <sql_query>    '))]), 
ChatOllama(callbacks=<
langchain_core.callbacks.manager.CallbackManager object at 0x7f409b773730>, 
model='kenneth85/llama-3-taiwan:8b-instruct')] last=SqlQueryParser()

崴寶結語

在這篇教學中,我們展示了如何使用 LangChain 和 Ollama 架設一個基於自然語言的 SQL 查詢系統,並基於查詢結果生成清晰的自然語言答案。這種方式讓非技術用戶也能夠輕鬆地與資料庫進行互動。🌟

你可以根據需要擴展這個系統來處理更多的資料庫和問題場景。

    喜歡 好崴寶 Weibert Weiberson 的文章嗎?在這裡留下你的評論!本留言區支援 Markdown 語法