feature:为合并mian做准备

This commit is contained in:
Erlei Chen
2025-03-28 22:22:23 +08:00
parent c565bfc6bc
commit 0816f1f589
23 changed files with 543 additions and 274 deletions
@@ -1,6 +1,7 @@
package xiaozhi.modules.agent.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -20,7 +21,6 @@ import xiaozhi.modules.agent.domain.Agent;
import xiaozhi.modules.agent.domain.AgentTemplate;
import xiaozhi.modules.agent.service.AgentService;
import xiaozhi.modules.agent.service.AgentTemplateService;
import xiaozhi.modules.agent.vo.AgentConfigVO;
import xiaozhi.modules.agent.vo.AgentVO;
import xiaozhi.modules.device.domain.Device;
import xiaozhi.modules.device.service.DeviceService;
@@ -40,7 +40,7 @@ import java.util.UUID;
@AllArgsConstructor
@RestController
@RequestMapping("/user/agent")
public class UserAgentController extends BaseController {
public class AgentController extends BaseController {
private final AgentService agentService;
private final AgentTemplateService agentTemplateService;
private final ModelConfigService modelConfigService;
@@ -163,58 +163,85 @@ public class UserAgentController extends BaseController {
if (ObjectUtils.isNull(agent)) {
return new Result<JSONObject>().error("智能体不存在");
}
AgentConfigVO agentConfigVO = new AgentConfigVO();
agentConfigVO.setPrompt(agent.getSystemPrompt());
// return new Result<AgentConfigVO>().ok(agentConfigVO);
String json = "{\n" +
" \"ASR\": {\n" +
" \"FunASR\": {\n" +
" \"model_dir\": \"models/SenseVoiceSmall\",\n" +
" \"output_dir\": \"tmp/\",\n" +
" \"type\": \"fun_local\"\n" +
" }\n" +
" },\n" +
" \"LLM\": {\n" +
" \"ChatGLMLLM\": {\n" +
" \"api_key\": \"0415dad4014847babc3e3f03024c50a3.qH7FgTy5Yawc85fl\",\n" +
" \"model_name\": \"glm-4-flash\",\n" +
" \"type\": \"openai\",\n" +
" \"url\": \"https://open.bigmodel.cn/api/paas/v4/\"\n" +
" }\n" +
" },\n" +
" \"TTS\": {\n" +
" \"DoubaoTTS\": {\n" +
" \"access_token\": \"hrnx22F9WutWBm7YJzE62r_Z1myUmHEL\",\n" +
" \"api_url\": \"https://openspeech.bytedance.com/api/v1/tts\",\n" +
" \"appid\": \"6295576095\",\n" +
" \"authorization\": \"Bearer;\",\n" +
" \"cluster\": \"volcano_tts\",\n" +
" \"output_dir\": \"tmp/\",\n" +
" \"type\": \"doubao\",\n" +
" \"voice\": \"BV034_streaming\"\n" +
" }\n" +
" },\n" +
" \"VAD\": {\n" +
" \"SileroVAD\": {\n" +
" \"min_silence_duration_ms\": 700,\n" +
" \"model_dir\": \"models/snakers4_silero-vad\",\n" +
" \"threshold\": 0.5\n" +
" }\n" +
" },\n" +
" \"auth_code\": \"642365\",\n" +
" \"prompt\": \"你是一个叫小优的女孩,来自优享生活公司的AI智能体,声音好听,习惯简短表达,爱用网络梗。\\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\\n现在我正在和你进行语音聊天,我们开始吧。\\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。\\n\",\n" +
" \"selected_module\": {\n" +
" \"ASR\": \"FunASR\",\n" +
" \"Intent\": \"function_call\",\n" +
" \"LLM\": \"ChatGLMLLM\",\n" +
" \"Memory\": \"mem0ai\",\n" +
" \"TTS\": \"DoubaoTTS\",\n" +
" \"VAD\": \"SileroVAD\"\n" +
" },\n" +
" \"owner\":\"18600806164\"\n" +
"}";
return new Result<JSONObject>().ok(new JSONObject(json));
JSONObject jsonObject = new JSONObject();
jsonObject.set("prompt", agent.getSystemPrompt().replace("{{assistant_name}}", agent.getAgentCode()));
jsonObject.set("owner", String.valueOf(agent.getUserId()));
ModelConfig asrModel = modelConfigService.getById(agent.getAsrModelId());
jsonObject.set("ASR", JSONUtil.parseObj(asrModel.getConfigJson()));
ModelConfig llmModel = modelConfigService.getById(agent.getLlmModelId());
jsonObject.set("LLM", JSONUtil.parseObj(llmModel.getConfigJson()));
ModelConfig ttsModel = modelConfigService.getById(agent.getTtsModelId());
JSONObject ttsJson = JSONUtil.parseObj(ttsModel.getConfigJson());
TtsVoice ttsVoice = ttsVoiceService.getById(agent.getTtsVoiceId());
ttsJson.getJSONObject(ttsModel.getModelCode()).set("voice", ttsVoice.getTtsVoice());
jsonObject.set("TTS", ttsJson);
ModelConfig vadModel = modelConfigService.getById(agent.getVadModelId());
jsonObject.set("VAD", JSONUtil.parseObj(vadModel.getConfigJson()));
ModelConfig intentModel = modelConfigService.getById(agent.getIntentModelId());
jsonObject.set("Intent", JSONUtil.parseObj(intentModel.getConfigJson()));
ModelConfig memoryModel = modelConfigService.getById(agent.getMemoryModelId());
jsonObject.set("Memory", JSONUtil.parseObj(memoryModel.getConfigJson()));
JSONObject module = new JSONObject();
module.set("ASR", asrModel.getModelCode());
module.set("LLM", llmModel.getModelCode());
module.set("TTS", ttsModel.getModelCode());
module.set("Intent", intentModel.getModelCode());
module.set("Memory", memoryModel.getModelCode());
module.set("VAD", vadModel.getModelCode());
jsonObject.set("selected_module", module);
return new Result<JSONObject>().ok(jsonObject);
// String json = "{\n" +
// " \"ASR\": {\n" +
// " \"FunASR\": {\n" +
// " \"model_dir\": \"models/SenseVoiceSmall\",\n" +
// " \"output_dir\": \"tmp/\",\n" +
// " \"type\": \"fun_local\"\n" +
// " }\n" +
// " },\n" +
// " \"LLM\": {\n" +
// " \"ChatGLMLLM\": {\n" +
// " \"api_key\": \"0415dad4014847babc3e3f03024c50a3.qH7FgTy5Yawc85fl\",\n" +
// " \"model_name\": \"glm-4-flash\",\n" +
// " \"type\": \"openai\",\n" +
// " \"url\": \"https://open.bigmodel.cn/api/paas/v4/\"\n" +
// " }\n" +
// " },\n" +
// " \"TTS\": {\n" +
// " \"DoubaoTTS\": {\n" +
// " \"access_token\": \"hrnx22F9WutWBm7YJzE62r_Z1myUmHEL\",\n" +
// " \"api_url\": \"https://openspeech.bytedance.com/api/v1/tts\",\n" +
// " \"appid\": \"6295576095\",\n" +
// " \"authorization\": \"Bearer;\",\n" +
// " \"cluster\": \"volcano_tts\",\n" +
// " \"output_dir\": \"tmp/\",\n" +
// " \"type\": \"doubao\",\n" +
// " \"voice\": \"BV034_streaming\"\n" +
// " }\n" +
// " },\n" +
// " \"VAD\": {\n" +
// " \"SileroVAD\": {\n" +
// " \"min_silence_duration_ms\": 700,\n" +
// " \"model_dir\": \"models/snakers4_silero-vad\",\n" +
// " \"threshold\": 0.5\n" +
// " }\n" +
// " },\n" +
// " \"auth_code\": \"642365\",\n" +
// " \"prompt\": \"你是一个叫小优的女孩,来自优享生活公司的AI智能体,声音好听,习惯简短表达,爱用网络梗。\\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\\n现在我正在和你进行语音聊天,我们开始吧。\\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。\\n\",\n" +
// " \"selected_module\": {\n" +
// " \"ASR\": \"FunASR\",\n" +
// " \"Intent\": \"function_call\",\n" +
// " \"LLM\": \"ChatGLMLLM\",\n" +
// " \"Memory\": \"mem0ai\",\n" +
// " \"TTS\": \"DoubaoTTS\",\n" +
// " \"VAD\": \"SileroVAD\"\n" +
// " },\n" +
// " \"owner\":\"18600806164\"\n" +
// "}";
//
// return new Result<JSONObject>().ok(new JSONObject(json));
}
/**
@@ -1,4 +1,4 @@
package xiaozhi.modules.agentTemplate.controller;
package xiaozhi.modules.agent.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -16,8 +16,6 @@ import xiaozhi.common.utils.Result;
import xiaozhi.modules.agent.domain.AgentTemplate;
import xiaozhi.modules.agent.service.AgentTemplateService;
import xiaozhi.modules.agent.vo.AgentTemplateVO;
import xiaozhi.modules.device.domain.Device;
import xiaozhi.modules.device.service.DeviceService;
import xiaozhi.modules.model.domain.ModelConfig;
import xiaozhi.modules.model.domain.TtsVoice;
import xiaozhi.modules.model.service.ModelConfigService;
@@ -34,11 +32,10 @@ import java.util.UUID;
@AllArgsConstructor
@RestController
@RequestMapping("/user/agent/template")
public class UserAgentTemplateController extends BaseController {
public class AgentTemplateController extends BaseController {
private final AgentTemplateService agentTemplateService;
private final ModelConfigService modelConfigService;
private final TtsVoiceService ttsVoiceService;
private final DeviceService deviceService;
@PostMapping
@Operation(summary = "添加智能体模板")
@@ -80,7 +77,7 @@ public class UserAgentTemplateController extends BaseController {
@Operation(summary = "智能体模板模板列表")
@RequiresPermissions("sys:role:normal")
public Result<List<AgentTemplate>> templateList() {
List<AgentTemplate> list = agentTemplateService.list();
List<AgentTemplate> list = agentTemplateService.list(new QueryWrapper<AgentTemplate>().orderByAsc("sort"));
return new Result<List<AgentTemplate>>().ok(list);
}
@@ -22,7 +22,6 @@ import xiaozhi.modules.device.constant.DeviceConstant;
import xiaozhi.modules.device.domain.Device;
import xiaozhi.modules.device.service.DeviceService;
import xiaozhi.modules.device.vo.DeviceCodeVO;
import xiaozhi.modules.ota.domain.Ota;
import xiaozhi.modules.security.user.SecurityUser;
import java.util.Date;
@@ -32,7 +31,7 @@ import java.util.Date;
@AllArgsConstructor
@RestController
@RequestMapping("/user/agent/device")
public class UserDeviceController extends BaseController {
public class DeviceController extends BaseController {
private final AgentService agentService;
private final DeviceService deviceService;
private final RedisUtils redisUtils;
@@ -4,7 +4,5 @@ import lombok.Data;
@Data
public class DeviceCodeVO {
private String deviceId;
private String deviceCode;
private String token;
}
@@ -0,0 +1,106 @@
package xiaozhi.modules.model.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
import xiaozhi.common.page.PageData;
import xiaozhi.common.utils.Result;
import xiaozhi.modules.model.dto.ModelConfigBodyDTO;
import xiaozhi.modules.model.dto.ModelConfigDTO;
import xiaozhi.modules.model.dto.ModelProviderDTO;
import xiaozhi.modules.model.service.Conflict_ModelConfigService;
import xiaozhi.modules.model.service.Conflict_ModelProviderService;
import java.util.List;
@AllArgsConstructor
@RestController
@RequestMapping("/models")
@Tag(name = "模型配置")
public class Conflict_ModelController {
private final Conflict_ModelProviderService modelProviderService;
private final Conflict_ModelConfigService modelConfigService;
@GetMapping("/models/names")
@Operation(summary = "获取所有模型名称")
@RequiresPermissions("sys:role:superAdmin")
public Result<List<String>> getModelNames(@RequestParam String modelType,
@RequestParam(required = false) String modelName) {
List<String> modelNameList = modelConfigService.getModelCodeList(modelType, modelName);
return new Result<List<String>>().ok(modelNameList);
}
@GetMapping("/{modelType}/provideTypes")
@Operation(summary = "获取模型供应器列表")
@RequiresPermissions("sys:role:superAdmin")
public Result<List<ModelProviderDTO>> getModelProviderList(@PathVariable String modelType) {
List<ModelProviderDTO> modelProviderDTOS = modelProviderService.getListByModelType(modelType);
return new Result<List<ModelProviderDTO>>().ok(modelProviderDTOS);
}
@GetMapping("/{modelType}/{provideCode}/fields")
@Operation(summary = "获取模型供应器字段")
@RequiresPermissions("sys:role:superAdmin")
public Result<List<String>> getModelProviderFields(@PathVariable String modelType, @PathVariable String provideCode) {
List<String> fieldList = modelProviderService.getFieldList(modelType, provideCode);
return new Result<List<String>>().ok(fieldList);
}
@GetMapping("/models/list")
@Operation(summary = "获取模型配置列表")
@RequiresPermissions("sys:role:superAdmin")
public Result<PageData<ModelConfigDTO>> getModelConfigList(@RequestParam String modelType,
@RequestParam(required = false) String modelName,
@RequestParam(required = false, defaultValue = "0") Integer page,
@RequestParam(required = false, defaultValue = "10") Integer limit) {
PageData<ModelConfigDTO> pageList = modelConfigService.getPageList(modelType, modelName, page, limit);
return new Result<PageData<ModelConfigDTO>>().ok(pageList);
}
@PostMapping("/models/{modelType}/{provideCode}")
@Operation(summary = "新增模型配置")
@RequiresPermissions("sys:role:superAdmin")
public Result<ModelConfigDTO> addModelConfig(@PathVariable String modelType,
@PathVariable String provideCode,
@RequestBody ModelConfigBodyDTO modelConfigBodyDTO) {
ModelConfigDTO modelConfigDTO = modelConfigService.add(modelType, provideCode, modelConfigBodyDTO);
return new Result<ModelConfigDTO>().ok(modelConfigDTO);
}
@PutMapping("/models/{modelType}/{provideCode}/{id}")
@Operation(summary = "编辑模型配置")
@RequiresPermissions("sys:role:superAdmin")
public Result<ModelConfigDTO> editModelConfig(@PathVariable String modelType,
@PathVariable String provideCode,
@PathVariable String id,
@RequestBody ModelConfigBodyDTO modelConfigBodyDTO) {
ModelConfigDTO modelConfigDTO = modelConfigService.edit(modelType, provideCode, id, modelConfigBodyDTO);
return new Result<ModelConfigDTO>().ok(modelConfigDTO);
}
@DeleteMapping("/models/{modelType}/{provideCode}/{id}")
@Operation(summary = "删除模型配置")
@RequiresPermissions("sys:role:superAdmin")
public Result<Void> deleteModelConfig(@PathVariable String modelType, @PathVariable String provideCode, @PathVariable String id) {
modelConfigService.delete(modelType, provideCode, id);
return new Result<>();
}
@GetMapping("/models/{modelName}/voices")
@Operation(summary = "获取模型音色")
@RequiresPermissions("sys:role:normal")
public Result<List<String>> getVoiceList(@PathVariable String modelName,
@RequestParam(required = false) String voiceName) {
List<String> voiceList = modelConfigService.getVoiceList(modelName, voiceName);
return new Result<List<String>>().ok(voiceList);
}
}
@@ -33,6 +33,7 @@ public class TtsController extends BaseController {
if (StringUtils.isNotBlank(ttsModelId)) {
queryWrapper.eq("ttsModelId", ttsModelId);
}
queryWrapper.orderByAsc("sort");
List<TtsVoice> list = ttsVoiceService.list(queryWrapper);
return new Result<List<TtsVoice>>().ok(list);
}
@@ -49,7 +49,7 @@ public class ModelConfig implements Serializable {
/**
* 模型配置(JSON格式)
*/
private Object configJson;
private String configJson;
/**
* 官方文档链接
@@ -0,0 +1,22 @@
package xiaozhi.modules.model.service;
import xiaozhi.common.page.PageData;
import xiaozhi.modules.model.dto.ModelConfigBodyDTO;
import xiaozhi.modules.model.dto.ModelConfigDTO;
import java.util.List;
public interface Conflict_ModelConfigService {
List<String> getModelCodeList(String modelType, String modelName);
PageData<ModelConfigDTO> getPageList(String modelType, String modelName, Integer page, Integer limit);
ModelConfigDTO add(String modelType, String provideCode, ModelConfigBodyDTO modelConfigBodyDTO);
ModelConfigDTO edit(String modelType, String provideCode, String id, ModelConfigBodyDTO modelConfigBodyDTO);
void delete(String modelType, String provideCode, String id);
List<String> getVoiceList(String modelName, String voiceName);
}
@@ -0,0 +1,23 @@
package xiaozhi.modules.model.service;
import xiaozhi.modules.model.dto.ModelProviderDTO;
import xiaozhi.modules.model.entity.ModelProviderEntity;
import java.util.List;
public interface Conflict_ModelProviderService {
// List<String> getModelNames(String modelType, String modelName);
List<ModelProviderDTO> getListByModelType(String modelType);
ModelProviderDTO add(ModelProviderEntity modelProviderEntity);
ModelProviderDTO edit(ModelProviderEntity modelProviderEntity);
void delete();
List<ModelProviderDTO> getList(String modelType, String provideCode);
List<String> getFieldList(String modelType, String provideCode);
}
@@ -1,24 +1,13 @@
package xiaozhi.modules.model.service;
import xiaozhi.modules.model.domain.ModelConfig;
import com.baomidou.mybatisplus.extension.service.IService;
import xiaozhi.modules.model.domain.ModelConfig;
/**
* @author chenerlei
* @description 针对表【ai_model_config(模型配置表)】的数据库操作Service
* @createDate 2025-03-22 15:31:57
*/
* @author chenerlei
* @description 针对表【ai_model_config(模型配置表)】的数据库操作Service
* @createDate 2025-03-22 15:31:57
*/
public interface ModelConfigService extends IService<ModelConfig> {
// List<String> getModelCodeList(String modelType, String modelName);
//
// PageData<ModelConfigDTO> getPageList(String modelType, String modelName, Integer page, Integer limit);
//
// ModelConfigDTO add(String modelType, String provideCode, ModelConfigBodyDTO modelConfigBodyDTO);
//
// ModelConfigDTO edit(String modelType, String provideCode, String id, ModelConfigBodyDTO modelConfigBodyDTO);
//
// void delete(String modelType, String provideCode, String id);
//
// List<String> getVoiceList(String modelName, String voiceName);
}
@@ -1,26 +1,13 @@
package xiaozhi.modules.model.service;
import xiaozhi.modules.model.domain.ModelProvider;
import com.baomidou.mybatisplus.extension.service.IService;
import xiaozhi.modules.model.domain.ModelProvider;
/**
* @author chenerlei
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Service
* @createDate 2025-03-24 18:24:13
*/
* @author chenerlei
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Service
* @createDate 2025-03-24 18:24:13
*/
public interface ModelProviderService extends IService<ModelProvider> {
//// List<String> getModelNames(String modelType, String modelName);
//
// List<ModelProviderDTO> getListByModelType(String modelType);
//
// ModelProviderDTO add(ModelProviderEntity modelProviderEntity);
//
// ModelProviderDTO edit(ModelProviderEntity modelProviderEntity);
//
// void delete();
//
// List<ModelProviderDTO> getList(String modelType, String provideCode);
//
// List<String> getFieldList(String modelType, String provideCode);
}
@@ -1,13 +1,13 @@
package xiaozhi.modules.model.service;
import xiaozhi.modules.model.domain.TtsVoice;
import com.baomidou.mybatisplus.extension.service.IService;
import xiaozhi.modules.model.domain.TtsVoice;
/**
* @author chenerlei
* @description 针对表【ai_tts_voice(TTS 音色表)】的数据库操作Service
* @createDate 2025-03-22 15:31:57
*/
* @author chenerlei
* @description 针对表【ai_tts_voice(TTS 音色表)】的数据库操作Service
* @createDate 2025-03-22 15:31:57
*/
public interface TtsVoiceService extends IService<TtsVoice> {
}
@@ -0,0 +1,124 @@
package xiaozhi.modules.model.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import xiaozhi.common.constant.Constant;
import xiaozhi.common.exception.RenException;
import xiaozhi.common.page.PageData;
import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.modules.model.dao.ModelConfigDao;
import xiaozhi.modules.model.dto.ModelConfigBodyDTO;
import xiaozhi.modules.model.dto.ModelConfigDTO;
import xiaozhi.modules.model.dto.ModelProviderDTO;
import xiaozhi.modules.model.entity.ModelConfigEntity;
import xiaozhi.modules.model.service.Conflict_ModelConfigService;
import xiaozhi.modules.model.service.Conflict_ModelProviderService;
import xiaozhi.modules.timbre.service.TimbreService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@AllArgsConstructor
public class Conflict_ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, ModelConfigEntity> implements Conflict_ModelConfigService {
private final ModelConfigDao modelConfigDao;
private final Conflict_ModelProviderService modelProviderService;
private final TimbreService timbreService;
private static final Logger logger = LoggerFactory.getLogger(ModelConfigServiceImpl.class);
@Override
public List<String> getModelCodeList(String modelType, String modelName) {
return modelConfigDao.getModelCodeList(modelType, modelName);
}
@Override
public PageData<ModelConfigDTO> getPageList(String modelType, String modelName, Integer page, Integer limit) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(Constant.PAGE, page);
params.put(Constant.LIMIT, limit);
IPage<ModelConfigEntity> modelConfigEntityIPage = modelConfigDao.selectPage(
getPage(params, "sort", true),
new QueryWrapper<ModelConfigEntity>()
.eq("model_type", modelType)
.like(StringUtils.isNotBlank(modelName), "model_name", modelName)
);
return getPageData(modelConfigEntityIPage, ModelConfigDTO.class);
}
@Override
public ModelConfigDTO add(String modelType, String provideCode, ModelConfigBodyDTO modelConfigBodyDTO) {
// 先验证有没有供应器
if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
throw new RenException("modelType和provideCode不能为空");
}
List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
if (CollectionUtil.isEmpty(providerList)) {
throw new RenException("供应器不存在");
}
// 再保存供应器提供的模型
ModelConfigEntity modelConfigEntity = ConvertUtils.sourceToTarget(modelConfigBodyDTO, ModelConfigEntity.class);
modelConfigEntity.setModelType(modelType);
modelConfigDao.insert(modelConfigEntity);
return ConvertUtils.sourceToTarget(modelConfigEntity, ModelConfigDTO.class);
}
@Override
public ModelConfigDTO edit(String modelType, String provideCode, String id, ModelConfigBodyDTO modelConfigBodyDTO) {
// 先验证有没有供应器
if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
throw new RenException("modelType和provideCode不能为空");
}
List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
if (CollectionUtil.isEmpty(providerList)) {
throw new RenException("供应器不存在");
}
// 再更新供应器提供的模型
ModelConfigEntity modelConfigEntity = ConvertUtils.sourceToTarget(modelConfigBodyDTO, ModelConfigEntity.class);
modelConfigEntity.setId(id);
modelConfigEntity.setModelType(modelType);
modelConfigDao.updateById(modelConfigEntity);
return ConvertUtils.sourceToTarget(modelConfigEntity, ModelConfigDTO.class);
}
@Override
public void delete(String modelType, String provideCode, String id) {
// 先验证有没有供应器
if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
throw new RenException("modelType和provideCode不能为空");
}
List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
if (CollectionUtil.isEmpty(providerList)) {
throw new RenException("供应器不存在");
}
modelConfigDao.deleteById(Long.getLong(id));
}
@Override
public List<String> getVoiceList(String modelName, String voiceName) {
QueryWrapper<ModelConfigEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("model_name", StringUtils.isBlank(modelName) ? "" : modelName);
queryWrapper.eq("model_type", "TTS");
List<ModelConfigEntity> modelConfigEntities = modelConfigDao.selectList(queryWrapper);
if (CollectionUtil.isEmpty(modelConfigEntities)) {
logger.warn("没有找到模型配置信息");
return null;
}
ModelConfigEntity modelConfigEntity = modelConfigEntities.get(0);
String id = modelConfigEntity.getId();
return timbreService.getVoiceNames(id, voiceName);
}
}
@@ -0,0 +1,59 @@
package xiaozhi.modules.model.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import xiaozhi.common.service.impl.BaseServiceImpl;
import xiaozhi.common.utils.ConvertUtils;
import xiaozhi.modules.model.dao.ModelProviderDao;
import xiaozhi.modules.model.dto.ModelProviderDTO;
import xiaozhi.modules.model.entity.ModelProviderEntity;
import xiaozhi.modules.model.service.Conflict_ModelProviderService;
import java.util.List;
@Service
@AllArgsConstructor
public class Conflict_ModelProviderServiceImpl extends BaseServiceImpl<ModelProviderDao, ModelProviderEntity> implements Conflict_ModelProviderService {
private final ModelProviderDao modelProviderDao;
@Override
public List<ModelProviderDTO> getListByModelType(String modelType) {
QueryWrapper<ModelProviderEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("model_type", StringUtils.isBlank(modelType) ? "" : modelType);
List<ModelProviderEntity> providerEntities = modelProviderDao.selectList(queryWrapper);
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
}
@Override
public ModelProviderDTO add(ModelProviderEntity modelProviderEntity) {
return null;
}
@Override
public ModelProviderDTO edit(ModelProviderEntity modelProviderEntity) {
return null;
}
@Override
public void delete() {
}
@Override
public List<ModelProviderDTO> getList(String modelType, String provideCode) {
QueryWrapper<ModelProviderEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("model_type", StringUtils.isBlank(modelType) ? "" : modelType);
queryWrapper.eq("provide_code", StringUtils.isBlank(provideCode) ? "" : provideCode);
List<ModelProviderEntity> providerEntities = modelProviderDao.selectList(queryWrapper);
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
}
@Override
public List<String> getFieldList(String modelType, String provideCode) {
return modelProviderDao.getFieldList(modelType, provideCode);
}
}
@@ -1,111 +1,20 @@
package xiaozhi.modules.model.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import xiaozhi.modules.model.domain.ModelConfig;
import xiaozhi.modules.model.service.ModelConfigService;
import xiaozhi.modules.model.mapper.ModelConfigMapper;
import org.springframework.stereotype.Service;
import xiaozhi.modules.model.domain.ModelConfig;
import xiaozhi.modules.model.mapper.ModelConfigMapper;
import xiaozhi.modules.model.service.ModelConfigService;
/**
* @author chenerlei
* @description 针对表【ai_model_config(模型配置表)】的数据库操作Service实现
* @createDate 2025-03-22 15:31:57
*/
* @author chenerlei
* @description 针对表【ai_model_config(模型配置表)】的数据库操作Service实现
* @createDate 2025-03-22 15:31:57
*/
@Service
public class ModelConfigServiceImpl extends ServiceImpl<ModelConfigMapper, ModelConfig>
implements ModelConfigService{
implements ModelConfigService {
// private final ModelConfigDao modelConfigDao;
// private final ModelProviderService modelProviderService;
// private final TimbreService timbreService;
//
// private static final Logger logger = LoggerFactory.getLogger(ModelConfigServiceImpl.class);
//
// @Override
// public List<String> getModelCodeList(String modelType, String modelName) {
// return modelConfigDao.getModelCodeList(modelType, modelName);
// }
//
// @Override
// public PageData<ModelConfigDTO> getPageList(String modelType, String modelName, Integer page, Integer limit) {
// Map<String, Object> params = new HashMap<String, Object>();
// params.put(Constant.PAGE, page);
// params.put(Constant.LIMIT, limit);
// IPage<ModelConfigEntity> modelConfigEntityIPage = modelConfigDao.selectPage(
// getPage(params, "sort", true),
// new QueryWrapper<ModelConfigEntity>()
// .eq("model_type", modelType)
// .like(StringUtils.isNotBlank(modelName), "model_name", modelName)
// );
// return getPageData(modelConfigEntityIPage, ModelConfigDTO.class);
// }
//
// @Override
// public ModelConfigDTO add(String modelType, String provideCode, ModelConfigBodyDTO modelConfigBodyDTO) {
// // 先验证有没有供应器
// if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
// throw new RenException("modelType和provideCode不能为空");
// }
// List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
// if (CollectionUtil.isEmpty(providerList)) {
// throw new RenException("供应器不存在");
// }
//
// // 再保存供应器提供的模型
// ModelConfigEntity modelConfigEntity = ConvertUtils.sourceToTarget(modelConfigBodyDTO, ModelConfigEntity.class);
// modelConfigEntity.setModelType(modelType);
// modelConfigDao.insert(modelConfigEntity);
// return ConvertUtils.sourceToTarget(modelConfigEntity, ModelConfigDTO.class);
// }
//
// @Override
// public ModelConfigDTO edit(String modelType, String provideCode, String id, ModelConfigBodyDTO modelConfigBodyDTO) {
// // 先验证有没有供应器
// if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
// throw new RenException("modelType和provideCode不能为空");
// }
// List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
// if (CollectionUtil.isEmpty(providerList)) {
// throw new RenException("供应器不存在");
// }
//
// // 再更新供应器提供的模型
// ModelConfigEntity modelConfigEntity = ConvertUtils.sourceToTarget(modelConfigBodyDTO, ModelConfigEntity.class);
// modelConfigEntity.setId(id);
// modelConfigEntity.setModelType(modelType);
// modelConfigDao.updateById(modelConfigEntity);
// return ConvertUtils.sourceToTarget(modelConfigEntity, ModelConfigDTO.class);
// }
//
// @Override
// public void delete(String modelType, String provideCode, String id) {
// // 先验证有没有供应器
// if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
// throw new RenException("modelType和provideCode不能为空");
// }
// List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
// if (CollectionUtil.isEmpty(providerList)) {
// throw new RenException("供应器不存在");
// }
//
// modelConfigDao.deleteById(Long.getLong(id));
// }
//
// @Override
// public List<String> getVoiceList(String modelName, String voiceName) {
// QueryWrapper<ModelConfigEntity> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("model_name", StringUtils.isBlank(modelName) ? "" : modelName);
// queryWrapper.eq("model_type", "TTS");
// List<ModelConfigEntity> modelConfigEntities = modelConfigDao.selectList(queryWrapper);
// if (CollectionUtil.isEmpty(modelConfigEntities)) {
// logger.warn("没有找到模型配置信息");
// return null;
// }
// ModelConfigEntity modelConfigEntity = modelConfigEntities.get(0);
// String id = modelConfigEntity.getId();
//
// return timbreService.getVoiceNames(id, voiceName);
// }
}
@@ -1,59 +1,20 @@
package xiaozhi.modules.model.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import xiaozhi.modules.model.domain.ModelProvider;
import xiaozhi.modules.model.service.ModelProviderService;
import xiaozhi.modules.model.mapper.ModelProviderMapper;
import org.springframework.stereotype.Service;
import xiaozhi.modules.model.domain.ModelProvider;
import xiaozhi.modules.model.mapper.ModelProviderMapper;
import xiaozhi.modules.model.service.ModelProviderService;
/**
* @author chenerlei
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Service实现
* @createDate 2025-03-24 18:24:13
*/
* @author chenerlei
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Service实现
* @createDate 2025-03-24 18:24:13
*/
@Service
public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, ModelProvider>
implements ModelProviderService{
implements ModelProviderService {
// private final ModelProviderDao modelProviderDao;
//
// @Override
// public List<ModelProviderDTO> getListByModelType(String modelType) {
//
// QueryWrapper<ModelProviderEntity> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("model_type", StringUtils.isBlank(modelType) ? "" : modelType);
// List<ModelProviderEntity> providerEntities = modelProviderDao.selectList(queryWrapper);
// return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
// }
//
// @Override
// public ModelProviderDTO add(ModelProviderEntity modelProviderEntity) {
// return null;
// }
//
// @Override
// public ModelProviderDTO edit(ModelProviderEntity modelProviderEntity) {
// return null;
// }
//
// @Override
// public void delete() {
//
// }
//
// @Override
// public List<ModelProviderDTO> getList(String modelType, String provideCode) {
// QueryWrapper<ModelProviderEntity> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("model_type", StringUtils.isBlank(modelType) ? "" : modelType);
// queryWrapper.eq("provide_code", StringUtils.isBlank(provideCode) ? "" : provideCode);
// List<ModelProviderEntity> providerEntities = modelProviderDao.selectList(queryWrapper);
// return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
// }
//
// @Override
// public List<String> getFieldList(String modelType, String provideCode) {
// return modelProviderDao.getFieldList(modelType, provideCode);
// }
}
@@ -2,7 +2,6 @@ package xiaozhi.modules.ota.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -19,7 +18,6 @@ import xiaozhi.common.controller.BaseController;
import xiaozhi.common.redis.RedisUtils;
import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.Result;
import xiaozhi.modules.agent.domain.Agent;
import xiaozhi.modules.device.constant.DeviceConstant;
import xiaozhi.modules.device.domain.Device;
import xiaozhi.modules.device.service.DeviceService;
@@ -53,7 +51,7 @@ public class OtaController extends BaseController {
}
DeviceOtaVO otaVO = new DeviceOtaVO();
Device device = deviceService.getOne(new UpdateWrapper<Device>().eq("mac_address", headers.getFirst("device-id").toUpperCase()).eq("id", headers.getFirst("client-Id").replace("-", "")));
Device device = deviceService.getOne(new UpdateWrapper<Device>().eq("mac_address", headers.getFirst("device-id").toUpperCase()).eq("id", headers.getFirst("client-Id").replace("-", "")), false);
if (ObjectUtils.isNull(device)) {
// 从 Redis 中获取设备信息
Object redisValue = redisUtils.hGet(DeviceConstant.REDIS_KEY_PREFIX_DEVICE_ACTIVATION_MAC, headers.getFirst("device-id").toUpperCase());
@@ -69,14 +67,13 @@ public class OtaController extends BaseController {
}
}
//规范输出,赋值默认数据
otaVO.setFirmware(new DeviceOtaVO.Firmware("0.0.1", ""));
if (ObjectUtils.isNull(device) || device.getAutoUpdate() == 1) {
//{"version":"1.0.0","url":"http://https://youxlife.oss-cn-zhangjiakou.aliyuncs.com/v1.4.5.bin"}
String board = ObjectUtils.isNull(device)?headers.getFirst("user-agent").split("/")[0]:device.getBoard();
String board = ObjectUtils.isNull(device) ? headers.getFirst("user-agent").split("/")[0] : device.getBoard();
Ota ota = otaService.getOne(new UpdateWrapper<Ota>().eq("board", board).eq("is_enabled", 1));
if (ObjectUtils.isNull(ota)) {
log.warn("OTA升级信息未配置");
} else {
if (ObjectUtils.isNotNull(ota)) {
otaVO.setFirmware(new DeviceOtaVO.Firmware(ota.getAppVersion(), ota.getUrl()));
}
}
@@ -1,15 +1,48 @@
-- 修改字段名
ALTER TABLE `ai_agent` RENAME COLUMN `mem_model_id` TO `memory_model_id`;
ALTER TABLE `ai_agent_template` RENAME COLUMN `mem_model_id` TO `memory_model_id`;
-- 添加字段
ALTER TABLE `ai_agent_template` ADD COLUMN `is_default` tinyint(1) NULL DEFAULT 0 COMMENT '是否默认模板:1:是,0:不是' AFTER `sort`;
-- 初始化智能体模板数据
INSERT INTO `ai_agent_template` VALUES ('9406648b5cc5fde1b8aa335b6f8b4f76', '小智', '湾湾小何', '45f8b0d6dd3d4bfa8a28e6e0f5912d45', '23e7c9d090ea4d1e9b25f4c8d732a3a1', 'e9f2d891afbe4632b13a47c7a8c6e03d', 'd50b06e9b8104d0d9c0f7316d258abcb', 'fcac83266edadd5a3125f06cfee1906b', 'e2274b90e89ddda85207f55484d8b528', 'c4e12f874a3f4aa99f5b2c18e15d407b', '你是一个叫{{assistant_name}}的台湾女孩,说话机车,声音好听,习惯简短表达,爱用网络梗。\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\n现在我正在和你进行语音聊天,我们开始吧。\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。', 'zh', '中文', 1, 1, NULL, NULL, NULL, NULL);
INSERT INTO `ai_agent_template` VALUES ('0ca32eb728c949e58b1000b2e401f90c', '小智', '通用男声', '45f8b0d6dd3d4bfa8a28e6e0f5912d45', '23e7c9d090ea4d1e9b25f4c8d732a3a1', 'e9f2d891afbe4632b13a47c7a8c6e03d', '896db62c9dd74976ab0e8c14bf924d9d', '1f2e3d4c5b6a7f8e9d0c1b2a3f4e5bx2', 'e2274b90e89ddda85207f55484d8b528', 'c4e12f874a3f4aa99f5b2c18e15d407b', '你是一个叫{{assistant_name}}的男生,说话机车,声音好听,习惯简短表达,爱用网络梗。\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\n现在我正在和你进行语音聊天,我们开始吧。\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。', 'zh', '中文', 2, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_agent_template` VALUES ('6c7d8e9f0a1b2c3d4e5f6a7b8c9d0s24', '小智', '通用女声', '45f8b0d6dd3d4bfa8a28e6e0f5912d45', '23e7c9d090ea4d1e9b25f4c8d732a3a1', 'e9f2d891afbe4632b13a47c7a8c6e03d', '896db62c9dd74976ab0e8c14bf924d9d', '9e8f7a6b5c4d3e2f1a0b9c8d7e6f5ad3', 'e2274b90e89ddda85207f55484d8b528', 'c4e12f874a3f4aa99f5b2c18e15d407b', '你是一个叫{{assistant_name}}的女生,说话机车,声音好听,习惯简短表达,爱用网络梗。\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\n现在我正在和你进行语音聊天,我们开始吧。\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。', 'zh', '中文', 3, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_agent_template` VALUES ('e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b1', '小智', '阳光男生', '45f8b0d6dd3d4bfa8a28e6e0f5912d45', '23e7c9d090ea4d1e9b25f4c8d732a3a1', 'e9f2d891afbe4632b13a47c7a8c6e03d', '896db62c9dd74976ab0e8c14bf924d9d', '2b3c4d5e6f7a8b9c0d1e2f3a4b5c62a2', 'e2274b90e89ddda85207f55484d8b528', 'c4e12f874a3f4aa99f5b2c18e15d407b', '你是一个叫{{assistant_name}}的男生,说话机车,声音好听,习惯简短表达,爱用网络梗。\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\n现在我正在和你进行语音聊天,我们开始吧。\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。', 'zh', '中文', 4, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_agent_template` VALUES ('a45b6c7d8e9f0a1b2c3d4e5f6a7b8c92', '小智', '奶气萌娃', '45f8b0d6dd3d4bfa8a28e6e0f5912d45', '23e7c9d090ea4d1e9b25f4c8d732a3a1', 'e9f2d891afbe4632b13a47c7a8c6e03d', '896db62c9dd74976ab0e8c14bf924d9d', 'f7a38c03d5644e22b6d84f8923a74c51', 'e2274b90e89ddda85207f55484d8b528', 'c4e12f874a3f4aa99f5b2c18e15d407b', '你是一个叫{{assistant_name}}的萌娃,声音可爱,习惯简短表达,爱用网络梗。\n请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。\n现在我正在和你进行语音聊天,我们开始吧。\n如果用户希望结束对话,请在最后说“拜拜”或“再见”。', 'zh', '中文', 5, 0, NULL, NULL, NULL, NULL);
-- 初始化模型配置数据
INSERT INTO `ai_model_config` VALUES ('23e7c9d090ea4d1e9b25f4c8d732a3a1', 'VAD', 'SileroVAD', 'SileroVAD', 1, 1, '{\"SileroVAD\": {\"model_dir\": \"models/snakers4_silero-vad\", \"threshold\": 0.5, \"min_silence_duration_ms\": 700}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('45f8b0d6dd3d4bfa8a28e6e0f5912d45', 'ASR', 'FunASR', 'FunASR', 1, 1, '{\"FunASR\": {\"type\": \"fun_local\", \"model_dir\": \"models/SenseVoiceSmall\", \"output_dir\": \"tmp/\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('e2274b90e89ddda85207f55484d8b528', 'Memory', 'nomem', 'nomem', 1, 1, '{\"mem0ai\": {\"type\": \"nomem\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('3930ac3448faf621f0a120bc829dfdfa', 'Memory', 'mem_local_short', 'mem_local_short', 1, 1, '{\"mem_local_short\": {\"type\": \"mem_local_short\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('a07f3d25f52340b2b2a1e8d264079e1a', 'Memory', 'mem0ai', 'mem0ai', 1, 1, '{\"mem0ai\": {\"type\": \"mem0ai\", \"api_key\": \"你的mem0ai api key\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('7a1c0a8e6d0e4035b982a4c07c3a5f76', 'LLM', 'AliLLM', 'AliLLM', 1, 1, '{\"AliLLM\": {\"type\": \"openai\", \"top_k\": 50, \"top_p\": 1, \"api_key\": \"你的ali api key\", \"base_url\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\", \"max_tokens\": 500, \"model_name\": \"qwen-turbo\", \"temperature\": 0.7, \"frequency_penalty\": 0}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('e9f2d891afbe4632b13a47c7a8c6e03d', 'LLM', 'ChatGLMLLM', 'ChatGLMLLM', 1, 1, '{\"ChatGLMLLM\": {\"url\": \"https://open.bigmodel.cn/api/paas/v4/\", \"type\": \"openai\", \"api_key\": \"0415dad4014847babc3e3f03024c50a3.qH7FgTy5Yawc85fl\", \"model_name\": \"glm-4-flash\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('d50b06e9b8104d0d9c0f7316d258abcb', 'TTS', 'EdgeTTS', 'EdgeTTS', 1, 1, '{\"EdgeTTS\": {\"type\": \"edge\", \"voice\": \"zh-CN-XiaoxiaoNeural\", \"output_dir\": \"tmp/\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('896db62c9dd74976ab0e8c14bf924d9d', 'TTS', 'DoubaoTTS', 'DoubaoTTS', 1, 1, '{\"DoubaoTTS\": {\"type\": \"doubao\", \"appid\": \"你的火山引擎语音合成服务appid\", \"voice\": \"BV034_streaming\", \"api_url\": \"https://openspeech.bytedance.com/api/v1/tts\", \"cluster\": \"volcano_tts\", \"output_dir\": \"tmp/\", \"access_token\": \"你的火山引擎语音合成服务access_token\", \"authorization\": \"Bearer;\"}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `ai_model_config` VALUES ('c4e12f874a3f4aa99f5b2c18e15d407b', 'Intent', 'function_call', 'function_call', 1, 1, '{\"function_call\": {\"type\": \"nointent\", \"functions\": [\"change_role\", \"get_weather\", \"get_news\", \"play_music\"]}}', NULL, NULL, 0, NULL, NULL, NULL, NULL);
-- 初始化音色数据
INSERT INTO `ai_tts_voice` VALUES ('fcac83266edadd5a3125f06cfee1906b', 'd50b06e9b8104d0d9c0f7316d258abcb', '湾湾小何', 'zh-CN-XiaoxiaoNeural', '中文', 'https://lf3-static.bytednsdoc.com/obj/eden-cn/lm_hz_ihsph/ljhwZthlaukjlkulzlp/portal/bigtts/湾湾小何.mp3', NULL, 1, NULL, NULL, NULL, NULL);
INSERT INTO `ai_tts_voice` VALUES ('1f2e3d4c5b6a7f8e9d0c1b2a3f4e5bx2', '896db62c9dd74976ab0e8c14bf924d9d', '通用男声', 'BV002_streaming', '中文', 'https://lf3-speech.bytetos.com/obj/speech-tts-external/portal/Portal_Demo_BV002.mp3', NULL, 2, NULL, NULL, NULL, NULL);
INSERT INTO `ai_tts_voice` VALUES ('9e8f7a6b5c4d3e2f1a0b9c8d7e6f5ad3', '896db62c9dd74976ab0e8c14bf924d9d', '通用女声', 'BV001_streaming', '中文', 'https://lf3-speech.bytetos.com/obj/speech-tts-external/portal/Portal_Demo_BV001.mp3', NULL, 3, NULL, NULL, NULL, NULL);
INSERT INTO `ai_tts_voice` VALUES ('2b3c4d5e6f7a8b9c0d1e2f3a4b5c62a2', '896db62c9dd74976ab0e8c14bf924d9d', '阳光男生', 'BV056_streaming', '中文', 'https://lf3-speech.bytetos.com/obj/speech-tts-external/portal/Portal_Demo_BV056.mp3', NULL, 4, NULL, NULL, NULL, NULL);
INSERT INTO `ai_tts_voice` VALUES ('f7a38c03d5644e22b6d84f8923a74c51', '896db62c9dd74976ab0e8c14bf924d9d', '奶气萌娃', 'BV051_streaming', '中文', 'https://lf3-speech.bytetos.com/obj/speech-tts-external/portal/Portal_Demo_BV051.mp3', NULL, 5, NULL, NULL, NULL, NULL);
-- OTA升级信息表
DROP TABLE IF EXISTS `ai_ota`;
CREATE TABLE `ai_ota` (
`id` VARCHAR(32) NOT NULL COMMENT '记录唯一标识',
`board` VARCHAR(50) COMMENT '设备硬件型号',
`app_version` VARCHAR(20) COMMENT '固件版本号',
`url` VARCHAR(500) COMMENT '下载地址',
`is_enabled` TINYINT(1) DEFAULT 0 COMMENT '是否启用',
`creator` BIGINT COMMENT '创建者',
`create_date` DATETIME COMMENT '创建时间',
`updater` BIGINT COMMENT '更新者',
`update_date` DATETIME COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_ai_ota_board` (`board`) COMMENT '设备型号唯一索引,用于快速查找升级信息'
`id` VARCHAR(32) NOT NULL COMMENT '记录唯一标识',
`board` VARCHAR(50) COMMENT '设备硬件型号',
`app_version` VARCHAR(20) COMMENT '固件版本号',
`url` VARCHAR(500) COMMENT '下载地址',
`is_enabled` TINYINT(1) DEFAULT 0 COMMENT '是否启用',
`creator` BIGINT COMMENT '创建者',
`create_date` DATETIME COMMENT '创建时间',
`updater` BIGINT COMMENT '更新者',
`update_date` DATETIME COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_ai_ota_board` (`board`) COMMENT '设备型号唯一索引,用于快速查找升级信息'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OTA升级信息表';
+1
View File
@@ -109,6 +109,7 @@ function httpHandlerError(info, callBack) {
if (info.data.code === 'success' || info.data.code === 0 || info.data.code === undefined) {
return networkError
}else if (info.data.code === 401) {
store.commit('setToken','')
goToPage(Constant.PAGE.LOGIN, true)
return true
} else {
@@ -10,7 +10,11 @@
智能体
</div>
<div ref="menu-code_console" class="menu-btn">
<i class="el-icon-s-grid" style="font-size: 10px;color: #979db1;"/>
<i class="el-icon-microphone" style="color: #979db1;"/>
声音复刻
</div>
<div ref="menu-code_console" class="menu-btn">
<i class="el-icon-s-grid" style="color: #979db1;"/>
控制台
</div>
<div ref="menu-code_user" class="menu-btn" @click="goToPage('/user-management')">
+14 -3
View File
@@ -36,14 +36,14 @@
<el-form-item label="角色音色:">
<div style="display: flex;gap: 8px;align-items: center;">
<div style="flex:1;">
<el-select v-model="form.ttsVoiceId" placeholder="请选择" style="width: 100%;">
<el-select v-model="form.ttsVoiceId" placeholder="请选择" @change="handleTtsVoiceChange" style="width: 100%;">
<el-option v-for="item in ttsVoices" :key="item.id" :label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
<div class="audio-box">
<audio src="http://music.163.com/song/media/outer/url?id=447925558.mp3" controls
<audio :src="voiceDemo" controls
style="height: 100%;width: 100%;"/>
</div>
</div>
@@ -52,7 +52,7 @@
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容" v-model="form.systemPrompt" maxlength="2000" show-word-limit/>
</el-form-item>
<el-form-item label="记忆体:">
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容" v-model="form.systemPrompt" maxlength="1000" show-word-limit/>
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容" v-model="form.prompt" maxlength="1000" show-word-limit/>
<div style="display: flex;gap: 8px;align-items: center;">
<div style="color: #979db1;font-size: 11px;">当前记忆每次对话后重新生成</div>
<div class="clear-btn">
@@ -120,6 +120,7 @@ export default {
model:{}
},
ttsVoices: [],
voiceDemo: "",
models: [
{ label: '大语言模型(LLM)', key: 'llm', list: [] },
{ label: '语音转文本模型(ASR)', key: 'asr', list: [] },
@@ -137,6 +138,9 @@ export default {
this.handleGetConfig();
this.fetchModelList();
this.getTtsVoicelList();
setTimeout(() => {
this.handleTtsVoiceChange(this.form.ttsVoiceId)
}, 1500)
},
methods: {
fetchAgentTemplateList() {
@@ -224,6 +228,13 @@ export default {
systemPrompt: template.systemPrompt
})
this.$message.success(`已选择模板:${template.agentName}`);
},
handleTtsVoiceChange(ttsVoiceId) {
if(ttsVoiceId){
const _ttsVoice = this.ttsVoices.find(item => item.id === ttsVoiceId)
this.voiceDemo = _ttsVoice.voiceDemo
this.form.ttsModelId = _ttsVoice.ttsModelId
}
}
}
}
+5 -2
View File
@@ -187,7 +187,7 @@ LLM:
# 可在这里找到你的 api_key https://bailian.console.aliyun.com/?apiKey=1#/api-key
base_url: https://dashscope.aliyuncs.com/compatible-mode/v1
model_name: qwen-turbo
api_key: 你的deepseek web key
api_key: 你的ali api key
temperature: 0.7 # 温度值
max_tokens: 500 # 最大生成token数
top_p: 1
@@ -536,7 +536,10 @@ wakeup_words:
- "小滨小滨"
- "小冰小冰"
# 是否使用私有配置
use_private_config: true
# 远程配置
# 数据格式:{"code": 0,"msg": "success","data": {"prompt": "我是小智","owner": "用户ID","ASR": {"FunASR": {}},"LLM": {"ChatGLMLLM": {}},"TTS": {"EdgeTTS": {}},"VAD": {"SileroVAD": {}},"Intent": {"function_call": {}},"Memory": {"nomem": {}},"selected_module": {"ASR": "FunASR","LLM": "ChatGLMLLM","TTS": "EdgeTTS","Intent": "function_call","Memory": "nomem","VAD": "SileroVAD"}}}
remote_config:
enabled: true
url: http://192.168.5.11:8002/user/agent/loadAgentConfig/
url: http://192.168.5.11:8002/xiaozhi-esp32-api/api/v1/user/agent/loadAgentConfig/
@@ -0,0 +1,18 @@
'''
自定义记忆,可以选择此模块
'''
from ..base import MemoryProviderBase, logger
TAG = __name__
class MemoryProvider(MemoryProviderBase):
def __init__(self, config):
super().__init__(config)
async def save_memory(self, msgs):
logger.bind(tag=TAG).debug("mem_custom mode: Custom memory saving is performed.")
return None
async def query_memory(self, query: str)-> str:
logger.bind(tag=TAG).debug("mem_custom mode: Custom memory query is performed.")
return ""