自然语言转SQL之Vanna.ai:AI集成数据库

自然语言转SQL之Vanna.ai:AI集成数据库

要实现的功能就是:用中文语言同数据库交流,而数据库给出的结果也是自然语言。

一、Vanna.ai是什么

同数据库对话的理论依据

我们知道,自古以来,数据库就是用来存储数据的。但是想要查数据,得找个懂数据库语言的程序员进行操作。数据库语言也叫"SQL语句"。比如,要查询"有没有一个叫张三的学生",那么SQL语句就是:"SELECT * FROM students WHERE name = '张三';"。而且,你得知道数据存在哪个库里的哪张表中。很显然,这种数据库语言,并不是每个人都能掌握的。

但是(转折来啦),大语言模型的出现,让这件事变简单了。大语言模型即懂你也懂SQL,因此它可以作为一个媒介。

毫无悬念,这段SQL是可用的。

可以再次借助大语言模型,将表格数据转化为我们看得懂的语言。

于是乎,这个对话过程就走通了。整体流程大概是下面这个样子:

上面只是理论知识,那在项目实践上,该如何写代码呢?

在具体落地时,会面临怎么管理大语言模型的问题。比如,怎么告诉它我提问题了你该这么这么回答。怎么衔接大模型生成的SQL语句,又怎么去连接数据库查询结果。拿到结果后,又怎么让大模型给出通俗的结论。上面图中的智能系统,那些个①号坑位、②号坑位都需要有流程来管理并通信。

这一切的一切,你可以来写。但是,有比你更聪明的人已经写完了,而且还开源了。合适你就用,不合适咱就改。这个项目就是Vanna框架。

二、落地步骤:实现三层需求

vanna的官网是:vanna.ai,开源地址是:github.com/vanna-ai/vanna

一般情况下,官网的示例会体现出两大特点:使用简单、功能强大。其目的就是告诉你它能干啥,以此吸引你使用。至于你想真正用上它,那是先爱上它再付出一番努力的后续。
安装vanna

powershell 复制代码
pip install vanna

2.1 官方示例看效果

5行代码就可以构建起来一个智能对话数据库系统。

powershell 复制代码
# The import statement will vary depending on your LLM and vector database. This is an example for OpenAI + ChromaDB

from vanna.openai.openai_chat import OpenAI_Chat
from vanna.chromadb.chromadb_vector import ChromaDB_VectorStore

class MyVanna(ChromaDB_VectorStore, OpenAI_Chat):
    def __init__(self, config=None):
        ChromaDB_VectorStore.__init__(self, config=config)
        OpenAI_Chat.__init__(self, config=config)

vn = MyVanna(config={'api_key': 'sk-...', 'model': 'gpt-4-...'})

# See the documentation for other options

注意:api_key需要从vanna.ai官网申请,免费点击一下就行。

官网提供个性化生成demo
https://vanna.ai/docs/mysql-ollama-chromadb/

powershell 复制代码
pip install vanna[chromadb,ollama,mysql]

运行这5行代码,会启动一个服务,生成一个网站,默认是 localhost:8084。访问这个地址,就可以与数据库对话了:

效果不错。

询问"最受欢迎的3位艺术家的销量",它生成了查询语句,列出了查询结果,还画出了柱形图。最后来了一个总结:根据销量数据,最受欢迎的3位艺术家分别是Iron Maiden(销量:140)、U2(销量:107)和Metallica(销量:91)。

等会儿......哪儿跟哪儿,怎么它就艺术家了,那些销量哪来的?数据库又在哪里?

这是个官方的例子,只求最简单,宣传5行代码搞定。它害怕让你自己部署一套服务器,因此默认了一个sqlite数据库。这个数据库可下载,地址就是代码vn.connect_to_sqlite连接的那个vanna.ai/Chinook.sqlite。

我下载这个sqlite数据库,执行它生成的语句,确实如此。

那它这个demo就不是故弄玄虚,其实是真的查询数据库了。只不过数据库是它提供的。

不是说它对接了大模型吗?代码里怎么没有看到?!

