【MySQL + 大模型实战】InnoAI SQL 助手:基于DeepSeek-V4-Pro的电商订单智能查询与性能调优系统
前言
在日常数据库运维中,业务人员想查数据却不会写 SQL,DBA 每天重复处理大量"帮我查个数据"的需求;线上慢查询来了,还要手动跑 EXPLAIN、逐行分析执行计划、再手写索引优化方案——这些重复性劳动占据了大量精力。
能不能让 AI 替我们干这些活?
本文介绍一个完整的实战项目——InnoAI SQL 助手。它以 MySQL 8.0 DBA 运维核心知识点为基础,结合腾讯云 TokenHub 大模型 API,构建了一套电商订单库智能查询与性能调优系统:
(1)自然语言转 SQL:输入"查询用户1001的所有订单",自动生成合规 SELECT 语句并执行
(2)AI 业务解读:查询结果自动由大模型生成通俗易懂的业务总结
(3)SQL 性能调优:输入任意 SQL,自动解析 EXPLAIN 执行计划,输出标准化索引优化方案
(4)安全加固:仅允许只读查询,拦截一切增删改危险操作
全程无需人工手写、分析 SQL,适配企业轻量化数据查询、SQL 性能优化、AI 智能解读一体化落地场景。
技术栈:openEuler 22.03 SP4 + MySQL 8.0.45 + Python 3.11.9 + LangChain + Streamlit + 腾讯云 TokenHub(Qwen3.5-Plus / DeepSeek-V4-Pro)
一、项目概述
本项目以 MySQL 8.0 DBA 运维核心知识点为基础,结合腾讯云 TokenHub 开源大模型 API,构建一套电商订单库智能查询与性能调优系统。
(1)核心能力
| 功能 | 说明 |
|---|---|
| 自然语言转 SQL | 接收业务自然语言,自动生成合规 MySQL 查询语句 |
| 自动执行 + 结构化输出 | 自动执行查询并输出格式化表格 |
| AI 业务解读 | 依托大模型完成订单数据业务总结 |
| SQL 性能调优 | 解析 EXPLAIN 执行计划,输出标准化索引优化方案 |
(2)核心价值
- 零门槛数据查询:业务人员无需掌握 SQL 语法,用自然语言即可完成数据查询与报表统计
- 自动化性能调优:自动解析 EXPLAIN 执行计划,输出可直接执行的索引创建与 SQL 改写方案
- 安全可控:内置 SQL 安全校验机制,仅允许 SELECT 查询,拦截所有增删改操作
- 分层解耦设计:代码结构清晰,便于二次开发与教学演示
二、技术架构设计
(1)整体架构分层
系统采用四层架构设计,职责边界清晰:
| 层级 | 模块 | 核心职责 |
|---|---|---|
| 接入交互层 | 命令行终端 / Streamlit Web | 面向用户提供交互入口,支持两种使用模式 |
| Python 程序核心层 | main.py / web_main.py / prompts.py / mysql_client.py | 业务逻辑调度、提示词管理、数据库封装 |
| 底层数据持久层 | MySQL 8.0.45 | 存储电商订单测试数据,作为唯一数据源 |
| AI 大模型服务层 | 腾讯云 TokenHub | 统一 AI 能力出口,支持多模型无缝切换 |
(2)核心文件说明
| 文件名 | 功能定位 | 核心作用 |
|---|---|---|
main.py |
总调度入口与公共服务层 | 封装三大核心业务流程,提供命令行交互入口 |
web_main.py |
Web 可视化界面层 | 基于 Streamlit 实现图形化交互,结果渲染 |
prompts.py |
提示词工程层 | 统一管理 NL2SQL 与 SQL 调优 Prompt 模板,SQL 提取工具 |
mysql_client.py |
数据访问层 | 封装 MySQL 连接、查询、执行计划获取,SQL 安全校验 |
.env |
独立配置文件 | 集中存放数据库参数与大模型密钥,敏感信息隔离 |
三、软硬件环境准备
| 类别 | 名称/规格 | 版本/参数 | 用途 | 备注 |
|---|---|---|---|---|
| 硬件环境 | 虚拟机 | CPU≥2核,内存≥4GB,磁盘≥20GB | 运行 Linux、MySQL、Python 程序 | 本地虚拟机或云 ECS 均可 |
| 软件环境 | 操作系统 | openEuler / RHEL9 | 项目底层运行系统 | 需配置外网访问 API |
| MySQL | 8.0.45 | 存储电商订单测试业务数据 | 内置 order_info 订单表 | |
| Python | 3.11.9(源码编译) | 项目主开发语言 | 依赖 pymysql、python-dotenv、openai、tabulate | |
| Shell | Bash | 系统环境操作、编译 Python | 系统默认自带 | |
| 网络环境 | 外网访问 | 可访问大模型 API | 调用大模型接口 | 防火墙放行 443 端口或关闭 |
| 账号资源 | 腾讯云账号 | 完成实名认证 | 获取 API Key,调用大模型 | 官网:腾讯云 产业智变·云启未来 - 腾讯 |
四、项目环境搭建
(1)系统初始化配置
安装 openEuler 2203_SP4 系统(过程略),完成以下初始化操作:
1、修改主机名
2、关闭SELinux与防火墙
3、配置时间同步
4、安装基础依赖包
#修改主机名
[root@node ~]# hostnamectl set-hostname server
#关闭防火墙
[root@server ~]# systemctl disable --now firewalld
[root@server ~]# systemctl status firewalld
○ firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; ve>
Active: inactive (dead)
Docs: man:firewalld(1)
#关闭SELinux
[root@server ~]# sed -i '7s/enforcing/disabled/' /etc/selinux/config
[root@server ~]# reboot
[root@server ~]# getenforce
Disabled
#配置时间同步服务
[root@server ~]# vim /etc/chrony.conf
server ntp.aliyun.com iburst
[root@server ~]# systemctl restart chronyd
[root@server ~]# chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* 203.107.6.88 2 6 17 7 -1434us[-2651us] +/- 30ms
#下载所需软件
[root@server ~]# dnf install -y gcc gcc-c++ make cmake zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel libffi-devel tk-devel wget tar vim tree net-tools openssh-server
(2)源码编译安装Python 3.11.9
1、下载源码包
从 Python 官网下载 3.11.9 源码包,上传至/usr/local/src目录
下载地址:Python 3.11.9
https://www.python.org/downloads/release/python-3119/


