在企业级系统智能化转型的趋势下,RuoYi-AI 开源项目以其成熟的技术架构和工程化实践,成为基于 RuoYi 生态集成 AI 对话能力的典范。本文将结合代码实现与流程图,从技术底层到业务流程,全方位拆解其 AI 对话接口的设计逻辑与落地价值。
一、技术入口:SSE 流式响应的技术选型
RuoYi-AI 选择 Server-Sent Events(SSE) 作为 AI 对话的通信协议,核心在于其 “服务端单向流式推送”的特性,完美契合大语言模型 “边生成边返回” 的交互体验。
在代码中,通过 Spring 提供的 SseEmitter 类实现长连接:
@PostMapping("/send")
@ResponseBody
public SseEmitter sseChat(@RequestBody @Valid ChatRequest chatRequest, HttpServletRequest request) {
return sseService.sseChat(chatRequest, request);
}
@Override
public SseEmitter sseChat(ChatRequest chatRequest, HttpServletRequest request) {
// 超时时间设为0,实现长连接不中断
SseEmitter sseEmitter = new SseEmitter(0L);
// 业务逻辑执行...
return sseEmitter;
}
这种设计让前端可以通过 EventSource API 实时监听 AI 生成的内容,无需轮询或等待完整响应,极大提升了对话的实时性与流畅度。
二、核心流程拆解:从请求到 AI 响应的全链路
结合流程图与代码,RuoYi-AI 对话接口的执行流程可分为“会话管理、知识库增强、模型调度、服务执行”四大核心阶段。
1. 会话与消息管理:对话上下文的持久化
对于登录用户,系统会自动创建会话(ChatSession)并持久化消息(ChatMessage),为多轮对话提供上下文支撑:
if (LoginHelper.isLogin()) {
// 自动生成会话ID
if (chatRequest.getSessionId() == null) {
ChatSessionBo chatSessionBo = new ChatSessionBo();
chatSessionBo.setUserId(LoginHelper.getUserId());
chatSessionBo.setSessionTitle(getFirst10Characters(chatRequest.getPrompt()));
chatSessionService.insertByBo(chatSessionBo);
chatRequest.setSessionId(chatSessionBo.getId());
}
// 保存用户消息
chatCostService.saveMessage(chatRequest);
}
对应流程图中“记录会话信息”“保存用户消息”等节点,这一步确保了对话的连续性,让 AI 能够基于历史上下文理解用户意图。
2. 知识库增强:让 AI 具备行业认知
当请求携带知识库ID(kid)时,系统会触发向量检索流程,将领域知识注入对话上下文:
private String processKnowledgeBase(ChatRequest chatRequest, List<Message> messages) {
// 省略参数校验逻辑...
// 查询知识库与向量模型
KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(chatRequest.getKid()));
ChatModelVo chatModel = chatModelService.selectModelByName(knowledgeInfoVo.getEmbeddingModelName());
// 构建向量查询参数并检索
List<String> nearestList = vectorStoreService.getQueryVector(queryVectorBo);
// 将知识库内容注入对话上下文
addKnowledgeMessages(messages, nearestList);
return getKnowledgeSystemPrompt(knowledgeInfoVo);
}
private void addKnowledgeMessages(List<Message> messages, List<String> nearestList) {
for (String prompt : nearestList) {
Message userMessage = Message.builder()
.content(prompt)
.role(Message.Role.USER)
.build();
messages.add(userMessage);
}
}
这一流程对应流程图中 “知识库处理分支”,通过 “向量生成→相似性检索→知识注入” 三步,让 AI 从 “通用助手” 升级为 “行业专家”,可应用于企业文档问答、业务规则咨询等场景。
3. 模型智能调度:多模型兼容与故障重试
为应对不同场景(如普通对话、图片生成)和模型故障,系统设计了动态模型选择 + 自动重试机制:
/**
* 处理知识库相关逻辑
*/
private String processKnowledgeBase(ChatRequest chatRequest, List<Message> messages) {
if (StringUtils.isEmpty(chatRequest.getKid())) {
return getPromptTemplatePrompt(promptTemplateEnum.VECTOR.getDesc());
}
try {
// 查询知识库信息
KnowledgeInfoVo knowledgeInfoVo = knowledgeInfoService.queryById(Long.valueOf(chatRequest.getKid()));
if (knowledgeInfoVo == null) {
log.warn("知识库信息不存在,kid: {}", chatRequest.getKid());
return getPromptTemplatePrompt(promptTemplateEnum.VECTOR.getDesc());
}
// 查询向量模型配置信息
ChatModelVo chatModel = chatModelService.selectModelByName(knowledgeInfoVo.getEmbeddingModelName());
if (chatModel == null) {
log.warn("向量模型配置不存在,模型名称: {}", knowledgeInfoVo.getEmbeddingModelName());
return getPromptTemplatePrompt(promptTemplateEnum.VECTOR.getDesc());
}
// 构建向量查询参数
QueryVectorBo queryVectorBo = buildQueryVectorBo(chatRequest, knowledgeInfoVo, chatModel);
// 获取向量查询结果
List<String> nearestList = vectorStoreService.getQueryVector(queryVectorBo);
// 添加知识库消息到上下文
addKnowledgeMessages(messages, nearestList);
// 返回知识库系统提示词
return getKnowledgeSystemPrompt(knowledgeInfoVo);
} catch (Exception e) {
log.error("处理知识库信息失败: {}", e.getMessage(), e);
return getPromptTemplatePrompt(promptTemplateEnum.VECTOR.getDesc());
}
}
对应流程图中“模型选择”“重试判断”等节点,这一设计让系统能在主模型故障时自动切换到备用模型,同时支持 “聊天、图像生成” 等多场景的模型异构集成,兼顾可用性与扩展性。
4. 计费代理设计:无侵入式的成本管控
为实现对话计费,项目采用代理模式对模型服务进行包装:
public IChatService getChatService(String category) {
IChatService originalService = chatServiceMap.get(category);
// 自动包装为计费代理,实现“调用后自动计费”
return new BillingChatServiceProxy(originalService, chatCostService);
}
三、流程图与代码的映射:可视化执行路径
将流程图与代码逐节点对应,可更直观理解整体逻辑:
| 流程图节点 | 代码实现关联 |
|---|---|
| 请求 → SseEmitter | SseEmitter sseEmitter = new SseEmitter(0L) 初始化长连接 |
| 记录会话信息 | ChatSessionService.insertByBo(chatSessionBo) 创建会话 |
| 保存用户消息 | chatCostService.saveMessage(chatRequest) 持久化用户输入 |
| 知识库处理分支 | processKnowledgeBase 方法中向量检索与知识注入 |
| 模型选择 | autoSelectModelAndGetService 方法中按类别 / 名称选择模型 |
| 重试判断 | ChatRetryHelper.executeWithRetry 实现多模型故障切换 |
| 服务调用 | IChatService.chat(chatRequest, sseEmitter) 触发 AI 模型推理 |
| 返回 SseEmitter | 方法最终返回 sseEmitter,完成流式响应闭环 |

223

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