在这个例子中,它把大模型也封装好了。它默认采用的GPT 3.5模型。

2.2 对接自己的数据库

"我肯定要用自己的数据库!",这是客户老孙在大山深处喊出来的。

上面我们说了,vanna是管理流程的,更换数据库对它来说,只不过是将坑位换一个参展商。

它支持很多种数据库,我们拿最常用的MySQL搞一搞。

我有这么一个数据库,这里面存储的是我写的文章,就相当于我的私人文库。

这个数据库很简单,就仨表,一个存文章信息,一个存文章评论信息,一个存文章的类型信息。

那我们就用自己的数据库替换一下。工具要为我所用才是真的有用。

关键点就是连接数据库的那一段代码:

powershell 复制代码
vn.connect_to_mysql(host='localhost', dbname='article_db', user='root', password='123', port=3306)

这句代码做了指定数据库信息,它的地址,端口,叫啥名,用户名密码是多少。

连接上了,你说话就好使了吗?肯定不是!数据库是你的,大模型怎么懂?!你要告诉大模型这个表是干什么的,里面有什么东西。当然它也足够智能,可以自己去读取库里的信息。

下面这句话就可以让它自己读取,然后自己理解并训练。

powershell 复制代码
info_schema = vn.run_sql("SELECT * FROM INFORMATION_SCHEMA.COLUMNS;")
plan = vn.get_training_plan_generic(info_schema)
vn.train(plan=plan)

但是,你家数据库设计的规范吗?你的字段名称起的标准吗?各类外键设置的是否正确?即便很规范,名字不是"mz"是"name"。但是特殊行业也会有自己的特色,比如"人情世故"就很难翻译成英文,还是叫"renqin_shigu"更便于理解。

这时候我们就需要告诉大模型我们的人情世故,要让它入乡随俗。

我们可以将ddl(数据描述语言)传给大模型,让它了解各个字段的含义。

powershell 复制代码
vn.train(ddl="""
    CREATE TABLE `article_types` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `type_name` varchar(100) NOT NULL COMMENT '文章类型名称',
        PRIMARY KEY (`id`),
        UNIQUE KEY `type_name` (`type_name`)
    ) ENGINE=InnoDB COMMENT='存储文章类型信息';
""")

有了上面的训练,当我们问有哪些文章类型时,大模型就会知道从article_types表中去查询type_name字段。

除此之外,我们还可以约定一些个性化的需求。

powershell 复制代码
vn.train(documentation="请注意,我们公司一般将1作为否,0作为是。")

一般来说,大众的认知,数值0表示否定,1表示肯定。但是我们可以通过documentation来重新改变通用模型的认知。告诉LLM在我这儿和外界是相反的,以此来符合自己的场景。

如果上面还不行。那么还有绝招。

powershell 复制代码
vn.train(question="天涯何处是我家?",sql="select name from tianya")

即便你用文言文的方式询问数据库,只要你告诉大模型你的风格是这样的,那么它也会成全你。反正最终就是生成SQL呗。用外语问都行,更何况是文言文了。但是,前提是你需要打个样。因为,在此之前没人这么干过。

好了,换完了数据库,下面开始问答。

这就是你的私人数据助手,到这里其实已经挺有意思了。没花钱,仅凭自己有数据,就搞了个带有AI属性的东西出来。

2.3 完全本地化之路

请注意,上面的vanna已经本地化安装,MySQL也是私有库,但是大模型用的还是人家的GPT 3.5。它支持好多大模型。

官方推荐的是vanna内嵌的openAI。这样最方便实现,也有利于它卖货。不过它也支持其他大厂的LLM,比如谷歌的Gemini,再比如所有符合OpenAI标准API的LLM,以及其他LLM。

我们先搞一个在线版本的,再搞一个本地版本的。

如果接入一个标准的OpenAI协议的LLM,该怎么搞呢?很简单:

powershell 复制代码
from vanna.openai import OpenAI_Chat
from vanna.chromadb import ChromaDB_VectorStore
from openai import OpenAI 

client = OpenAI(
    api_key="你得写你的",
    base_url="https://xx.cn/api/paas/v4/"
) 

