# double-ai-agent
**Repository Path**: zhoudev49/double-ai-agent
## Basic Information
- **Project Name**: double-ai-agent
- **Description**: 企业级双引擎 AI 智能体 — 基于 Spring AI Alibaba Graph 构建,实现自然语言驱动的 BI 查询与智能库存调拨。支持 RAG、人工审批、图状态持久化等企业级能力。
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 3
- **Created**: 2026-05-28
- **Last Updated**: 2026-07-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 🤖 Double AI Agent
### 双引擎 AI 智能体 — 自然语言驱动的 BI 查询 + 智能库存调拨
**Spring AI Alibaba Graph + RAG + Milvus + Kafka**
[](https://openjdk.org/)
[](https://spring.io/projects/spring-boot)
[](https://spring.io/projects/spring-ai)
[](https://www.apache.org/licenses/LICENSE-2.0)
[功能特性](#-功能特性) • [架构设计](#-架构设计) • [快速开始](#-快速开始) • [使用指南](#-使用指南) • [技术栈](#-技术栈)
---
## ✨ 项目简介
**Double AI Agent** 是一个企业级双引擎 AI 智能体项目,基于 **Spring AI Alibaba Graph**(有向图状态机)构建了两条完整的 AI Agent 工作流,覆盖零售供应链的核心业务场景:
| 智能体 | 场景 | 一句话描述 |
|--------|------|-----------|
| 🔍 **AI BI Helper** | 数据查询 | 用自然语言问问题,AI 自动生成 SQL → 评估 → 执行 → 发送 Excel 到邮箱 |
| 📦 **AI Transfer** | 库存调拨 | AI 分析销售趋势,预测调拨建议 → 发邮件等审批 → 人工审批后自动创建调拨单 |
> 💡 **这不是一个简单的 ChatBot Demo** —— 它展示了如何在生产级架构中用 **Spring AI Alibaba Graph**(有向图状态机)编排复杂的多步骤 AI 工作流,包括条件路由、循环重试、中断恢复、人工审批、RAG 增强等企业级能力。
---
## 🎯 功能特性
### 🔍 AI BI Helper — 自然语言转 SQL 查询
- **自然语言 → SQL**:用户用中文提问,AI 通过 RAG 检索数据字典,自动生成可执行的 SQL
- **AI 自评自纠**:生成的 SQL 经过 AI 评估节点审核,不合格自动循环重试(最多 N 次)
- **表名安全校验**:执行前通过 JDBC 元数据校验表名是否真实存在,防止 AI "幻觉" 导致 SQL 报错
- **SQL 安全防护**:仅允许 SELECT 查询,自动注入 LIMIT,拒绝一切危险操作
- **结果自动推送**:查询结果转为 Excel 附件,邮件发送给用户
### 📦 AI Transfer — AI 智能库存调拨
- **数据并行采集**:销售记录 + 调拨历史双分支并行获取,提升执行效率
- **AI 预测建议**:基于销售趋势和库存数据,AI 生成调拨建议(JSON 格式)
- **Human-in-the-Loop**:发送审批邮件后图执行中断,等待人工通过 HTTP 回调审批
- **幂等消费**:Kafka 消费端基于 Redis 分布式锁实现幂等去重
- **审批回调**:审批通过自动创建调拨单,拒绝则流程终止
### 🏗️ 通用架构能力
- **Spring AI Alibaba Graph 图编排**:用声明式 API 定义节点、边、条件路由,而非硬编码 if-else
- **Redis 状态持久化**:图执行状态实时保存到 Redis,支持断点恢复
- **Nacos 动态配置**:循环次数、LIMIT 行数等参数支持热更新
- **自定义文档切分**:HeadingBasedSplitter 按数字标题层级切分,前置标题路径增强上下文
- **统一邮件服务**:支持 HTML/附件/模板邮件
---
## 🏛️ 架构设计
### 整体架构

### AI BI Helper 图流程
```
START
│
▼
genSqlNode ← RAG 检索数据字典 + AI 生成 SQL
│
▼
evaluateNode ← AI 评估 SQL(表名/字段名/语法/语义)
│
[EvaluateEdge] ← 条件路由
/ | \
PASS FAIL 空结果/超循环
│ │ │
▼ ▼ ▼
execNode genSqlNode END ← FAIL 循环重试
│
▼
sendEmailNode ← Excel 附件邮件发送
│
▼
END
```
### AI Transfer 图流程
```
START
/ \
▼ ▼
saleRecord inventoryOrder ← 并行采集数据
\ /
▼ ▼
predictNode ← AI 预测调拨建议
│
▼
extractNode ← 提取纯 JSON
│
▼
sendEmailNode ← 发送审批邮件
│
▼
[interrupt:中断] ← 等待人工审批
humanDecisionNode
/ \
approval reject
▼ ▼
createNode END ← 审批通过创建调拨单
│
▼
END
```
---
## 🛠️ 技术栈
| 分类 | 技术 | 版本 | 说明 |
|------|------|------|------|
| **核心框架** | Spring Boot | 3.5.8 | 基础框架 |
| | Spring Cloud | 2025.0.2 | 微服务治理 |
| | Spring Cloud Alibaba | 2025.0.0.0 | Nacos 配置中心 |
| **AI 框架** | Spring AI | 1.1.2 | AI 抽象层 |
| | Spring AI Alibaba | 1.1.2.0 | 通义千问集成 + Graph 图编排 |
| **LLM** | Qwen3.6-Plus | - | 通义千问大模型 |
| | text-embedding-v3 | - | 文本向量化(768维) |
| **向量数据库** | Milvus | 2.x | RAG 文档检索 |
| **中间件** | Redis + Redisson | - | 图状态持久化 / 分布式锁 |
| | Kafka | - | 审批回调消息 |
| | MySQL | 8.0+ | 业务数据库 |
| **工具库** | MyBatis-Plus | - | ORM |
| | Apache POI | - | Excel 读写 |
| | Apache Tika | - | 文档解析(PDF/Word/Markdown) |
| | Hutool | 5.8.42 | Java 工具集 |
| | MapStruct | 1.6.3 | 对象映射 |
---
## 🚀 快速开始
### 前置条件
| 组件 | 版本要求 | 说明 |
|------|---------|------|
| JDK | 21+ | 项目使用了虚拟线程等新特性 |
| Maven | 3.8+ | 构建工具 |
| MySQL | 8.0+ | 业务数据库 |
| Redis | 6.0+ | 图状态持久化 |
| Milvus | 2.x | 向量数据库(AI BI Helper 使用) |
| Kafka | 3.x | 消息队列(AI Transfer 使用) |
| Nacos | 2.x | 配置中心 |
### 1. 克隆项目
**GitHub**:
```bash
git clone https://github.com/zhoudev49/double-ai-agent.git
cd double-ai-agent
```
**Gitee**:
```bash
git clone https://gitee.com/zhoudev49/double-ai-agent.git
cd double-ai-agent
```
### 2. 初始化数据库
```bash
# 建库建表
mysql -u root -p < db/init.sql
# 插入测试数据
mysql -u root -p < db/test-data.sql
```
### 3. 配置环境变量
```bash
# 通义千问 API Key(必填)
export AI_DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx
```
### 4. Nacos 配置
在 Nacos 中创建以下配置:
**ai-bi-helper.yaml**(AI BI Helper 专用):
```yaml
ai:
bi:
loop: 3 # SQL 生成-评估最大循环次数
limit: 3000 # SQL 查询结果行数限制
```
**ai-transfer.yaml**(AI Transfer 专用):
```yaml
ai:
transfer:
email:
to: your-email@example.com # 审批邮件收件人
```
### 5. 修改配置文件
根据实际环境修改各服务的 `application.yml`:
- MySQL 连接地址/密码
- Redis 地址/密码
- Milvus 地址
- Kafka 地址
- Nacos 地址/命名空间
- 邮件 SMTP 配置
### 6. 编译启动
```bash
# 编译
mvn clean package -DskipTests
# 启动 AI BI Helper(端口 8092)
java -jar ai-bi-helper/target/ai-bi-helper-1.0-SNAPSHOT.jar
# 启动 AI Transfer(端口 8091)
java -jar ai-transfer/target/ai-transfer-1.0-SNAPSHOT.jar
```
---
## 📖 使用指南
### AI BI Helper — 自然语言查询
**第一步:上传数据字典到向量库**
```bash
curl -X POST http://localhost:8092/document/upload \
-F "file=@ai-bi-helper/doc/数据字典.txt"
```
**第二步:用自然语言查询**
```bash
curl "http://localhost:8092/genSql/test?userInput=查询北京中心仓所有商品的商品名称与库存数量"
```
AI 会自动:生成 SQL → 评估 SQL → 执行查询 → 生成 Excel → 发送邮件
**更多查询示例**:
| 自然语言问题 | 涉及表 |
|-------------|--------|
| 查询北京中心仓所有商品的库存数量 | bb_inventory + bb_product + bb_warehouse |
| 统计2024年各仓库的总销售金额 | bb_sales_record + bb_warehouse |
| 找出可用库存低于200的商品 | bb_inventory + bb_product + bb_warehouse |
| 统计AI智能调拨和人工调拨各自的数量 | bb_transfer_order |
| 查询各仓库调出调入汇总 | bb_transfer_order + bb_transfer_order_item + bb_warehouse |
### AI Transfer — 智能库存调拨
**触发调拨建议**:
```bash
curl -X POST http://localhost:8091/product/sale \
-H "Content-Type: application/json" \
-d '{"productId": 1, "warehouseId": 1, "quantity": 50, "saleDate": "2025-05-26"}'
```
AI 会自动:采集销售/库存数据 → 预测调拨建议 → 发审批邮件 → **中断等待**
**人工审批回调**:
```bash
# 审批通过
curl "http://localhost:8091/product/decision?approval=true&threadId=xxx"
# 审批拒绝
curl "http://localhost:8091/product/decision?approval=false&threadId=xxx"
```
---
## 📁 项目结构
```
double-ai-agent/
├── pom.xml # 父 POM(统一依赖版本管理)
├── db/
│ ├── init.sql # 数据库建表脚本(6 张表)
│ └── test-data.sql # 测试数据(4 仓 8 商品 5 季度)
│
├── ai-common/ # 公共模块
│ └── src/main/java/com/zhou/common/
│ ├── config/ # Redis / Redisson 配置
│ ├── constant/ # 图常量 / Kafka / Redis Key
│ ├── result/ # 统一响应封装 R.java
│ ├── service/ # 邮件发送服务
│ └── util/ # Excel 读写工具
│
├── ai-bi-helper/ # 🔍 AI BI 查询服务(:8092)
│ ├── doc/
│ │ ├── 数据字典.txt # RAG 数据字典文档
│ └── src/main/java/com/zhou/ai/bi/helper/
│ ├── config/GraphConfig.java # 图编排配置
│ ├── controller/ # 文档上传 / SQL 生成接口
│ ├── edges/EvaluateEdge.java # 评估条件路由
│ ├── nodes/ # 图节点
│ │ ├── GenSqlNode.java # AI 生成 SQL(RAG 增强)
│ │ ├── EvaluateNode.java # AI 评估 SQL
│ │ ├── ExecSqlAndConvertExcelNode.java # 执行 SQL + 转换 Excel
│ │ └── SendEmailNode.java # 发送结果邮件
│ ├── service/ # 文档服务
│ └── splitter/ # 文档切分器
│ └── HeadingBasedSplitter.java # 数字标题层级切分
│
└── ai-transfer/ # 📦 AI 智能调拨服务(:8091)
└── src/main/java/com/zhou/transfer/
├── config/GraphConfig.java # 图编排配置(含中断点)
├── consumer/ # Kafka 消费者(幂等去重)
├── controller/ # 销售触发 / 审批回调
├── edges/HumanDecisionEdge.java # 人工决策路由
├── entity/ # 6 张表实体类
├── mapper/ # MyBatis-Plus Mapper
├── nodes/ # 图节点
│ ├── CollectSaleRecordDataNode.java # 采集销售数据
│ ├── CollectionInventoryOrderDataNode.java # 采集调拨历史
│ ├── PredictNode.java # AI 预测调拨建议
│ ├── ExtractNode.java # 提取纯 JSON
│ ├── SendEmailNode.java # 发送审批邮件
│ ├── HumanDecisionNode.java # 人工决策节点
│ └── CreateInventoryTransferNode.java # 创建调拨单
└── service/ # 业务服务层
```
---
## 🔑 核心设计亮点
### 1. Spring AI Alibaba Graph 有向图编排,告别面条代码
传统做法用 if-else 硬编码流程,难以维护。本项目用 Spring AI Alibaba 的 `spring-ai-alibaba-graph-core` 模块声明式定义:
```java
// 定义节点
graph.addNode("genSql", new GenSqlNode(builder, vectorStore));
graph.addNode("evaluate", new EvaluateNode(builder, vectorStore));
// 定义边 + 条件路由
graph.addEdge("genSql", "evaluate");
graph.addConditionalEdges("evaluate", new EvaluateEdge(loop),
Map.of("execSql", "execSql", "genSql", "genSql", END, END));
```
### 2. AI 自评自纠循环
AI 生成的 SQL 不一定正确 → AI 评估节点审核 → 不通过自动回到生成节点重试,形成闭环。
### 3. Human-in-the-Loop 人工审批
AI Transfer 的调拨流程在发送审批邮件后 **主动中断**,等待人工审批回调后才继续执行:
```java
// 在 humanDecision 节点前设置中断点
CompileConfig compileConfig = CompileConfig.builder()
.interruptBefore("humanDecision")
.saverConfig(saverConfig) // Redis 持久化状态
.build();
```
### 4. 多层 SQL 安全防护
| 防护层 | 机制 |
|--------|------|
| AI 层 | System Prompt 禁止生成非 SELECT 语句 |
| 评估层 | AI EvaluateNode 校验安全性 |
| 代码层 | `isSafeSql()` 白名单校验(仅允许 SELECT) |
| 表名层 | `validateTableNames()` 通过 JDBC 元数据校验表名真实存在 |
| 数据层 | `addLimitToQuery()` 自动注入 LIMIT 防止全表扫描 |
### 5. RAG + 自定义切分策略
`HeadingBasedSplitter` 按数字标题层级(1. / 1.1 / 2.3.1)切分文档,自动前置标题路径,让每个 chunk 都携带完整的上下文信息:
```
1.1 数据库与表命名规范 > 4.3 bb_inventory 常见查询示例
查询某仓库所有商品的库存(关联 bb_product 和 bb_warehouse):
SELECT w.warehouse_name AS '仓库名称' ...
```
---
## 🤝 参与贡献
1. Fork 本仓库
2. 新建分支 `git checkout -b feature/your-feature`
3. 提交改动 `git commit -m 'Add some feature'`
4. 推送分支 `git push origin feature/your-feature`
5. 提交 Pull Request
---
## � 联系方式
| 方式 | 地址 |
|----------|---------------------------|
| 📧 Email | zhoudev49@163.com.com |
| 💬 QQ | 1369048443 |
欢迎交流讨论,如有问题请提 Issue 或直接联系。
---
## �📄 开源协议
本项目基于 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 协议开源。
---
**如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!**