1. 立项背景和目标
NLP2SQL 是从零搭建的智能数据库查询 Demo。立项背景是想验证一条朴素的假设:让业务人员用自然语言直接查库,能不能用现有
LLM 加 LangChain 拼出一条端到端、不依赖写代码就能用的最短路径。
系统解决的核心问题是"懂业务的人查不到数据,懂数据的人问不到业务"——业务侧的需求(比如"研发部和市场部的人数对比"、"他们
薪资呢")必须经过开发翻译成 SQL,且每次新需求都要排期。立项目标只有一句话:让用户用中文提问,系统自己生成
SQL、执行、总结结果,三步内拿到答案。
项目以 employees 示例库(5 张表、20 员工)为基准,覆盖统计、过滤、聚合、JOIN、模糊匹配、多轮引用 6
类典型问题。设计文档里明确写了不做什么:不支持写操作、不做多租户与权限隔离、不做生产监控、只支持 MySQL
一种方言、不引入 ReAct Agent 的多步推理——避免范围蔓延。
2. 软件功能与核心功能模块
系统暴露 6 个 HTTP 端点,对应 6 类能力,全部在 app/main.py 里实现。
主端点是 POST /api/v1/query,承担"自然语言→SQL→执行→总结"的全流程。辅助端点包括 GET /api/v1/schema/tables 和
/schema/tables/{name} 浏览库表和单表 schema、/schema/tables/{name}/sample 读样本行;POST /api/v1/schema/reload
在数据库结构变更后重建向量索引;GET 与 DELETE /api/v1/sessions/{sid} 拉取和清空多轮对话历史;GET /health
用于健康探活,GET /docs 是 Swagger UI,零额外成本即可调试。
核心代码按单一职责拆成 7 个模块。Pipeline 是 app/pipeline.py 里的编排器,run 方法按"检索 schema→生成
SQL→校验→执行→总结→写记忆"六步串行执行,任意一步失败都返回结构化 QueryResponse,含
sql_validated、validation_error、execution_time_ms 三个可观测字段。SQLGenerator 在
app/chains/sql_generator.py,负责调用 LLM 并把"LLM 自由输出"压成"纯 SQL",需要剥离 think 标签、Markdown
代码块、按分号切分后逐条验证取第一条合法只读语句。validate_sql 在 app/chains/validator.py,是系统的安全防线,用
sqlglot 解析 AST,白名单只放 Select、Uni
架构选的是单链 Pipeline,明确放弃 ReAct Agent,避免循环调试成本。HTTP 进入后 6
步顺序执行,每一步独立可测,失败立即返回结构化错误。
各模块的技术栈如下。Web 层用 FastAPI ≥0.110 配 Uvicorn ≥0.27,因为异步原生、Pydantic 模型自校验、/docs 零成本生成
Swagger。LLM 适配用 LangChain ≥0.3 配 langchain-openai,通过 OpenAI 兼容接口接入 MiniMax-M3,无需为单家厂商写适配。SQL
校验用 sqlglot ≥20,真正解析 AST 而不是正则,支持方言且能递归扫子节点。数据库用 SQLAlchemy 2 配 PyMySQL,2.x 新风格
API,pymysql 纯 Python 免编译。向量检索用 ChromaDB ≥0.5 配 ONNX embedding,轻量、本地持久化、不引入 torch
那套重依赖,schema 改动可手动 reload。配置用 pydantic-settings ≥2 做 .env 强类型解析,启动即失败。测试用 pytest 加
pytest-asyncio 加 httpx 加 pytest-cov。
前后端是分离的。后端纯 REST;前端(frontend/)是独立的 Vite 加 React 加 shadcn/ui 工程,开发端口 5173 通过 Vite proxy
把 /api、/health 转给 8000,跨机部署用 VITE_API_TARGET 环境变量覆盖,无需改代码。