一、Text2SQL概述
Text2SQL应用主要是帮助用户减少开发时间,降低开发成本。“打破人与结构化数据之间的壁垒”,即普通用户可以通过自然语言描述完成复杂数据库的查询工作,得到想要的结果。
二、LLM 应用架构
LangChian 作为一个大语言模型开发框架,是 LLM 应用架构的重要一环。那什么是 LLM 应用架构呢?其实就是指基于语言模型的应用程序设计和开发的架构。
LangChian 可以将 LLM 模型、向量数据库、交互层 Prompt、外部知识、外部工具整合到一起,进而可以自由构建 LLM 应用。

基于LLM的应用开发基本架构如上图,本文介绍以LangChain + LLM + RDB的方式来实现Text2SQL的实践方案。
三、LangChain 组件

如上图,LangChain 包含六部分组成,分别为:Models、Prompts、Indexes、Memory、Chains、Agents。
四、Text2SQL实战应用
架构
在高层次上,任何SQL链和代理的步骤包括:
环境部署
安装LangChain组件
pip install --upgrade --quiet langchain langchain-community langchain-openai
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
print(db.dialect)
print(db.get_usable_table_names())
db.run("SELECT * FROM Artist LIMIT 10;")
案例使用SQLite 和示例Chinook 数据库,用户可按照https://database.guide/2-sample-databases-sqlite/ 上的说明进行设置。Chinook表示一个数字多媒体商店,包含了顾客(Customer)、雇员(Employee)、歌曲(Track)、订单(Invoice)及其相关的表和数据,数据模型如下图所示。

Chain
让我们来创建一个简单的链,它接收一个问题,将其转化为SQL查询,执行这个查询,并使用结果来回答原始问题。
将问题转换为SQL查询
SQL链或代理的第一步是将用户输入转换成SQL查询。LangChain内置了一个用于此目的的链:create_sql_query_chain。
from langchain.chains import create_sql_query_chain
from langchain_community.utilities.sql_database import SQLDatabase
# 但问封装的大模型调用接口
from langchain_community.llms.dquestion import DQuestion
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
# from langchain_openai import ChatOpenAI
# llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 调用但问封装的大模型对象
llm = DQuestion(temperature=0)
chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "有多少名员工?"})
print(response)
result = db.run(response)
print(result)
chain.get_prompts()[0].pretty_print()
现在我们已经生成了一个SQL查询,我们想要执行它。这是创建SQL链中最危险的部分。仔细考虑是否适合在您的数据上运行自动化查询。尽可能最小化数据库连接权限。考虑在查询执行之前添加一个人工审批步骤到您的链中(见下文)。
from langchain.chains import create_sql_query_chain
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
# 但问封装的大模型调用接口
from langchain_community.llms.dquestion import DQuestion
from langchain_community.utilities.sql_database import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
# 调用但问封装的大模型对象
llm = DQuestion(temperature=0)
generate_query = create_sql_query_chain(llm, db)
execute_query = QuerySQLDataBaseTool(db=db)
chain = generate_query | execute_query
result = chain.invoke({"question": "有多少名员工?"})
print(result)
既然已经有了自动生成和执行查询的方法,我们只需要将原始问题和SQL查询结果结合起来生成最终答案。我们可以通过再次将问题和结果传递给大型语言模型(LLM)来实现这一点:
from operator import itemgetter
from langchain.chains import create_sql_query_chain
from langchain_community.llms.dquestion import DQuestion
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
from langchain_community.utilities.sql_database import SQLDatabase
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
answer_prompt = PromptTemplate.from_template(
"""Given the following user question, corresponding SQL query, and SQL result, answer the user question.
Question: {question}
SQL Query: {query}
SQL Result: {result}
Answer: """
)
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
# 调用但问封装的大模型对象
llm = DQuestion(temperature=0)
generate_query = create_sql_query_chain(llm, db)
execute_query = QuerySQLDataBaseTool(db=db)
answer = answer_prompt | llm | StrOutputParser()
chain = (
RunnablePassthrough.assign(query=generate_query).assign(
result=itemgetter("query") | execute_query
)
| answer
)
response = chain.invoke({"question": "有多少名员工?"})
print(response)
LangChain 提供了一个 SQL Agent,它提供了一种更灵活的方式来与 SQL 数据库交互。使用 SQL Agent 的主要优势包括:
示例
agent首先会选择哪些表格是相关的,然后将这些表格的模式(schema)以及一些示例行添加到提示(prompt)中。
from dotenv import load_dotenv
from langchain_community.agent_toolkits import create_sql_agent
from langchain_community.utilities.sql_database import SQLDatabase
from text2sql import DQuestionChat
load_dotenv()
# from langchain_openai import ChatOpenAI
llm = DQuestionChat(temperature=0)
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
agent_executor = create_sql_agent(llm, db=db, agent_type="openai-tools", verbose=True)
agent_executor.invoke({"input": "列出每个国家的总销售额。哪个国家的客户消费最多?"})



