Skip to content

Repository files navigation

ChatBI

基于自然语言查询 MySQL 数据库的 ChatBI 工具(MVP):用户输入一句自然语言问题,系统自动生成 SQL、执行查询,并把结果以可视化表格(列名 + 结果行)的形式返回。

功能特性

  • 自然语言转 SQL:调用 LLM 根据用户问题生成 MySQL SQL 语句
  • Schema 上下文:自动读取数据库表结构并注入 Prompt,提升 SQL 生成准确率
  • 可视化输出:查询结果以带边框的对齐表格展示,支持中文对齐、NULL、日期时间等类型
  • 安全护栏:执行前校验 SQL 只读性,拒绝 INSERT / UPDATE / DELETE / DROP 等破坏性语句
  • 多模式入口:支持交互式对话、一次性查询和 FastAPI 服务

项目结构

chatbi/
├── main.py              # 主流程编排(校验 → 生成 SQL → 执行 → 格式化)
├── api_service.py       # FastAPI 服务入口
├── prompt_builder.py    # Prompt 构造
├── llm_client.py        # LLM 调用(OpenAI 兼容接口)
├── query_parser.py      # 用户查询解析与校验
├── schema_generator.py  # 从数据库生成表结构描述
├── database.py          # MySQL 查询执行,返回列名 + 结果行
├── result_formatter.py  # 查询结果格式化为可视化表格
├── config.py            # 数据库 / LLM 配置读取
├── .env.example         # 环境变量示例(复制为 .env 使用)
├── pyproject.toml       # 项目与依赖配置
└── src/chatbi/          # 包入口(chatbi 命令)

环境要求

  • Python >= 3.12
  • MySQL(或其他兼容 MySQL 协议的数据库)
  • 可访问的 OpenAI 兼容 API(可通过 OPENAI_BASE_URL 切换服务商)

安装与配置

1. 安装依赖

项目使用 uv 管理依赖:

uv sync

也可以使用 pip:

pip install -e .

2. 配置环境变量

将根目录的 .env.example 复制为 .env,并填写真实配置:

cp .env.example .env

各配置项说明:

变量 说明 默认值
OPENAI_API_KEY LLM API Key(必填)
OPENAI_BASE_URL LLM 接口地址 https://api.openai.com/v1
LLM_MODEL 使用的模型名称 gpt-4o
DB_HOST 数据库地址 localhost
DB_PORT 数据库端口 3306
DB_USER 数据库用户名 root
DB_PASSWORD 数据库密码
DB_NAME 数据库名称 chatbi_mvp

使用方法

交互式对话

python main.py

输入 exitquit退出 结束程序。

一次性查询

python main.py "查询用户数量"
python main.py "列出销量前 10 的商品名称和销售额"

通过包入口运行

uv run chatbi

启动 FastAPI 服务

python api_service.py

也可以通过 Uvicorn 启动:

uvicorn api_service:app --host 0.0.0.0 --port 8000

服务启动后可访问:

  • 查询接口:POST http://127.0.0.1:8000/chatbi
  • 健康检查:GET http://127.0.0.1:8000/health
  • Swagger 文档:http://127.0.0.1:8000/docs

查询示例:

curl.exe -X POST "http://127.0.0.1:8000/chatbi" `
  -H "Content-Type: application/json" `
  -d '{"user_query":"统计每个城市有多少用户"}'

成功响应:

{
  "question": "统计每个城市有多少用户",
  "sql": "SELECT city, COUNT(*) AS user_count FROM t_user GROUP BY city",
  "columns": ["city", "user_count"],
  "rows": [["上海", 128], ["北京", 96]],
  "formatted_result": "+--------+------------+\n..."
}

空问题或非只读 SQL 返回 HTTP 400;LLM、数据库或其他服务异常返回 HTTP 500。 API 当前允许任意来源跨域访问,适合开发环境;生产环境建议改为明确的域名白名单。

单独运行辅助模块

生成数据库 Schema 描述:

python schema_generator.py

预览表格格式化效果(使用内置示例数据):

python result_formatter.py

运行示例

请输入您的查询: 统计每个城市有多少用户

用户问题: 统计每个城市有多少用户
生成的 SQL: SELECT city, COUNT(*) AS user_count FROM t_user GROUP BY city
+--------+------------+
| city   | user_count |
+--------+------------+
| 上海   | 128        |
| 北京   | 96         |
+--------+------------+

工作流程

用户问题
  ↓ QueryParser 校验(非空)
  ↓ schema_generator 生成表结构(会话内缓存,失败则降级)
  ↓ prompt_builder 构造 Prompt(系统指令 + Schema + 问题)
  ↓ llm_client 调用 LLM 生成 SQL
  ↓ is_read_only_sql 只读安全检查
  ↓ database.execute 执行查询,返回 {columns, rows}
  ↓ result_formatter.format_result 输出可视化表格

模块说明

模块 职责 关键接口
main.py 流程编排、只读校验、交互入口 execute_chatbi()run_chatbi()main()
api_service.py FastAPI 查询服务与健康检查 appquery_chatbi()
prompt_builder.py 构造发送给 LLM 的消息 build_messages(query, schema)
llm_client.py LLM 调用与结果清理 generate_sql(query, schema)
query_parser.py 用户输入解析与校验 QueryParser.parse() / validate()
schema_generator.py 从数据库生成表结构描述 generate_schema()
database.py SQL 执行,返回列名与结果行 Database.execute(sql)
result_formatter.py 结果格式化为表格 format_result(result)format_table(...)
config.py 数据库 / LLM 配置读取 database_configllm_config

安全说明

  • main.py 在 SQL 执行前会做只读检查:仅允许 SELECT / SHOW / EXPLAIN / DESCRIBE / WITH 开头的语句;多条语句中只要混入写操作也会被拒绝。
  • 该检查属于粗略防护,不能替代完整的权限控制。生产环境建议使用只读数据库账号,遵循最小权限原则,并引入更严格的 SQL 校验(如 SQL 解析器、表/列白名单)。

后续扩展方向

  • QueryParser 升级为意图识别与实体抽取(时间范围、表名、筛选条件等)
  • 为查询结果增加图表渲染(如 ECharts)
  • 将命令行入口包装为 Web / API 服务,支持多轮对话

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages