mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-27 01:23:55 +08:00
update:创建智能体设置默认的插件
This commit is contained in:
+6
-33
@@ -1,6 +1,5 @@
|
|||||||
package xiaozhi.modules.agent.controller;
|
package xiaozhi.modules.agent.controller;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -33,7 +32,6 @@ import xiaozhi.common.page.PageData;
|
|||||||
import xiaozhi.common.redis.RedisKeys;
|
import xiaozhi.common.redis.RedisKeys;
|
||||||
import xiaozhi.common.redis.RedisUtils;
|
import xiaozhi.common.redis.RedisUtils;
|
||||||
import xiaozhi.common.user.UserDetail;
|
import xiaozhi.common.user.UserDetail;
|
||||||
import xiaozhi.common.utils.ConvertUtils;
|
|
||||||
import xiaozhi.common.utils.Result;
|
import xiaozhi.common.utils.Result;
|
||||||
import xiaozhi.common.utils.ResultUtils;
|
import xiaozhi.common.utils.ResultUtils;
|
||||||
import xiaozhi.modules.agent.dto.AgentChatHistoryDTO;
|
import xiaozhi.modules.agent.dto.AgentChatHistoryDTO;
|
||||||
@@ -46,6 +44,7 @@ import xiaozhi.modules.agent.entity.AgentEntity;
|
|||||||
import xiaozhi.modules.agent.entity.AgentTemplateEntity;
|
import xiaozhi.modules.agent.entity.AgentTemplateEntity;
|
||||||
import xiaozhi.modules.agent.service.AgentChatAudioService;
|
import xiaozhi.modules.agent.service.AgentChatAudioService;
|
||||||
import xiaozhi.modules.agent.service.AgentChatHistoryService;
|
import xiaozhi.modules.agent.service.AgentChatHistoryService;
|
||||||
|
import xiaozhi.modules.agent.service.AgentPluginMappingService;
|
||||||
import xiaozhi.modules.agent.service.AgentService;
|
import xiaozhi.modules.agent.service.AgentService;
|
||||||
import xiaozhi.modules.agent.service.AgentTemplateService;
|
import xiaozhi.modules.agent.service.AgentTemplateService;
|
||||||
import xiaozhi.modules.agent.vo.AgentInfoVO;
|
import xiaozhi.modules.agent.vo.AgentInfoVO;
|
||||||
@@ -63,6 +62,7 @@ public class AgentController {
|
|||||||
private final DeviceService deviceService;
|
private final DeviceService deviceService;
|
||||||
private final AgentChatHistoryService agentChatHistoryService;
|
private final AgentChatHistoryService agentChatHistoryService;
|
||||||
private final AgentChatAudioService agentChatAudioService;
|
private final AgentChatAudioService agentChatAudioService;
|
||||||
|
private final AgentPluginMappingService agentPluginMappingService;
|
||||||
private final RedisUtils redisUtils;
|
private final RedisUtils redisUtils;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@@ -99,37 +99,8 @@ public class AgentController {
|
|||||||
@Operation(summary = "创建智能体")
|
@Operation(summary = "创建智能体")
|
||||||
@RequiresPermissions("sys:role:normal")
|
@RequiresPermissions("sys:role:normal")
|
||||||
public Result<String> save(@RequestBody @Valid AgentCreateDTO dto) {
|
public Result<String> save(@RequestBody @Valid AgentCreateDTO dto) {
|
||||||
AgentEntity entity = ConvertUtils.sourceToTarget(dto, AgentEntity.class);
|
String agentId = agentService.createAgent(dto);
|
||||||
|
return new Result<String>().ok(agentId);
|
||||||
// 获取默认模板
|
|
||||||
AgentTemplateEntity template = agentTemplateService.getDefaultTemplate();
|
|
||||||
if (template != null) {
|
|
||||||
// 设置模板中的默认值
|
|
||||||
entity.setAsrModelId(template.getAsrModelId());
|
|
||||||
entity.setVadModelId(template.getVadModelId());
|
|
||||||
entity.setLlmModelId(template.getLlmModelId());
|
|
||||||
entity.setVllmModelId(template.getVllmModelId());
|
|
||||||
entity.setTtsModelId(template.getTtsModelId());
|
|
||||||
entity.setTtsVoiceId(template.getTtsVoiceId());
|
|
||||||
entity.setMemModelId(template.getMemModelId());
|
|
||||||
entity.setIntentModelId(template.getIntentModelId());
|
|
||||||
entity.setSystemPrompt(template.getSystemPrompt());
|
|
||||||
entity.setSummaryMemory(template.getSummaryMemory());
|
|
||||||
entity.setChatHistoryConf(template.getChatHistoryConf());
|
|
||||||
entity.setLangCode(template.getLangCode());
|
|
||||||
entity.setLanguage(template.getLanguage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置用户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<String>().ok(entity.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/saveMemory/{macAddress}")
|
@PutMapping("/saveMemory/{macAddress}")
|
||||||
@@ -161,6 +132,8 @@ public class AgentController {
|
|||||||
deviceService.deleteByAgentId(id);
|
deviceService.deleteByAgentId(id);
|
||||||
// 删除关联的聊天记录
|
// 删除关联的聊天记录
|
||||||
agentChatHistoryService.deleteByAgentId(id, true, true);
|
agentChatHistoryService.deleteByAgentId(id, true, true);
|
||||||
|
// 删除关联的插件
|
||||||
|
agentPluginMappingService.deleteByAgentId(id);
|
||||||
// 再删除智能体
|
// 再删除智能体
|
||||||
agentService.deleteById(id);
|
agentService.deleteById(id);
|
||||||
return new Result<>();
|
return new Result<>();
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
package xiaozhi.modules.agent.entity;
|
package xiaozhi.modules.agent.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Agent与插件的唯一映射表
|
* Agent与插件的唯一映射表
|
||||||
|
*
|
||||||
* @TableName ai_agent_plugin_mapping
|
* @TableName ai_agent_plugin_mapping
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName(value ="ai_agent_plugin_mapping")
|
@TableName(value = "ai_agent_plugin_mapping")
|
||||||
@Schema(description = "Agent与插件的唯一映射表")
|
@Schema(description = "Agent与插件的唯一映射表")
|
||||||
public class AgentPluginMapping implements Serializable {
|
public class AgentPluginMapping implements Serializable {
|
||||||
/**
|
/**
|
||||||
@@ -37,12 +39,11 @@ public class AgentPluginMapping implements Serializable {
|
|||||||
private String pluginId;
|
private String pluginId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件参数(Json)格式
|
* 插件参数(Json)格式
|
||||||
*/
|
*/
|
||||||
@Schema(description = "插件参数(Json)格式")
|
@Schema(description = "插件参数(Json)格式")
|
||||||
private String paramInfo;
|
private String paramInfo;
|
||||||
|
|
||||||
|
|
||||||
// 冗余字段,用于方便在根据id查询插件时,对照查出插件的Provider_code,详见dao层xml文件
|
// 冗余字段,用于方便在根据id查询插件时,对照查出插件的Provider_code,详见dao层xml文件
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
@Schema(description = "插件provider_code, 对应表ai_model_provider")
|
@Schema(description = "插件provider_code, 对应表ai_model_provider")
|
||||||
|
|||||||
+20
-6
@@ -1,15 +1,29 @@
|
|||||||
package xiaozhi.modules.agent.service;
|
package xiaozhi.modules.agent.service;
|
||||||
|
|
||||||
import xiaozhi.modules.agent.entity.AgentPluginMapping;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import xiaozhi.modules.agent.entity.AgentPluginMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 针对表【ai_agent_plugin_mapping(Agent与插件的唯一映射表)】的数据库操作Service
|
* @description 针对表【ai_agent_plugin_mapping(Agent与插件的唯一映射表)】的数据库操作Service
|
||||||
* @createDate 2025-05-25 22:33:17
|
* @createDate 2025-05-25 22:33:17
|
||||||
*/
|
*/
|
||||||
public interface AgentPluginMappingService extends IService<AgentPluginMapping> {
|
public interface AgentPluginMappingService extends IService<AgentPluginMapping> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据智能体id获取插件参数
|
||||||
|
*
|
||||||
|
* @param agentId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
List<AgentPluginMapping> agentPluginParamsByAgentId(String agentId);
|
List<AgentPluginMapping> agentPluginParamsByAgentId(String agentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据智能体id删除插件参数
|
||||||
|
*
|
||||||
|
* @param agentId
|
||||||
|
*/
|
||||||
|
void deleteByAgentId(String agentId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import xiaozhi.common.page.PageData;
|
import xiaozhi.common.page.PageData;
|
||||||
import xiaozhi.common.service.BaseService;
|
import xiaozhi.common.service.BaseService;
|
||||||
|
import xiaozhi.modules.agent.dto.AgentCreateDTO;
|
||||||
import xiaozhi.modules.agent.dto.AgentDTO;
|
import xiaozhi.modules.agent.dto.AgentDTO;
|
||||||
import xiaozhi.modules.agent.dto.AgentUpdateDTO;
|
import xiaozhi.modules.agent.dto.AgentUpdateDTO;
|
||||||
import xiaozhi.modules.agent.entity.AgentEntity;
|
import xiaozhi.modules.agent.entity.AgentEntity;
|
||||||
@@ -82,5 +83,19 @@ public interface AgentService extends BaseService<AgentEntity> {
|
|||||||
*/
|
*/
|
||||||
boolean checkAgentPermission(String agentId, Long userId);
|
boolean checkAgentPermission(String agentId, Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新智能体
|
||||||
|
*
|
||||||
|
* @param agentId 智能体ID
|
||||||
|
* @param dto 更新智能体所需的信息
|
||||||
|
*/
|
||||||
void updateAgentById(String agentId, AgentUpdateDTO dto);
|
void updateAgentById(String agentId, AgentUpdateDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建智能体
|
||||||
|
*
|
||||||
|
* @param dto 创建智能体所需的信息
|
||||||
|
* @return 创建的智能体ID
|
||||||
|
*/
|
||||||
|
String createAgent(AgentCreateDTO dto);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -4,6 +4,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -26,4 +27,11 @@ public class AgentPluginMappingServiceImpl extends ServiceImpl<AgentPluginMappin
|
|||||||
return agentPluginMappingMapper.selectPluginsByAgentId(agentId);
|
return agentPluginMappingMapper.selectPluginsByAgentId(agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteByAgentId(String agentId) {
|
||||||
|
UpdateWrapper<AgentPluginMapping> updateWrapper = new UpdateWrapper<>();
|
||||||
|
updateWrapper.eq("agent_id", agentId);
|
||||||
|
agentPluginMappingMapper.delete(updateWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+73
-1
@@ -1,6 +1,8 @@
|
|||||||
package xiaozhi.modules.agent.service.impl;
|
package xiaozhi.modules.agent.service.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -23,18 +25,24 @@ import xiaozhi.common.redis.RedisKeys;
|
|||||||
import xiaozhi.common.redis.RedisUtils;
|
import xiaozhi.common.redis.RedisUtils;
|
||||||
import xiaozhi.common.service.impl.BaseServiceImpl;
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
import xiaozhi.common.user.UserDetail;
|
import xiaozhi.common.user.UserDetail;
|
||||||
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
import xiaozhi.common.utils.JsonUtils;
|
import xiaozhi.common.utils.JsonUtils;
|
||||||
import xiaozhi.modules.agent.dao.AgentDao;
|
import xiaozhi.modules.agent.dao.AgentDao;
|
||||||
|
import xiaozhi.modules.agent.dto.AgentCreateDTO;
|
||||||
import xiaozhi.modules.agent.dto.AgentDTO;
|
import xiaozhi.modules.agent.dto.AgentDTO;
|
||||||
import xiaozhi.modules.agent.dto.AgentUpdateDTO;
|
import xiaozhi.modules.agent.dto.AgentUpdateDTO;
|
||||||
import xiaozhi.modules.agent.entity.AgentEntity;
|
import xiaozhi.modules.agent.entity.AgentEntity;
|
||||||
import xiaozhi.modules.agent.entity.AgentPluginMapping;
|
import xiaozhi.modules.agent.entity.AgentPluginMapping;
|
||||||
|
import xiaozhi.modules.agent.entity.AgentTemplateEntity;
|
||||||
import xiaozhi.modules.agent.service.AgentChatHistoryService;
|
import xiaozhi.modules.agent.service.AgentChatHistoryService;
|
||||||
import xiaozhi.modules.agent.service.AgentPluginMappingService;
|
import xiaozhi.modules.agent.service.AgentPluginMappingService;
|
||||||
import xiaozhi.modules.agent.service.AgentService;
|
import xiaozhi.modules.agent.service.AgentService;
|
||||||
|
import xiaozhi.modules.agent.service.AgentTemplateService;
|
||||||
import xiaozhi.modules.agent.vo.AgentInfoVO;
|
import xiaozhi.modules.agent.vo.AgentInfoVO;
|
||||||
import xiaozhi.modules.device.service.DeviceService;
|
import xiaozhi.modules.device.service.DeviceService;
|
||||||
|
import xiaozhi.modules.model.dto.ModelProviderDTO;
|
||||||
import xiaozhi.modules.model.service.ModelConfigService;
|
import xiaozhi.modules.model.service.ModelConfigService;
|
||||||
|
import xiaozhi.modules.model.service.ModelProviderService;
|
||||||
import xiaozhi.modules.security.user.SecurityUser;
|
import xiaozhi.modules.security.user.SecurityUser;
|
||||||
import xiaozhi.modules.sys.enums.SuperAdminEnum;
|
import xiaozhi.modules.sys.enums.SuperAdminEnum;
|
||||||
import xiaozhi.modules.timbre.service.TimbreService;
|
import xiaozhi.modules.timbre.service.TimbreService;
|
||||||
@@ -49,6 +57,8 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
|
|||||||
private final DeviceService deviceService;
|
private final DeviceService deviceService;
|
||||||
private final AgentPluginMappingService agentPluginMappingService;
|
private final AgentPluginMappingService agentPluginMappingService;
|
||||||
private final AgentChatHistoryService agentChatHistoryService;
|
private final AgentChatHistoryService agentChatHistoryService;
|
||||||
|
private final AgentTemplateService agentTemplateService;
|
||||||
|
private final ModelProviderService modelProviderService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageData<AgentEntity> adminAgentList(Map<String, Object> params) {
|
public PageData<AgentEntity> adminAgentList(Map<String, Object> params) {
|
||||||
@@ -250,7 +260,6 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
|
|||||||
List<AgentUpdateDTO.FunctionInfo> functions = dto.getFunctions();
|
List<AgentUpdateDTO.FunctionInfo> functions = dto.getFunctions();
|
||||||
if (functions != null) {
|
if (functions != null) {
|
||||||
// 1. 收集本次提交的 pluginId
|
// 1. 收集本次提交的 pluginId
|
||||||
// TODO: 提交的参数信息里,这里是允许为空,后续可以扩展required字段限制避免为空
|
|
||||||
List<String> newPluginIds = functions.stream()
|
List<String> newPluginIds = functions.stream()
|
||||||
.map(AgentUpdateDTO.FunctionInfo::getPluginId)
|
.map(AgentUpdateDTO.FunctionInfo::getPluginId)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -317,4 +326,67 @@ public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> imp
|
|||||||
}
|
}
|
||||||
this.updateById(existingEntity);
|
this.updateById(existingEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public String createAgent(AgentCreateDTO dto) {
|
||||||
|
// 转换为实体
|
||||||
|
AgentEntity entity = ConvertUtils.sourceToTarget(dto, AgentEntity.class);
|
||||||
|
|
||||||
|
// 获取默认模板
|
||||||
|
AgentTemplateEntity template = agentTemplateService.getDefaultTemplate();
|
||||||
|
if (template != null) {
|
||||||
|
// 设置模板中的默认值
|
||||||
|
entity.setAsrModelId(template.getAsrModelId());
|
||||||
|
entity.setVadModelId(template.getVadModelId());
|
||||||
|
entity.setLlmModelId(template.getLlmModelId());
|
||||||
|
entity.setVllmModelId(template.getVllmModelId());
|
||||||
|
entity.setTtsModelId(template.getTtsModelId());
|
||||||
|
entity.setTtsVoiceId(template.getTtsVoiceId());
|
||||||
|
entity.setMemModelId(template.getMemModelId());
|
||||||
|
entity.setIntentModelId(template.getIntentModelId());
|
||||||
|
entity.setSystemPrompt(template.getSystemPrompt());
|
||||||
|
entity.setSummaryMemory(template.getSummaryMemory());
|
||||||
|
entity.setChatHistoryConf(template.getChatHistoryConf());
|
||||||
|
entity.setLangCode(template.getLangCode());
|
||||||
|
entity.setLanguage(template.getLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置用户ID和创建者信息
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
entity.setUserId(user.getId());
|
||||||
|
entity.setCreator(user.getId());
|
||||||
|
entity.setCreatedAt(new Date());
|
||||||
|
|
||||||
|
// 保存智能体
|
||||||
|
insert(entity);
|
||||||
|
|
||||||
|
// 设置默认插件
|
||||||
|
List<AgentPluginMapping> toInsert = new ArrayList<>();
|
||||||
|
// 播放音乐、查天气、查新闻
|
||||||
|
String[] pluginIds = new String[] { "SYSTEM_PLUGIN_MUSIC", "SYSTEM_PLUGIN_WEATHER",
|
||||||
|
"SYSTEM_PLUGIN_NEWS_NEWSNOW" };
|
||||||
|
for (String pluginId : pluginIds) {
|
||||||
|
ModelProviderDTO provider = modelProviderService.getById(pluginId);
|
||||||
|
if (provider == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AgentPluginMapping mapping = new AgentPluginMapping();
|
||||||
|
mapping.setPluginId(pluginId);
|
||||||
|
|
||||||
|
Map<String, Object> paramInfo = new HashMap<>();
|
||||||
|
List<Map<String, Object>> fields = JsonUtils.parseObject(provider.getFields(), List.class);
|
||||||
|
if (fields != null) {
|
||||||
|
for (Map<String, Object> field : fields) {
|
||||||
|
paramInfo.put((String) field.get("key"), field.get("default"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapping.setParamInfo(JsonUtils.toJsonString(paramInfo));
|
||||||
|
mapping.setAgentId(entity.getId());
|
||||||
|
toInsert.add(mapping);
|
||||||
|
}
|
||||||
|
// 保存默认插件
|
||||||
|
agentPluginMappingService.saveBatch(toInsert);
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,10 +8,10 @@ import xiaozhi.modules.model.dto.ModelProviderDTO;
|
|||||||
|
|
||||||
public interface ModelProviderService {
|
public interface ModelProviderService {
|
||||||
|
|
||||||
// List<String> getModelNames(String modelType, String modelName);
|
|
||||||
|
|
||||||
List<ModelProviderDTO> getPluginList();
|
List<ModelProviderDTO> getPluginList();
|
||||||
|
|
||||||
|
ModelProviderDTO getById(String id);
|
||||||
|
|
||||||
List<ModelProviderDTO> getPluginListByIds(Collection<String> ids);
|
List<ModelProviderDTO> getPluginListByIds(Collection<String> ids);
|
||||||
|
|
||||||
List<ModelProviderDTO> getListByModelType(String modelType);
|
List<ModelProviderDTO> getListByModelType(String modelType);
|
||||||
|
|||||||
+12
-3
@@ -1,11 +1,15 @@
|
|||||||
package xiaozhi.modules.model.service.impl;
|
package xiaozhi.modules.model.service.impl;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
|
||||||
@@ -38,6 +42,12 @@ public class ModelProviderServiceImpl extends BaseServiceImpl<ModelProviderDao,
|
|||||||
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
|
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelProviderDTO getById(String id) {
|
||||||
|
ModelProviderEntity entity = modelProviderDao.selectById(id);
|
||||||
|
return ConvertUtils.sourceToTarget(entity, ModelProviderDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ModelProviderDTO> getPluginListByIds(Collection<String> ids) {
|
public List<ModelProviderDTO> getPluginListByIds(Collection<String> ids) {
|
||||||
LambdaQueryWrapper<ModelProviderEntity> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<ModelProviderEntity> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
@@ -47,7 +57,6 @@ public class ModelProviderServiceImpl extends BaseServiceImpl<ModelProviderDao,
|
|||||||
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
|
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ModelProviderDTO> getListByModelType(String modelType) {
|
public List<ModelProviderDTO> getListByModelType(String modelType) {
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,16 @@ VALUES ('SYSTEM_PLUGIN_WEATHER',
|
|||||||
),
|
),
|
||||||
10, 0, NOW(), 0, NOW());
|
10, 0, NOW(), 0, NOW());
|
||||||
|
|
||||||
|
-- 6. 本地播放音乐
|
||||||
|
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
||||||
|
sort, creator, create_date, updater, update_date)
|
||||||
|
VALUES ('SYSTEM_PLUGIN_MUSIC',
|
||||||
|
'Plugin',
|
||||||
|
'play_music',
|
||||||
|
'服务器音乐播放',
|
||||||
|
JSON_ARRAY(),
|
||||||
|
20, 0, NOW(), 0, NOW());
|
||||||
|
|
||||||
-- 2. 新闻订阅
|
-- 2. 新闻订阅
|
||||||
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
||||||
sort, creator, create_date, updater, update_date)
|
sort, creator, create_date, updater, update_date)
|
||||||
@@ -80,7 +90,7 @@ VALUES ('SYSTEM_PLUGIN_NEWS_CHINANEWS',
|
|||||||
'https://www.chinanews.com.cn/rss/finance.xml'
|
'https://www.chinanews.com.cn/rss/finance.xml'
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
20, 0, NOW(), 0, NOW());
|
30, 0, NOW(), 0, NOW());
|
||||||
|
|
||||||
-- 3. 新闻订阅
|
-- 3. 新闻订阅
|
||||||
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
||||||
@@ -98,7 +108,8 @@ VALUES ('SYSTEM_PLUGIN_NEWS_NEWSNOW',
|
|||||||
'https://newsnow.busiyi.world/api/s?id='
|
'https://newsnow.busiyi.world/api/s?id='
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
20, 0, NOW(), 0, NOW());
|
40, 0, NOW(), 0, NOW());
|
||||||
|
|
||||||
|
|
||||||
-- 4. HomeAssistant 状态查询
|
-- 4. HomeAssistant 状态查询
|
||||||
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
||||||
@@ -106,7 +117,7 @@ INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
|||||||
VALUES ('SYSTEM_PLUGIN_HA_GET_STATE',
|
VALUES ('SYSTEM_PLUGIN_HA_GET_STATE',
|
||||||
'Plugin',
|
'Plugin',
|
||||||
'hass_get_state',
|
'hass_get_state',
|
||||||
'HomeAssistant 状态查询',
|
'HomeAssistant设备状态查询',
|
||||||
JSON_ARRAY(
|
JSON_ARRAY(
|
||||||
JSON_OBJECT(
|
JSON_OBJECT(
|
||||||
'key', 'base_url',
|
'key', 'base_url',
|
||||||
@@ -130,7 +141,7 @@ VALUES ('SYSTEM_PLUGIN_HA_GET_STATE',
|
|||||||
(SELECT param_value FROM sys_params WHERE param_code = 'plugins.home_assistant.devices')
|
(SELECT param_value FROM sys_params WHERE param_code = 'plugins.home_assistant.devices')
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
30, 0, NOW(), 0, NOW());
|
50, 0, NOW(), 0, NOW());
|
||||||
|
|
||||||
-- 5. HomeAssistant 状态写入
|
-- 5. HomeAssistant 状态写入
|
||||||
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
||||||
@@ -138,41 +149,19 @@ INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
|||||||
VALUES ('SYSTEM_PLUGIN_HA_SET_STATE',
|
VALUES ('SYSTEM_PLUGIN_HA_SET_STATE',
|
||||||
'Plugin',
|
'Plugin',
|
||||||
'hass_set_state',
|
'hass_set_state',
|
||||||
'HomeAssistant 状态写入',
|
'HomeAssistant设备状态修改',
|
||||||
JSON_ARRAY(
|
JSON_ARRAY(),
|
||||||
JSON_OBJECT(
|
60, 0, NOW(), 0, NOW());
|
||||||
'key', 'base_url',
|
|
||||||
'type', 'string',
|
|
||||||
'label', 'HA 服务器地址',
|
|
||||||
'default',
|
|
||||||
(SELECT param_value FROM sys_params WHERE param_code = 'plugins.home_assistant.base_url')
|
|
||||||
),
|
|
||||||
JSON_OBJECT(
|
|
||||||
'key', 'api_key',
|
|
||||||
'type', 'string',
|
|
||||||
'label', 'HA API 访问令牌',
|
|
||||||
'default',
|
|
||||||
(SELECT param_value FROM sys_params WHERE param_code = 'plugins.home_assistant.api_key')
|
|
||||||
),
|
|
||||||
JSON_OBJECT(
|
|
||||||
'key', 'devices',
|
|
||||||
'type', 'array',
|
|
||||||
'label', '设备列表(名称,实体ID;…)',
|
|
||||||
'default',
|
|
||||||
(SELECT param_value FROM sys_params WHERE param_code = 'plugins.home_assistant.devices')
|
|
||||||
)
|
|
||||||
),
|
|
||||||
40, 0, NOW(), 0, NOW());
|
|
||||||
|
|
||||||
-- 6. 本地播放音乐
|
-- 5. HomeAssistant 音乐播放
|
||||||
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
INSERT INTO ai_model_provider (id, model_type, provider_code, name, fields,
|
||||||
sort, creator, create_date, updater, update_date)
|
sort, creator, create_date, updater, update_date)
|
||||||
VALUES ('SYSTEM_PLUGIN_MUSIC',
|
VALUES ('SYSTEM_PLUGIN_HA_PLAY_MUSIC',
|
||||||
'Plugin',
|
'Plugin',
|
||||||
'play_music',
|
'hass_play_music',
|
||||||
'本地音乐播放',
|
'HomeAssistant音乐播放',
|
||||||
JSON_ARRAY(),
|
JSON_ARRAY(),
|
||||||
50, 0, NOW(), 0, NOW());
|
70, 0, NOW(), 0, NOW());
|
||||||
|
|
||||||
|
|
||||||
-- ===============================
|
-- ===============================
|
||||||
|
|||||||
@@ -445,14 +445,17 @@ class ConnectionHandler:
|
|||||||
if private_config.get("Intent", None) is not None:
|
if private_config.get("Intent", None) is not None:
|
||||||
init_intent = True
|
init_intent = True
|
||||||
self.config["Intent"] = private_config["Intent"]
|
self.config["Intent"] = private_config["Intent"]
|
||||||
model_intent = private_config.get('selected_module', {}).get('Intent', {})
|
model_intent = private_config.get("selected_module", {}).get("Intent", {})
|
||||||
self.config["selected_module"]["Intent"] = model_intent
|
self.config["selected_module"]["Intent"] = model_intent
|
||||||
# 加载插件配置
|
# 加载插件配置
|
||||||
if model_intent != 'Intent_nointent':
|
if model_intent != "Intent_nointent":
|
||||||
plugin_from_server = private_config.get("plugins", {})
|
plugin_from_server = private_config.get("plugins", {})
|
||||||
for plugin, config_str in plugin_from_server.items():
|
for plugin, config_str in plugin_from_server.items():
|
||||||
plugin_from_server[plugin] = json.loads(config_str)
|
plugin_from_server[plugin] = json.loads(config_str)
|
||||||
self.config['plugins'] = plugin_from_server
|
self.config["plugins"] = plugin_from_server
|
||||||
|
self.config["Intent"][self.config["selected_module"]["Intent"]][
|
||||||
|
"functions"
|
||||||
|
] = plugin_from_server.keys()
|
||||||
if private_config.get("prompt", None) is not None:
|
if private_config.get("prompt", None) is not None:
|
||||||
self.config["prompt"] = private_config["prompt"]
|
self.config["prompt"] = private_config["prompt"]
|
||||||
if private_config.get("summaryMemory", None) is not None:
|
if private_config.get("summaryMemory", None) is not None:
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ class FunctionHandler:
|
|||||||
self.function_registry.register_function("plugin_loader")
|
self.function_registry.register_function("plugin_loader")
|
||||||
self.function_registry.register_function("get_time")
|
self.function_registry.register_function("get_time")
|
||||||
self.function_registry.register_function("get_lunar")
|
self.function_registry.register_function("get_lunar")
|
||||||
# self.function_registry.register_function("handle_speaker_volume_or_screen_brightness")
|
|
||||||
|
|
||||||
def register_config_functions(self):
|
def register_config_functions(self):
|
||||||
"""注册配置中的函数,可以不同客户端使用不同的配置"""
|
"""注册配置中的函数,可以不同客户端使用不同的配置"""
|
||||||
|
|||||||
@@ -12,10 +12,6 @@ class MemoryProviderBase(ABC):
|
|||||||
|
|
||||||
def set_llm(self, llm):
|
def set_llm(self, llm):
|
||||||
self.llm = llm
|
self.llm = llm
|
||||||
# 获取模型名称和类型信息
|
|
||||||
model_name = getattr(llm, "model_name", str(llm.__class__.__name__))
|
|
||||||
# 记录更详细的日志
|
|
||||||
logger.bind(tag=TAG).info(f"记忆总结设置LLM: {model_name}")
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def save_memory(self, msgs):
|
async def save_memory(self, msgs):
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
from config.logger import setup_logging
|
|
||||||
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
|
||||||
from core.handle.iotHandle import get_iot_status, send_iot_conn
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
TAG = __name__
|
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
async def _get_device_status(conn, device_name, device_type, property_name):
|
|
||||||
"""获取设备状态"""
|
|
||||||
status = await get_iot_status(conn, device_type, property_name)
|
|
||||||
if status is None:
|
|
||||||
raise Exception(f"你的设备不支持{device_name}控制")
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
|
||||||
async def _set_device_property(
|
|
||||||
conn,
|
|
||||||
device_name,
|
|
||||||
device_type,
|
|
||||||
method_name,
|
|
||||||
property_name,
|
|
||||||
new_value=None,
|
|
||||||
action=None,
|
|
||||||
step=10,
|
|
||||||
):
|
|
||||||
"""设置设备属性"""
|
|
||||||
current_value = await _get_device_status(
|
|
||||||
conn, device_name, device_type, property_name
|
|
||||||
)
|
|
||||||
|
|
||||||
if action == "raise":
|
|
||||||
current_value += step
|
|
||||||
elif action == "lower":
|
|
||||||
current_value -= step
|
|
||||||
elif action == "set":
|
|
||||||
if new_value is None:
|
|
||||||
raise Exception(f"缺少{property_name}参数")
|
|
||||||
current_value = new_value
|
|
||||||
|
|
||||||
# 限制属性范围在0到100之间
|
|
||||||
current_value = max(0, min(100, current_value))
|
|
||||||
|
|
||||||
await send_iot_conn(conn, device_type, method_name, {property_name: current_value})
|
|
||||||
return current_value
|
|
||||||
|
|
||||||
|
|
||||||
def _handle_device_action(conn, func, success_message, error_message, *args, **kwargs):
|
|
||||||
"""处理设备操作的通用函数"""
|
|
||||||
future = asyncio.run_coroutine_threadsafe(func(conn, *args, **kwargs), conn.loop)
|
|
||||||
try:
|
|
||||||
result = future.result()
|
|
||||||
logger.bind(tag=TAG).info(f"{success_message}: {result}")
|
|
||||||
response = f"{success_message}{result}"
|
|
||||||
return ActionResponse(action=Action.RESPONSE, result=result, response=response)
|
|
||||||
except Exception as e:
|
|
||||||
logger.bind(tag=TAG).error(f"{error_message}: {e}")
|
|
||||||
response = f"{error_message}: {e}"
|
|
||||||
return ActionResponse(action=Action.RESPONSE, result=None, response=response)
|
|
||||||
|
|
||||||
|
|
||||||
# 设备控制
|
|
||||||
handle_device_function_desc = {
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": "handle_speaker_volume_or_screen_brightness",
|
|
||||||
"description": (
|
|
||||||
"用户想要获取或者设置设备的音量/亮度大小,或者用户觉得声音/亮度过高或过低,或者用户想提高或降低音量/亮度。\n"
|
|
||||||
"**严格限制**:仅当用户明确操作 **Speaker(音量)或Screen(亮度)** 时才能调用此函数!\n"
|
|
||||||
"对于其他设备(如AC、Battery、Switch等),请不要调用此函数,而是继续正常的对话。\n\n"
|
|
||||||
"示例:\n"
|
|
||||||
"- 用户说『现在亮度多少』 → 调用函数:device_type: Screen, action: get\n"
|
|
||||||
"- 用户说『设置音量为50』 → 调用函数:device_type: Speaker, action: set, value: 50\n"
|
|
||||||
"- 用户说『亮度太高了』 → 调用函数:device_type: Screen, action: lower\n"
|
|
||||||
"- 用户说『调大音量』 → 调用函数:device_type: Speaker, action: raise\n\n"
|
|
||||||
"**拒绝调用示例**(应继续对话而非调用本函数):\n"
|
|
||||||
"- 用户说『空调调低一度』 → 不调用(设备类型为AC)\n"
|
|
||||||
"- 用户说『开关灯』 → 不调用(设备类型为Switch)\n"
|
|
||||||
"- 用户说『电量多少』 → 不调用(设备类型为Battery)\n"
|
|
||||||
),
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"device_type": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "设备类型,**严格限定为Speaker(音量)或Screen(亮度)**,其他设备类型禁止调用此函数",
|
|
||||||
"enum": ["Speaker", "Screen"],
|
|
||||||
},
|
|
||||||
"action": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "动作名称,可选值:get(获取),set(设置),raise(提高),lower(降低)",
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "值大小,可选值:0-100之间的整数",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"required": ["device_type", "action"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@register_function(
|
|
||||||
"handle_speaker_volume_or_screen_brightness",
|
|
||||||
handle_device_function_desc,
|
|
||||||
ToolType.IOT_CTL,
|
|
||||||
)
|
|
||||||
def handle_speaker_volume_or_screen_brightness(
|
|
||||||
conn, device_type: str, action: str, value: int = None
|
|
||||||
):
|
|
||||||
# 检查value是否为中文值
|
|
||||||
if (
|
|
||||||
value is not None
|
|
||||||
and isinstance(value, str)
|
|
||||||
and any("\u4e00" <= char <= "\u9fff" for char in str(value))
|
|
||||||
):
|
|
||||||
raise Exception(
|
|
||||||
f"请直接告诉我要将{'音量' if device_type=='Speaker' else '亮度'}调整成多少"
|
|
||||||
)
|
|
||||||
|
|
||||||
if device_type == "Speaker":
|
|
||||||
method_name, property_name, device_name = "SetVolume", "volume", "音量"
|
|
||||||
elif device_type == "Screen":
|
|
||||||
method_name, property_name, device_name = "SetBrightness", "brightness", "亮度"
|
|
||||||
else:
|
|
||||||
raise Exception(f"未识别的设备类型: {device_type}")
|
|
||||||
|
|
||||||
if action not in ["get", "set", "raise", "lower"]:
|
|
||||||
raise Exception(f"未识别的动作名称: {action}")
|
|
||||||
|
|
||||||
if action == "get":
|
|
||||||
# get
|
|
||||||
return _handle_device_action(
|
|
||||||
conn,
|
|
||||||
_get_device_status,
|
|
||||||
f"当前{device_name}",
|
|
||||||
f"获取{device_name}失败",
|
|
||||||
device_name=device_name,
|
|
||||||
device_type=device_type,
|
|
||||||
property_name=property_name,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# set, raise, lower
|
|
||||||
return _handle_device_action(
|
|
||||||
conn,
|
|
||||||
_set_device_property,
|
|
||||||
f"{device_name}已调整到",
|
|
||||||
f"{device_name}调整失败",
|
|
||||||
device_name=device_name,
|
|
||||||
device_type=device_type,
|
|
||||||
method_name=method_name,
|
|
||||||
property_name=property_name,
|
|
||||||
new_value=value,
|
|
||||||
action=action,
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user