class MyVanna(ChromaDB_VectorStore, OpenAI_Chat):
    def __init__(self,client=None, config=None):
        ChromaDB_VectorStore.__init__(self, config=config)
        OpenAI_Chat.__init__(self,client=client, config=config)

vn = MyVanna(client=client, config={"model": "xx"})

区别看出来了吗?原来是VannaDefault,这里面人家都封装好了,内置有LLM。

powershell 复制代码
vn = VannaDefault(model='x', api_key='x', config={"language":"chinese"})

但是现在你不想用它的,那需要你新建一个类指定一下用哪个。具体指定谁家的大模型,得看你手里的资源。通过MyVanna实例化出vn之后,后面连接数据库啥的都一样一样的。这就是用框架管理的好处。

除了符合这种OpenAI标准的大模型之外,其他LLM可以吗?当然可以。比如智普出的GLM4,也可以作为Vanna流程中的LLM使用。

powershell 复制代码
from vanna.chromadb import ChromaDB_VectorStore
from vanna.ZhipuAI import ZhipuAI_Chat

class MyVanna(ChromaDB_VectorStore, ZhipuAI_Chat):
    def __init__(self, config=None):
        ChromaDB_VectorStore.__init__(self, config=config)
        ZhipuAI_Chat.__init__(self, config=config)

vn = MyVanna(config={"api_key":"x","language":"chinese"})

同样,也是构建一个MyVanna,将一个ZhipuAI_Chat初始化进去。从vanna.ZhipuAI中我们发现,ZhipuAI已经内嵌到vanna中作为它的一部分了。

大模型的选型会对效果产生什么影响呢?

我们看同样的问题"最近10篇文章的阅读量趋势"在不同大模型中的表现。

在GLM4中是这样的:

在GPT 3.5中是这样的:

他们生成的SQL查询语句都是一样的,因此查询结果也是一样的。但是,他们后续对结果的分析,以及绘图和总结是不同的。

有细心的朋友发现了,怎么你一直没提代码里面的那个ChromaDB_VectorStore,chroma是个什么东西?

它是一个词向量数据库。Chroma词向量数据库是一个用于自然语言处理和机器学习的工具,它主要用于词嵌入,可以将单词转换为向量表示,能捕获单词之间的语义和语法关系,使得计算机能够更好地理解和处理自然语言。

总而言之,大语言模型离不开词向量的支持。vanna框架考虑到不让用户再去搭建复杂的词向量数据库,因此提供了线上默认版本。但是,咱们非要本地化部署,那么只能再安装一套词向量的数据库在本地。chroma只是其中一个选择。这也导致,我们训练完成之后,根目录下会产生一些数据文件。这里面存储的就是词向量相关的信息。就像是"为何"、"因何"、"缘何"它们其实指的是同样的意思,词向量相近。

你要是不想将词向量数据放在根目录(有人嫌乱),可以指定chroma的存储路径,在构建自定义Vanna类时传入config的path路径即可。

powershell 复制代码
vn = MyVanna(config={"path":model_path, ...})

本地化大模型

我们选用清华大学的ChatGLM3做本地化部署。干完了这一票,整个数据库问答系统就完全本地化。

假设你已经搭建好了一套ChatGLM3环境。因为搭建环境部署程序这类教程太多了,我不多说了。下载项目 github.com/THUDM/ChatGLM3 ,然后最好去HuggingFace下载权重模型和bge-m3。这样会更快,下载完了保存到本地。

找到ChatGLM3下的openai_api_demo文件下的api_server.py文件。这个文件是API服务,启动了它就相当于具备了一个任意基于ChatGPT应用的后端。

运行之前,注意配置好模型文件路径,修改它的路径为你下载文件的真实路径。

调用python api_server.py就可以启动它。启动了它,就相当于你本地127.0.0.1有了一个OpenAI大模型。

于是,Vanna替换为本地LLM就像下面这么简单。

powershell 复制代码
base_url = "http://127.0.0.1:8000/v1/"
client = OpenAI(api_key="EMPTY", base_url=base_url)
vn = MyVanna(client=client, config={"model": "chatglm3-6b"})

