package com.zy.ai.controller; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.annotations.ManagerAuth; import com.core.common.R; import com.zy.ai.domain.autotune.AutoTuneApplyResult; import com.zy.ai.entity.AiAutoTuneChange; import com.zy.ai.entity.AiAutoTuneJob; import com.zy.ai.service.AiAutoTuneChangeService; import com.zy.ai.service.AiAutoTuneJobService; import com.zy.ai.service.AutoTuneApplyService; import com.zy.ai.service.AutoTuneCoordinatorService; import com.zy.ai.service.AutoTuneSnapshotService; import com.zy.common.web.BaseController; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/ai/autoTune") @RequiredArgsConstructor public class AutoTuneConsoleController extends BaseController { private static final int DEFAULT_JOB_LIMIT = 10; private static final int MAX_JOB_LIMIT = 50; private final AutoTuneSnapshotService autoTuneSnapshotService; private final AutoTuneCoordinatorService autoTuneCoordinatorService; private final AutoTuneApplyService autoTuneApplyService; private final AiAutoTuneJobService aiAutoTuneJobService; private final AiAutoTuneChangeService aiAutoTuneChangeService; @GetMapping("/snapshot/auth") @ManagerAuth(memo = "查看AI自动调参快照") public R snapshot() { return R.ok(autoTuneSnapshotService.buildSnapshot()); } @GetMapping("/jobs/auth") @ManagerAuth(memo = "查看AI自动调参记录") public R jobs(@RequestParam(value = "limit", required = false) Integer limit) { int safeLimit = normalizeLimit(limit); List jobs = aiAutoTuneJobService.list(new QueryWrapper() .orderByDesc("start_time") .orderByDesc("id") .last("limit " + safeLimit)); return R.ok(toJobSummaries(jobs)); } @PostMapping("/triggerManual/auth") @ManagerAuth(memo = "手动触发AI自动调参Agent") public R triggerManual() { return R.ok(autoTuneCoordinatorService.runManualAutoTune()); } @PostMapping("/triggerScheduler/auth") @ManagerAuth(memo = "按后台规则触发AI自动调参") public R triggerScheduler() { return R.ok(autoTuneCoordinatorService.runAutoTuneIfEligible()); } @PostMapping("/rollback/auth") @ManagerAuth(memo = "回滚最近一次AI自动调参") public R rollback(@RequestParam(value = "reason", required = false) String reason) { AutoTuneApplyResult result = autoTuneApplyService.rollbackLastSuccessfulJob(reason); return R.ok(result); } private int normalizeLimit(Integer limit) { if (limit == null || limit <= 0) { return DEFAULT_JOB_LIMIT; } return Math.min(limit, MAX_JOB_LIMIT); } private List> toJobSummaries(List jobs) { List> result = new ArrayList<>(); if (jobs == null || jobs.isEmpty()) { return result; } for (AiAutoTuneJob job : jobs) { result.add(toJobSummary(job)); } return result; } private Map toJobSummary(AiAutoTuneJob job) { LinkedHashMap item = new LinkedHashMap<>(); item.put("id", job.getId()); item.put("triggerType", job.getTriggerType()); item.put("status", job.getStatus()); item.put("startTime", job.getStartTime()); item.put("finishTime", job.getFinishTime()); item.put("hasActiveTasks", job.getHasActiveTasks()); item.put("summary", job.getSummary()); item.put("reasoningDigest", job.getReasoningDigest()); item.put("snapshotDigest", job.getSnapshotDigest()); item.put("intervalBefore", job.getIntervalBefore()); item.put("intervalAfter", job.getIntervalAfter()); item.put("successCount", job.getSuccessCount()); item.put("rejectCount", job.getRejectCount()); item.put("errorMessage", job.getErrorMessage()); item.put("llmCallCount", job.getLlmCallCount()); item.put("promptTokens", job.getPromptTokens()); item.put("completionTokens", job.getCompletionTokens()); item.put("totalTokens", job.getTotalTokens()); item.put("changes", listChangeSummaries(job.getId())); return item; } private List> listChangeSummaries(Long jobId) { List> result = new ArrayList<>(); if (jobId == null) { return result; } List changes = aiAutoTuneChangeService.list(new QueryWrapper() .eq("job_id", jobId) .orderByAsc("id")); if (changes == null || changes.isEmpty()) { return result; } for (AiAutoTuneChange change : changes) { result.add(toChangeSummary(change)); } return result; } private Map toChangeSummary(AiAutoTuneChange change) { LinkedHashMap item = new LinkedHashMap<>(); item.put("id", change.getId()); item.put("targetType", change.getTargetType()); item.put("targetId", change.getTargetId()); item.put("targetKey", change.getTargetKey()); item.put("oldValue", change.getOldValue()); item.put("requestedValue", change.getRequestedValue()); item.put("appliedValue", change.getAppliedValue()); item.put("resultStatus", change.getResultStatus()); item.put("rejectReason", change.getRejectReason()); item.put("cooldownExpireTime", change.getCooldownExpireTime()); item.put("createTime", change.getCreateTime()); return item; } }