mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-25 00:15:06 +08:00
Merge branch 'master-jdk21-ai' of https://gitee.com/cherishsince/ruoyi-vue-pro into master-jdk17
This commit is contained in:
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - AI 知识库")
|
||||
@RestController
|
||||
@RequestMapping("/ai/knowledge")
|
||||
@Validated
|
||||
public class AiKnowledgeController {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeService knowledgeService;
|
||||
|
||||
@GetMapping("/my-page")
|
||||
@Operation(summary = "获取【我的】知识库分页")
|
||||
public CommonResult<PageResult<AiKnowledgeRespVO>> getKnowledgePageMy(@Validated PageParam pageReqVO) {
|
||||
PageResult<AiKnowledgeDO> pageResult = knowledgeService.getKnowledgePageMy(getLoginUserId(), pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiKnowledgeRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/create-my")
|
||||
@Operation(summary = "创建【我的】知识库")
|
||||
public CommonResult<Long> createKnowledgeMy(@RequestBody @Valid AiKnowledgeCreateMyReqVO createReqVO) {
|
||||
return success(knowledgeService.createKnowledgeMy(createReqVO, getLoginUserId()));
|
||||
}
|
||||
|
||||
@PutMapping("/update-my")
|
||||
@Operation(summary = "更新【我的】知识库")
|
||||
public CommonResult<Boolean> updateKnowledgeMy(@RequestBody @Valid AiKnowledgeUpdateMyReqVO updateReqVO) {
|
||||
knowledgeService.updateKnowledgeMy(updateReqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - AI 知识库文档")
|
||||
@RestController
|
||||
@RequestMapping("/ai/knowledge/document")
|
||||
@Validated
|
||||
public class AiKnowledgeDocumentController {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeDocumentService documentService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "新建文档")
|
||||
public CommonResult<Long> createKnowledgeDocument(@Valid AiKnowledgeDocumentCreateReqVO reqVO) {
|
||||
Long knowledgeDocumentId = documentService.createKnowledgeDocument(reqVO);
|
||||
return success(knowledgeDocumentId);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获取文档分页")
|
||||
public CommonResult<PageResult<AiKnowledgeDocumentRespVO>> getKnowledgeDocumentPageMy(@Valid AiKnowledgeDocumentPageReqVO pageReqVO) {
|
||||
PageResult<AiKnowledgeDocumentDO> pageResult = documentService.getKnowledgeDocumentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiKnowledgeDocumentRespVO.class));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新文档")
|
||||
public CommonResult<Boolean> updateKnowledgeDocument(@Valid @RequestBody AiKnowledgeDocumentUpdateReqVO reqVO) {
|
||||
documentService.updateKnowledgeDocument(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - AI 知识库段落")
|
||||
@RestController
|
||||
@RequestMapping("/ai/knowledge/segment")
|
||||
@Validated
|
||||
public class AiKnowledgeSegmentController {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeSegmentService segmentService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获取段落分页")
|
||||
public CommonResult<PageResult<AiKnowledgeSegmentRespVO>> getKnowledgeSegmentPageMy(@Valid AiKnowledgeSegmentPageReqVO pageReqVO) {
|
||||
PageResult<AiKnowledgeSegmentDO> pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新段落内容")
|
||||
public CommonResult<Boolean> updateKnowledgeSegment(@Valid @RequestBody AiKnowledgeSegmentUpdateReqVO reqVO) {
|
||||
segmentService.updateKnowledgeSegment(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "启禁用段落内容")
|
||||
public CommonResult<Boolean> updateKnowledgeSegmentStatus(@Valid @RequestBody AiKnowledgeSegmentUpdateStatusReqVO reqVO) {
|
||||
segmentService.updateKnowledgeSegmentStatus(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库文档的分页 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "文档名称", example = "Java 开发手册")
|
||||
private String name;
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库-文档 Response VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentRespVO extends PageParam {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long knowledgeId;
|
||||
|
||||
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 是一门面向对象的语言.....")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "文档 url", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer tokens;
|
||||
|
||||
@Schema(description = "字符数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1008")
|
||||
private Integer wordCount;
|
||||
|
||||
@Schema(description = "切片状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sliceStatus;
|
||||
|
||||
@Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 更新 知识库-文档 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentUpdateReqVO {
|
||||
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "是否启用", example = "1")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "名称", example = "Java 开发手册")
|
||||
private String name;
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库创建【我的】 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeCreateMyReqVO {
|
||||
|
||||
@Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南")
|
||||
@NotBlank(message = "知识库名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "存储 ruoyi-vue-pro 操作文档")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "可见权限,只能选择哪些人可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1]")
|
||||
private List<Long> visibilityPermissions;
|
||||
|
||||
@Schema(description = "嵌入模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "嵌入模型不能为空")
|
||||
private Long modelId;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库文档的创建 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentCreateReqVO {
|
||||
|
||||
@Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204")
|
||||
@NotNull(message = "知识库编号不能为空")
|
||||
private Long knowledgeId;
|
||||
|
||||
@Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆")
|
||||
@NotBlank(message = "文档名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn")
|
||||
@URL(message = "文档 URL 格式不正确")
|
||||
private String url;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库 Response VO")
|
||||
@Data
|
||||
public class AiKnowledgeRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "知识库描述", example = "帮助你快速构建系统")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "14")
|
||||
private Long modelId;
|
||||
|
||||
@Schema(description = "模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "qwen-72b-chat")
|
||||
private String model;
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库更新【我的】 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeUpdateMyReqVO {
|
||||
|
||||
@Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204")
|
||||
@NotNull(message = "知识库编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
|
||||
@NotBlank(message = "知识库名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "可见权限,只能选择哪些人可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1]")
|
||||
private List<Long> visibilityPermissions;
|
||||
|
||||
@Schema(description = "嵌入模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "嵌入模型不能为空")
|
||||
private Long modelId;
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库分段的分页 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "分段状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "文档编号", example = "1")
|
||||
private Integer documentId;
|
||||
|
||||
@Schema(description = "分段内容关键字", example = "Java 开发")
|
||||
private String keyword;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库-文档 Response VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long documentId;
|
||||
|
||||
@Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long knowledgeId;
|
||||
|
||||
@Schema(description = "向量库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1858496a-1dde-4edf-a43e-0aed08f37f8c")
|
||||
private String vectorId;
|
||||
|
||||
@Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer tokens;
|
||||
|
||||
@Schema(description = "字符数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1008")
|
||||
private Integer wordCount;
|
||||
|
||||
@Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 更新 知识库-段落 request VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentUpdateReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
|
||||
private String content;
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - AI 知识库段落的更新状态 Request VO")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentUpdateStatusReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "是否启用不能为空")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ public class AiImageDO extends BaseDO {
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,61 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI 知识库 DO
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@TableName(value = "ai_knowledge", autoResultMap = true)
|
||||
@Data
|
||||
public class AiKnowledgeDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 用户编号
|
||||
* <p>
|
||||
* 关联 AdminUserDO 的 userId 字段
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 知识库名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 知识库描述
|
||||
*/
|
||||
private String description;
|
||||
// TODO @新:如果全部可见,需要怎么设置?
|
||||
/**
|
||||
* 可见权限,只能选择哪些人可见
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<Long> visibilityPermissions;
|
||||
/**
|
||||
* 嵌入模型编号
|
||||
*/
|
||||
private Long modelId;
|
||||
/**
|
||||
* 模型标识
|
||||
*/
|
||||
private String model;
|
||||
/**
|
||||
* 状态
|
||||
* <p>
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档 DO
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@TableName(value = "ai_knowledge_document")
|
||||
@Data
|
||||
public class AiKnowledgeDocumentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 知识库编号
|
||||
*
|
||||
* 关联 {@link AiKnowledgeDO#getId()}
|
||||
*/
|
||||
private Long knowledgeId;
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 文件 URL
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* token 数量
|
||||
*/
|
||||
private Integer tokens;
|
||||
/**
|
||||
* 字符数
|
||||
*/
|
||||
private Integer wordCount;
|
||||
/**
|
||||
* 切片状态
|
||||
* <p>
|
||||
* 枚举 {@link AiKnowledgeDocumentStatusEnum}
|
||||
*/
|
||||
private Integer sliceStatus;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* <p>
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档分段 DO
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@TableName(value = "ai_knowledge_segment")
|
||||
@Data
|
||||
public class AiKnowledgeSegmentDO extends BaseDO {
|
||||
|
||||
public static final String FIELD_KNOWLEDGE_ID = "knowledgeId";
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 向量库的编号
|
||||
*/
|
||||
private String vectorId;
|
||||
/**
|
||||
* 知识库编号
|
||||
*
|
||||
* 关联 {@link AiKnowledgeDO#getId()}
|
||||
*/
|
||||
private Long knowledgeId;
|
||||
/**
|
||||
* 文档编号
|
||||
*
|
||||
* 关联 {@link AiKnowledgeDocumentDO#getId()}
|
||||
*/
|
||||
private Long documentId;
|
||||
/**
|
||||
* 切片内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 字符数
|
||||
*/
|
||||
private Integer wordCount;
|
||||
/**
|
||||
* token 数量
|
||||
*/
|
||||
private Integer tokens;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -19,7 +19,7 @@ public class AiMindMapDO extends BaseDO {
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ public class AiMusicDO extends BaseDO {
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ public class AiWriteDO extends BaseDO {
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.mysql.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档 Mapper
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@Mapper
|
||||
public interface AiKnowledgeDocumentMapper extends BaseMapperX<AiKnowledgeDocumentDO> {
|
||||
|
||||
default PageResult<AiKnowledgeDocumentDO> selectPage(AiKnowledgeDocumentPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<AiKnowledgeDocumentDO>()
|
||||
.likeIfPresent(AiKnowledgeDocumentDO::getName, reqVO.getName())
|
||||
.orderByDesc(AiKnowledgeDocumentDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.mysql.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* AI 知识库基础信息 Mapper
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@Mapper
|
||||
public interface AiKnowledgeMapper extends BaseMapperX<AiKnowledgeDO> {
|
||||
|
||||
default PageResult<AiKnowledgeDO> selectPageByMy(Long userId, PageParam pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<AiKnowledgeDO>()
|
||||
.eq(AiKnowledgeDO::getUserId, userId)
|
||||
.eq(AiKnowledgeDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
|
||||
.orderByDesc(AiKnowledgeDO::getId));
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.ai.dal.mysql.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* AI 知识库-分片 Mapper
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@Mapper
|
||||
public interface AiKnowledgeSegmentMapper extends BaseMapperX<AiKnowledgeSegmentDO> {
|
||||
|
||||
default PageResult<AiKnowledgeSegmentDO> selectPage(AiKnowledgeSegmentPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<AiKnowledgeSegmentDO>()
|
||||
.eq(AiKnowledgeSegmentDO::getDocumentId, reqVO.getDocumentId())
|
||||
.eqIfPresent(AiKnowledgeSegmentDO::getStatus, reqVO.getStatus())
|
||||
.likeIfPresent(AiKnowledgeSegmentDO::getContent, reqVO.getKeyword())
|
||||
.orderByDesc(AiKnowledgeSegmentDO::getId));
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
|
||||
|
||||
/**
|
||||
* AI 知识库-文档 Service 接口
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
public interface AiKnowledgeDocumentService {
|
||||
|
||||
/**
|
||||
* 创建文档
|
||||
*
|
||||
* @param createReqVO 文档创建 Request VO
|
||||
* @return 文档编号
|
||||
*/
|
||||
Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO);
|
||||
|
||||
|
||||
/**
|
||||
* 获取文档分页
|
||||
*
|
||||
* @param pageReqVO 分页参数
|
||||
* @return 文档分页
|
||||
*/
|
||||
PageResult<AiKnowledgeDocumentDO> getKnowledgeDocumentPage(AiKnowledgeDocumentPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 更新文档
|
||||
*
|
||||
* @param reqVO 更新信息
|
||||
*/
|
||||
void updateKnowledgeDocument(AiKnowledgeDocumentUpdateReqVO reqVO);
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeDocumentMapper;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper;
|
||||
import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.reader.tika.TikaDocumentReader;
|
||||
import org.springframework.ai.tokenizer.TokenCountEstimator;
|
||||
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_DOCUMENT_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* AI 知识库文档 Service 实现类
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentService {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeDocumentMapper documentMapper;
|
||||
@Resource
|
||||
private AiKnowledgeSegmentMapper segmentMapper;
|
||||
|
||||
@Resource
|
||||
private TokenTextSplitter tokenTextSplitter;
|
||||
@Resource
|
||||
private TokenCountEstimator tokenCountEstimator;
|
||||
|
||||
@Resource
|
||||
private AiApiKeyService apiKeyService;
|
||||
@Resource
|
||||
private AiKnowledgeService knowledgeService;
|
||||
@Resource
|
||||
private AiChatModelService chatModelService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) {
|
||||
// 0. 校验
|
||||
AiKnowledgeDO knowledge = knowledgeService.validateKnowledgeExists(createReqVO.getKnowledgeId());
|
||||
AiChatModelDO model = chatModelService.validateChatModel(knowledge.getModelId());
|
||||
|
||||
// 1.1 下载文档
|
||||
TikaDocumentReader loader = new TikaDocumentReader(downloadFile(createReqVO.getUrl()));
|
||||
List<Document> documents = loader.get();
|
||||
Document document = CollUtil.getFirst(documents);
|
||||
// 1.2 文档记录入库
|
||||
String content = document.getContent();
|
||||
AiKnowledgeDocumentDO documentDO = BeanUtils.toBean(createReqVO, AiKnowledgeDocumentDO.class)
|
||||
.setTokens(tokenCountEstimator.estimate(content)).setWordCount(content.length())
|
||||
.setStatus(CommonStatusEnum.ENABLE.getStatus()).setSliceStatus(AiKnowledgeDocumentStatusEnum.SUCCESS.getStatus());
|
||||
documentMapper.insert(documentDO);
|
||||
Long documentId = documentDO.getId();
|
||||
if (CollUtil.isEmpty(documents)) {
|
||||
return documentId;
|
||||
}
|
||||
|
||||
// 2.1 文档分段
|
||||
List<Document> segments = tokenTextSplitter.apply(documents);
|
||||
// 2.2 分段内容入库
|
||||
List<AiKnowledgeSegmentDO> segmentDOList = CollectionUtils.convertList(segments,
|
||||
segment -> new AiKnowledgeSegmentDO().setContent(segment.getContent()).setDocumentId(documentId)
|
||||
.setKnowledgeId(createReqVO.getKnowledgeId()).setVectorId(segment.getId())
|
||||
.setTokens(tokenCountEstimator.estimate(segment.getContent())).setWordCount(segment.getContent().length())
|
||||
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||
segmentMapper.insertBatch(segmentDOList);
|
||||
|
||||
// 3.1 获取向量存储实例
|
||||
VectorStore vectorStore = apiKeyService.getOrCreateVectorStore(model.getKeyId());
|
||||
// 3.2 向量化并存储
|
||||
segments.forEach(segment -> segment.getMetadata().put(AiKnowledgeSegmentDO.FIELD_KNOWLEDGE_ID, createReqVO.getKnowledgeId()));
|
||||
vectorStore.add(segments);
|
||||
return documentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<AiKnowledgeDocumentDO> getKnowledgeDocumentPage(AiKnowledgeDocumentPageReqVO pageReqVO) {
|
||||
return documentMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateKnowledgeDocument(AiKnowledgeDocumentUpdateReqVO reqVO) {
|
||||
// 1. 校验文档是否存在
|
||||
validateKnowledgeDocumentExists(reqVO.getId());
|
||||
// 2. 更新文档
|
||||
AiKnowledgeDocumentDO document = BeanUtils.toBean(reqVO, AiKnowledgeDocumentDO.class);
|
||||
documentMapper.updateById(document);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验文档是否存在
|
||||
*
|
||||
* @param id 文档编号
|
||||
* @return 文档信息
|
||||
*/
|
||||
private AiKnowledgeDocumentDO validateKnowledgeDocumentExists(Long id) {
|
||||
AiKnowledgeDocumentDO knowledgeDocument = documentMapper.selectById(id);
|
||||
if (knowledgeDocument == null) {
|
||||
throw exception(KNOWLEDGE_DOCUMENT_NOT_EXISTS);
|
||||
}
|
||||
return knowledgeDocument;
|
||||
}
|
||||
|
||||
private org.springframework.core.io.Resource downloadFile(String url) {
|
||||
try {
|
||||
byte[] bytes = HttpUtil.downloadBytes(url);
|
||||
return new ByteArrayResource(bytes);
|
||||
} catch (Exception e) {
|
||||
log.error("[downloadFile][url({}) 下载失败]", url, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
|
||||
/**
|
||||
* AI 知识库段落 Service 接口
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
public interface AiKnowledgeSegmentService {
|
||||
|
||||
/**
|
||||
* 获取段落分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 文档分页
|
||||
*/
|
||||
PageResult<AiKnowledgeSegmentDO> getKnowledgeSegmentPage(AiKnowledgeSegmentPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 更新段落的内容
|
||||
*
|
||||
* @param reqVO 更新内容
|
||||
*/
|
||||
void updateKnowledgeSegment(AiKnowledgeSegmentUpdateReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 更新段落的状态
|
||||
*
|
||||
* @param reqVO 更新内容
|
||||
*/
|
||||
void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO);
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* AI 知识库分片 Service 实现类
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService {
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeSegmentMapper segmentMapper;
|
||||
|
||||
@Override
|
||||
public PageResult<AiKnowledgeSegmentDO> getKnowledgeSegmentPage(AiKnowledgeSegmentPageReqVO pageReqVO) {
|
||||
return segmentMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateKnowledgeSegment(AiKnowledgeSegmentUpdateReqVO reqVO) {
|
||||
segmentMapper.updateById(BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class));
|
||||
// TODO @xin 重新向量化
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO) {
|
||||
segmentMapper.updateById(BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class));
|
||||
// TODO @xin 1.禁用删除向量 2.启用重新向量化
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
|
||||
/**
|
||||
* AI 知识库-基础信息 Service 接口
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
public interface AiKnowledgeService {
|
||||
|
||||
/**
|
||||
* 创建【我的】知识库
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @param userId 用户编号
|
||||
* @return 编号
|
||||
*/
|
||||
Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId);
|
||||
|
||||
|
||||
/**
|
||||
* 创建【我的】知识库
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void updateKnowledgeMy(AiKnowledgeUpdateMyReqVO updateReqVO, Long userId);
|
||||
|
||||
|
||||
/**
|
||||
* 校验知识库是否存在
|
||||
*
|
||||
* @param id 记录编号
|
||||
*/
|
||||
AiKnowledgeDO validateKnowledgeExists(Long id);
|
||||
|
||||
/**
|
||||
* 获得【我的】知识库分页
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 知识库分页
|
||||
*/
|
||||
PageResult<AiKnowledgeDO> getKnowledgePageMy(Long userId, PageParam pageReqVO);
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeMapper;
|
||||
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* AI 知识库-基础信息 Service 实现类
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AiKnowledgeServiceImpl implements AiKnowledgeService {
|
||||
|
||||
@Resource
|
||||
private AiChatModelService chatModalService;
|
||||
|
||||
@Resource
|
||||
private AiKnowledgeMapper knowledgeMapper;
|
||||
|
||||
@Override
|
||||
public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) {
|
||||
// 1. 校验模型配置
|
||||
AiChatModelDO model = chatModalService.validateChatModel(createReqVO.getModelId());
|
||||
|
||||
// 2. 插入知识库
|
||||
AiKnowledgeDO knowledgeBase = BeanUtils.toBean(createReqVO, AiKnowledgeDO.class)
|
||||
.setModel(model.getModel()).setUserId(userId).setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
knowledgeMapper.insert(knowledgeBase);
|
||||
return knowledgeBase.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateKnowledgeMy(AiKnowledgeUpdateMyReqVO updateReqVO, Long userId) {
|
||||
// 1.1 校验知识库存在
|
||||
AiKnowledgeDO knowledgeBaseDO = validateKnowledgeExists(updateReqVO.getId());
|
||||
if (ObjUtil.notEqual(knowledgeBaseDO.getUserId(), userId)) {
|
||||
throw exception(KNOWLEDGE_NOT_EXISTS);
|
||||
}
|
||||
// 1.2 校验模型配置
|
||||
AiChatModelDO model = chatModalService.validateChatModel(updateReqVO.getModelId());
|
||||
|
||||
// 2. 更新知识库
|
||||
AiKnowledgeDO updateDO = BeanUtils.toBean(updateReqVO, AiKnowledgeDO.class);
|
||||
updateDO.setModel(model.getModel());
|
||||
knowledgeMapper.updateById(updateDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiKnowledgeDO validateKnowledgeExists(Long id) {
|
||||
AiKnowledgeDO knowledgeBase = knowledgeMapper.selectById(id);
|
||||
if (knowledgeBase == null) {
|
||||
throw exception(KNOWLEDGE_NOT_EXISTS);
|
||||
}
|
||||
return knowledgeBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<AiKnowledgeDO> getKnowledgePageMy(Long userId, PageParam pageReqVO) {
|
||||
return knowledgeMapper.selectPageByMy(userId, pageReqVO);
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
/**
|
||||
* AI 知识库 Service 接口
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
public interface DocService {
|
||||
|
||||
/**
|
||||
* 向量化文档
|
||||
*/
|
||||
void embeddingDoc();
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package cn.iocoder.yudao.module.ai.service.knowledge;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.document.Document;
|
||||
import org.springframework.ai.reader.tika.TikaDocumentReader;
|
||||
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
|
||||
import org.springframework.ai.vectorstore.RedisVectorStore;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI 知识库 Service 实现类
|
||||
*
|
||||
* @author xiaoxin
|
||||
*/
|
||||
//@Service // TODO 芋艿:临时注释,避免无法启动
|
||||
@Slf4j
|
||||
public class DocServiceImpl implements DocService {
|
||||
|
||||
@Resource
|
||||
private RedisVectorStore vectorStore;
|
||||
@Resource
|
||||
private TokenTextSplitter tokenTextSplitter;
|
||||
|
||||
// TODO @xin 临时测试用,后续删
|
||||
@Value("classpath:/webapp/test/Fel.pdf")
|
||||
private org.springframework.core.io.Resource data;
|
||||
|
||||
@Override
|
||||
public void embeddingDoc() {
|
||||
// 读取文件
|
||||
TikaDocumentReader loader = new TikaDocumentReader(data);
|
||||
List<Document> documents = loader.get();
|
||||
// 文档分段
|
||||
List<Document> segments = tokenTextSplitter.apply(documents);
|
||||
// 向量化并存储
|
||||
vectorStore.add(segments);
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,9 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.image.ImageModel;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -111,4 +113,20 @@ public interface AiApiKeyService {
|
||||
*/
|
||||
SunoApi getSunoApi();
|
||||
|
||||
/**
|
||||
* 获得 EmbeddingModel 对象
|
||||
*
|
||||
* @param id 编号
|
||||
* @return EmbeddingModel 对象
|
||||
*/
|
||||
EmbeddingModel getEmbeddingModel(Long id);
|
||||
|
||||
/**
|
||||
* 获得 VectorStore 对象
|
||||
*
|
||||
* @param id 编号
|
||||
* @return VectorStore 对象
|
||||
*/
|
||||
VectorStore getOrCreateVectorStore(Long id);
|
||||
|
||||
}
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.model;
|
||||
|
||||
import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory;
|
||||
import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactory;
|
||||
import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
@ -13,7 +14,9 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.image.ImageModel;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@ -36,6 +39,8 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
|
||||
|
||||
@Resource
|
||||
private AiModelFactory modelFactory;
|
||||
@Resource
|
||||
private AiVectorStoreFactory vectorFactory;
|
||||
|
||||
@Override
|
||||
public Long createApiKey(AiApiKeySaveReqVO createReqVO) {
|
||||
@ -132,4 +137,19 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
|
||||
}
|
||||
return modelFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddingModel getEmbeddingModel(Long id) {
|
||||
AiApiKeyDO apiKey = validateApiKey(id);
|
||||
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
|
||||
return modelFactory.getOrCreateEmbeddingModel(platform, apiKey.getApiKey(), apiKey.getUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VectorStore getOrCreateVectorStore(Long id) {
|
||||
AiApiKeyDO apiKey = validateApiKey(id);
|
||||
AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
|
||||
return vectorFactory.getOrCreateVectorStore(getEmbeddingModel(id), platform, apiKey.getApiKey(), apiKey.getUrl());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user