diff --git a/Dockerfile-server-base b/Dockerfile-server-base
index ab232a17..70429ab1 100644
--- a/Dockerfile-server-base
+++ b/Dockerfile-server-base
@@ -4,7 +4,9 @@ FROM python:3.10-slim
# 安装系统依赖
RUN apt-get update && \
- apt-get install -y --no-install-recommends libopus0 ffmpeg && \
+ apt-get install -y --no-install-recommends libopus0 ffmpeg locales && \
+ sed -i '/zh_CN.UTF-8/s/^# //g' /etc/locale.gen && \
+ locale-gen && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
@@ -14,6 +16,12 @@ RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ && \
pip config set global.timeout 120 && \
pip config set install.retries 5
+# 设置环境变量以确保正确的字符编码
+ENV LANG=zh_CN.UTF-8 \
+ LC_ALL=zh_CN.UTF-8 \
+ LANGUAGE=zh_CN:zh \
+ PYTHONIOENCODING=utf-8
+
WORKDIR /opt/xiaozhi-esp32-server
# 复制requirements.txt
diff --git a/docs/Deployment.md b/docs/Deployment.md
index 55fef3c3..aff1287e 100644
--- a/docs/Deployment.md
+++ b/docs/Deployment.md
@@ -80,7 +80,7 @@ xiaozhi-server
打开命令行工具,使用`终端`或`命令行`工具 进入到你的`xiaozhi-server`,执行以下命令
```
-docker-compose up -d
+docker compose up -d
```
执行完后,再执行以下命令,查看日志信息。
diff --git a/docs/FAQ.md b/docs/FAQ.md
index 844ee3d4..1e237921 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -76,8 +76,9 @@ VAD:
3、[如何开启视觉模型实现拍照识物](./mcp-vision-integration.md)
4、[如何部署MCP接入点](./mcp-endpoint-enable.md)
5、[如何接入MCP接入点](./mcp-endpoint-integration.md)
-6、[如何开启声纹识别](./voiceprint-integration.md)
-10、[新闻插件源配置指南](./newsnow_plugin_config.md)
+6、[MCP方法如何获取设备信息](./mcp-get-device-info.md)
+7、[如何开启声纹识别](./voiceprint-integration.md)
+8、[新闻插件源配置指南](./newsnow_plugin_config.md)
### 11、语音克隆、本地语音部署相关教程
1、[如何在智控台克隆音色](./huoshan-streamTTS-voice-cloning.md)
diff --git a/docs/docker-build.md b/docs/docker-build.md
index 45102a7d..118ed1c9 100644
--- a/docs/docker-build.md
+++ b/docs/docker-build.md
@@ -17,5 +17,5 @@ docker build -t xiaozhi-esp32-server:web_latest -f ./Dockerfile-web .
# 编译完成后,可以使用docker-compose启动项目
# docker-compose.yml你需要修改成自己编译的镜像版本
cd main/xiaozhi-server
-docker-compose up -d
+docker compose up -d
```
diff --git a/docs/mcp-get-device-info.md b/docs/mcp-get-device-info.md
new file mode 100644
index 00000000..bf479958
--- /dev/null
+++ b/docs/mcp-get-device-info.md
@@ -0,0 +1,40 @@
+# MCP 方法如何获取设备信息
+
+本教程将指导你如何使用MCP方法获取设备信息。
+
+第一步:自定义你的`agent-base-prompt.txt`文件
+
+把xiaozhi-server目录的`agent-base-prompt.txt`文件内容复制到你的`data`目录下,并重命名为`.agent-base-prompt.txt`。
+
+第二步:修改`data/.agent-base-prompt.txt`文件,找到``标签,在标签内容中添加以下代码内容:
+```
+- **设备ID:** {{device_id}}
+```
+
+添加完成后,你的`data/.agent-base-prompt.txt`文件的``标签内容大致如下:
+```
+
+【重要!以下信息已实时提供,无需调用工具查询,请直接使用:】
+- **设备ID:** {{device_id}}
+- **当前时间:** {{current_time}}
+- **今天日期:** {{today_date}} ({{today_weekday}})
+- **今天农历:** {{lunar_date}}
+- **用户所在城市:** {{local_address}}
+- **当地未来7天天气:** {{weather_info}}
+
+```
+
+第三步:修改`data/.config.yaml`文件,找到`agent-base-prompt`配置,修改前内容如下:
+```
+prompt_template: agent-base-prompt.txt
+```
+修改成
+```
+prompt_template: data/.agent-base-prompt.txt
+```
+
+第四步:重启你的xiaozhi-server服务。
+
+第五步:在你的mcp方法增加名称为`device_id`,类型为`string`,描述为`设备ID`的参数。
+
+第六步:重新唤醒小智,让他调用mcp方法,查看你的mcp方法是否可以获取`设备ID`。
diff --git a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java
index 83bb5c18..4e4dc245 100644
--- a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java
+++ b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java
@@ -151,6 +151,11 @@ public interface Constant {
*/
String VOICE_CLONE_HUOSHAN_DOUBLE_STREAM = "huoshan_double_stream";
+ /**
+ * RAG配置类型
+ */
+ String RAG_CONFIG_TYPE = "RAG";
+
enum SysBaseParam {
/**
* ICP备案号
@@ -294,7 +299,7 @@ public interface Constant {
/**
* 版本号
*/
- public static final String VERSION = "0.8.5";
+ public static final String VERSION = "0.8.7";
/**
* 无效固件URL
diff --git a/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java b/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java
index 82b16ec5..b8525e63 100644
--- a/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java
+++ b/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java
@@ -119,10 +119,6 @@ public interface ErrorCode {
int VOICEPRINT_UNREGISTER_PROCESS_ERROR = 10090; // 声纹注销处理失败
int VOICEPRINT_IDENTIFY_REQUEST_ERROR = 10091; // 声纹识别请求失败
- // 设备相关错误码
- int MAC_ADDRESS_ALREADY_EXISTS = 10161; // Mac地址已存在
- // 模型相关错误码
- int MODEL_PROVIDER_NOT_EXIST = 10162; // 供应器不存在
int LLM_NOT_EXIST = 10092; // 设置的LLM不存在
int MODEL_REFERENCED_BY_AGENT = 10093; // 该模型配置已被智能体引用,无法删除
int LLM_REFERENCED_BY_INTENT = 10094; // 该LLM模型已被意图识别配置引用,无法删除
@@ -198,4 +194,19 @@ public interface ErrorCode {
int VOICE_CLONE_PREFIX = 10158; // 复刻音色前缀
int VOICE_ID_ALREADY_EXISTS = 10159; // 音色ID已存在
int VOICE_CLONE_HUOSHAN_VOICE_ID_ERROR = 10160; // 火山引擎音色ID格式错误
+
+ // 设备相关错误码
+ int MAC_ADDRESS_ALREADY_EXISTS = 10161; // Mac地址已存在
+ // 模型相关错误码
+ int MODEL_PROVIDER_NOT_EXIST = 10162; // 供应器不存在
+
+ // 知识库相关错误码
+ int Knowledge_Base_RECORD_NOT_EXISTS = 10163; // 知识库记录不存在
+ int RAG_CONFIG_NOT_FOUND = 10164; // RAG配置未找到
+ int RAG_CONFIG_TYPE_ERROR = 10165; // RAG配置类型错误
+ int RAG_DEFAULT_CONFIG_NOT_FOUND = 10166; // 默认RAG配置未找到
+ int RAG_API_ERROR = 10167; // RAG配置缺少必要参数
+ int UPLOAD_FILE_ERROR = 10168; // 上传文件失败
+ int NO_PERMISSION = 10169; // 没有权限
+ int KNOWLEDGE_BASE_NAME_EXISTS = 10170; // 同名知识库已存在
}
diff --git a/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java b/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java
index a6b33b62..95add2f0 100644
--- a/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java
+++ b/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java
@@ -32,13 +32,23 @@ public class FieldMetaObjectHandler implements MetaObjectHandler {
// 创建者
strictInsertFill(metaObject, CREATOR, Long.class, user.getId());
- // 创建时间
- strictInsertFill(metaObject, CREATE_DATE, Date.class, date);
+ // 创建时间 - 支持createDate和createdAt两种字段名
+ if (metaObject.hasSetter(CREATE_DATE)) {
+ strictInsertFill(metaObject, CREATE_DATE, Date.class, date);
+ }
+ if (metaObject.hasSetter("createdAt")) {
+ strictInsertFill(metaObject, "createdAt", Date.class, date);
+ }
// 更新者
strictInsertFill(metaObject, UPDATER, Long.class, user.getId());
- // 更新时间
- strictInsertFill(metaObject, UPDATE_DATE, Date.class, date);
+ // 更新时间 - 支持updateDate和updatedAt两种字段名
+ if (metaObject.hasSetter(UPDATE_DATE)) {
+ strictInsertFill(metaObject, UPDATE_DATE, Date.class, date);
+ }
+ if (metaObject.hasSetter("updatedAt")) {
+ strictInsertFill(metaObject, "updatedAt", Date.class, date);
+ }
// 数据标识
strictInsertFill(metaObject, DATA_OPERATION, String.class, Constant.DataOperation.INSERT.getValue());
@@ -46,10 +56,17 @@ public class FieldMetaObjectHandler implements MetaObjectHandler {
@Override
public void updateFill(MetaObject metaObject) {
+ Date date = new Date();
+
// 更新者
strictUpdateFill(metaObject, UPDATER, Long.class, SecurityUser.getUserId());
- // 更新时间
- strictUpdateFill(metaObject, UPDATE_DATE, Date.class, new Date());
+ // 更新时间 - 支持updateDate和updatedAt两种字段名
+ if (metaObject.hasSetter(UPDATE_DATE)) {
+ strictUpdateFill(metaObject, UPDATE_DATE, Date.class, date);
+ }
+ if (metaObject.hasSetter("updatedAt")) {
+ strictUpdateFill(metaObject, "updatedAt", Date.class, date);
+ }
// 数据标识
strictInsertFill(metaObject, DATA_OPERATION, String.class, Constant.DataOperation.UPDATE.getValue());
diff --git a/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java b/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java
index d25c72b6..3a969713 100644
--- a/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java
+++ b/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java
@@ -152,4 +152,11 @@ public class RedisKeys {
public static String getVoiceCloneAudioIdKey(String uuid) {
return "voiceClone:audio:id:" + uuid;
}
+
+ /**
+ * 获取知识库缓存key
+ */
+ public static String getKnowledgeBaseCacheKey(String datasetId) {
+ return "knowledge:base:" + datasetId;
+ }
}
diff --git a/main/manager-api/src/main/java/xiaozhi/common/utils/SensitiveDataUtils.java b/main/manager-api/src/main/java/xiaozhi/common/utils/SensitiveDataUtils.java
index 05f4853a..4d5715cc 100644
--- a/main/manager-api/src/main/java/xiaozhi/common/utils/SensitiveDataUtils.java
+++ b/main/manager-api/src/main/java/xiaozhi/common/utils/SensitiveDataUtils.java
@@ -1,14 +1,15 @@
package xiaozhi.common.utils;
-import cn.hutool.json.JSONObject;
-import org.apache.commons.lang3.StringUtils;
-
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
-import java.util.HashMap;
import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+
+import cn.hutool.json.JSONObject;
+
/**
* 敏感数据处理工具类
*/
@@ -30,7 +31,7 @@ public class SensitiveDataUtils {
* 隐藏字符串中间部分
*/
public static String maskMiddle(String value) {
- if (StringUtils.isBlank(value)) {
+ if (StringUtils.isBlank(value) || value.length() == 1) {
return value;
}
diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java
index 2a53d474..1ebb522a 100644
--- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java
+++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java
@@ -1,16 +1,25 @@
package xiaozhi.modules.agent.service.impl;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
+import xiaozhi.common.utils.JsonUtils;
import xiaozhi.modules.agent.dao.AgentPluginMappingMapper;
import xiaozhi.modules.agent.entity.AgentPluginMapping;
import xiaozhi.modules.agent.service.AgentPluginMappingService;
+import xiaozhi.modules.knowledge.entity.KnowledgeBaseEntity;
+import xiaozhi.modules.knowledge.service.KnowledgeBaseService;
+import xiaozhi.modules.model.entity.ModelConfigEntity;
+import xiaozhi.modules.model.service.ModelConfigService;
/**
* @description 针对表【ai_agent_plugin_mapping(Agent与插件的唯一映射表)】的数据库操作Service实现
@@ -21,10 +30,69 @@ import xiaozhi.modules.agent.service.AgentPluginMappingService;
public class AgentPluginMappingServiceImpl extends ServiceImpl
implements AgentPluginMappingService {
private final AgentPluginMappingMapper agentPluginMappingMapper;
+ private final KnowledgeBaseService knowledgeBaseService;
+ private final ModelConfigService modelConfigService;
@Override
public List agentPluginParamsByAgentId(String agentId) {
- return agentPluginMappingMapper.selectPluginsByAgentId(agentId);
+ List list = agentPluginMappingMapper.selectPluginsByAgentId(agentId);
+ Map> knowledgeBaseMap = new HashMap<>();
+ Map modelConfigMap = new HashMap<>();
+ for (int i = list.size() - 1; i >= 0; i--) {
+ AgentPluginMapping mapping = list.get(i);
+ if (StringUtils.isBlank(mapping.getProviderCode())) {
+ // 查询知识库插件参数
+ KnowledgeBaseEntity knowledgeBaseEntity = knowledgeBaseService.selectById(mapping.getPluginId());
+ if (knowledgeBaseEntity == null) {
+ list.remove(i);
+ continue;
+ }
+ ModelConfigEntity modelConfigEntity = modelConfigService
+ .getModelByIdFromCache(knowledgeBaseEntity.getRagModelId());
+ if (modelConfigEntity == null) {
+ list.remove(i);
+ continue;
+ }
+ List knowledgeBaseList = knowledgeBaseMap.get(modelConfigEntity.getModelCode());
+ if (knowledgeBaseList == null) {
+ knowledgeBaseList = new ArrayList<>();
+ }
+ modelConfigMap.put(modelConfigEntity.getModelCode(), modelConfigEntity);
+ knowledgeBaseList.add(knowledgeBaseEntity);
+ knowledgeBaseMap.put(modelConfigEntity.getModelCode(), knowledgeBaseList);
+ list.remove(i);
+ }
+ }
+ if (knowledgeBaseMap.size() > 0) {
+ for (String pluginCode : knowledgeBaseMap.keySet()) {
+ List knowledgeBaseList = knowledgeBaseMap.get(pluginCode);
+ if (knowledgeBaseList == null || knowledgeBaseList.isEmpty()) {
+ continue;
+ }
+
+ AgentPluginMapping agentPluginMapping = new AgentPluginMapping();
+ agentPluginMapping.setAgentId(agentId);
+ agentPluginMapping.setPluginId(pluginCode);
+ agentPluginMapping.setProviderCode("search_from_" + pluginCode);
+ agentPluginMapping.setId(Long.valueOf(list.size() + 1));
+
+ Map paramInfo = new HashMap<>(4);
+ ModelConfigEntity modelConfigEntity = modelConfigMap.get(pluginCode);
+ paramInfo.put("base_url", modelConfigEntity.getConfigJson().getStr("base_url"));
+ paramInfo.put("api_key", modelConfigEntity.getConfigJson().getStr("api_key"));
+ paramInfo.put("dataset_ids",
+ knowledgeBaseList.stream().map(KnowledgeBaseEntity::getDatasetId).toList());
+
+ String description = "如果用户询问与【"
+ + String.join(",", knowledgeBaseList.stream().map(KnowledgeBaseEntity::getName).toList())
+ + "】相关的问题应调用本方法,用于查询:" + String.join(",",
+ knowledgeBaseList.stream().map(KnowledgeBaseEntity::getDescription).toList());
+ paramInfo.put("description", description);
+ agentPluginMapping.setParamInfo(JsonUtils.toJsonString(paramInfo));
+ list.add(agentPluginMapping);
+ }
+ }
+ return list;
}
@Override
diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java
index 8c562edb..321b5cb2 100644
--- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java
+++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java
@@ -45,6 +45,10 @@ public class AgentTemplateServiceImpl extends ServiceImpl wrapper = new UpdateWrapper<>();
switch (modelType) {
diff --git a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java
index a34c73dd..7883b8c1 100644
--- a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java
+++ b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java
@@ -91,6 +91,7 @@ public class ConfigServiceImpl implements ConfigService {
null,
null,
null,
+ null,
result,
isCache);
@@ -195,6 +196,7 @@ public class ConfigServiceImpl implements ConfigService {
agent.getTtsModelId(),
agent.getMemModelId(),
agent.getIntentModelId(),
+ null,
result,
true);
@@ -371,12 +373,14 @@ public class ConfigServiceImpl implements ConfigService {
String ttsModelId,
String memModelId,
String intentModelId,
+ String ragModelId,
Map result,
boolean isCache) {
Map selectedModule = new HashMap<>();
- String[] modelTypes = { "VAD", "ASR", "TTS", "Memory", "Intent", "LLM", "VLLM" };
- String[] modelIds = { vadModelId, asrModelId, ttsModelId, memModelId, intentModelId, llmModelId, vllmModelId };
+ String[] modelTypes = { "VAD", "ASR", "TTS", "Memory", "Intent", "LLM", "VLLM", "RAG" };
+ String[] modelIds = { vadModelId, asrModelId, ttsModelId, memModelId, intentModelId, llmModelId, vllmModelId,
+ ragModelId };
String intentLLMModelId = null;
String memLocalShortLLMModelId = null;
diff --git a/main/manager-api/src/main/java/xiaozhi/modules/knowledge/controller/KnowledgeBaseController.java b/main/manager-api/src/main/java/xiaozhi/modules/knowledge/controller/KnowledgeBaseController.java
new file mode 100644
index 00000000..cddfead5
--- /dev/null
+++ b/main/manager-api/src/main/java/xiaozhi/modules/knowledge/controller/KnowledgeBaseController.java
@@ -0,0 +1,159 @@
+package xiaozhi.modules.knowledge.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import xiaozhi.common.exception.ErrorCode;
+import xiaozhi.common.exception.RenException;
+import xiaozhi.common.page.PageData;
+import xiaozhi.common.utils.Result;
+import xiaozhi.modules.knowledge.dto.KnowledgeBaseDTO;
+import xiaozhi.modules.knowledge.service.KnowledgeBaseService;
+import xiaozhi.modules.security.user.SecurityUser;
+
+@AllArgsConstructor
+@RestController
+@RequestMapping("/datasets")
+@Tag(name = "知识库管理")
+public class KnowledgeBaseController {
+
+ private final KnowledgeBaseService knowledgeBaseService;
+
+ @GetMapping
+ @Operation(summary = "分页查询知识库列表")
+ @RequiresPermissions("sys:role:normal")
+ public Result> getPageList(
+ @RequestParam(required = false) String name,
+ @RequestParam(required = false, defaultValue = "1") Integer page,
+ @RequestParam(required = false, defaultValue = "10") Integer page_size) {
+ // 获取当前登录用户ID
+ Long currentUserId = SecurityUser.getUserId();
+
+ KnowledgeBaseDTO knowledgeBaseDTO = new KnowledgeBaseDTO();
+ knowledgeBaseDTO.setName(name);
+ knowledgeBaseDTO.setCreator(currentUserId); // 设置创建者ID,用于权限过滤
+
+ PageData pageData = knowledgeBaseService.getPageList(knowledgeBaseDTO, page, page_size);
+ return new Result>().ok(pageData);
+ }
+
+ @GetMapping("/{dataset_id}")
+ @Operation(summary = "根据知识库ID获取知识库详情")
+ @RequiresPermissions("sys:role:normal")
+ public Result getByDatasetId(@PathVariable("dataset_id") String datasetId) {
+ // 获取当前登录用户ID
+ Long currentUserId = SecurityUser.getUserId();
+
+ KnowledgeBaseDTO knowledgeBaseDTO = knowledgeBaseService.getByDatasetId(datasetId);
+
+ // 检查权限:用户只能查看自己创建的知识库
+ if (knowledgeBaseDTO.getCreator() == null || !knowledgeBaseDTO.getCreator().equals(currentUserId)) {
+ throw new RenException(ErrorCode.NO_PERMISSION);
+ }
+
+ return new Result().ok(knowledgeBaseDTO);
+ }
+
+ @PostMapping
+ @Operation(summary = "创建知识库")
+ @RequiresPermissions("sys:role:normal")
+ public Result save(@RequestBody @Validated KnowledgeBaseDTO knowledgeBaseDTO) {
+ KnowledgeBaseDTO resp = knowledgeBaseService.save(knowledgeBaseDTO);
+ return new Result().ok(resp);
+ }
+
+ @PutMapping("/{dataset_id}")
+ @Operation(summary = "更新知识库")
+ @RequiresPermissions("sys:role:normal")
+ public Result update(@PathVariable("dataset_id") String datasetId,
+ @RequestBody @Validated KnowledgeBaseDTO knowledgeBaseDTO) {
+ // 获取当前登录用户ID
+ Long currentUserId = SecurityUser.getUserId();
+
+ // 先获取现有知识库信息以检查权限
+ KnowledgeBaseDTO existingKnowledgeBase = knowledgeBaseService.getByDatasetId(datasetId);
+
+ // 检查权限:用户只能更新自己创建的知识库
+ if (existingKnowledgeBase.getCreator() == null || !existingKnowledgeBase.getCreator().equals(currentUserId)) {
+ throw new RenException(ErrorCode.NO_PERMISSION);
+ }
+
+ knowledgeBaseDTO.setDatasetId(datasetId);
+ KnowledgeBaseDTO resp = knowledgeBaseService.update(knowledgeBaseDTO);
+ return new Result().ok(resp);
+ }
+
+ @DeleteMapping("/{dataset_id}")
+ @Operation(summary = "删除单个知识库")
+ @Parameter(name = "dataset_id", description = "知识库ID", required = true)
+ @RequiresPermissions("sys:role:normal")
+ public Result delete(@PathVariable("dataset_id") String datasetId) {
+ // 获取当前登录用户ID
+ Long currentUserId = SecurityUser.getUserId();
+
+ // 先获取现有知识库信息以检查权限
+ KnowledgeBaseDTO existingKnowledgeBase = knowledgeBaseService.getByDatasetId(datasetId);
+
+ // 检查权限:用户只能删除自己创建的知识库
+ if (existingKnowledgeBase.getCreator() == null || !existingKnowledgeBase.getCreator().equals(currentUserId)) {
+ throw new RenException(ErrorCode.NO_PERMISSION);
+ }
+
+ knowledgeBaseService.deleteByDatasetId(datasetId);
+ return new Result<>();
+ }
+
+ @DeleteMapping("/batch")
+ @Operation(summary = "批量删除知识库")
+ @Parameter(name = "ids", description = "知识库ID列表,用逗号分隔", required = true)
+ @RequiresPermissions("sys:role:normal")
+ public Result deleteBatch(@RequestParam("ids") String ids) {
+ if (StringUtils.isBlank(ids)) {
+ throw new RenException(ErrorCode.PARAMS_GET_ERROR);
+ }
+
+ // 获取当前登录用户ID
+ Long currentUserId = SecurityUser.getUserId();
+ String[] idArray = ids.split(",");
+ for (String datasetId : idArray) {
+ if (StringUtils.isNotBlank(datasetId)) {
+ // 先获取现有知识库信息以检查权限
+ KnowledgeBaseDTO existingKnowledgeBase = knowledgeBaseService.getByDatasetId(datasetId.trim());
+
+ // 检查权限:用户只能删除自己创建的知识库
+ if (existingKnowledgeBase.getCreator() == null
+ || !existingKnowledgeBase.getCreator().equals(currentUserId)) {
+ throw new RenException(ErrorCode.NO_PERMISSION);
+ }
+
+ knowledgeBaseService.deleteByDatasetId(datasetId.trim());
+ }
+ }
+ return new Result<>();
+ }
+
+ @GetMapping("/rag-models")
+ @Operation(summary = "获取RAG模型列表")
+ @RequiresPermissions("sys:role:normal")
+ public Result>> getRAGModels() {
+ List