从 SQL 到语义,Java 开发者的 Agent 实战革命——用 LangChain4j + 通义千问 + MySQL 8.0 打造企业级数据分析智能体
一、为什么这不是一篇“Hello Agent”文章
过去两年,很多团队都做过类似的尝试:
- 给大模型接一个数据库,让它回答“上个月华东区销售额是多少”
- 给大模型接一个知识库,让它解释“为什么这个区域环比下降”
- 给大模型接一个图表服务,让它自动生成趋势解读
PoC 阶段通常进展很快。一个下午,就能拼出一个“自然语言转 SQL”的原型系统。
但一旦进入真实业务,问题会立刻出现:
- 用户问题并不规范:“帮我看看最近几个月华东表现怎么样,最好顺手对比去年同期”
- 同一个问题既需要精确数值,又需要语义解释
- 会话上下文会影响后续问题:“那华南呢”“把时间改成近 6 个季度”
- 大模型调用慢、贵、偶发超时,还会被限流
- 数据权限复杂,不同租户、不同角色、不同区域能看到的数据不一样
- 高峰期并发请求上来以后,线程池、连接池、模型额度、缓存命中率都会成为瓶颈
所以,企业级数据分析智能体的本质,不是“让 LLM 帮你写 SQL”,而是:
构建一个由 LLM 负责意图理解和决策、由业务工具负责精确执行、由工程体系负责稳定交付的智能化服务系统。
这也是本文的主线。
我们要实现的,不只是一个聊天机器人,而是一个真正可落地的销售分析 Agent:
- 用户用自然语言提问
- Agent 自动判断是走 SQL、RAG、还是混合流程
- 系统根据租户和权限只查询允许访问的数据
- 查询结果经过大模型解释与结构化整理后输出
- 整个过程具备缓存、限流、异步削峰、降级、审计和监控能力
如果你把它理解为“会思考、会调工具、受治理约束的微服务”,你就抓住重点了。
二、问题抽象:从“问答”到“智能体执行链”
2.1 一个真实业务场景
假设你在做一家零售企业的数据中台。业务部门希望通过自然语言直接查询经营数据:
- “华东区 2026 年第一季度销售额是多少?”
- “最近 6 个季度华南区趋势怎么样?有没有异常波动?”
- “为什么上月客单价上涨但总销售额没明显增长?”
- “把华北和华东过去一年的数据做个对比总结”
这几类问题看似都在“问数据”,但底层处理路径完全不同:
- 第一类问题是精确查询,核心是 SQL
- 第二类问题是聚合查询 + 趋势分析
- 第三类问题可能需要多个指标联合计算,再交给模型生成解释
- 第四类问题既要查结构化数据,也可能要参考历史运营结论、营销活动说明、节假日备注等非结构化知识
这意味着系统不能只有单一路径,而要具备“路由判断”能力。
2.2 Agent 在这个场景里到底负责什么
很多人会误以为 Agent 就是“让模型自己想办法”。这在生产环境里是危险的。
一个合格的企业级 Agent,应该只承担三类职责:
理解用户意图
将模糊自然语言映射为可执行任务,例如识别时间范围、指标、维度、对比对象、输出方式。规划执行路径
判断应该调用哪个工具,以及工具调用顺序。例如先查销售额,再查订单数,再做同比环比,再生成解释。整合执行结果
把工具返回的结构化结果、语义检索结果和上下文合并成用户可读的最终答案。
至于真正高风险、强约束、需要可审计的动作,比如:
- 数据库访问
- 权限判断
- 聚合逻辑
- 指标口径计算
- 报表导出
都必须由我们自己的业务代码完成,而不是交给模型“自由发挥”。
这就是企业落地 Agent 的第一原则:
让模型负责理解与决策,让代码负责执行与约束。
三、整体技术方案:为什么是 LangChain4j + 通义千问 + MySQL 8.0
3.1 技术栈选择
| 层次 | 技术选型 | 作用 |
|---|---|---|
| Web/API 层 | Spring Boot 3.x | 提供 REST/Streaming 接口、认证鉴权、治理能力 |
| Agent 编排层 | LangChain4j | 实现 Tool Calling、AiServices、记忆管理、RAG 编排 |
| 大模型层 | 通义千问或兼容模型 | 负责意图理解、工具选择、答案生成 |
| Embedding 层 | 通义千问 Embedding | 将问题和知识片段转为向量 |
| 结构化数据层 | MySQL 8.0 | 存放销售事实表、维表、审计日志、知识片段元数据 |
| 缓存层 | Redis + Caffeine | 分布式会话记忆、热点查询缓存、本地短缓存 |
| 异步层 | Kafka/RocketMQ | 削峰、长任务解耦、离线分析 |
| 可观测层 | Micrometer + Prometheus + Grafana + OpenTelemetry | 指标、日志、链路追踪 |
3.2 为什么 Java 仍然是这类系统的主场
原因很简单,不是因为 Java 更“先进”,而是因为企业现实。
- 数据源大多早就在 Java 微服务体系里
- 安全、审计、认证、网关、配置中心、消息队列、数据库连接池都已经成熟
- 团队对 Spring Boot、MyBatis/JPA、Redis、Kafka、Kubernetes 更熟
- 运维体系也早就围绕 JVM 和容器构建好了
如果只是做实验,Python 的确更快;但如果是要进生产,Java 往往能更快地接入现有基础设施,更好地复用团队已有经验。
3.3 为什么不是纯 Text2SQL,而是 SQL + 语义检索协同
纯 Text2SQL 的典型问题是:
- 对复杂业务口径理解不稳定
- 容易生成超出权限的数据查询
- 对“原因解释”“历史经验”“运营说明”这类问题无能为力
纯 RAG 的典型问题是:
- 适合找知识、找经验、找解释
- 不适合做精确财务数值与实时统计
因此,企业数据分析 Agent 的正确思路通常是:
- 精确数值、聚合统计、口径一致性,交给 SQL/业务服务
- 背景知识、术语说明、历史案例,交给向量检索
- 输出总结与解释,交给 LLM
换句话说,这不是“SQL 或语义”,而是“SQL 与语义协同”。
四、架构升级:从 Demo 到企业级系统
4.1 总体架构图![]()
4.2 分层设计
推荐把系统拆成 6 层:
接入层
负责 REST/Streaming API、身份认证、租户识别、请求幂等、限流和灰度。Agent 编排层
负责 Prompt 模板、工具注册、执行链规划、会话上下文拼装。领域服务层
负责业务口径、指标聚合、权限过滤、时间维度转换、异常处理。工具层
将 SQL 查询、语义检索、报表导出、告警解释等能力暴露给 Agent。数据层
包括 MySQL、Redis、消息队列以及知识库索引。可观测与治理层
包括日志、指标、Trace、审计、成本统计、熔断、降级。
这个分层的价值在于:Agent 并不是“悬浮在系统之上的神秘能力”,它只是编排层的一部分,真正的业务可靠性仍然来自经典工程体系。
五、核心原理讲透:这个 Agent 是怎么工作的
5.1 一次请求的完整生命周期
以问题“帮我看下华东区最近两个季度销售趋势,并解释一下波动原因”为例:
- API 层接收请求,解析用户身份、租户信息、权限范围、sessionId
- 系统从 Redis 中恢复该会话最近若干轮上下文
- Orchestrator 组装系统提示词、用户问题、上下文、可用工具描述
- 大模型判断需要调用哪些工具
- 先调用 SQL 工具获取最近两个季度销售趋势
- 再调用语义检索工具获取“波动原因”相关知识片段,例如营销活动、节假日、库存波动说明
- 工具结果返回后,LLM 进行综合生成
- 返回最终答案,并写入审计日志、指标监控和对话记忆
这里最重要的是:LLM 并不直接访问数据库,而是通过受控工具间接访问。
5.2 Tool Calling 的工程本质
Tool Calling 不是魔法,本质上是一种“模型驱动的函数选择机制”。
系统会把工具元信息发给模型,例如:
- 工具名称
- 工具作用
- 参数说明
- 返回结构
- 使用约束
模型根据用户问题判断该调用哪个工具,并生成参数。运行时由 LangChain4j 把这次“工具调用意图”映射到 Java 方法执行,再把结果喂回模型。
因此,工具设计质量决定了 Agent 质量。一个生产级工具应该满足:
- 参数强约束,避免歧义
- 返回格式稳定,便于模型消费
- 逻辑可审计,可监控,可测试
- 权限校验前置,不信任模型
5.3 为什么要混合检索,而不是纯向量检索
对于“2026 年 Q1 华东区销售额”这类问题,时间、区域、指标都是高精度条件。纯向量检索容易召回语义相近但时间错误的数据。
更合理的做法是:
- 结构化条件先过滤:租户、区域、时间、产品线
- 语义检索再补充:历史经验、备注、FAQ、业务定义
- 最后做融合排序:把 SQL 结果作为硬事实,把 RAG 结果作为软上下文
这实际上是一种典型的混合检索架构:
- Hard Filter:精确条件
- Semantic Recall:语义召回
- Rank/Fuse:结果融合
- Generate:答案生成
5.4 会话记忆为什么必须隔离
如果没有基于 sessionId 或 memoryId 的记忆隔离,就会出现经典事故:
- 用户 A 的问题上下文进入用户 B 的回答
- 不同租户之间的分析结论串话
- 长会话越来越长,导致 token 成本和延迟持续恶化
因此,记忆管理必须遵守三个原则:
- 按会话隔离
- 按租户约束
- 按窗口裁剪
生产实践里,不建议无限堆积对话历史,而是保留:
- 最近若干轮原始消息
- 关键事实摘要
- 已确认的分析上下文,例如“当前比较的是华东与华南”
六、数据建模:先把底盘打稳
没有稳定的数据模型,Agent 只会把混乱放大。
6.1 销售事实表设计
CREATE TABLE sales_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, tenant_id BIGINT NOT NULL, order_id VARCHAR(64) NOT NULL, customer_id BIGINT NOT NULL, region_code VARCHAR(32) NOT NULL, product_category VARCHAR(64) NOT NULL, amount DECIMAL(18,2) NOT NULL, quantity INT NOT NULL, sale_date DATE NOT NULL, channel VARCHAR(32) NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_tenant_date_region (tenant_id, sale_date, region_code), KEY idx_tenant_category_date (tenant_id, product_category, sale_date), KEY idx_order_id (order_id) );6.2 知识片段表设计
知识片段不一定要和向量完全耦合在一张表里,但至少要保留可追踪元数据:
CREATE TABLE knowledge_segment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, tenant_id BIGINT NOT NULL, doc_id VARCHAR(64) NOT NULL, title VARCHAR(255) NOT NULL, segment_text TEXT NOT NULL, source_type VARCHAR(32) NOT NULL, biz_date DATE NULL, tags VARCHAR(255) NULL, enabled TINYINT NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_tenant_doc (tenant_id, doc_id), KEY idx_tenant_enabled (tenant_id, enabled) );6.3 审计日志表设计
企业级 Agent 一定要留审计,至少记录:
- 谁问的
- 什么时候问的
- 实际调用了哪些工具
- 执行耗时
- 是否命中缓存
- 是否发生降级
CREATE