前言
这两年 AI 应用开发非常火,越来越多开发者开始尝试把大模型能力接入到自己的业务系统中,比如智能客服、知识库问答、企业助手、代码助手、数据分析助手等。
不过在实际开发过程中,我发现一个比较明显的问题:
很多 AI 应用框架和示例更偏向 Python 生态,而企业级业务系统里,Java / Spring Boot 仍然是非常常见的技术栈。
对于 Java 开发者来说,如果想在现有系统中接入大模型能力,通常会遇到这些问题:
- 大模型 API 调用方式不统一
- 流式输出需要自己封装
- 多轮对话记忆需要额外维护
- RAG 知识库问答链路比较长
- Tool Calling 与业务方法集成不够自然
- Agent 执行流程缺少统一抽象
- Spring Boot 项目中接入 AI 能力的工程化成本较高
所以我最近基于 Java / Spring Boot 的技术体系,整理并实现了一个轻量级 AI 应用开发框架:VertexFlow AI Framework 。
它的目标不是简单封装一个大模型接口,而是围绕真实 AI 应用开发场景,把 Chat、Memory、RAG、Tool Calling、Agent、Spring Boot Starter 等能力串起来,让 Java 开发者可以用更熟悉的方式构建 AI 应用。
一、为什么 Java 也需要自己的 AI 应用开发框架?
现在很多人一提到 AI 应用开发,第一反应就是 Python。
Python 生态确实非常强,比如各种大模型调用框架、RAG 框架、Agent 框架都比较成熟。
但是从企业业务系统角度来看,Java 仍然有几个非常明显的优势。
1. 企业系统大量使用 Java / Spring Boot
很多公司的核心业务系统、后台管理系统、订单系统、用户系统、客服系统、权限系统,都是 Java / Spring Boot 技术栈。
如果 AI 能力最终要接入真实业务系统,那么 Java 侧一定需要比较自然的接入方式。
比如一个智能客服系统,可能需要调用订单服务、用户服务、商品服务、售后服务。如果这些服务本身就是 Java 写的,那么直接在 Java 体系中集成大模型能力,会比单独拆一个 Python 服务更加自然。
2. Java 工程化能力成熟
Java 在工程化方面非常成熟,比如:
- Spring Boot 自动配置
- Maven 依赖管理
- 配置文件管理
- 日志体系
- Bean 生命周期管理
- 微服务生态
- 数据库访问
- 缓存
- 权限认证
- 监控告警
这些能力对于 AI 应用落地非常重要。
AI 应用并不是只调用一次大模型接口就结束了。真正上线到业务系统中,还需要考虑配置管理、异常处理、权限控制、日志追踪、接口安全、服务稳定性等问题。
这些正是 Java / Spring Boot 比较擅长的地方。
3. AI 应用最终还是要和业务系统结合
AI 应用不是单纯的聊天机器人。
真实业务里通常需要:
- 查询数据库
- 调用内部接口
- 读取知识库
- 识别用户意图
- 调用业务工具
- 维护上下文
- 做权限校验
- 返回结构化结果
这些事情本身就是 Java 后端比较擅长的领域。
因此,我认为 Java 不是不能做 AI 应用,而是需要一套更贴合 Java / Spring Boot 开发习惯的 AI 应用开发方式。
二、一个 Java AI 应用框架应该具备哪些能力?
如果从实际业务场景出发,一个 Java AI 应用框架至少应该包含以下几个核心模块。
1. Chat:大模型基础对话能力
Chat 是最基础的能力,也就是封装大模型的普通对话调用。
常见流程是:
用户输入问题
↓
构造 Prompt
↓
调用大模型 API
↓
解析模型结果
↓
返回给用户
在框架层面,Chat 模块需要屏蔽不同模型厂商之间的差异。
比如 DeepSeek、通义千问、OpenAI、智谱等模型,它们的 API 格式可能不完全一致,但对于业务开发者来说,最好只面对一个统一的调用接口。
示例代码:
String answer = chatClient.call("请介绍一下 RAG 是什么");
System.out.println(answer);
这样业务层只关心"我要问什么"和"模型回答什么",不用每次都关心 HTTP 请求、鉴权、JSON 解析、异常处理等细节。
这类统一封装对于业务项目很重要。因为一旦模型厂商发生变化,比如从 DeepSeek 切换到通义千问,业务代码不应该大面积修改,而是尽量通过配置或适配层完成切换。
⸻
- Streaming Chat:流式输出能力
在 AI 对话类应用中,流式输出体验非常重要。
如果用户提了一个比较长的问题,模型完整生成可能需要几秒甚至十几秒。如果后端等模型全部生成完再返回,用户体验会比较差。
更好的方式是边生成边返回,也就是流式输出。
常见场景包括:
- AI 聊天助手
- 智能客服
- 知识库问答
- 代码生成
- 长文本总结
流式输出在后端通常需要处理:
- SSE
- WebSocket
- 模型返回的增量内容
- 前端逐字展示
- 异常中断处理
- 会话状态维护
框架层可以把这些复杂度封装起来,让业务侧只关心模型生成的内容。
示例伪代码:
streamingChatModel.stream("请解释一下 Spring Boot 自动配置原理", chunk -> {
System.out.print(chunk);
});
这样可以让 Java 后端更容易构建类似 ChatGPT 的交互体验。
如果是 Web 项目,也可以结合 SSE 进行输出:
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter stream(@RequestParam String message) {
SseEmitter emitter = new SseEmitter();
streamingChatModel.stream(message, chunk -> {
try {
emitter.send(chunk);
} catch (IOException e) {
emitter.completeWithError(e);
}
});
return emitter;
}
当然,真实项目中还需要考虑超时、异常、连接关闭、前端重连等问题。
⸻
- Memory:多轮对话记忆能力
很多 AI 应用都不是单轮问答,而是多轮对话。
比如:
用户:帮我推荐一个 Java AI 项目架构
AI:可以使用 Spring Boot + RAG + Tool Calling...
用户:那这个项目怎么接入知识库?
AI:这里的"这个项目"需要理解为上一轮提到的 Java AI 项目
第二个问题里的"这个项目",依赖上一轮上下文。如果没有 Memory,模型就无法理解用户真正指的是什么。
因此,Memory 模块需要维护会话上下文,例如:
- sessionId
- userId
- message history
- system prompt
- user message
- assistant message
- 历史消息裁剪策略
简单来说,就是让模型"记住当前对话中发生过什么"。
示例设计:
chatMemory.addUserMessage(sessionId, "什么是 RAG?");
chatMemory.addAssistantMessage(sessionId, "RAG 是检索增强生成...");
然后在下一次调用模型时,把必要的上下文重新组装到 Prompt 中。
示例:
List history = chatMemory.getMessages(sessionId);
String answer = chatClient.call(history, "那它适合用在哪些场景?");
chatMemory.addUserMessage(sessionId, "那它适合用在哪些场景?");
chatMemory.addAssistantMessage(sessionId, answer);
Memory 的关键不是无限保存所有历史,而是合理控制上下文长度,避免 Token 过长,同时保留对回答最有价值的信息。
常见策略包括:
- 保留最近 N 轮对话
- 对历史对话进行摘要
- 根据当前问题检索相关历史
- 区分短期记忆和长期记忆
- 对不同用户、不同会话进行隔离
如果 Memory 设计不好,很容易出现两个问题:
第一,历史上下文太短,模型无法理解多轮对话。
第二,历史上下文太长,导致 Token 成本变高,甚至超过模型限制。
所以 Memory 是 AI 应用工程化中非常重要的一环。
⸻
- RAG:知识库增强生成能力
RAG 是当前 AI 应用开发中非常重要的能力。
它的全称是 Retrieval-Augmented Generation,也就是检索增强生成。
为什么需要 RAG?
因为大模型本身不一定知道你的私有知识,比如:
- 公司内部文档
- 产品说明书
- 业务规则
- 订单政策
- 用户手册
- 项目接口文档
- 数据库说明
- 代码规范
如果直接问大模型,它可能不知道,甚至会编造答案。
RAG 的核心思路是:
用户提问
↓
从知识库中检索相关内容
↓
把检索到的内容拼接进 Prompt
↓
让大模型基于资料回答
一个基础 RAG 流程通常包括:
文档加载
↓
文本切分
↓
向量化
↓
存入向量库
↓
用户提问
↓
问题向量化
↓
相似度检索
↓
构造增强 Prompt
↓
模型生成答案
在 Java 框架中,可以把这些步骤拆成几个组件:
DocumentLoader 文档加载
TextSplitter 文本切分
EmbeddingModel 向量模型
VectorStore 向量存储
Retriever 检索器
PromptTemplate 提示词模板
ChatModel 大模型生成
示例伪代码:
List documents = documentLoader.load("docs/manual.pdf");
List chunks = textSplitter.split(documents);
vectorStore.add(chunks);
List relatedChunks = retriever.retrieve("如何配置 API Key?");
String answer = ragClient.ask("如何配置 API Key?", relatedChunks);
RAG 的价值在于,它可以让 AI 应用基于真实资料回答问题,而不是完全依赖模型自己的记忆。
不过 RAG 也不是简单把文档塞给模型就可以了。
实际开发中需要考虑:
- 文档格式如何解析
- 文本切分粒度如何设置
- chunk 太大还是太小
- 向量模型怎么选择
- 检索结果如何排序
- 是否需要重排序
- Prompt 如何设计
- 如何让模型减少幻觉
- 如何返回引用来源
- 如何更新知识库
这些都是 RAG 工程化落地时需要重点处理的问题。
⸻
- Tool Calling:让大模型调用业务工具
Tool Calling 是 AI 应用从"聊天机器人"走向"业务助手"的关键能力。
普通 Chat 只能回答问题,而 Tool Calling 可以让模型根据用户意图调用具体工具。
比如用户问:
帮我查询一下订单 10086 的物流状态
这时候模型不能只回答"我无法查询物流",而是应该识别出用户想查询订单,然后调用后端的订单查询方法。
比如:
@AiTool(name = "queryOrderStatus", description = "查询订单物流状态")
public OrderStatus queryOrderStatus(String orderNo) {
return orderService.queryStatus(orderNo);
}
调用流程大概是:
用户输入
↓
模型识别是否需要调用工具
↓
生成工具名称和参数
↓
后端执行对应 Java 方法
↓
拿到工具执行结果
↓
再次交给模型生成自然语言回答
Tool Calling 的关键点包括:
- 工具注册
- 工具描述
- 参数定义
- 参数解析
- 方法调用
- 结果返回
- 异常处理
- 权限控制
在 Java / Spring Boot 体系中,Tool Calling 可以和 Bean、注解、反射、业务 Service 结合起来,让大模型自然调用后端已有能力。
比如可以设计成这样:
@Component
public class OrderTools {
private final OrderService orderService;
public OrderTools(OrderService orderService) {
this.orderService = orderService;
}
@AiTool(name = "queryOrderStatus", description = "根据订单号查询订单状态")
public String queryOrderStatus(String orderNo) {
return orderService.queryStatus(orderNo);
}
}
这样,业务开发者只需要把允许 AI 调用的方法标记出来,框架负责完成工具注册、参数解析和调用执行。
当然,Tool Calling 也需要注意安全问题。
不是所有接口都应该暴露给 AI 调用。比较合理的做法是:
- 只注册允许 AI 调用的方法
- 为工具设置清晰描述和参数约束
- 对高风险操作增加人工确认
- 记录工具调用日志
- 对异常结果做兜底处理
- 对用户权限进行校验
Tool Calling 做好了,AI 应用就不再只是一个问答机器人,而是可以真正连接业务系统,帮助用户完成具体任务。
⸻
- Agent:任务规划与执行流程
Agent 可以理解为更进一步的智能体能力。
普通 Chat 是问一句答一句。
Tool Calling 是模型可以调用工具。
Agent 则更像是模型可以围绕一个目标,进行多步骤规划和执行。
比如用户说:
帮我分析这个项目的 README,并生成一份优化建议
Agent 可能需要执行:
读取 README
↓
分析项目定位
↓
检查文档结构
↓
总结问题
↓
生成优化建议
一个简单 Agent 通常包含:
- 任务输入
- 任务规划
- 工具选择
- 工具执行
- 中间结果
- 最终回答
在框架设计上,可以先实现 Simple Agent,不必一开始就做特别复杂的多 Agent 协作。
先让它能完成基本的"理解任务 → 调用工具 → 生成结果",就已经能覆盖很多业务场景。
示例伪代码:
AgentResult result = simpleAgent.run("分析项目 README,并生成优化建议");
System.out.println(result.getFinalAnswer());
Agent 的难点在于控制执行过程。
如果完全放任模型自己规划,可能会出现执行步骤不可控、工具调用错误、成本过高等问题。
所以在企业应用中,Agent 更适合做成可控流程,例如:
- 限制最大执行轮数
- 限制可调用工具范围
- 记录每一步执行日志
- 对关键操作进行人工确认
- 对失败步骤进行兜底处理
这样 Agent 才更容易落地到真实业务系统中。
⸻
三、VertexFlow AI Framework 的设计思路
基于上面的思考,我整理了一个面向 Java / Spring Boot 开发者的轻量级 AI 应用开发框架:VertexFlow AI Framework。
它的定位是:
让 Java 开发者用熟悉的 Spring Boot 方式,快速构建 AI 应用。
目前框架主要包含以下能力:
- Chat 大模型调用
- Streaming 流式对话
- Memory 多轮会话记忆
- Prompt Template 提示词模板
- RAG 知识库问答
- Document Loader 文档加载
- Text Splitter 文本切分
- Tool Calling 工具调用
- Simple Agent 智能体
- Spring Boot Starter 自动配置
整体目标不是做一个"大而全"的复杂框架,而是先把 Java AI 应用开发中最常用的能力抽象出来,降低 Java 开发者接入 AI 的成本。
⸻
四、框架整体架构
可以把 VertexFlow AI Framework 理解成几层:
应用层
↓
AI Client 层
↓
能力编排层
↓
模型适配层
↓
基础设施层
- 应用层
应用层就是业务系统,例如:
- AI 助手
- 智能客服
- 知识库问答
- 企业内部助手
- Agent 工作流
- 代码助手
这些应用不应该直接关心底层模型 API 的细节。
业务开发者最好只需要调用一个简单的方法,就可以完成 AI 能力接入。
- AI Client 层
这一层提供统一入口,例如:
chatClient.call(message);
ragClient.ask(question);
agent.run(task);
让业务开发者可以用简单 API 调用 AI 能力。
- 能力编排层
这一层负责组合不同模块,例如:
- Chat
- Memory
- Prompt
- RAG
- Tool Calling
- Agent
比如 RAG 问答不是单独调用模型,而是要先检索知识,再构造 Prompt,再调用模型生成答案。
Tool Calling 也不是单独调用业务方法,而是要先让模型识别工具调用意图,再执行工具,再把工具结果交给模型生成最终回答。
- 模型适配层
这一层负责适配不同大模型厂商。
不同模型 API 的请求格式、响应格式、鉴权方式可能不同,但框架应该尽量统一上层接口。
这样业务代码不用关心底层模型是谁,只需要关注自己的业务逻辑。
- 基础设施层
这一层包括:
- HTTP Client
- JSON 序列化
- 配置管理
- 日志
- 异常处理
- 向量存储
- 文件读取
- Spring Boot 自动配置
这些能力决定了框架是否真正适合工程化落地。
⸻
五、Spring Boot Starter 的意义
对于 Java 开发者来说,Spring Boot Starter 是非常熟悉的接入方式。
理想情况下,开发者只需要三步就可以使用 AI 能力。
- 引入依赖
io.github.guoqingniu vertexflow-ai-spring-boot-starter 0.4.x
- 配置模型参数
vertexflow:
ai:
model:
provider: deepseek
api-key: ${DEEPSEEK_API_KEY}
- 注入并使用
@RestController
@RequestMapping("/ai")
public class AiController {
private final ChatClient chatClient;
public AiController(ChatClient chatClient) {
this.chatClient = chatClient;
}
@GetMapping("/chat")
public String chat(String message) {
return chatClient.call(message);
}
}
这种方式对于 Spring Boot 开发者来说非常自然。
不需要每个项目都重复写模型调用、配置读取、Bean 注册、异常处理等基础代码。
Spring Boot Starter 的意义在于降低接入成本。
如果一个框架需要大量手动配置,开发者很可能还没跑通 Demo 就放弃了。
而 Starter 可以让开发者更快进入业务开发阶段。
⸻
六、一个简单的 Chat 示例
下面是一个最基础的 AI 对话接口示例。
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient chatClient) {
this.chatClient = chatClient;
}
@GetMapping
public String chat(@RequestParam String message) {
return chatClient.call(message);
}
}
调用接口:
curl "http://localhost:8080/chat?message=什么是RAG"
返回结果示例:
RAG 是 Retrieval-Augmented Generation 的缩写,中文通常叫检索增强生成。
它通过先从知识库中检索相关资料,再让大模型基于这些资料进行回答,从而提升回答的准确性和可控性。
这个例子虽然简单,但它体现了框架最基础的目标:
让 Java 开发者不用重复关心底层模型 API,而是专注于业务本身。
⸻
七、一个简单的 Memory 示例
多轮对话可以通过 sessionId 来区分不同会话。
示例:
@PostMapping("/chat")
public String chat(@RequestParam String sessionId,
@RequestParam String message) {
chatMemory.addUserMessage(sessionId, message);
List history = chatMemory.getMessages(sessionId);
String answer = chatClient.call(history);
chatMemory.addAssistantMessage(sessionId, answer);
return answer;
}
这样每个 session 都可以拥有自己的上下文。
用户连续提问时,模型可以结合历史消息理解当前问题。
例如:
用户:什么是 RAG?
AI:RAG 是检索增强生成...
用户:它适合用在哪些场景?
AI:这里的"它"指的是 RAG,所以可以继续回答 RAG 的应用场景。
在真实业务中,还可以把 Memory 存储到 Redis 或数据库中,避免服务重启后上下文丢失。
⸻
八、一个简单的 RAG 示例
RAG 示例可以拆成几个步骤。
- 加载文档
List documents = documentLoader.load("docs/product-manual.md");
- 文本切分
List chunks = textSplitter.split(documents);
- 存入向量库
vectorStore.add(chunks);
- 用户提问并检索
List relatedChunks = retriever.retrieve("如何配置模型 API Key?");
- 构造增强 Prompt 并生成答案
String answer = ragClient.ask("如何配置模型 API Key?", relatedChunks);
完整链路可以理解为:
用户问题 + 检索到的资料 + Prompt 模板 → 大模型 → 最终答案
RAG 的难点不只在模型调用,而在整个链路的工程化处理。
比如:
- 文档格式如何加载
- 文本如何切分
- chunk 大小如何设置
- 检索结果如何排序
- Prompt 如何设计
- 如何避免模型胡编
- 如何返回引用来源
这些都是后续需要持续优化的地方。
⸻
九、Tool Calling 示例
Tool Calling 的目标是让大模型可以调用后端业务方法。
比如有一个天气查询工具:
@Component
public class WeatherTools {
private final WeatherService weatherService;
public WeatherTools(WeatherService weatherService) {
this.weatherService = weatherService;
}
@AiTool(name = "getWeather", description = "根据城市名称查询天气")
public String getWeather(String city) {
return weatherService.query(city);
}
}
用户输入:
帮我查一下北京今天的天气
模型可以识别出:
{
"tool": "getWeather",
"arguments": {
"city": "北京"
}
}
然后后端执行对应方法,拿到结果后再交给模型组织成自然语言回答。
这个过程对于业务系统非常有价值,因为它可以让 AI 助手不只是"回答问题",而是可以"执行动作"。
例如:
- 查询订单
- 查询库存
- 查询用户信息
- 创建工单
- 生成报表
- 调用第三方接口
- 触发业务流程
当然,Tool Calling 也需要注意权限控制,不能让模型随意调用敏感接口。
比较合理的做法是:
- 只注册允许 AI 调用的方法
- 为工具设置描述和参数约束
- 对高风险操作增加人工确认
- 记录工具调用日志
- 对异常结果做兜底处理
⸻
十、开发这个框架过程中的一些思考
在开发 VertexFlow AI Framework 的过程中,我最大的感受是:
AI 应用开发并不是简单调用一个大模型 API。
真正要落地到业务系统里,需要考虑很多工程化问题。
- 模型调用要统一
不同模型厂商接口不同,如果每接一个模型都在业务代码里写一套调用逻辑,后期维护成本会很高。
比较好的方式是通过统一接口屏蔽底层差异。
业务层只依赖 ChatClient、EmbeddingModel、StreamingChatModel 这类抽象,而不是直接依赖某个厂商的 HTTP API。
- Prompt 要可管理
Prompt 不应该散落在业务代码中,应该有统一的模板管理方式。
否则项目变大之后,Prompt 很难维护,也不方便调整和复用。
- Memory 要可控
多轮对话不能无限追加历史,需要考虑 Token 限制和上下文裁剪。
对于一些长对话场景,可以考虑摘要记忆、最近消息窗口、重要信息抽取等方式。
- RAG 要可解释
知识库问答不能只给一个结果,最好能说明答案来自哪些资料。
这样用户才更容易信任 AI 的回答。
- Tool Calling 要安全
模型可以调用工具,但不能无限制调用所有业务方法。
尤其是涉及支付、删除、修改、审批等高风险操作时,需要额外增加确认机制。
- Spring Boot 接入要简单
如果一个 AI 框架接入成本很高,Java 开发者就很难在真实项目中使用它。
所以 VertexFlow AI 的设计目标一直是:
轻量、清晰、可扩展、适合 Java / Spring Boot 项目接入。
⸻
十一、项目当前状态
目前 VertexFlow AI Framework 还在持续迭代中,已经整理了以下方向:
- 模型调用
- 流式输出
- Prompt 模板
- 多轮记忆
- RAG 检索增强生成
- 文档加载
- 文本切分
- Tool Calling
- Simple Agent
- Spring Boot Starter 自动配置
后续计划继续完善:
- 更多模型适配
- 更完整的 RAG Demo
- 向量数据库集成示例
- Tool Calling 参数校验
- Agent 执行链路优化
- 更多 Spring Boot 示例项目
- 文档和快速开始教程
⸻
十二、相关实践项目
为了验证上面的设计思路,我整理了一个开源实践项目:VertexFlow AI Framework。
它主要用于演示 Java / Spring Boot 中 Chat、Memory、RAG、Tool Calling、Agent 等能力的封装方式。
项目地址:
项目目前还在持续迭代中,欢迎体验、提 Issue、交流建议。
如果你也在做 Java + AI 应用开发,欢迎在评论区交流你的使用场景。我后续会根据大家反馈继续补充 RAG、Tool Calling、Agent、Spring Boot Starter 等模块的实现细节。
⸻
十三、总结
Java 生态并不是不能做 AI 应用。
相反,在企业级系统中,Java / Spring Boot 仍然有很强的工程化优势。
如果能把大模型能力和 Java 后端体系结合起来,就可以让很多已有业务系统更自然地接入 AI 能力。
VertexFlow AI Framework 的目标,就是让 Java 开发者可以用熟悉的 Spring Boot 方式,快速构建 Chat、Memory、RAG、Tool Calling、Agent 等 AI 应用能力。
后续我会继续更新几篇文章:
- Java 实现 RAG 知识库问答:文档加载、切分、检索与增强生成
- Java Tool Calling 实践:让大模型调用 Spring Boot 业务方法
- Spring Boot Starter 自动配置在 AI 框架中的设计实践
- Java Agent 简单实现:从任务理解到工具调用
如果这些方向你也感兴趣,可以关注后续更新。