AIGC系列之三-从零开始建立自己的NL2SQL数据分析机器人(保姆式教程)
搭建整个流程和步骤 案例实践过程 结果展示以及相关问题分析以及优化建议
01
—
流程与步骤
搭建一个NL2SQL的整体步骤包括以下5个步骤。
1、配置环境、完成LangChain依赖环境的配置以及访问大模型相关的配置要求。
2、链接数据库,即配置LangChain访问数据库的链接,因为后续进行问题回答都是需要访问数据库。
3、链接大语言模型、即配置LangChain访问大语言模型的能力。
4、构造执行的链,即使用LangChainAPI完成自然语言查询数据的三个基本步骤。
a、生成SQL,完成输入自然语言问题,生成SQL的能力。
b、执行SQL、完成将SQL链接到数据库执行的能力。
c、生成自然语言的回答,将数据库返回的结果形成自然语言表达的能力。
5、UI聊天界面,即配合一个UI界面完成输入自然语言,回答数据的UI界面。
02
—
案例实践过程
背景情况是数据库有两种张股票相关数据表,我们看看怎么通过中文对话查询需要的股票数据。
1、配置环境
创建一个文件夹作为Python项目的根目录,建议使用venv或者conda作为虚拟化环境,可以减少很多包依赖的问题,这个以venv为例。先通过pip安装基础的依赖包
pip install langchain langchain-community langchain-openai pymysql
项目需要用到大语言模型,选择了微软的服务,用OpenAI或者其他的也可以。在根目录下创建一个文件.env,用来配置密钥、链接地址等环境变量。
MYSQL_URL=mysql+pymysql://username:password@localhost:3306/database
AZURE_OPENAI_API_KEY=yourkey
AZURE_OPENAI_ENDPOINT=yourendpoint
2、链接数据库
LangChain提供一套范围SQL数据库的封装,SQLDatabase基于SQLAlchemy,用于执行sql和读取数据基础信息。LangChain v0.1版本以后对包结构做了一些重新的组织,实际使用时如果找不到对应的引入对象,可以到官方的API网站查看,大部分都是包结构变了。
初始化SQLDatabase对象
import os
from dotenv import load_dotenv
from langchain_community.utilities.sql_database import SQLDatabase
#加载环境变量
load_dotenv()
#初始化SQLDatabase
mysql = SQLDatabase.from_uri(os.environ["MYSQL_URL"])
输出信息,看看数据库连接是不是正常
print(mysql.dialect)
print(mysql.get_usable_table_names())
mysql
['share_d_hist', 'share_info']
3、链接大语言模型
from langchain_openai import AzureChatOpenAI
llm = AzureChatOpenAI(
temperature=0.3,
model="gpt-4-32k",
api_version="2023-07-01-preview",
)
AzureChatOpenAI默认会读取AZURE_OPENAI_API_KEY,AZURE_OPENAI_ENDPOINT这两个环境变量的配置。
4、造执行的链
LangChain的最大的作用就是提供了一套AI应用的封装,让开发AI应用变成像一个个组建的拼装,极大简化了开发的复杂度。接下来我们构建执行流程的Chain。
4.1 自然语言生成SQL
把用户输入问题转化成SQL查询,LangChain提供了一个简单的示例实现,把上面的llm和mysql作为参数传入
from langchain.chains.sql_database.query import create_sql_query_chain
chain = create_sql_query_chain(llm, mysql)
看看是不是可以
response = chain.invoke({"question": "上海交易所有多少支股票?"})
print(response)
SELECT COUNT(code) FROM share_info WHERE exchange = 'SH'
还不错,执行正确.
4.2 执行SQL
有了SQL查询语句,我们还需要执行语句,chain就是一系列实现runnable的组建,都有invoke和stream等函数实现,可以简单把上一步的输出作为下一步的输入。
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
execute_query = QuerySQLDataBaseTool(db=mysql)
使用LCEL(LangChain Expression Language)的语法组建起来,重写一下,增加代码可读性.
write_query = create_sql_query_chain(llm, mysql)
execute_query = QuerySQLDataBaseTool(db=mysql)
chain = write_query | execute_query
response = chain.invoke({"question": "上海交易所有多少支股票?"})
print(response)
[(2360,)]
4.3 使用自然语言回答
这个输出的结果还不是我们要的,下一步利用大模型的能力,给出自然语言的回答。先构建一个根据用户问题,查询语句,查询结果给出回答的Chain,在把回答Chain和上面两步组装起来。
from operator import itemgetter
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
answer_prompt = PromptTemplate.from_template(
"""基于以下用户问题(Question)、相应的查询语句(SQL Query)和查询结果(SQL Result),请回答用户问题。
Question: {question}
SQL Query: {query}
SQL Result: {result}
Answer: """
)
answer = answer_prompt | llm | StrOutputParser()
重写一下最终的chain
chain = (
RunnablePassthrough.assign(query=write_query).assign(
result=itemgetter("query") | execute_query
)
| answer
)
response = chain.invoke({"question": "上海交易所有多少支股票?"})
print(response)
上海交易所有2360支股票。
RunnablePassthrough提供了把上一步输入的值透传到下一步的能力,所以当调用answer.invoke函数时,输入是一个dict。
{
"question": "上海交易所有多少支股票?",
"query": "SELECT COUNT(code) FROM share_info WHERE exchange = 'SH'",
"result": "[(2360,)]"
}
5、UI聊天界面
Chainlit 是一个开源的 Python 包,用于构建AI聊天应用,提供了很方便的能力,通过python代码的调用就可以生成UI界面,类似科研人员喜爱的streamlit。
安装chainlit的包
pip install chainlit
引入chainlit使用on_message这个装饰器,接收用户输入并包装成chain的输入,这里由于我们chain输出是字符串,所以直接就传给message返回给用户。
import chainlit as cl
from langchain.schema.runnable.config import RunnableConfig
@cl.on_message
async def on_message(message: cl.Message):
result = await chain.ainvoke(
{"question": message.content},
config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
)
await cl.Message(content=result).send()
RunnableConfig是LangChain提供的运行时配置接口,让开发者可以根据需要在每次调用时,确认要传入的参数,使得应用可以灵活应对多种不同的场景。
chainlit run main.py #main.py是python文件名
03
—
结果展示和分析
启动chainlit,会自动打开默认浏览器,在聊天输入框发送“上海交易所有多少支股票?”
点击 “Took 4 steps”,可以看到chain执行的每一步以及输出
尝试稍微复杂一点的查询,回答还可以
总结
当然这只是个最简单的应用,如果要实现可用于生产的软件产品,要完善的事情还很多,列举几个:
安全性:一般的应用场景,确保不能执行DELETE、INSERT、UPDATE的操作。
准确性:当数据库比较大,关系复杂时,可以使用Few-shot-prompt提升查询的准确性;Fine-tune也是一种方式;使用SQL的垂直大模型。
可用性:Memory的管理,确保上下文对话以及token window的限制;流式响应提升用户体验;增加获取实时信息工具、画图表工具,丰富使用场景。
例如要提高自然语言查询数据准确性,以及能够让大模型回答复杂的问题的情况下,需要使用Few-shot-prompt提升查询的准确性,这些都是有一些开源框架存在。例如:vanna.ai、askyourdatabase、dataherald。
后期继续分享相关问题的解决方法案例。贴的代码都是真实的,大家可以直接复制粘贴试一试搭建自己的数据分析机器人吧。
欢迎加入【数据行业交流群】社群,长按以下二维码加入专业微信群,商务合作加微信备注商务合作,AIGC应用开发交流入群备注AIGC应用
往期历史热门文章:
基于DataOps的数据开发治理:实现数据流程的自动化和规范化
数据库有两种张股票相关数据表,我们看看怎么通过中文对话查询需要的股票数据。