refactor(phase1): 完成包名重构 (org.example → com.superbiz.agent)

Task 4.1: 包名统一重构
- 重命名 41 个 Java 文件的包名
- 更新所有 import 语句
- 恢复枚举类(FaultCategory、DiagnosisStatus、SourceType)
- 更新测试类的 import

重构范围:
- domain/entity: 3 个实体类
- domain/model: 2 个数据类
- domain/enums: 3 个枚举类
- repository: 3 个接口
- service/session: 2 个类(接口 + 实现)
- config: 9 个配置类
- controller: 2 个控制器
- agent/tool: 4 个工具类
- client: 1 个客户端
- Main.java: 主类

验证结果:
- 编译成功,无错误
- 所有测试通过 (27/27)
  - ApiDocumentRepositoryTest: 7/7 ✅
  - CaseLibraryRepositoryTest: 6/6 ✅
  - DiagnosisRecordRepositoryTest: 6/6 ✅
  - RedisSessionManagerTest: 8/8 ✅

Progress: 21/33 tasks completed (64%)
This commit is contained in:
zhuyongxin
2026-06-23 14:56:04 +08:00
parent 8bd758dbaf
commit c3a232540a
59 changed files with 103 additions and 104 deletions
@@ -0,0 +1,190 @@
package com.superbiz.agent.service;
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
import com.superbiz.agent.agent.tool.DateTimeTools;
import com.superbiz.agent.agent.tool.InternalDocsTools;
import com.superbiz.agent.agent.tool.QueryLogsTools;
import com.superbiz.agent.agent.tool.QueryMetricsTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 聊天服务
* 封装 ReactAgent 对话的公共逻辑,包括模型创建、系统提示词构建、Agent 配置等
*/
@Service
public class ChatService {
private static final Logger logger = LoggerFactory.getLogger(ChatService.class);
@Autowired
private InternalDocsTools internalDocsTools;
@Autowired
private DateTimeTools dateTimeTools;
@Autowired
private QueryMetricsTools queryMetricsTools;
@Autowired(required = false) // Mock 模式下才注册,所以设置为 optional,真实环境通过mcp配置注入
private QueryLogsTools queryLogsTools;
@Autowired(required = false)
private ToolCallbackProvider tools;
@Autowired
private ChatModel chatModel;
/**
* 获取注入的 ChatModel
*/
public ChatModel getChatModel() {
return chatModel;
}
/**
* 构建系统提示词(包含历史消息)
* @param history 历史消息列表
* @return 完整的系统提示词
*/
public String buildSystemPrompt(List<Map<String, String>> history) {
StringBuilder systemPromptBuilder = new StringBuilder();
// 基础系统提示
systemPromptBuilder.append("你是一个专业的智能助手,可以获取当前时间、查询天气信息、搜索内部文档知识库,以及查询 Prometheus 告警信息。\n");
systemPromptBuilder.append("当用户询问时间相关问题时,**必须每次都调用 getCurrentDateTime 工具**,因为时间会不断变化。即使历史消息中有时间信息,也不要直接复用,必须重新查询最新时间。\n");
systemPromptBuilder.append("当用户需要查询公司内部文档、流程、最佳实践或技术指南时,使用 queryInternalDocs 工具。\n");
systemPromptBuilder.append("当用户需要查询 Prometheus 告警、监控指标或系统告警状态时,使用 queryPrometheusAlerts 工具。\n");
systemPromptBuilder.append("当用户需要查询腾讯云日志时,请调用腾讯云mcp服务查询,默认查询地域ap-guangzhou,查询时间范围为近一个月。\n\n");
// 添加历史消息(过滤时间查询相关内容)
if (!history.isEmpty()) {
systemPromptBuilder.append("--- 对话历史 ---\n");
for (Map<String, String> msg : history) {
String role = msg.get("role");
String content = msg.get("content");
// 🔧 过滤时间查询相关的历史消息,避免 LLM 复用旧的时间信息
if ("user".equals(role) && isTimeQuery(content)) {
continue; // 跳过时间查询问题
}
if ("assistant".equals(role) && containsTimeInfo(content)) {
continue; // 跳过包含时间信息的回答
}
if ("user".equals(role)) {
systemPromptBuilder.append("用户: ").append(content).append("\n");
} else if ("assistant".equals(role)) {
systemPromptBuilder.append("助手: ").append(content).append("\n");
}
}
systemPromptBuilder.append("--- 对话历史结束 ---\n\n");
}
systemPromptBuilder.append("请基于以上对话历史,回答用户的新问题。");
return systemPromptBuilder.toString();
}
/**
* 判断是否为时间查询问题
*/
private boolean isTimeQuery(String content) {
if (content == null) {
return false;
}
// 匹配常见的时间查询模式
return content.matches(".*(现在|当前|此时).*(几点|时间).*") ||
content.matches(".*(几点|时间).*(了|呢|[??]).*") ||
content.toLowerCase().matches(".*(what.*time|current.*time).*");
}
/**
* 判断是否包含时间信息
*/
private boolean containsTimeInfo(String content) {
if (content == null) {
return false;
}
// 匹配日期时间格式:2026年5月31日、15:57、下午3点 等
return content.matches(".*(\\d{4}年\\d{1,2}月\\d{1,2}日|\\d{1,2}:\\d{2}|[上下午]+\\d{1,2}[点时]).*");
}
/**
* 动态构建方法工具数组
* 根据 cls.mock-enabled 决定是否包含 QueryLogsTools
*/
public Object[] buildMethodToolsArray() {
if (queryLogsTools != null) {
// Mock 模式:包含 QueryLogsTools
return new Object[]{dateTimeTools, internalDocsTools, queryMetricsTools, queryLogsTools};
} else {
// 真实模式:不包含 QueryLogsTools(由 MCP 提供日志查询功能)
return new Object[]{dateTimeTools, internalDocsTools, queryMetricsTools};
}
}
/**
* 获取工具回调列表,mcp服务提供的工具
*/
public ToolCallback[] getToolCallbacks() {
if (tools == null) {
return new ToolCallback[0];
}
return tools.getToolCallbacks();
}
/**
* 记录可用工具列表:mcp服务提供的工具
*/
public void logAvailableTools() {
if (tools == null) {
logger.info("MCP 未启用,无远程工具");
return;
}
ToolCallback[] toolCallbacks = tools.getToolCallbacks();
logger.info("可用工具列表:");
for (ToolCallback toolCallback : toolCallbacks) {
logger.info(">>> {}", toolCallback.getToolDefinition().name());
}
}
/**
* 创建 ReactAgent
* @param chatModel 聊天模型
* @param systemPrompt 系统提示词
* @return 配置好的 ReactAgent
*/
public ReactAgent createReactAgent(ChatModel chatModel, String systemPrompt) {
return ReactAgent.builder()
.name("intelligent_assistant")
.model(chatModel)
.systemPrompt(systemPrompt)
.methodTools(buildMethodToolsArray())
.tools(getToolCallbacks())
.build();
}
/**
* 执行 ReactAgent 对话(非流式)
* @param agent ReactAgent 实例
* @param question 用户问题
* @return AI 回复
*/
public String executeChat(ReactAgent agent, String question) throws GraphRunnerException {
logger.info("执行 ReactAgent.call() - 自动处理工具调用");
var response = agent.call(question);
String answer = response.getText();
logger.info("ReactAgent 对话完成,答案长度: {}", answer.length());
return answer;
}
}