2、解压并编译
解压:
[root@server src]# tar -xzvf Python-3.11.9.tgz

编译配置:
[root@server src]# cd Python-3.11.9
[root@server Python-3.11.9]# ./configure --prefix=/usr/local/python3.11 --enable-shared

多核编译安装:
[root@server Python-3.11.9]# make -j$(nproc) && make install
3、配置动态链接库
[root@server Python-3.11.9]# echo "/usr/local/python3.11/lib" > /etc/ld.so.conf.d/python311.conf
[root@server Python-3.11.9]# ldconfig
目的:解决libpython缺失报错
4、建立全局软连接
[root@server Python-3.11.9]# ln -s /usr/local/python3.11/bin/python3.11 /usr/local/bin/python3
[root@server Python-3.11.9]# ln -s /usr/local/python3.11/bin/pip3.11 /usr/local/bin/pip3
5、验证安装
#验证Python安装
[root@server Python-3.11.9]# python3 -V
Python 3.11.9
[root@server Python-3.11.9]# pip3 -V
pip 24.0 from /usr/local/python3.11/lib/python3.11/site-packages/pip (python 3.11)
#校验SSL模块
[root@server Python-3.11.9]# python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"

(3)配置 pip 源与安装项目依赖
1. 配置阿里镜像源
[root@server ~]# mkdir .pip
[root@server ~]# vim ~/.pip/pip.conf
[root@server ~]# cat ~/.pip/pip.conf
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
2、安装依赖
[root@server ~]# pip3 install --upgrade pip
[root@server ~]# pip3 install pymysql python-dotenv tabulate langchain langchain-openai

