为什么我们要再造一个 NL2SQL 轮子?
“NL2SQL 这个方向已经卷成红海了,你再写一个有什么意思?”
这是我立项 easy-data-agent之前被问得最多的一句话。
这篇不写代码,先把“为什么做”、“做成什么样”、“选型怎么定”这几个问题说清楚,后面再拆细节。
痛点不是“能不能生成 SQL”,而是“敢不敢执行”
前段时间我们调研过不少 NL2SQL 方案,开源的、商业的都看过。Demo 都很惊艳——丢一句“查询最近 7 天订单总金额”,3 秒返回一条 SQL,结果也对。
但真正丢到企业场景里跑,普遍会撞到三堵墙:
第一堵墙:表名瞎编。LLM 没见过你的 Schema,它根据问题“猜”表名。用户问“商品销量”,它给你生成SELECT * FROM product_sales,但你库里这张表叫bb_sales_record。SQL 语法没问题,一执行就报Table doesn’t exist。
第二堵墙:不敢执行。NL2SQL 直接对接生产库,LLM 偶尔会幻觉出
DROP TABLE、UPDATE … SET …这种语句。即使加了READ_ONLY
权限,一条SELECT * FROM big_table也能把库拖死。企业里没人敢让 LLM 直接执行 SQL,必须有人审一眼。
第三堵墙:执行完了就完了。大部分方案止步于“返回一张表格”。但业务用户要的不是表,是结论。“这个月比上个月涨了多少”、“哪个商品占比最高”——这些需要图表、需要对比、需要可视化。
easy-data-agent这三堵墙都得翻过去。所以立项时定下三个硬目标:
不让 LLM 瞎编表名:用 RAG 把真实 Schema 喂给它。
关键节点必须有人审:用工作流引擎在 SQL 执行前中断。
执行结果自动出图:根据数据特征选合适的图表类型。
为什么选 Spring AI Alibaba Graph?
选型阶段对比过 LangChain4j、Spring AI 原生、Spring AI Alibaba Graph 三个方案。
LangChain4j:生态成熟,但它本质是一套工具箱,工作流得自己拼。我们这个场景有 6 个节点、3 个条件分支、还要在中间中断恢复——自己拼工作流意味着自己维护状态机,太重了。
Spring AI 原生 (1.1.x):提供了ChatClient和VectorStore抽象,但没有工作流引擎。要实现“SQL 生成失败自动重试”、“人工审核中断恢复”这种逻辑,得自己写编排代码。
Spring AI Alibaba Graph:这是阿里巴巴在 Spring AI 之上补的一层工作流引擎,核心是StateGraph——借鉴了 LangGraph 的设计。它原生支持:
- 节点 (Node):一个
NodeAction,输入是OverAllState,输出是状态更新。 - 边 (Edge):节点之间的固定跳转。
- 条件边 (Conditional Edge):根据状态动态决定下一个节点。
- 检查点 (Checkpoint):工作流状态持久化,支持中断/恢复。
- 中断 (Interrupt):在指定节点前暂停,等外部信号。
这套模型几乎是为NL2SQL + Human-in-the-Loop量身定做的。我们的 节点工作流用 Graph 表达非常自然:
最后选 Alibaba Graph 还有一个现实原因:国内访问 OpenAI 不稳定,DashScope(通义千问)是国内合规且效果不差的选择,Alibaba Graph 对 DashScope 适配最好。
为什么不用 LangChain4j 的内置 RAG?
LangChain4j 自带 EmbeddingStoreContentRetriever,三行代码就能接上 RAG。但我没用,原因是它只支持单路向量检索。
企业场景里,用户问“查询 GMV 排名前 10 的商品”——“GMV”是业务术语,向量检索可能召回不到,因为它不知道 GMV 等于 SUM(revenue)。但 BM25 全文检索能精确匹配到“GMV”这个词。
所以我们自己实现了 HybridSearchService,BM25 + 向量 + RRF 融合。实测在术语密集的查询上,召回率比纯向量检索高 30% 以上。这块第 06 篇会详细拆。
整体架构:三模块分层
项目按经典的三个 Maven 模块拆分:
为什么 common 单独拆出来?阿里手册里有一条:“通用常量、工具类、异常定义应放在独立模块,避免业务模块循环依赖。” 我们 core 和 web 都要用Constants、SqlSafetyUtil、BizException,不拆 common 的话 web 就得反向依赖 core 的内部包,结构很丑。
为什么 core 不依赖 web?core 是纯业务逻辑,web 是入口。哪天想加一个定时任务批量跑 NL2SQL,或者加一个 gRPC 接口,都不应该改 core。这种分层让 core 可以单独被打成 jar 给别的服务复用。
节点工作流长什么样?
直接看 DataAgentGraphConfig.java的核心代码:
这段代码定义了完整的业务流程。我把它翻译成人话:
注意 sql_validate后面是条件边——校验通过走人工审核,校验失败回 sql_generate重试,重试超限直接结束。这就是 Graph 引擎的价值:状态机不用自己写。
检查点持久化:为什么不用内存版?
Graph 引擎默认提供 MemorySaver(内存检查点),开发调试够用。但我们生产上必须用 MysqlSaver:
理由很现实:人工审核不是 10 秒内能完成的,用户可能去看电影了,半小时后回来点“批准”。这期间服务不能重启,重启了状态就丢了。用 MySQL 持久化 checkpoint,应用重启后用户还能接着审。
interruptBefore(“human_review”)这一行是Human-in-the-Loop的关键——工作流执行到 human_review节点前会暂停,把状态写库,等待外部 resume 信号。
踩过的坑
坑 1:BOM 版本不匹配导致类找不到
spring-ai-alibaba-bom1.1.2.3 没有管理 spring-ai-alibaba-starter-dashscope的版本,得单独指定。pom.xml里能看到这段注释:
<!-- Spring AI Alibaba DashScope Starter (BOM 1.1.2.3 未管理, 单独指定版本) --> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> <version>${spring-ai-alibaba-dashscope.version}</version> <!-- 1.1.2.0 --> </dependency>如果你问我再造这个轮子值不值得,我的回答是:当市面上的轮子都跑不稳你这条路时,亲手造一个,就是最快的捷径。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~