建立了vn之后,随后的连接数据库、训练数据、启动服务,代码都是一样的。这里只是一个坑位的变化。

至此,这套可以对话数据库的智能系统就建立好了。你以为这样就结束了吗?没有!不可能!

三、构建自己的产品

你觉得有自己的智能数据助手,万事大吉了吗?可以不用加班了?呵呵,被短暂的愉悦冲昏了头脑吧!

你没有界面啊,你甘心用Vanna提供的这套对话页面吗?

虽然它提供了很多配置:

powershell 复制代码
auth:要使用的身份验证方法。
debug:控制是否显示调试控制台。
allow_llm_to_see_data:指示是否允许LLM查看数据。
logo:用户界面中显示的标志。默认为Vanna标志。
title:设置要在UI中显示的标题。
subtitle:设置要在UI中显示的副标题。
show_training_data:控制是否在UI中显示训练数据。
sql:控制是否在UI中显示SQL输入。
table:控制是否在UI中显示表格输出。
csv_download:指示是否允许将表格输出作为CSV文件下载。
chart:控制是否在UI中显示图表输出。
ask_results_correct:指示是否询问用户结果是否正确。
summarization:控制是否显示摘要。
......

但是这些依然会很难符合你的需求。听我说,我们可以调用它的接口,自己来实现界面。

通过查询VannaFlaskApp的接口,我们可以获得业务流程最多分为4步。

3.1 提问转SQL

第1步,调用api/v0/generate_sql。

此步收到用户的提问文本,调用大模型接口生成sql语句。这个接口中,经过训练的大模型会将自然语言转为sql语句。转换成功后还会返回一个业务id。这个id一直绑定后续流程直至任务结束。

3.2 执行SQL查询

第2步,调用api/v0/run_sql。

此步执行上一步生成的sql语句。执行过后,会获得查询结果。在数据库查询结果中,对于希望获得一些趋势或者走向的问题,会返回是否需要绘制图表的字段 should_generate_chart 。

3.3 生成图表

第3步,如果需要展示图表,那么调用 api/v0/generate_plotly_figure 生成绘制数据,绘制并保存为图片。

3.4 答案总结

第4步,根据以上数据,将结果交给大模型进行总结。如果觉得总结的不好,你也可以加上一些prompt引导,最终获得一条可阅读的结论。调用的接口是 api/v0/generate_summary 。

3.5 集成到UI

接口全都有了。从问题到数据,再到趋势图表,最后有总结答案。就看你想展示什么,自己调用就可以了。

对于带图表的情况,也可以正常展示

实例2

powershell 复制代码
docker pull marqoai/marqo:latest
docker run --name marqo -it -p 8882:8882 marqoai/marqo:latest

未完待续

相关推荐
大龄程序员狗哥4 小时前
第25篇:Q-Learning算法解析——强化学习中的经典“价值”学习(原理解析)
人工智能·学习·算法
陶陶然Yay4 小时前
神经网络常见层Numpy封装参考(5):其他层
人工智能·神经网络·numpy
极客老王说Agent4 小时前
2026实战指南:如何用智能体实现药品不良反应报告的自动录入?
人工智能·ai·chatgpt
imbackneverdie4 小时前
本科毕业论文怎么写?需要用到什么工具?
人工智能·考研·aigc·ai写作·学术·毕业论文·ai工具
IT摆渡者4 小时前
MySQL性能巡检脚本分析报告
数据库·mysql
lulu12165440784 小时前
Claude Code项目大了响应慢怎么办?Subagents、Agent Teams、Git Worktree、工作流编排四种方案深度解析
java·人工智能·python·ai编程
大橙子打游戏4 小时前
talkcozy像聊微信一样多项目同时开发
人工智能·vibecoding
deephub4 小时前
LangChain 还是 LangGraph?一个是编排一个是工具包
人工智能·langchain·大语言模型·langgraph
Lyyaoo.5 小时前
Redis基础
数据库·redis·缓存
OidEncoder5 小时前
编码器分辨率与机械精度的关系
人工智能·算法·机器人·自动化