diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java new file mode 100644 index 00000000..9f2cb10d --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java @@ -0,0 +1,149 @@ +package xiaozhi.modules.agent.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.page.PageData; +import xiaozhi.common.user.UserDetail; +import xiaozhi.common.utils.ConvertUtils; +import xiaozhi.common.utils.Result; +import xiaozhi.modules.agent.dto.AgentCreateDTO; +import xiaozhi.modules.agent.dto.AgentUpdateDTO; +import xiaozhi.modules.agent.entity.AgentEntity; +import xiaozhi.modules.agent.service.AgentService; +import xiaozhi.modules.security.user.SecurityUser; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Tag(name = "智能体管理") +@AllArgsConstructor +@RestController +@RequestMapping("/agent") +public class AgentController { + private final AgentService agentService; + + @GetMapping("/list") + @Operation(summary = "获取用户智能体列表") + @RequiresPermissions("sys:role:normal") + public Result> getUserAgents() { + UserDetail user = SecurityUser.getUser(); + List agents = agentService.getUserAgents(user.getId()); + return new Result>().ok(agents); + } + + @GetMapping("/all") + @Operation(summary = "智能体列表(管理员)") + @RequiresPermissions("sys:role:superAdmin") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true), + }) + public Result> adminAgentList( + @Parameter(hidden = true) @RequestParam Map params) { + PageData page = agentService.adminAgentList(params); + return new Result>().ok(page); + } + + @GetMapping("/{id}") + @Operation(summary = "获取智能体详情") + @RequiresPermissions("sys:role:normal") + public Result getAgentById(@PathVariable("id") String id) { + AgentEntity agent = agentService.getAgentById(id); + return new Result().ok(agent); + } + + @PostMapping + @Operation(summary = "创建智能体") + @RequiresPermissions("sys:role:normal") + public Result save(@RequestBody @Valid AgentCreateDTO dto) { + AgentEntity entity = ConvertUtils.sourceToTarget(dto, AgentEntity.class); + + // 设置用户ID和创建者信息 + UserDetail user = SecurityUser.getUser(); + entity.setUserId(user.getId()); + entity.setCreator(user.getId()); + entity.setCreatedAt(new Date()); + + // ID、智能体编码和排序会在Service层自动生成 + agentService.insert(entity); + + return new Result<>(); + } + + @PutMapping + @Operation(summary = "更新智能体") + @RequiresPermissions("sys:role:normal") + public Result update(@RequestBody @Valid AgentUpdateDTO dto) { + // 先查询现有实体 + AgentEntity existingEntity = agentService.getAgentById(dto.getId()); + if (existingEntity == null) { + return new Result().error("智能体不存在"); + } + + // 只更新提供的非空字段 + if (dto.getAgentName() != null) { + existingEntity.setAgentName(dto.getAgentName()); + } + if (dto.getAgentCode() != null) { + existingEntity.setAgentCode(dto.getAgentCode()); + } + if (dto.getAsrModelId() != null) { + existingEntity.setAsrModelId(dto.getAsrModelId()); + } + if (dto.getVadModelId() != null) { + existingEntity.setVadModelId(dto.getVadModelId()); + } + if (dto.getLlmModelId() != null) { + existingEntity.setLlmModelId(dto.getLlmModelId()); + } + if (dto.getTtsModelId() != null) { + existingEntity.setTtsModelId(dto.getTtsModelId()); + } + if (dto.getTtsVoiceId() != null) { + existingEntity.setTtsVoiceId(dto.getTtsVoiceId()); + } + if (dto.getMemModelId() != null) { + existingEntity.setMemModelId(dto.getMemModelId()); + } + if (dto.getIntentModelId() != null) { + existingEntity.setIntentModelId(dto.getIntentModelId()); + } + if (dto.getSystemPrompt() != null) { + existingEntity.setSystemPrompt(dto.getSystemPrompt()); + } + if (dto.getLangCode() != null) { + existingEntity.setLangCode(dto.getLangCode()); + } + if (dto.getLanguage() != null) { + existingEntity.setLanguage(dto.getLanguage()); + } + if (dto.getSort() != null) { + existingEntity.setSort(dto.getSort()); + } + + // 设置更新者信息 + UserDetail user = SecurityUser.getUser(); + existingEntity.setUpdater(user.getId()); + existingEntity.setUpdatedAt(new Date()); + + agentService.updateById(existingEntity); + + return new Result<>(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除智能体") + @RequiresPermissions("sys:role:normal") + public Result delete(@PathVariable String id) { + agentService.deleteById(id); + return new Result<>(); + } +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java new file mode 100644 index 00000000..169346bf --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentDao.java @@ -0,0 +1,10 @@ +package xiaozhi.modules.agent.dao; + +import org.apache.ibatis.annotations.Mapper; +import xiaozhi.common.dao.BaseDao; +import xiaozhi.modules.agent.entity.AgentEntity; + +@Mapper +public interface AgentDao extends BaseDao { + +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentCreateDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentCreateDTO.java new file mode 100644 index 00000000..302a55fb --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentCreateDTO.java @@ -0,0 +1,51 @@ +package xiaozhi.modules.agent.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 智能体创建DTO + * 专用于新增智能体,不包含id、agentCode和sort字段,这些字段由系统自动生成/设置默认值 + */ +@Data +@Schema(description = "智能体创建对象") +public class AgentCreateDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "智能体名称", example = "客服助手") + @NotBlank(message = "智能体名称不能为空") + private String agentName; + + @Schema(description = "语音识别模型标识", example = "asr_model_01") + private String asrModelId; + + @Schema(description = "语音活动检测标识", example = "vad_model_01") + private String vadModelId; + + @Schema(description = "大语言模型标识", example = "llm_model_01") + private String llmModelId; + + @Schema(description = "语音合成模型标识", example = "tts_model_01") + private String ttsModelId; + + @Schema(description = "音色标识", example = "voice_01") + private String ttsVoiceId; + + @Schema(description = "记忆模型标识", example = "mem_model_01") + private String memModelId; + + @Schema(description = "意图模型标识", example = "intent_model_01") + private String intentModelId; + + @Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题") + private String systemPrompt; + + @Schema(description = "语言编码", example = "zh_CN") + private String langCode; + + @Schema(description = "交互语种", example = "中文") + private String language; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java new file mode 100644 index 00000000..6445bdda --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentUpdateDTO.java @@ -0,0 +1,61 @@ +package xiaozhi.modules.agent.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +/** + * 智能体更新DTO + * 专用于更新智能体,id字段是必需的,用于标识要更新的智能体 + * 其他字段均为非必填,只更新提供的字段 + */ +@Data +@Schema(description = "智能体更新对象") +public class AgentUpdateDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "智能体唯一标识", example = "a1b2c3d4e5f6", required = true) + @NotBlank(message = "智能体ID不能为空") + private String id; + + @Schema(description = "智能体编码", example = "AGT_1234567890", required = false) + private String agentCode; + + @Schema(description = "智能体名称", example = "客服助手", required = false) + private String agentName; + + @Schema(description = "语音识别模型标识", example = "asr_model_02", required = false) + private String asrModelId; + + @Schema(description = "语音活动检测标识", example = "vad_model_02", required = false) + private String vadModelId; + + @Schema(description = "大语言模型标识", example = "llm_model_02", required = false) + private String llmModelId; + + @Schema(description = "语音合成模型标识", example = "tts_model_02", required = false) + private String ttsModelId; + + @Schema(description = "音色标识", example = "voice_02", required = false) + private String ttsVoiceId; + + @Schema(description = "记忆模型标识", example = "mem_model_02", required = false) + private String memModelId; + + @Schema(description = "意图模型标识", example = "intent_model_02", required = false) + private String intentModelId; + + @Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题并提供帮助", required = false) + private String systemPrompt; + + @Schema(description = "语言编码", example = "zh_CN", required = false) + private String langCode; + + @Schema(description = "交互语种", example = "中文", required = false) + private String language; + + @Schema(description = "排序", example = "1", required = false) + private Integer sort; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java new file mode 100644 index 00000000..6800aefb --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentEntity.java @@ -0,0 +1,69 @@ +package xiaozhi.modules.agent.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("ai_agent") +@Schema(description = "智能体信息") +public class AgentEntity { + @Schema(description = "智能体唯一标识") + private String id; + + @Schema(description = "所属用户ID") + private Long userId; + + @Schema(description = "智能体编码") + private String agentCode; + + @Schema(description = "智能体名称") + private String agentName; + + @Schema(description = "语音识别模型标识") + private String asrModelId; + + @Schema(description = "语音活动检测标识") + private String vadModelId; + + @Schema(description = "大语言模型标识") + private String llmModelId; + + @Schema(description = "语音合成模型标识") + private String ttsModelId; + + @Schema(description = "音色标识") + private String ttsVoiceId; + + @Schema(description = "记忆模型标识") + private String memModelId; + + @Schema(description = "意图模型标识") + private String intentModelId; + + @Schema(description = "角色设定参数") + private String systemPrompt; + + @Schema(description = "语言编码") + private String langCode; + + @Schema(description = "交互语种") + private String language; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "创建者") + private Long creator; + + @Schema(description = "创建时间") + private Date createdAt; + + @Schema(description = "更新者") + private Long updater; + + @Schema(description = "更新时间") + private Date updatedAt; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java new file mode 100644 index 00000000..76439ede --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentService.java @@ -0,0 +1,25 @@ +package xiaozhi.modules.agent.service; + +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.BaseService; +import xiaozhi.modules.agent.entity.AgentEntity; + +import java.util.List; +import java.util.Map; + +public interface AgentService extends BaseService { + /** + * 根据用户ID获取智能体列表 + */ + List getUserAgents(Long userId); + + /** + * 管理员获取所有智能体列表(分页) + */ + PageData adminAgentList(Map params); + + /** + * 获取智能体详情 + */ + AgentEntity getAgentById(String id); +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java new file mode 100644 index 00000000..b41310ab --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java @@ -0,0 +1,64 @@ +package xiaozhi.modules.agent.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.springframework.stereotype.Service; +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.impl.BaseServiceImpl; +import xiaozhi.modules.agent.dao.AgentDao; +import xiaozhi.modules.agent.entity.AgentEntity; +import xiaozhi.modules.agent.service.AgentService; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Service +public class AgentServiceImpl extends BaseServiceImpl implements AgentService { + private final AgentDao agentDao; + + public AgentServiceImpl(AgentDao agentDao) { + this.agentDao = agentDao; + } + + @Override + public List getUserAgents(Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + return agentDao.selectList(wrapper); + } + + @Override + public PageData adminAgentList(Map params) { + IPage page = agentDao.selectPage( + getPage(params, "sort", true), + new QueryWrapper<>() + ); + return new PageData<>(page.getRecords(), page.getTotal()); + } + + @Override + public AgentEntity getAgentById(String id) { + return agentDao.selectById(id); + } + + @Override + public boolean insert(AgentEntity entity) { + // 如果ID为空,自动生成一个UUID作为ID + if (entity.getId() == null || entity.getId().trim().isEmpty()) { + entity.setId(UUID.randomUUID().toString().replace("-", "")); + } + + // 如果智能体编码为空,自动生成一个带前缀的编码 + if (entity.getAgentCode() == null || entity.getAgentCode().trim().isEmpty()) { + entity.setAgentCode("AGT_" + System.currentTimeMillis()); + } + + // 如果排序字段为空,设置默认值0 + if (entity.getSort() == null) { + entity.setSort(0); + } + + return super.insert(entity); + } +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java index c7ab9e2e..a7ba9b10 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java @@ -86,7 +86,7 @@ public class ModelConfigServiceImpl extends BaseServiceImpl