refactor(ai): 重构AI命令服务实现类
- 重命名变量名 log 为 commandLog 以提高代码可读性
This commit is contained in:
@@ -32,17 +32,17 @@ public class AiCommandLogServiceImpl extends ServiceImpl<AiCommandLogMapper, AiC
|
||||
|
||||
@Override
|
||||
public void rollbackCommand(String logId) {
|
||||
AiCommandLog log = this.getById(logId);
|
||||
if (log == null) {
|
||||
AiCommandLog commandLog = this.getById(logId);
|
||||
if (commandLog == null) {
|
||||
throw new RuntimeException("命令记录不存在");
|
||||
}
|
||||
|
||||
if (log.getExecuteStatus() == null || log.getExecuteStatus() != 1) {
|
||||
if (commandLog.getExecuteStatus() == null || commandLog.getExecuteStatus() != 1) {
|
||||
throw new RuntimeException("只能撤销成功执行的命令");
|
||||
}
|
||||
|
||||
// TODO: 实现具体的回滚逻辑
|
||||
log.info("撤销命令执行: logId={}, function={}", logId, log.getFunctionName());
|
||||
log.info("撤销命令执行: logId={}, function={}", logId, commandLog.getFunctionName());
|
||||
throw new UnsupportedOperationException("回滚功能尚未实现");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,288 +37,288 @@ import java.util.Optional;
|
||||
@RequiredArgsConstructor
|
||||
public class AiCommandServiceImpl implements AiCommandService {
|
||||
|
||||
private static final String SYSTEM_PROMPT = """
|
||||
你是一个智能的企业操作助手,需要将用户的自然语言命令解析成标准的函数调用。
|
||||
请返回严格的 JSON 格式,包含字段:
|
||||
- success: boolean
|
||||
- explanation: string
|
||||
- confidence: number (0-1)
|
||||
- error: string
|
||||
- provider: string
|
||||
- model: string
|
||||
- functionCalls: 数组,每个元素包含 name、description、arguments(对象)
|
||||
当无法识别命令时,success=false,并给出 error。
|
||||
""";
|
||||
private static final String SYSTEM_PROMPT = """
|
||||
你是一个智能的企业操作助手,需要将用户的自然语言命令解析成标准的函数调用。
|
||||
请返回严格的 JSON 格式,包含字段:
|
||||
- success: boolean
|
||||
- explanation: string
|
||||
- confidence: number (0-1)
|
||||
- error: string
|
||||
- provider: string
|
||||
- model: string
|
||||
- functionCalls: 数组,每个元素包含 name、description、arguments(对象)
|
||||
当无法识别命令时,success=false,并给出 error。
|
||||
""";
|
||||
|
||||
private final AiCommandLogService logService;
|
||||
private final UserTools userTools;
|
||||
private final ChatClient chatClient;
|
||||
private final AiCommandLogService logService;
|
||||
private final UserTools userTools;
|
||||
private final ChatClient chatClient;
|
||||
|
||||
@Override
|
||||
public AiParseResponseDTO parseCommand(AiParseRequestDTO request, HttpServletRequest httpRequest) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
String command = Optional.ofNullable(request.getCommand()).orElse("").trim();
|
||||
@Override
|
||||
public AiParseResponseDTO parseCommand(AiParseRequestDTO request, HttpServletRequest httpRequest) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
String command = Optional.ofNullable(request.getCommand()).orElse("").trim();
|
||||
|
||||
if (StrUtil.isBlank(command)) {
|
||||
return AiParseResponseDTO.builder()
|
||||
.success(false)
|
||||
.error("命令不能为空")
|
||||
.functionCalls(Collections.emptyList())
|
||||
.build();
|
||||
if (StrUtil.isBlank(command)) {
|
||||
return AiParseResponseDTO.builder()
|
||||
.success(false)
|
||||
.error("命令不能为空")
|
||||
.functionCalls(Collections.emptyList())
|
||||
.build();
|
||||
}
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
String username = SecurityUtils.getUsername();
|
||||
String ipAddress = JakartaServletUtil.getClientIP(httpRequest);
|
||||
|
||||
AiCommandLog commandLog = new AiCommandLog();
|
||||
commandLog.setUserId(userId);
|
||||
commandLog.setUsername(username);
|
||||
commandLog.setOriginalCommand(command);
|
||||
commandLog.setIpAddress(ipAddress);
|
||||
commandLog.setAiProvider("spring-ai");
|
||||
commandLog.setAiModel("auto");
|
||||
|
||||
String systemPrompt = buildSystemPrompt();
|
||||
String userPrompt = buildUserPrompt(request);
|
||||
|
||||
try {
|
||||
log.info("📤 发送命令至 AI 模型: {}", command);
|
||||
ChatResponse chatResponse = chatClient.prompt()
|
||||
.system(systemPrompt)
|
||||
.user(userPrompt)
|
||||
.call().chatResponse();
|
||||
|
||||
String rawContent = Optional.ofNullable(chatResponse.getResult())
|
||||
.map(result -> result.getOutput().getText())
|
||||
.orElse("");
|
||||
|
||||
ParseResult parseResult = parseAiResponse(rawContent);
|
||||
|
||||
commandLog.setAiProvider(StrUtil.emptyToDefault(parseResult.provider(), "spring-ai"));
|
||||
commandLog.setAiModel(StrUtil.emptyToDefault(parseResult.model(), "auto"));
|
||||
commandLog.setParseStatus(parseResult.success() ? 1 : 0);
|
||||
commandLog.setExplanation(parseResult.explanation());
|
||||
commandLog.setFunctionCalls(JSONUtil.toJsonStr(parseResult.functionCalls()));
|
||||
commandLog.setConfidence(parseResult.confidence() != null ? BigDecimal.valueOf(parseResult.confidence()) : null);
|
||||
commandLog.setParseErrorMessage(parseResult.success() ? null : StrUtil.emptyToDefault(parseResult.error(), "解析失败"));
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
commandLog.setParseDurationMs((int) duration);
|
||||
|
||||
logService.save(commandLog);
|
||||
|
||||
AiParseResponseDTO response = AiParseResponseDTO.builder()
|
||||
.parseLogId(commandLog.getId())
|
||||
.success(parseResult.success())
|
||||
.functionCalls(parseResult.functionCalls())
|
||||
.explanation(parseResult.explanation())
|
||||
.confidence(parseResult.confidence())
|
||||
.error(parseResult.error())
|
||||
.rawResponse(rawContent)
|
||||
.build();
|
||||
|
||||
if (!parseResult.success()) {
|
||||
log.warn("❗️ AI 未能解析命令: {}", parseResult.error());
|
||||
} else {
|
||||
log.info("✅ 解析成功,审计记录ID: {}", commandLog.getId());
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
commandLog.setParseStatus(0);
|
||||
commandLog.setFunctionCalls(JSONUtil.toJsonStr(Collections.emptyList()));
|
||||
commandLog.setParseErrorMessage(e.getMessage());
|
||||
commandLog.setParseDurationMs((int) duration);
|
||||
logService.save(commandLog);
|
||||
|
||||
log.error("❌ 解析命令失败: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("解析命令失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
String username = SecurityUtils.getUsername();
|
||||
String ipAddress = JakartaServletUtil.getClientIP(httpRequest);
|
||||
|
||||
AiCommandLog log = new AiCommandLog();
|
||||
log.setUserId(userId);
|
||||
log.setUsername(username);
|
||||
log.setOriginalCommand(command);
|
||||
log.setIpAddress(ipAddress);
|
||||
log.setAiProvider("spring-ai");
|
||||
log.setAiModel("auto");
|
||||
|
||||
String systemPrompt = buildSystemPrompt();
|
||||
String userPrompt = buildUserPrompt(request);
|
||||
|
||||
try {
|
||||
log.info("📤 发送命令至 AI 模型: {}", command);
|
||||
ChatResponse chatResponse = chatClient.prompt()
|
||||
.system(systemPrompt)
|
||||
.user(userPrompt)
|
||||
.call().chatResponse();
|
||||
|
||||
String rawContent = Optional.ofNullable(chatResponse.getResult())
|
||||
.map(result -> result.getOutput().getText())
|
||||
.orElse("");
|
||||
|
||||
ParseResult parseResult = parseAiResponse(rawContent);
|
||||
|
||||
log.setAiProvider(StrUtil.emptyToDefault(parseResult.provider(), "spring-ai"));
|
||||
log.setAiModel(StrUtil.emptyToDefault(parseResult.model(), "auto"));
|
||||
log.setParseStatus(parseResult.success() ? 1 : 0);
|
||||
log.setExplanation(parseResult.explanation());
|
||||
log.setFunctionCalls(JSONUtil.toJsonStr(parseResult.functionCalls()));
|
||||
log.setConfidence(parseResult.confidence() != null ? BigDecimal.valueOf(parseResult.confidence()) : null);
|
||||
log.setParseErrorMessage(parseResult.success() ? null : StrUtil.emptyToDefault(parseResult.error(), "解析失败"));
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
log.setParseDurationMs((int) duration);
|
||||
|
||||
logService.save(log);
|
||||
|
||||
AiParseResponseDTO response = AiParseResponseDTO.builder()
|
||||
.parseLogId(log.getId())
|
||||
.success(parseResult.success())
|
||||
.functionCalls(parseResult.functionCalls())
|
||||
.explanation(parseResult.explanation())
|
||||
.confidence(parseResult.confidence())
|
||||
.error(parseResult.error())
|
||||
.rawResponse(rawContent)
|
||||
.build();
|
||||
|
||||
if (!parseResult.success()) {
|
||||
log.warn("❗️ AI 未能解析命令: {}", parseResult.error());
|
||||
} else {
|
||||
log.info("✅ 解析成功,审计记录ID: {}", log.getId());
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
log.setParseStatus(0);
|
||||
log.setFunctionCalls(JSONUtil.toJsonStr(Collections.emptyList()));
|
||||
log.setParseErrorMessage(e.getMessage());
|
||||
log.setParseDurationMs((int) duration);
|
||||
logService.save(log);
|
||||
|
||||
log.error("❌ 解析命令失败: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("解析命令失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildSystemPrompt() {
|
||||
return SYSTEM_PROMPT;
|
||||
}
|
||||
|
||||
private String buildUserPrompt(AiParseRequestDTO request) {
|
||||
JSONObject payload = JSONUtil.createObj()
|
||||
.set("command", request.getCommand())
|
||||
.set("currentRoute", request.getCurrentRoute())
|
||||
.set("currentComponent", request.getCurrentComponent())
|
||||
.set("context", Optional.ofNullable(request.getContext()).orElse(Collections.emptyMap()))
|
||||
.set("availableFunctions", availableFunctions());
|
||||
|
||||
return StrUtil.format("""
|
||||
请根据以下上下文识别用户意图,并输出符合系统提示要求的 JSON:
|
||||
{}
|
||||
""", JSONUtil.toJsonPrettyStr(payload));
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> availableFunctions() {
|
||||
return List.of(
|
||||
Map.of(
|
||||
"name", "updateUserNickname",
|
||||
"description", "根据用户名更新用户昵称",
|
||||
"requiredParameters", List.of("username", "nickname")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private ParseResult parseAiResponse(String rawContent) {
|
||||
if (StrUtil.isBlank(rawContent)) {
|
||||
throw new IllegalStateException("AI 返回内容为空");
|
||||
private String buildSystemPrompt() {
|
||||
return SYSTEM_PROMPT;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(rawContent);
|
||||
boolean success = jsonObject.getBool("success", false);
|
||||
String explanation = jsonObject.getStr("explanation");
|
||||
Double confidence = jsonObject.containsKey("confidence") ? jsonObject.getDouble("confidence") : null;
|
||||
String error = jsonObject.getStr("error");
|
||||
String provider = jsonObject.getStr("provider");
|
||||
String model = jsonObject.getStr("model");
|
||||
private String buildUserPrompt(AiParseRequestDTO request) {
|
||||
JSONObject payload = JSONUtil.createObj()
|
||||
.set("command", request.getCommand())
|
||||
.set("currentRoute", request.getCurrentRoute())
|
||||
.set("currentComponent", request.getCurrentComponent())
|
||||
.set("context", Optional.ofNullable(request.getContext()).orElse(Collections.emptyMap()))
|
||||
.set("availableFunctions", availableFunctions());
|
||||
|
||||
List<AiFunctionCallDTO> functionCalls = toFunctionCallList(jsonObject.getJSONArray("functionCalls"));
|
||||
|
||||
return new ParseResult(success, explanation, confidence, error, provider, model, functionCalls);
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("无法解析 AI 响应: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private List<AiFunctionCallDTO> toFunctionCallList(JSONArray array) {
|
||||
if (array == null || array.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
return StrUtil.format("""
|
||||
请根据以下上下文识别用户意图,并输出符合系统提示要求的 JSON:
|
||||
{}
|
||||
""", JSONUtil.toJsonPrettyStr(payload));
|
||||
}
|
||||
|
||||
List<AiFunctionCallDTO> result = new ArrayList<>();
|
||||
for (Object element : array) {
|
||||
JSONObject functionJson = JSONUtil.parseObj(element);
|
||||
Map<String, Object> arguments = Optional.ofNullable(functionJson.getJSONObject("arguments"))
|
||||
.map(obj -> obj.toBean(new TypeReference<Map<String, Object>>() {
|
||||
}))
|
||||
.orElse(Collections.emptyMap());
|
||||
|
||||
result.add(AiFunctionCallDTO.builder()
|
||||
.name(functionJson.getStr("name"))
|
||||
.description(functionJson.getStr("description"))
|
||||
.arguments(arguments)
|
||||
.build());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private record ParseResult(
|
||||
boolean success,
|
||||
String explanation,
|
||||
Double confidence,
|
||||
String error,
|
||||
String provider,
|
||||
String model,
|
||||
List<AiFunctionCallDTO> functionCalls
|
||||
) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeCommand(AiExecuteRequestDTO request, HttpServletRequest httpRequest) throws Exception {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 获取用户信息
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
String username = SecurityUtils.getUsername();
|
||||
String ipAddress = JakartaServletUtil.getClientIP(httpRequest);
|
||||
|
||||
AiFunctionCallDTO functionCall = request.getFunctionCall();
|
||||
|
||||
// 根据解析日志ID获取审计记录,如果不存在则创建新记录
|
||||
AiCommandLog log;
|
||||
if (StrUtil.isNotBlank(request.getParseLogId())) {
|
||||
// 更新已存在的审计记录(解析阶段已创建)
|
||||
log = logService.getById(request.getParseLogId());
|
||||
if (log == null) {
|
||||
throw new IllegalStateException("未找到对应的解析记录,ID: " + request.getParseLogId());
|
||||
}
|
||||
} else {
|
||||
// 如果没有解析日志ID,创建新记录(兼容直接执行的情况)
|
||||
log = new AiCommandLog();
|
||||
log.setUserId(userId);
|
||||
log.setUsername(username);
|
||||
log.setOriginalCommand(request.getOriginalCommand());
|
||||
log.setIpAddress(ipAddress);
|
||||
logService.save(log);
|
||||
private List<Map<String, Object>> availableFunctions() {
|
||||
return List.of(
|
||||
Map.of(
|
||||
"name", "updateUserNickname",
|
||||
"description", "根据用户名更新用户昵称",
|
||||
"requiredParameters", List.of("username", "nickname")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// 更新执行相关字段
|
||||
log.setFunctionName(functionCall.getName());
|
||||
log.setFunctionArguments(JSONUtil.toJsonStr(functionCall.getArguments()));
|
||||
log.setExecuteStatus(0); // 0-待执行
|
||||
private ParseResult parseAiResponse(String rawContent) {
|
||||
if (StrUtil.isBlank(rawContent)) {
|
||||
throw new IllegalStateException("AI 返回内容为空");
|
||||
}
|
||||
|
||||
try {
|
||||
// 🎯 执行具体的函数调用
|
||||
Object result = executeFunctionCall(functionCall);
|
||||
try {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(rawContent);
|
||||
boolean success = jsonObject.getBool("success", false);
|
||||
String explanation = jsonObject.getStr("explanation");
|
||||
Double confidence = jsonObject.containsKey("confidence") ? jsonObject.getDouble("confidence") : null;
|
||||
String error = jsonObject.getStr("error");
|
||||
String provider = jsonObject.getStr("provider");
|
||||
String model = jsonObject.getStr("model");
|
||||
|
||||
// 更新执行成功
|
||||
log.setExecuteStatus(1); // 1-成功
|
||||
log.setExecuteErrorMessage(null);
|
||||
List<AiFunctionCallDTO> functionCalls = toFunctionCallList(jsonObject.getJSONArray("functionCalls"));
|
||||
|
||||
// 更新审计记录
|
||||
logService.updateById(log);
|
||||
|
||||
log.info("✅ 命令执行成功,审计记录ID: {}", log.getId());
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
// 更新执行失败
|
||||
log.setExecuteStatus(-1); // -1-失败
|
||||
log.setExecuteErrorMessage(e.getMessage());
|
||||
|
||||
// 更新审计记录
|
||||
logService.updateById(log);
|
||||
|
||||
log.error("❌ 命令执行失败,审计记录ID: {}", log.getId(), e);
|
||||
|
||||
// 抛出异常,由 Controller 统一处理
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行具体的函数调用
|
||||
*/
|
||||
private Object executeFunctionCall(AiFunctionCallDTO functionCall) {
|
||||
String functionName = functionCall.getName();
|
||||
Map<String, Object> arguments = functionCall.getArguments();
|
||||
|
||||
log.info("🎯 执行函数: {}, 参数: {}", functionName, arguments);
|
||||
|
||||
// 根据函数名称路由到不同的处理器
|
||||
switch (functionName) {
|
||||
case "updateUserNickname":
|
||||
return executeUpdateUserNickname(arguments);
|
||||
default:
|
||||
throw new UnsupportedOperationException("不支持的函数: " + functionName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 Tool: 根据用户名更新用户昵称
|
||||
*/
|
||||
private Object executeUpdateUserNickname(Map<String, Object> arguments) {
|
||||
String username = (String) arguments.get("username");
|
||||
String nickname = (String) arguments.get("nickname");
|
||||
|
||||
log.info("🔧 [Tool] 更新用户昵称: username={}, nickname={}", username, nickname);
|
||||
String resultMsg = userTools.updateUserNickname(username, nickname);
|
||||
|
||||
boolean success = resultMsg != null && resultMsg.contains("成功");
|
||||
if (!success) {
|
||||
throw new RuntimeException(resultMsg != null ? resultMsg : "更新用户昵称失败");
|
||||
return new ParseResult(success, explanation, confidence, error, provider, model, functionCalls);
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("无法解析 AI 响应: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return Map.of("username", username, "nickname", nickname, "message", resultMsg);
|
||||
}
|
||||
private List<AiFunctionCallDTO> toFunctionCallList(JSONArray array) {
|
||||
if (array == null || array.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<AiFunctionCallDTO> result = new ArrayList<>();
|
||||
for (Object element : array) {
|
||||
JSONObject functionJson = JSONUtil.parseObj(element);
|
||||
Map<String, Object> arguments = Optional.ofNullable(functionJson.getJSONObject("arguments"))
|
||||
.map(obj -> obj.toBean(new TypeReference<Map<String, Object>>() {
|
||||
}))
|
||||
.orElse(Collections.emptyMap());
|
||||
|
||||
result.add(AiFunctionCallDTO.builder()
|
||||
.name(functionJson.getStr("name"))
|
||||
.description(functionJson.getStr("description"))
|
||||
.arguments(arguments)
|
||||
.build());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private record ParseResult(
|
||||
boolean success,
|
||||
String explanation,
|
||||
Double confidence,
|
||||
String error,
|
||||
String provider,
|
||||
String model,
|
||||
List<AiFunctionCallDTO> functionCalls
|
||||
) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeCommand(AiExecuteRequestDTO request, HttpServletRequest httpRequest) throws Exception {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 获取用户信息
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
String username = SecurityUtils.getUsername();
|
||||
String ipAddress = JakartaServletUtil.getClientIP(httpRequest);
|
||||
|
||||
AiFunctionCallDTO functionCall = request.getFunctionCall();
|
||||
|
||||
// 根据解析日志ID获取审计记录,如果不存在则创建新记录
|
||||
AiCommandLog commandLog;
|
||||
if (StrUtil.isNotBlank(request.getParseLogId())) {
|
||||
// 更新已存在的审计记录(解析阶段已创建)
|
||||
commandLog = logService.getById(request.getParseLogId());
|
||||
if (commandLog == null) {
|
||||
throw new IllegalStateException("未找到对应的解析记录,ID: " + request.getParseLogId());
|
||||
}
|
||||
} else {
|
||||
// 如果没有解析日志ID,创建新记录(兼容直接执行的情况)
|
||||
commandLog = new AiCommandLog();
|
||||
commandLog.setUserId(userId);
|
||||
commandLog.setUsername(username);
|
||||
commandLog.setOriginalCommand(request.getOriginalCommand());
|
||||
commandLog.setIpAddress(ipAddress);
|
||||
logService.save(commandLog);
|
||||
}
|
||||
|
||||
// 更新执行相关字段
|
||||
commandLog.setFunctionName(functionCall.getName());
|
||||
commandLog.setFunctionArguments(JSONUtil.toJsonStr(functionCall.getArguments()));
|
||||
commandLog.setExecuteStatus(0); // 0-待执行
|
||||
|
||||
try {
|
||||
// 🎯 执行具体的函数调用
|
||||
Object result = executeFunctionCall(functionCall);
|
||||
|
||||
// 更新执行成功
|
||||
commandLog.setExecuteStatus(1); // 1-成功
|
||||
commandLog.setExecuteErrorMessage(null);
|
||||
|
||||
// 更新审计记录
|
||||
logService.updateById(commandLog);
|
||||
|
||||
log.info("✅ 命令执行成功,审计记录ID: {}", commandLog.getId());
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
// 更新执行失败
|
||||
commandLog.setExecuteStatus(-1); // -1-失败
|
||||
commandLog.setExecuteErrorMessage(e.getMessage());
|
||||
|
||||
// 更新审计记录
|
||||
logService.updateById(commandLog);
|
||||
|
||||
log.error("❌ 命令执行失败,审计记录ID: {}", commandLog.getId(), e);
|
||||
|
||||
// 抛出异常,由 Controller 统一处理
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行具体的函数调用
|
||||
*/
|
||||
private Object executeFunctionCall(AiFunctionCallDTO functionCall) {
|
||||
String functionName = functionCall.getName();
|
||||
Map<String, Object> arguments = functionCall.getArguments();
|
||||
|
||||
log.info("🎯 执行函数: {}, 参数: {}", functionName, arguments);
|
||||
|
||||
// 根据函数名称路由到不同的处理器
|
||||
switch (functionName) {
|
||||
case "updateUserNickname":
|
||||
return executeUpdateUserNickname(arguments);
|
||||
default:
|
||||
throw new UnsupportedOperationException("不支持的函数: " + functionName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 Tool: 根据用户名更新用户昵称
|
||||
*/
|
||||
private Object executeUpdateUserNickname(Map<String, Object> arguments) {
|
||||
String username = (String) arguments.get("username");
|
||||
String nickname = (String) arguments.get("nickname");
|
||||
|
||||
log.info("🔧 [Tool] 更新用户昵称: username={}, nickname={}", username, nickname);
|
||||
String resultMsg = userTools.updateUserNickname(username, nickname);
|
||||
|
||||
boolean success = resultMsg != null && resultMsg.contains("成功");
|
||||
if (!success) {
|
||||
throw new RuntimeException(resultMsg != null ? resultMsg : "更新用户昵称失败");
|
||||
}
|
||||
|
||||
return Map.of("username", username, "nickname", nickname, "message", resultMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user