查看原文
其他

AIGC系列之三-从零开始建立自己的NL2SQL数据分析机器人(保姆式教程)

ruby ruby的数据漫谈
2024-09-27
摘要:自然语言查询数据是AIGC(Artificial Intelligence and Graph Computing)应用场景中常见的应用之一。AIGC可以将自然语言输入转化为图查询,并根据查询结果进行分析和展现。以下是一些常见的使用自然语言查询数据的AIGC应用场景:1、智能助理:使用自然语言查询数据可以与智能助理进行对话,并通过问题和回答的方式获取所需信息。例如,用户可以询问“最近的餐厅在哪里?”助理可以根据用户的位置信息和餐厅数据回答用户的问题。2、数据探索和可视化:使用自然语言查询数据可以直接在可视化工具中输入查询,以获得特定数据的图表或可视化结果。例如,用户可以输入“近十年全球GDP增长率”,AIGC可以查询相关数据并生成相应的折线图或柱状图。3、信息检索和推荐:使用自然语言查询数据可以快速检索和推荐特定信息或资源。例如,用户可以输入“最近的电影有哪些?”AIGC可以根据用户的偏好和最新的电影数据生成相应的推荐列表。4、企业智能分析:在企业中,使用自然语言查询数据可以帮助决策者轻松获取和分析企业数据。例如,高层经理可以直接向系统中提问“近三个季度销售额和利润率的变化情况如何?”AIGC可以基于企业数据源进行查询和分析,并以图表或自然语言形式返回结果。使用自然语言查询数据可以将复杂的数据分析和查询变得更加直观和易于使用,使用户无需事先了解特定查询语言或数据结构,从而更方便地获取所需信息。本文将以案例的方式讲述使用LangChain的组件搭建一个NL2SQL的数据查询机器人,允许提出关于 SQL 数据库中数据的问题,并获得自然语言答案。展示LangChain的链式编程和大语言模型的能力,最后使用Chainlit做UI可视化的交互。


  • 搭建整个流程和步骤‍‍
  • 案例实践过程‍‍‍
  • 结果展示以及相关问题分析以及优化建议‍‍



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、链接大语言模型‍‍‍‍‍‍‍‍‍‍‍

LLM 和 ChatModel 都是大语言模型的对象。可以使用参数(如温度等)对它们进行初始化,并在Chain中传递到各处。它们之间的主要区别在于输入和输出模式。LLM 对象以字符串作为输入,并输出字符串。ChatModel 对象以消息列表作为输入,并输出一条消息。
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.aiaskyourdatabase‍‍‍‍dataherald。


后期继续分享相关问题的解决方法案例。贴的代码都是真实的,大家可以直接复制粘贴试一试搭建自己的数据分析机器人吧。


欢迎加入【数据行业交流群】社群,长按以下二维码加入专业微信群,商务合作加微信备注商务合作,AIGC应用开发交流入群备注AIGC应用




往期历史热门文章:

基于DataOps的数据开发治理:实现数据流程的自动化和规范化

数据平台:湖仓一体、流批一体、存算分离的核心问题及原因解析

数据治理体系该怎么建设?

实时数仓&流批一体技术发展趋势

数据仓库、数据中台、大数据平台的关系?

数字化转型如何促进业务的发展

数据中台中的核心概念解析

数据治理中的数据标准的作用?

全面数字化转型:打造全新营销模式



数据库有两种张股票相关数据表,我们看看怎么通过中文对话查询需要的股票数据。

继续滑动看下一个
ruby的数据漫谈
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存