(4)部署并初始化 MySQL 8.0.45
1、虚拟机部署部分的超详细版(含原理与高可用分析)见本人专栏文章
2、创建测试库与订单表
mysql> CREATE TABLE order_info(
-> id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '订单ID',
-> user_id INT COMMENT '用户ID',
-> order_name VARCHAR(200) COMMENT '商品名称',
-> pay_amount DECIMAL(10,2) COMMENT '支付金额',
-> create_time DATETIME COMMENT '下单时间'
-> ) ENGINE=InnoDB COMMENT='电商订单业务表';
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO order_info(user_id,order_name,pay_amount,create_time)
-> VALUES
-> (1001,'智能手机',2999.00,'2026-05-01 10:20:00'),
-> (1001,'有线入耳耳机',199.00,'2026-05-02 14:10:00'),
-> (1002,'14英寸轻薄笔记本电脑',5499.00,'2026-05-03 09:30:00'),
-> (1002,'无线蓝牙鼠标',89.00,'2026-05-03 09:35:00'),
-> (1003,'平板学习机',1799.00,'2026-05-04 11:05:00'),
-> (1003,'平板专用保护壳',49.00,'2026-05-04 11:08:00'),
-> (1004,'机械游戏键盘',349.00,'2026-05-05 16:42:00'),
-> (1004,'电竞头戴耳机',459.00,'2026-05-05 16:48:00'),
-> (1005,'大屏智能电视',3299.00,'2026-05-06 08:15:00'),
-> (1005,'电视壁挂支架',129.00,'2026-05-06 08:20:00'),
-> (1006,'无线快充充电器',129.00,'2026-05-03 13:22:00'),
-> (1006,'降噪蓝牙耳机',399.00,'2026-05-03 13:25:00'),
-> (1007,'电竞显示器',1899.00,'2026-05-07 10:10:00'),
-> (1007,'显示器增高支架',79.00,'2026-05-07 10:15:00'),
-> (1008,'折叠平板支架',39.00,'2026-05-04 15:30:00'),
-> (1008,'便携充电宝',159.00,'2026-05-04 15:33:00'),
-> (1009,'台式游戏主机',6999.00,'2026-05-08 09:05:00'),
-> (1009,'电竞防滑鼠标垫',59.00,'2026-05-08 09:08:00'),
-> (1010,'手机钢化膜',29.00,'2026-05-05 17:12:00'),
-> (1010,'桌面收纳支架',45.00,'2026-05-05 17:16:00');
Query OK, 20 rows affected (0.00 sec)
Records: 20 Duplicates: 0 Warnings: 0

五、获取大模型 API Key
(1)访问腾讯云官网,注册账号并完成实名认证

(2)进入 TokenHub 控制台,进入 "API Key 管理" → "新建 API 密钥"


(3)填写密钥名称并保存,记录生成的 API Key
(4)模型选择:推荐使用qwen3.5-plus或deepseek-v4-pro

