架构
Vanna 是一个开源 Python RAG(检索增强生成)框架,用于 SQL 生成和相关功能。
机制
Vanna 的工作过程分为两个简单步骤 - 在您的数据上训练 RAG“模型”,然后提出问题,这些问题将返回 SQL 查询,这些查询可以设置为在您的数据库上自动运行。
训练:根据您的数据训练 RAG“模型”,或者说根据数据结构构建向量库。用户可以使用 DDL 语句、文档或样例 SQL 查询对 Vanna 进行训练,让它掌握数据库的结构、业务术语和查询模式。Vanna 会将训练数据转化为向量嵌入,存储在向量数据库中,并建立元数据索引,以便于后续检索。
问问题:问Vanna关于数据的各种问题,如"上个月销量最大的5个商品"
检索:Vanna对问题的处理与其他RAG系统一样,检索对应的DDL 语句、文档或样例 SQL。
生成 SQL: Vanna 利用LLM(例如 GPT-4),结合上下文信息,将自然语言问题转化为精准的 SQL 查询语句。
执行 & 展示:数据库收到 Vanna 生成的 SQL 查询后,就会执行查询。Vanna 会将查询结果整理成易于理解的格式,例如表格或图表,呈现给用户。
安装
系统说明
##当前验证环境是
win 10
python 3.10
qwen3 8b、deepseek-r1:7b、qwen2.5 code:7b
vanna 0.7.9
chroma-hnswlib 0.7.6
chromadb 0.6.3
mysql 8.0.42
安装命令
conda activate vanna
pip install vanna[chromadb,ollama,mysql]
启动服务
from vanna.ollama.ollama import Ollama
from vanna.chromadb import ChromaDB_VectorStore
class MyVanna(ChromaDB_VectorStore, Ollama):
def __init__(self, config=None):
ChromaDB_VectorStore.__init__(self, config=config)
Ollama.__init__(self, config=config)
#Ollama.system_message(self, message="请不用思考,你是Mysql生成专家:1、基于用户的需求生成SQL 2、只返回可执行的SQL语句/no_think")
vn = MyVanna(config={'model': 'qwen3:8b', 'ollama_host': 'http://localhost:11434'})
vn.connect_to_mysql(host='localhost', dbname='test', user='root', password='root1234', port=3306)
vn.train(ddl="""
CREATE TABLE `vuser` (
`id` int NOT NULL COMMENT '用户ID',
`username` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
`email` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '电子邮件',
`age` int DEFAULT NULL COMMENT '年龄',
`gender` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '性别(男/女)',
`city` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '城市',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息表';
""")
from vanna.flask import VannaFlaskApp
app = VannaFlaskApp(vn, debug=False, allow_llm_to_see_data=True, title="数据库问答系统")
app.run()
使用
明细
Q:查询名字里含小的用户
汇总
Q:查询名字里含小的用户数/nothink
多轮会话
1、Q:按照性别统计3月以内加入的用户数,用柱状图展示
2、Q:只看女呢?
注:这里写女生、女性、女的估计有报错,需要train个doc。
3、Q:近半年的呢?
4、Q:加入时间最长和最短的用户的差几个月?
5、Q:按照性别统计年龄大于25的用户数
特定词汇
这里定义了特定词,年龄段: 30以下定义为稚嫩, 30-45定义为核心 45以上定义为福宝
多表
Q:查询最近三天的入库记录
Q:按照产品名称分组统计3月到5月的入库量
注:这里时间明显有误,没取到当前日期。
Q:按照产品名称统计当前时间所在的3月到5月的入库量
加入Doc训练后
Q:按照产品名称统计3月到5月的入库量/nothink
Q:查询库存数据最少和最多的商品和仓库名称。/nothink
注:返回的SQL不准确,当前模型是Qwen3:8B
deepseek-r1:7b返回的代码不能执行。
qwen2.5-coder:latest 7B
可正确返回
总结
1、Vanna多轮会话时有时识别不太准确
2、qwen3 8b、deepseek-r1:7b的SQL生成效果不如qwen2.5 code:7b
3、自定义术语或逻辑说明,可以转换成正确SQL
4、使用简单主要有train方法进行自定义训练(DDL、Document、SQL对)
附录
-- 建表语句见下:
DROP TABLE IF EXISTS `t_inventory`;
CREATE TABLE `t_inventory` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '记录ID',
`product_id` int NOT NULL COMMENT '商品ID,关联product_id表的id',
`product_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称(冗余)',
`warehouse_id` int NOT NULL COMMENT '仓库ID,关联t_warehouse表的id',
`quantity` int NOT NULL DEFAULT 0 COMMENT '库存数量',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `product_id`(`product_id` ASC, `warehouse_id` ASC) USING BTREE COMMENT '防止重复记录',
INDEX `warehouse_id`(`warehouse_id` ASC) USING BTREE,
CONSTRAINT `t_inventory_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `t_product` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `t_inventory_ibfk_2` FOREIGN KEY (`warehouse_id`) REFERENCES `t_warehouse` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '库存表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for t_product
-- ----------------------------
DROP TABLE IF EXISTS `t_product`;
CREATE TABLE `t_product` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '商品ID',
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称',
`unit` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '单位',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '商品表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for t_stock_in
-- ----------------------------
DROP TABLE IF EXISTS `t_stock_in`;
CREATE TABLE `t_stock_in` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '记录ID',
`product_id` int NOT NULL COMMENT '商品ID,关联product_id表的id',
`product_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称(冗余)',
`warehouse_id` int NOT NULL COMMENT '仓库ID,关联t_warehouse表的id',
`quantity` int NOT NULL COMMENT '入库数量',
`operator` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '操作人',
`batch_no` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '批次号',
`create_time` datetime(3) NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '入库时间',
`is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`) USING BTREE,
INDEX `product_id`(`product_id` ASC) USING BTREE,
INDEX `warehouse_id`(`warehouse_id` ASC) USING BTREE,
CONSTRAINT `t_stock_in_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `t_product` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `t_stock_in_ibfk_2` FOREIGN KEY (`warehouse_id`) REFERENCES `t_warehouse` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '入库记录表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for t_warehouse
-- ----------------------------
DROP TABLE IF EXISTS `t_warehouse`;
CREATE TABLE `t_warehouse` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '仓库ID',
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '仓库名称',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '仓库表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for vuser
-- ----------------------------
DROP TABLE IF EXISTS `vuser`;
CREATE TABLE `vuser` (
`id` int NOT NULL COMMENT '用户ID',
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户名',
`email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电子邮件',
`age` int NULL DEFAULT NULL COMMENT '年龄',
`gender` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '性别(男/女)',
`city` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '城市',
`joindate` date NULL DEFAULT NULL COMMENT '加入日期',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表' ROW_FORMAT = Dynamic;