随着大语言模型逐渐进入企业应用,单纯的聊天机器人已经无法满足真实业务需求。企业更希望 AI 能够查询实时业务数据、理解内部文档、记住上下文,并以图表等直观形式展示结果。
本文介绍一个基于 Spring AI 构建的制造业 ERP 智能助手项目。该项目同时集成了 RAG、Tool Calling、多模型切换、会话记忆、多租户隔离、动态 Tool 管理、计费管理和业务数据图表可视化等功能。
项目地址:
演示
1. 项目介绍
Spring AI RAG Demo 是一个面向制造业 ERP 场景的智能助手项目。
它不仅能够回答普通问题,还可以根据用户的自然语言指令自动查询 ERP 数据库。例如:
- 查询本月销售订单
- 查询某个产品的库存
- 查询采购订单收货情况
- 查询生产工单完成进度
- 查询某个批次的质检结果
- 查询客户应收账款
- 根据查询结果生成图表
- 根据企业上传的文档回答问题
项目将 AI 能力分成两条主要链路:
- Tool Calling:查询 MySQL 中的实时 ERP 业务数据。
- RAG:从 PgVector 中检索企业导入的知识文档。
用户可以根据实际场景选择智能模式、数据查询模式或者知识问答模式。
2. 核心功能
2.1 三种 AI 对话模式
项目提供了三种问答模式:
| 模式 | 说明 |
|---|---|
| 智能模式 | 同时启用 Tool Calling 和 RAG,由模型判断应该查询业务数据还是检索文档 |
| 数据查询模式 | 仅启用 Tool Calling,适合查询 ERP 实时数据 |
| 知识问答模式 | 仅启用 RAG,根据用户导入的文档回答问题 |
智能模式适合普通用户使用。用户不需要了解系统内部实现,只需要用自然语言描述自己的问题。
2.2 ERP Tool Calling
项目通过 Spring AI Tool Calling 将后端业务查询能力暴露给大语言模型。
当用户输入:
查询 2026 年 3 月份的销售订单,并按照产品统计销售数量。
大语言模型会根据 Tool 描述选择合适的方法、生成参数并调用后端 Tool。后端查询 MySQL 后,再由模型组织成自然语言回答。
目前代码中包含 8 个 ERP 业务模块,共计 39 个工具方法:
| 模块 | 工具数量 | 支持的查询 |
|---|---|---|
| 销售 | 6 | 订单列表、订单详情、发货、应收、销售汇总和时间范围查询 |
| 采购 | 5 | 采购订单、订单详情、收货、应付和时间范围查询 |
| 生产 | 5 | 工单状态、工单列表、物料、工序和时间范围查询 |
| 质检 | 5 | 质检结果、不良明细、合格率和时间范围查询 |
| 仓库 | 5 | 库存、仓库明细、出入库记录和库存预警 |
| 财务 | 5 | 应收账龄、应付账龄、月度汇总、收款和收支明细 |
| 售后 | 4 | 售后工单、工单详情、退换货和时间范围查询 |
| 委外 | 4 | 委外订单、订单详情、来料、回货和退料 |
这些工具支持“最近一周”“本月”“今年”等自然语言时间表达。大语言模型会将其转换成实际的日期范围。
2.3 动态数据库 Tool
除了代码中通过 @Tool 定义的固定工具,项目还支持在管理页面中维护动态数据库 Tool。
动态 Tool 可以配置:
- Tool 名称
- Tool 描述
- 入参 JSON Schema
- SQL 模板
- 主表别名
- 最大返回行数
- 启用状态
保存、删除或者启停 Tool 后,系统会刷新运行期 ToolSnapshot,后续问答不需要重启应用即可使用最新配置。
为了降低模型生成 SQL 带来的风险,动态 Tool 采用受控 SQL 方案:
- 只允许只读
SELECT - 使用绑定变量传递参数
- 拒绝写入语句和 DDL
- 拒绝多条 SQL
- 校验主表别名
- 自动加入租户条件
- 限制返回数据规模
因此,动态 Tool 并不是让大语言模型随意执行 SQL,而是让模型调用已经经过约束和审核的查询模板。
2.4 RAG 知识问答
项目使用 Spring AI 的 QuestionAnswerAdvisor 实现 RAG。
文档导入后,系统会完成以下处理:
- 使用 Apache Tika 解析文档内容。
- 将文档内容转换为文本片段。
- 使用本地 ONNX 嵌入模型生成向量。
- 将向量和文档内容保存到 PgVector。
- 用户提问时进行向量相似度检索。
- 将检索结果注入大语言模型的 Prompt。
- 由大语言模型根据检索到的内容生成回答。
项目支持导入以下文件:
- Word
- Excel
- TXT
项目还支持一键加载 classpath:docs/ 下的预置文档,并提供文档向量搜索功能,方便调试检索效果。
2.5 Tool 结果图表可视化
当 Tool 返回的数据适合可视化时,系统可以在 Markdown 回答后附加图表。
项目对图表生成过程进行了职责拆分:
- 大语言模型只负责选择图表类型和标题。
- 后端从当前轮 Tool 返回的结构化数据中选择字段。
- 后端完成字段绑定、数据转换和协议校验。
- 前端使用本地 Apache ECharts 渲染图表。
业务数值并不是由大语言模型生成的,而是来自当前轮 Tool 的真实查询结果。
后端最终生成版本化的 ChartSpec 图表协议。图表规划、编译或者渲染失败时,系统会自动降级为普通 Markdown 文本,不影响原始业务回答。
当前支持 23 种图表,包括:
- 环形图
- 条形图
- 瀑布图
- 子弹图
- 面积图
- 阶梯图
- 雷达图
- 散点图
- 气泡图
- 直方图
- 箱线图
- 热力图
- 桑基图
- 矩形树图
- 甘特图
- 漏斗图
- 词云图
- 仪表盘图
- 水位图
- 平行坐标图
- 折线图
- 饼图
- 旭日图
每个助手回答最多返回一个图表,但同一个会话的后续回答仍然可以继续生成图表。
图表会随助手消息一起持久化。重新打开历史会话时,系统可以直接回放图表,不需要重新查询业务数据或者再次调用模型。
2.6 多模型切换
项目支持接入多个模型服务商,目前包括:
- DeepSeek
- 通义千问
- Google Gemini
前端可以通过下拉框切换模型,后端通过 ModelRegistry 将请求路由到对应的 ChatModel。
通义千问通过 OpenAI 兼容协议接入,因此可以复用 Spring AI OpenAI Starter。
2.7 流式对话
项目通过 SSE 和 Reactor 实现流式输出。
模型生成内容后,后端会逐步将数据发送到浏览器,前端使用 marked.js 实时渲染 Markdown,并通过 highlight.js 实现代码高亮。
流式响应使用类型化事件,例如:
delta:增量文本chart:图表数据done:回答结束error:回答异常
这种设计让文本、图表和结束状态拥有明确的协议边界。
2.8 会话记忆
项目使用:
MessageChatMemoryAdvisorJdbcChatMemoryRepository


265

被折叠的 条评论
为什么被折叠?