六、核心脚本开发
(1)新建目录及脚本
[root@server ~]# mkdir -p /opt/mysql_ai_tools
[root@server ~]# cd /opt/mysql_ai_tools
[root@server mysql_ai_tools]# touch main.py mysql_client.py prompts.py web_main.py .env
[root@server mysql_ai_tools]# tree -La 1
.
|-- .env
|-- main.py
|-- mysql_client.py
|-- prompts.py
|-- web_main.py
`-- \343.env
0 directories, 6 files
[root@server mysql_ai_tools]#

(2)编写环境变量配置(.env)
[root@server mysql_ai_tools]# vim /opt/mysql_ai_tools/.env
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=123456
MYSQL_DB=testdb
LLM_API_KEY=你自己的API密钥
LLM_BASE_URL=https://tokenhub.tencentmaas.com/v1
LLM_MODEL_NAME=DeepSeek-V4-Pro
LLM_TEMPERATURE=0

加固文件权限:
[root@server mysql_ai_tools]# chmod 600 /opt/mysql_ai_tools/.env
(3)编写数据库连接脚本(mysql_client.py)
[root@server mysql_ai_tools]# vim mysql_client.py
# -*- coding: utf-8 -*-
# 文件名: mysql_client.py
# 功能: MySQL8.0数据库统一封装类
import pymysql
import os
import re
from dotenv import load_dotenv
load_dotenv()
class Mysql80Client:
def __init__(self):
self.host = os.getenv("MYSQL_HOST", "127.0.0.1")
self.port = int(os.getenv("MYSQL_PORT", "3306"))
self.user = os.getenv("MYSQL_USER", "root")
self.password = os.getenv("MYSQL_PASSWORD", "")
self.database = os.getenv("MYSQL_DB", "testdb")
self.conn = None
self.connect()
def connect(self):
"""创建数据库连接"""
try:
self.conn = pymysql.connect(
host=self.host,
port=self.port,
user=self.user,
password=self.password,
database=self.database,
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
except pymysql.MySQLError as e:
raise Exception(f"数据库连接失败,请检查地址/账号/密码:{e.args[1]}")
except Exception as e:
raise Exception(f"数据库连接异常:{str(e)}")
@staticmethod
def _check_sql_safety(sql: str) -> None:
"""SQL安全校验,仅允许SELECT查询"""
sql_trim = sql.strip().upper()
danger_keywords = [
"INSERT", "UPDATE", "DELETE", "DROP", "ALTER",
"CREATE", "TRUNCATE", "REPLACE"
]
for kw in danger_keywords:
if re.search(r'\b' + re.escape(kw) + r'\b', sql_trim):
raise Exception(f"安全拦截:禁止执行 {kw} 类型语句,仅支持 SELECT 查询")
def execute_query(self, sql: str):
"""执行SELECT查询"""
self._check_sql_safety(sql)
try:
with self.conn.cursor() as cursor:
cursor.execute(sql)
columns = [desc[0] for desc in cursor.description]
rows = cursor.fetchall()
return columns, rows
except pymysql.MySQLError as e:
raise Exception(f"SQL执行失败(错误码 {e.args[0]}):{e.args[1]}")
except Exception as e:
raise Exception(f"查询异常:{str(e)}")
def get_explain_plan(self, sql: str):
"""获取SQL执行计划"""
self._check_sql_safety(sql)
explain_sql = f"EXPLAIN {sql}"
try:
with self.conn.cursor() as cursor:
cursor.execute(explain_sql)
columns = [desc[0] for desc in cursor.description]
rows = cursor.fetchall()
return columns, rows
except pymysql.MySQLError as e:
raise Exception(f"获取执行计划失败:{e.args[1]}")
except Exception as e:
raise Exception(f"执行计划异常:{str(e)}")
def close(self):
"""关闭数据库连接"""
if self.conn and not self.conn._closed:
self.conn.close()
(4)编写提示词工程脚本(prompts.py)
[root@server mysql_ai_tools]# vim prompts.py
# -*- coding: utf-8 -*-
# 文件名: prompts.py
# 功能: 统一管理大模型提示词模板与SQL提取工具
import re
class UnifiedPrompt:
# 数据表结构定义
TABLE_SCHEMA = """
表名: order_info (订单信息表)
字段说明:
- id: 订单ID (主键,INT类型)
- user_id: 用户ID (INT类型)
- order_name: 商品名称 (VARCHAR类型)
- pay_amount: 支付金额 (DECIMAL类型)
- create_time: 下单时间 (DATETIME类型)
"""
# 自然语言转SQL提示词
NL_TO_SQL_PROMPT = f"""
你是严谨的 MySQL 8.0 数据库开发工程师。
【任务目标】
根据用户自然语言描述的业务需求,生成可直接执行、无语法错误的MySQL查询SQL。
【表结构参考】
{TABLE_SCHEMA}
【强制输出规则】
1. 只能生成 SELECT 查询语句,绝对不允许生成 INSERT/UPDATE/DELETE/DROP 等修改、删除数据的语句。
2. 只能使用上面列出的5个字段,禁止自己编造不存在的字段名。
3. 查询字段可使用中文别名,格式固定为:字段 AS 别名。
4. SQL语法遵循MySQL8.0标准,所有关键字统一大写。
5. 最终SQL必须包裹在 ```sql ``` Markdown代码块内。
6. 禁止输出任何解释、说明文字,只返回纯SQL代码块。
7. 中文别名内部不能带空格。
【用户需求】
{{user_input}}
"""
# SQL性能调优提示词
SQL_TUNE_PROMPT = f"""
你是资深 MySQL DBA 性能优化专家。
【任务目标】
根据原始SQL + EXPLAIN执行计划数据,定位查询性能问题并给出可直接落地的优化方案。
【表结构参考】
{TABLE_SCHEMA}
【待分析SQL】
{{sql_input}}
【执行计划数据】
{{explain_data}}
【输出要求】
1. 先点明核心性能问题:全表扫描、无索引、索引失效、扫描行数过多等。
2. 给出完整建索引SQL语句,可直接复制执行。
3. 若原SQL写法存在缺陷,提供改写后的完整优化SQL。
4. 内容简洁、分点罗列,不输出多余废话。
"""
@staticmethod
def extract_sql(response_text: str) -> str:
"""从大模型返回文本中提取纯净SQL语句"""
if not response_text:
return ""
# 优先级1: markdown sql代码块
match = re.search(
r"```sql\s*(.*?)\s*```",
response_text,
re.DOTALL | re.IGNORECASE
)
if match:
return match.group(1).strip()
# 优先级2: <sql>标签
match = re.search(
r"<sql>\s*(.*?)\s*</sql>",
response_text,
re.DOTALL | re.IGNORECASE
)
if match:
return match.group(1).strip()
# 优先级3: SELECT开头兜底匹配
match = re.search(
r"(SELECT\s+.*?;)",
response_text,
re.DOTALL | re.IGNORECASE
)
if match:
return match.group(1).strip()
return ""
# 全局单例
prompt_helper = UnifiedPrompt()
(5)编写程序入口脚本(main.py)
[root@server mysql_ai_tools]# vim main.py
# -*- coding: utf-8 -*-
# 文件名: main.py
# 功能: 核心业务逻辑 + 终端交互式菜单入口
import os
import re
import logging
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from mysql_client import Mysql80Client
from tabulate import tabulate
from prompts import UnifiedPrompt, prompt_helper
load_dotenv()
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
def check_config() -> None:
"""启动前配置校验"""
required_llm = ["LLM_API_KEY", "LLM_BASE_URL", "LLM_MODEL_NAME"]
missing = [k for k in required_llm if not os.getenv(k)]
if missing:
raise ValueError(f"配置缺失:请在 .env 文件中填写 {', '.join(missing)}")
required_db = ["MYSQL_HOST", "MYSQL_USER", "MYSQL_DB"]
missing_db = [k for k in required_db if not os.getenv(k)]
if missing_db:
raise ValueError(f"数据库配置缺失:请检查 {', '.join(missing_db)}")
def get_llm() -> ChatOpenAI:
"""初始化大模型客户端"""
api_key = os.getenv("LLM_API_KEY")
base_url = os.getenv("LLM_BASE_URL")
model_name = os.getenv("LLM_MODEL_NAME")
temperature = float(os.getenv("LLM_TEMPERATURE", 0.1))
return ChatOpenAI(
api_key=api_key,
base_url=base_url,
model=model_name,
temperature=temperature
)
def clean_sql_spacing(sql: str) -> str:
"""SQL标准化清洗函数"""
if not sql:
return ""
# 1. 替换各类空白字符
special_spaces = [
'\xa0', '\u200b', '\u200c', '\u200d', '\u200e', '\u200f',
'\u3000', '\t', '\n', '\r'
]
for sp in special_spaces:
sql = sql.replace(sp, ' ')
# 2. 删除控制字符
sql = re.sub(r'[\x00-\x1f\x7f]', '', sql)
# 3. 中文标点转英文
sql = sql.replace(',', ',').replace(';', ';').replace('(', '(').replace(')', ')')
# 4. 合并连续空格
sql = re.sub(r'\s+', ' ', sql).strip()
# 5. 清理别名中的空格
def _clean_alias_space(match):
prefix = match.group(1)
alias = match.group(2)
alias_clean = re.sub(r'\s+', '', alias)
return f"{prefix} {alias_clean}"
sql = re.sub(
r'\b(AS)\s+(.+?)(?=\s*,\s*|\s+FROM\b|\s+WHERE\b|\s+ORDER\b|\s+GROUP\b|\s+LIMIT\b|\s*;)',
_clean_alias_space,
sql,
flags=re.IGNORECASE
)
# 6. 关键字补空格
keywords_upper = [
"SELECT", "FROM", "WHERE", "ORDER BY", "GROUP BY",
"AND", "OR", "LIMIT", "DESC", "ASC", "AS",
"INNER JOIN", "LEFT JOIN", "RIGHT JOIN", "ON",
"LIKE", "IN", "BETWEEN", "IS NULL",
"COUNT", "SUM", "AVG", "MAX", "MIN"
]
for kw in keywords_upper:
pattern = r'([a-z_])(' + re.escape(kw) + r')'
sql = re.sub(pattern, r'\1 \2', sql)
pattern_cn = r'([\u4e00-\u9fa5])(' + re.escape(kw) + r')'
sql = re.sub(pattern_cn, r'\1 \2', sql)
# 7. 关键字统一大写
for kw in keywords_upper:
sql = re.sub(
r'\b' + re.escape(kw.lower()) + r'\b',
kw.upper(),
sql,
flags=re.IGNORECASE
)
sql = re.sub(r'\s+', ' ', sql).strip()
return sql
def nl2sql_query(user_input: str) -> dict:
"""核心业务1: 自然语言转SQL并执行查询"""
llm = get_llm()
db = Mysql80Client()
try:
logger.info("正在生成SQL语句...")
prompt = UnifiedPrompt.NL_TO_SQL_PROMPT.format(user_input=user_input)
response = llm.invoke(prompt)
raw_content = response.content.strip()
extracted_sql = prompt_helper.extract_sql(raw_content)
if not extracted_sql:
raise Exception("大模型未返回有效SQL,请重新描述需求")
clean_sql = clean_sql_spacing(extracted_sql)
logger.info(f"生成SQL:{clean_sql}")
columns, rows = db.execute_query(clean_sql)
summary = ""
if rows:
logger.info("正在生成数据总结...")
summary_prompt = f"""
以下是真实的SQL查询结果,请作为电商数据分析师给出简练的业务总结。
语句:{clean_sql}
查询数据:{str(rows)}
重点说明数据反映的业务含义,如有异常值请指出。
"""
summary_resp = llm.invoke(summary_prompt)
summary = summary_resp.content.strip()
return {
"success": True,
"sql": clean_sql,
"columns": columns,
"rows": rows,
"summary": summary,
"raw_llm": raw_content
}
except Exception as e:
logger.error(f"查询处理失败:{str(e)}")
return {
"success": False,
"error": str(e),
"raw_llm": raw_content if 'raw_content' in dir() else ""
}
finally:
db.close()
def sql_tune_analyze(raw_sql: str) -> dict:
"""核心业务2: SQL性能调优分析"""
llm = get_llm()
db = Mysql80Client()
try:
clean_sql = clean_sql_spacing(raw_sql)
logger.info("正在获取执行计划...")
columns, plan_rows = db.get_explain_plan(clean_sql)
logger.info("正在分析性能瓶颈...")
prompt = UnifiedPrompt.SQL_TUNE_PROMPT.format(
sql_input=clean_sql,
explain_data=str(plan_rows)
)
response = llm.invoke(prompt)
return {
"success": True,
"sql": clean_sql,
"plan_columns": columns,
"plan_rows": plan_rows,
"suggestion": response.content.strip()
}
except Exception as e:
logger.error(f"调优分析失败:{str(e)}")
return {
"success": False,
"error": str(e)
}
finally:
db.close()
def main_cli():
"""终端交互主函数"""
try:
check_config()
except ValueError as e:
print(f"❌ {e}")
return
while True:
print("\n=============== InnoAI SQL 助手 ===============")
print("1. 自然语言生成SQL,自动查询并AI总结数据")
print("2. 输入SQL语句,AI分析执行计划并给出调优方案")
print("0. 退出程序")
choice = input("请输入功能序号: ").strip()
if choice == '1':
query = input("请输入你的数据查询需求: ").strip()
if not query:
print("⚠️ 请输入有效需求")
continue
result = nl2sql_query(query)
if not result["success"]:
print(f"\n❌ 处理失败:{result['error']}")
if result.get("raw_llm"):
print(f"大模型原始回复:\n{result['raw_llm']}")
continue
print(f"\n✅ 生成SQL:")
print(result["sql"])
if result["rows"]:
print(f"\n📊 查询结果(共 {len(result['rows'])} 条):")
print(tabulate(result["rows"], headers="keys", tablefmt="pretty"))
if result["summary"]:
print(f"\n💡 业务总结:\n{result['summary']}")
else:
print("\n⚠️ 未查询到匹配数据")
elif choice == '2':
sql_input = input("\n请输入需要分析的 SQL 语句: ").strip()
if not sql_input:
print("⚠️ 请输入有效SQL")
continue
result = sql_tune_analyze(sql_input)
if not result["success"]:
print(f"\n❌ 分析失败:{result['error']}")
continue
print(f"\n📊 执行计划详情:")
print(tabulate(result["plan_rows"], headers="keys", tablefmt="pretty"))
print(f"\n📈 调优建议:\n{result['suggestion']}")
elif choice == '0':
print("程序已安全退出。")
break
else:
print("无效输入,请重试。")
print("\n" + "-" * 40)
if __name__ == "__main__":
main_cli()
七、功能测试
(1)自然语言查询测试
启动程序:
[root@server mysql_ai_tools]# python3 /opt/mysql_ai_tools/main.py

(2)SQL 性能调优测试
输入待分析 SQL:
SELECT order_name AS 商品名称, pay_amount AS 支付金额, create_time AS 下单时间 FROM order_info WHERE user_id = 1001;


八、Web 可视化版本(Streamlit)
(1)Streamlit 介绍
Streamlit 是开源、纯 Python Web 开发库,核心定位:不用写 HTML/CSS/JS,只用 Python 就能快速做交互式网页。
1、特点:
- MIT 开源,商用免费
- 组件开箱即用,内置全套交互控件
- 开发热重载,改代码自动刷新页面
- 部署极其简单,支持服务器 systemd 常驻
- 无缝兼容 Python 全生态
2、局限性:
- 并发性能一般,单进程模型
- 自定义 UI 能力弱
- 原生无登录权限控制
(2)部署流程
1、安装并检查 Streamlit 依赖
[root@server mysql_ai_tools]# /usr/local/python3.11/bin/pip3 install streamlit
[root@server mysql_ai_tools]# /usr/local/python3.11/bin/python3 -c "import langchain_openai; print('3.11依赖全部正常')"
3.11依赖全部正常

2、创建 Streamlit 可视化入口(web_main.py)
[root@server mysql_ai_tools]# vim web_main.py
# -*- coding: utf-8 -*-
# 文件名: web_main.py
# 功能: Streamlit网页可视化界面
import streamlit as st
import os
import re
from main import check_config, nl2sql_query, sql_tune_analyze
st.set_page_config(page_title="InnoAI SQL 助手", layout="wide")
# 全局样式优化
st.markdown("""
<style>
html, body, [class*="css"] {
font-size: 15px;
line-height: 1.6;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}
.block-container {
padding-top: 2.5rem;
padding-bottom: 3rem;
max-width: 1100px;
margin: 0 auto;
}
h1 {
font-size: 2rem !important;
font-weight: 600;
margin-bottom: 1.8rem;
}
h2, h3 {
font-weight: 600;
margin-top: 1.5rem;
margin-bottom: 1rem;
}
.stButton > button {
font-size: 15px !important;
font-weight: 500;
padding: 0.65rem 2.2rem !important;
border-radius: 8px !important;
min-width: 160px;
}
.stCodeBlock {
position: relative !important;
border-radius: 8px !important;
}
.stCodeBlock code, .stCodeBlock pre {
font-size: 14.5px !important;
line-height: 1.7 !important;
font-family: "JetBrains Mono", Consolas, Monaco, monospace;
}
.stDataFrame {
font-size: 14.5px;
border-radius: 8px;
overflow: hidden;
}
</style>
""", unsafe_allow_html=True)
# 配置校验
if "config_checked" not in st.session_state:
try:
check_config()
st.session_state.config_checked = True
except ValueError as e:
st.error(f"配置错误:{e}")
st.stop()
# 侧边栏导航
with st.sidebar:
st.title("🚀 InnoAI SQL 助手")
st.info(f"当前模型:{os.getenv('LLM_MODEL_NAME', '未知')}")
page = st.radio("功能导航", ["🔍 数据查询与总结", "⚙️ SQL 性能调优"])
# 页面1: 自然语言查询
if page == "🔍 数据查询与总结":
st.header("💬 自然语言转 SQL 查询")
user_input = st.text_area("请输入你的业务查询需求:", height=150)
if st.button("🚀 生成并执行", type="primary"):
input_trim = user_input.strip()
if not input_trim:
st.warning("请输入有效的业务查询需求后再提交")
elif re.match(r'(?i)^\s*SELECT\s+', input_trim):
st.warning("此处请输入自然语言描述的查询需求,请勿直接粘贴 SQL 语句。")
else:
with st.spinner("AI 正在生成 SQL 并查询数据..."):
result = nl2sql_query(user_input)
if not result["success"]:
st.error(f"处理失败:{result['error']}")
if result.get("raw_llm"):
with st.expander("查看大模型原始回复"):
st.code(result["raw_llm"])
else:
st.success("SQL 生成并执行成功")
st.code(result["sql"], language="sql")
if result["rows"]:
st.dataframe(result["rows"], use_container_width=True)
if result["summary"]:
st.markdown("### 💡 业务总结")
st.info(result["summary"])
else:
st.info("未查询到匹配的数据")
# 页面2: SQL性能调优
else:
st.header("🔧 SQL 性能调优分析")
raw_sql = st.text_area("请输入待分析的 SQL 语句:", height=200)
if st.button("📊 开始分析", type="primary"):
input_trim = raw_sql.strip()
if not input_trim:
st.warning("请输入有效的 SQL 语句后再提交")
elif not re.match(r'(?i)^\s*SELECT\s+', input_trim):
st.warning("此处请输入待分析的 SELECT SQL 语句,请勿输入自然语言描述。")
else:
with st.spinner("正在获取执行计划并分析..."):
result = sql_tune_analyze(raw_sql)
if not result["success"]:
st.error(f"分析失败:{result['error']}")
else:
st.success("执行计划获取成功")
st.dataframe(result["plan_rows"], use_container_width=True)
st.markdown("### 💡 调优建议")
st.markdown(result["suggestion"])
3、配置 systemd 后台服务
[root@server mysql_ai_tools]# vim /etc/systemd/system/mysql-ai-web.service
[Unit]
Description=InnoAI SQL Streamlit Web Tool
After=network.target mysqld.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/mysql_ai_tools
ExecStart=/usr/local/python3.11/bin/python3 -m streamlit run web_main.py \
--server.address 0.0.0.0 \
--server.port 8501 \
--server.headless true
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
启动服务:
[root@server mysql_ai_tools]# vim /etc/systemd/system/mysql-ai-web.service
[root@server mysql_ai_tools]# systemctl daemon-reload
[root@server mysql_ai_tools]# systemctl enable --now mysql-ai-web
Created symlink /etc/systemd/system/multi-user.target.wants/mysql-ai-web.service → /etc/systemd/system/mysql-ai-web.service.
4、访问测试


即可看到 InnoAI SQL 助手的 Web 可视化界面,支持自然语言查询和 SQL 性能调优两大功能。
九、总结
本文完整实现了 InnoAI SQL 助手 项目,从 openEuler 系统初始化、Python 3.11.9 源码编译、MySQL 8.0.45 部署,到大模型 API 对接、Python 分层脚本开发、功能测试、Streamlit Web 可视化部署,全流程可复现。
| 亮点 | 说明 |
|---|---|
| 🔒 安全设计 | SQL 黑名单拦截 + .env 密钥隔离 + 600 权限加固 |
| 🧠 提示词工程 | 严格约束模型输出格式,三层 SQL 提取兜底 |
| 🛡️ 容错清洗 | 7 步 SQL 标准化清洗,兼容各大模型输出差异 |
| 📐 分层架构 | 数据层/提示词层/业务层/展示层完全解耦 |
| 🌐 双端支持 | CLI 终端 + Streamlit Web 可视化,一套核心逻辑 |
更多推荐



所有评论(0)