以下文章来源于DataSpeed ,作者DataSpeed
[
DataSpeed .
慢慢积累,稳稳前行,用数据说话,为成长助力
](#)
一、背景
随着DeepSeek的火爆,基于AI的应用也如雨后春笋般迸发出来,如何根据用户的一句话来找到用户所需要的信息,采用传统的方式无法通过模糊匹配等实现复杂的业务场景,故探索一种新的思路来实现信息获取。Text2SQL将自然语言文本转换为SQL(结构化查询语言)语句的技术,该技术可以让用户使用自然语言来查询数据库,而无需掌握复杂的SQL语法。
二、Vanna是什么?
Vanna的核心是一个Python包,它使用检索增强功能来帮助您使用llm为数据库生成准确的SQL查询。Vanna的工作分为两个简单的步骤——在你的数据上训练一个RAG“模型”,然后问一些问题,这些问题将返回SQL查询,这些查询可以设置为自动在你的数据库上运行。
三、为啥要使用Vanna
起初是通过Dify实现Text2SQL查询,DDL语句放在提示词中,如果DDL比较多,容易造成提示词比较长,输入Token比较多,目前这种方案还处于优化中,目前只是实现此功能。另外一种方案也是想通过Vanna来实现Text2SQL查询。
四、Vanna能力
这个是参考官网的流程图,比较清楚的看出包括两部分在你的数据集上训练RAG模型和问答
4.1 训练RAG模型
把DDL/Schemas描述、文档、参考SQL等交给Vanna训练一个用于RAG检索的“模型”。Vanna的RAG模型训练,支持以下几种方式:
1、DDL语句
DDL语句有助于Vanna了解你的数据库表结构信息
vn.train(ddl="CREATE TABLE my_table (id INT, name TEXT)")
2、文档内容
可以是你的企业、应用、数据库相关的任何文档内容,只要有助于Vanna正确生成SQL即可,比如对你行业特有名词的解释、特殊指标的计算方式等。
vn.train(documentation="Our business defines XYZ as ABC")
3、SQL或者SQL问答对
即SQL的样例,这显然有助于大模型学习针对您数据库的知识,特别是有助于理解提出问题的上下文,可以大大提高sql生成正确性。
vn.train(question="What is the average age of our customers?",sql="SELECT AVG(age) FROM customers")
4、训练计划
这是vanna提供的一种针对大型数据库自动训练的简易方法。借助RDBMS本身的数据库内元数据信息来训练RAG model,从而了解到库内的表结构、列名、关系、备注等有用信息。
df_information_schema=vn.run_sql("SELECT * FROM INFORMATION_SCHEMA.COLUMNS")plan=vn.get_training_plan_generic(df_information_schema) vn.train(plan=plan)
4.2 问答
提出问题,获得回答,RAG模型训练完成后,可以用自然语言直接提问。Vanna会利用RAG与LLM生成SQL,并自动运行后返回结果。
4.3 实践
基于以上初步的了解,本地环境进行部署实践,需要先初始化本地的python env,这里使用anaconnda来初始化,ollama模型部署框架,词向量嵌入模型(放在本地向量数据库的缓存目录),以及数据准备。
五、vanna部署
5.1 大模型环境
这里部赘述了,有需要的看公众号 DataSpeed 历史的文章。此处以千问模型为例
ollama run qwen:7b
5.2 chromaDB本地向量数据库
vanna 默认使用 chromaDB
本地向量库,chromaDB默认使用all-MiniLM-L6-v2
模型[1]。
5.3 Anaconda本地环境
需要准备一些必要的依赖
conda create -n vanna -y python=3.9 conda activate vanna pip install 'vanna[chromadb,ollama,mysql]' pip install ipykernel
- 若包安装时出现的 chroma-hnswlib 问题,下载vs\_tools 并安装如下内容,然后重试安装依赖。
5.4 数据准备
准备一些演示数据
CREATE TABLEIFNOTEXISTS vuser ( `id`INT PRIMARY KEYCOMMENT'用户ID', username VARCHAR(50) COMMENT'用户名', email VARCHAR(100) COMMENT'电子邮件', age INTCOMMENT'年龄', gender VARCHAR(10) COMMENT'性别(男/女)', city VARCHAR(50) COMMENT'城市' ) COMMENT='用户信息表'CHARACTERSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERTINTO vuser (`id`, username, email, age, gender, city) VALUES (1, '张三', 'zhangsan@example.com', 30, '男', '北京'), (2, '李四', 'lisi@example.com', 25, '女', '上海'), (3, '王五', 'wangwu@example.com', 40, '男', '广州'), (4, '赵六', 'zhaoliu@example.com', 35, '女', '深圳'), (5, '小明', 'xiaoming@example.com', 28, '男', '成都'), (6, '小红', 'xiaohong@example.com', 45, '女', '重庆'), (7, '小华', 'xiaohua@example.com', 32, '男', '天津'), (8, '小丽', 'xiaoli@example.com', 27, '女', '南京'), (9, '小李', 'xiaoli2@example.com', 38, '男', '武汉'), (10, '小美', 'xiaomei@example.com', 33, '女', '西安');
5.4、Vanna启动部署
python代码demo如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @author: zhyaoeng @Project :vannaTest @Time : 2025/3/18 16:27 @File : testv.py @Software: PyCharm # code is far away from bugs with the god animal protecting I love animals. They taste delicious. ┏┓ ┏┓ ┏┛┻━━━┛┻┓ ┃ ☃ ┃ ┃ ┳┛ ┗┳ ┃ ┃ ┻ ┃ ┗━┓ ┏━┛ ┃ ┗━━━┓ ┃ 神兽保佑 ┣┓ ┃ 永无BUG! ┏┛ ┗┓┓┏━┳┓┏┛ ┃┫┫ ┃┫┫ ┗┻┛ ┗┻┛ """ from vanna.ollama import Ollama from vanna.chromadb import ChromaDB_VectorStore from vanna.flask import VannaFlaskApp class MyVanna(ChromaDB_VectorStore, Ollama): def __init__(self, config=None): ChromaDB_VectorStore.__init__(self, config=config) Ollama.__init__(self, config=config) vn = MyVanna(config={'model': 'qwen:7b','ollama_host': 'http://127.0.0.1:11434'}) vn.connect_to_mysql(host='192.168.15.xxx', dbname='las', user='rot', password='1234', port=3306) # The information schema query may need some tweaking depending on your database. This is a good starting point. df_information_schema = vn.run_sql("SELECT * FROM INFORMATION_SCHEMA.COLUMNS") # This will break up the information schema into bite-sized chunks that can be referenced by the LLM plan = vn.get_training_plan_generic(df_information_schema) vn.train(ddl="""CREATE TABLE IF NOT EXISTS vuser ( `id` INT PRIMARY KEY COMMENT '用户ID', username VARCHAR(50) COMMENT '用户名', email VARCHAR(100) COMMENT '电子邮件', age INT COMMENT '年龄', gender VARCHAR(10) COMMENT '性别(男/女)', city VARCHAR(50) COMMENT '城市' ) COMMENT='用户信息表' CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; """) if __name__ == '__main__': app = VannaFlaskApp(vn) app.run()
5.5 查询结果
执行以上py文件后运行结果如图所示,点击http://localhost:8084进入页面
这里举个例子: 要查询表中年龄最小的用户,就会根据问题转化成对应的SQL,执行查询语句,返回结果,查询的正确结果为李四,如果查询结果正确,可以点击Yes,将此问答结果添加到训练数据中
六、vanai本地化
上面代码只能进行demo验证,日常使用时还是使用本地向量库和大模型,并放在服务器上长期使用和训练。笔者搜了很多本地化的教程,大家都写的很简单,为了助力读者快速上收,我写的详细一些。
这里使用已有的qdrant向量库和ollama大模型。
6.1 添加依赖
pip install fastembed pip install PyMySQL
6.2 本地化Python案例
from vanna.ollama import Ollama from vanna.flask import VannaFlaskApp from vanna.qdrant import Qdrant_VectorStore from qdrant_client import QdrantClient qdrant_url = 'http://xxx:6333' ollama_url = 'http://xxx:11434' class MyVanna(Qdrant_VectorStore, Ollama): def __init__(self, config=None): Qdrant_VectorStore.__init__(self, config=config) Ollama.__init__(self, config=config) vn = MyVanna(config={'url':qdrant_url,'https':qdrant_url,'ollama_host': ollama_url,'model': 'deepseek-r1:14b'}) vn.connect_to_mysql(host='192.168.15.xxx', dbname='las', user='rot', password='1234', port=3306) # The information schema query may need some tweaking depending on your database. This is a good starting point. df_information_schema = vn.run_sql("SELECT * FROM INFORMATION_SCHEMA.COLUMNS") # This will break up the information schema into bite-sized chunks that can be referenced by the LLM plan = vn.get_training_plan_generic(df_information_schema) vn.train(ddl="""CREATE TABLE IF NOT EXISTS vuser ( `id` INT PRIMARY KEY COMMENT '用户ID', username VARCHAR(50) COMMENT '用户名', email VARCHAR(100) COMMENT '电子邮件', age INT COMMENT '年龄', gender VARCHAR(10) COMMENT '性别(男/女)', city VARCHAR(50) COMMENT '城市' ) COMMENT='用户信息表' CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; """) if __name__ == '__main__': app = VannaFlaskApp(vn) app.run()
6.3 代码解释
代码关键在于 MyVanna
与config
的参数如何写,也是很多教程没说清楚的地方。
class MyVanna(Qdrant_VectorStore, Ollama): def __init__(self, config=None): Qdrant_VectorStore.__init__(self, config=config) Ollama.__init__(self, config=config) vn = MyVanna(config={'url':qdrant_url,'https':qdrant_url,'ollama_host': ollama_url,'model': 'deepseek-r1:14b'})
授人以鱼不如授人以渔,其实关键要看源码,以Qdrant_VectorStore
为例,源码中是对config做出了要求,下面是Qdrant_VectorStore.__init__
的config关键代码,因此要在config
增加url
这个key。 其他的向量或大模型可以参照这个方式来解决。
if client is None: self._client = QdrantClient( location=config.get("location", None), url=config.get("url", None), prefer_grpc=config.get("prefer_grpc", False), https=config.get("https", None), api_key=config.get("api_key", None), timeout=config.get("timeout", None), path=config.get("path", None), prefix=config.get("prefix", None), )
七、总结
vanna可以结合自己的数据库以及向量库进行先训练后问答,这一块儿可以参考官网https://vanna.ai/docs/app/,官网还提供了使用 Vanna 构建一个网站应用程序或者一个应用程序接口(API)https://github.com/vanna-ai/v...,欢迎大家一起探讨学习。
引用链接
[1]
模型: https://docs.trychroma.com/do...
关于作者
作者重视实战与理论的结合,文章干货满满,有较为丰富的平台、数开经验,欢迎和作者一起交流,共同进步。
DataSpeed聚焦"大数据+AI"实战与资讯,技术干货和行业消息一网打尽。期待与你同行,欢迎扫码添加作者微信。
关于社区
PowerData社区是由一群数据从业人员,因为热爱凝聚在一起,以开源精神为基础,组成的数据开源社区。
社区群内会定期组织模拟面试、线上分享、行业研讨(涉及金融、医疗、能源、工业、互联网等)、线下Meet UP、城市聚会、求职内推等。同时,在社区群内您可以进行技术讨论、问题请教,届时更多志同道合的数据朋友。
社区整理了一份每日一题汇总及社区分享PPT,内容涵盖大数据组件、编程语言、数据结构与算法、企业真实面试题等各个领域,帮助您自我提升,成功上岸。可以添加作者微信(zwhuihuiz),进入PowerData官方社区群。
往期推荐
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。