Commit 261011d1a8b8f80d0c45f99a0f34d2e725d85eca
Committed by
Gitee
!19 AI 知识库
Merge pull request !19 from 小新/master-jdk21-ai
Showing
39 changed files
with
773 additions
and
191 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java
| 1 | package cn.iocoder.yudao.module.ai.enums; | 1 | package cn.iocoder.yudao.module.ai.enums; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | ||
| 4 | import lombok.AllArgsConstructor; | 3 | import lombok.AllArgsConstructor; |
| 5 | import lombok.Getter; | 4 | import lombok.Getter; |
| 6 | 5 | ||
| 7 | -import java.util.Arrays; | ||
| 8 | - | ||
| 9 | /** | 6 | /** |
| 10 | * AI 内置聊天角色的枚举 | 7 | * AI 内置聊天角色的枚举 |
| 11 | * | 8 | * |
| @@ -13,16 +10,16 @@ import java.util.Arrays; | @@ -13,16 +10,16 @@ import java.util.Arrays; | ||
| 13 | */ | 10 | */ |
| 14 | @AllArgsConstructor | 11 | @AllArgsConstructor |
| 15 | @Getter | 12 | @Getter |
| 16 | -public enum AiChatRoleEnum implements IntArrayValuable { | 13 | +public enum AiChatRoleEnum { |
| 17 | 14 | ||
| 18 | - AI_WRITE_ROLE(1, "写作助手", """ | 15 | + AI_WRITE_ROLE("写作助手", """ |
| 19 | 你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括: | 16 | 你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括: |
| 20 | 1. 撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。 | 17 | 1. 撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。 |
| 21 | 2. 回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。 | 18 | 2. 回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。 |
| 22 | 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。 | 19 | 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。 |
| 23 | """), | 20 | """), |
| 24 | 21 | ||
| 25 | - AI_MIND_MAP_ROLE(2, "导图助手", """ | 22 | + AI_MIND_MAP_ROLE("导图助手", """ |
| 26 | 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子: | 23 | 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子: |
| 27 | # Geek-AI 助手 | 24 | # Geek-AI 助手 |
| 28 | ## 完整的开源系统 | 25 | ## 完整的开源系统 |
| @@ -39,11 +36,6 @@ public enum AiChatRoleEnum implements IntArrayValuable { | @@ -39,11 +36,6 @@ public enum AiChatRoleEnum implements IntArrayValuable { | ||
| 39 | 除此之外不要任何解释性语句。 | 36 | 除此之外不要任何解释性语句。 |
| 40 | """); | 37 | """); |
| 41 | 38 | ||
| 42 | - // TODO @xin:这个 role 是不是删除掉好点哈。= = 目前主要是没做角色枚举。这里多了 role 反倒容易误解哈 | ||
| 43 | - /** | ||
| 44 | - * 角色 | ||
| 45 | - */ | ||
| 46 | - private final Integer role; | ||
| 47 | /** | 39 | /** |
| 48 | * 角色名 | 40 | * 角色名 |
| 49 | */ | 41 | */ |
| @@ -54,11 +46,4 @@ public enum AiChatRoleEnum implements IntArrayValuable { | @@ -54,11 +46,4 @@ public enum AiChatRoleEnum implements IntArrayValuable { | ||
| 54 | */ | 46 | */ |
| 55 | private final String systemMessage; | 47 | private final String systemMessage; |
| 56 | 48 | ||
| 57 | - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiChatRoleEnum::getRole).toArray(); | ||
| 58 | - | ||
| 59 | - @Override | ||
| 60 | - public int[] array() { | ||
| 61 | - return ARRAYS; | ||
| 62 | - } | ||
| 63 | - | ||
| 64 | } | 49 | } |
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
| @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * AI 错误码枚举类 | 6 | * AI 错误码枚举类 |
| 7 | - * | 7 | + * <p> |
| 8 | * ai 系统,使用 1-040-000-000 段 | 8 | * ai 系统,使用 1-040-000-000 段 |
| 9 | */ | 9 | */ |
| 10 | public interface ErrorCodeConstants { | 10 | public interface ErrorCodeConstants { |
| @@ -55,5 +55,7 @@ public interface ErrorCodeConstants { | @@ -55,5 +55,7 @@ public interface ErrorCodeConstants { | ||
| 55 | 55 | ||
| 56 | // ========== API 知识库 1-022-008-000 ========== | 56 | // ========== API 知识库 1-022-008-000 ========== |
| 57 | ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_022_008_000, "知识库不存在!"); | 57 | ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_022_008_000, "知识库不存在!"); |
| 58 | + ErrorCode KNOWLEDGE_DOCUMENT_NOT_EXISTS = new ErrorCode(1_022_008_001, "文档不存在!"); | ||
| 59 | + ErrorCode KNOWLEDGE_SEGMENT_NOT_EXISTS = new ErrorCode(1_022_008_002, "段落不存在!"); | ||
| 58 | 60 | ||
| 59 | } | 61 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java
| 1 | package cn.iocoder.yudao.module.ai.controller.admin.knowledge; | 1 | package cn.iocoder.yudao.module.ai.controller.admin.knowledge; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeCreateMyReqVO; | ||
| 5 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeUpdateMyReqVO; | ||
| 6 | -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeBaseService; | 4 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; | ||
| 11 | +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService; | ||
| 7 | import io.swagger.v3.oas.annotations.Operation; | 12 | import io.swagger.v3.oas.annotations.Operation; |
| 8 | import io.swagger.v3.oas.annotations.tags.Tag; | 13 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 9 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 10 | import jakarta.validation.Valid; | 15 | import jakarta.validation.Valid; |
| 16 | +import org.springframework.validation.annotation.Validated; | ||
| 11 | import org.springframework.web.bind.annotation.*; | 17 | import org.springframework.web.bind.annotation.*; |
| 12 | 18 | ||
| 13 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 19 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -19,19 +25,27 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | @@ -19,19 +25,27 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | ||
| 19 | public class AiKnowledgeController { | 25 | public class AiKnowledgeController { |
| 20 | 26 | ||
| 21 | @Resource | 27 | @Resource |
| 22 | - private AiKnowledgeBaseService knowledgeBaseService; | 28 | + private AiKnowledgeService knowledgeService; |
| 29 | + | ||
| 30 | + @GetMapping("/my-page") | ||
| 31 | + @Operation(summary = "获取【我的】知识库分页") | ||
| 32 | + public CommonResult<PageResult<AiKnowledgeRespVO>> getKnowledgePageMy(@Validated PageParam pageReqVO) { | ||
| 33 | + PageResult<AiKnowledgeDO> pageResult = knowledgeService.getKnowledgePageMy(getLoginUserId(), pageReqVO); | ||
| 34 | + return success(BeanUtils.toBean(pageResult, AiKnowledgeRespVO.class)); | ||
| 35 | + } | ||
| 36 | + | ||
| 23 | 37 | ||
| 24 | @PostMapping("/create-my") | 38 | @PostMapping("/create-my") |
| 25 | @Operation(summary = "创建【我的】知识库") | 39 | @Operation(summary = "创建【我的】知识库") |
| 26 | public CommonResult<Long> createKnowledgeMy(@RequestBody @Valid AiKnowledgeCreateMyReqVO createReqVO) { | 40 | public CommonResult<Long> createKnowledgeMy(@RequestBody @Valid AiKnowledgeCreateMyReqVO createReqVO) { |
| 27 | - return success(knowledgeBaseService.createKnowledgeMy(createReqVO, getLoginUserId())); | 41 | + return success(knowledgeService.createKnowledgeMy(createReqVO, getLoginUserId())); |
| 28 | } | 42 | } |
| 29 | 43 | ||
| 30 | 44 | ||
| 31 | @PutMapping("/update-my") | 45 | @PutMapping("/update-my") |
| 32 | @Operation(summary = "更新【我的】知识库") | 46 | @Operation(summary = "更新【我的】知识库") |
| 33 | public CommonResult<Boolean> updateKnowledgeMy(@RequestBody @Valid AiKnowledgeUpdateMyReqVO updateReqVO) { | 47 | public CommonResult<Boolean> updateKnowledgeMy(@RequestBody @Valid AiKnowledgeUpdateMyReqVO updateReqVO) { |
| 34 | - knowledgeBaseService.updateKnowledgeMy(updateReqVO, getLoginUserId()); | 48 | + knowledgeService.updateKnowledgeMy(updateReqVO, getLoginUserId()); |
| 35 | return success(true); | 49 | return success(true); |
| 36 | } | 50 | } |
| 37 | 51 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; | ||
| 11 | +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; | ||
| 12 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import org.springframework.validation.annotation.Validated; | ||
| 16 | +import org.springframework.web.bind.annotation.*; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +@Tag(name = "管理后台 - AI 知识库-文档") | ||
| 22 | +@RestController | ||
| 23 | +@RequestMapping("/ai/knowledge/document") | ||
| 24 | +public class AiKnowledgeDocumentController { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private AiKnowledgeDocumentService documentService; | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + @PostMapping("/create") | ||
| 31 | + @Operation(summary = "新建文档") | ||
| 32 | + public CommonResult<Long> createKnowledgeDocument(@Validated AiKnowledgeDocumentCreateReqVO reqVO) { | ||
| 33 | + Long knowledgeDocumentId = documentService.createKnowledgeDocument(reqVO); | ||
| 34 | + return success(knowledgeDocumentId); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + @GetMapping("/page") | ||
| 39 | + @Operation(summary = "获取文档分页") | ||
| 40 | + public CommonResult<PageResult<AiKnowledgeDocumentRespVO>> getKnowledgeDocumentPageMy(@Validated AiKnowledgeDocumentPageReqVO pageReqVO) { | ||
| 41 | + PageResult<AiKnowledgeDocumentDO> pageResult = documentService.getKnowledgeDocumentPage(pageReqVO); | ||
| 42 | + return success(BeanUtils.toBean(pageResult, AiKnowledgeDocumentRespVO.class)); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + @PutMapping("/update") | ||
| 47 | + @Operation(summary = "更新文档") | ||
| 48 | + public CommonResult<Boolean> updateKnowledgeDocument(@Validated @RequestBody AiKnowledgeDocumentUpdateReqVO reqVO) { | ||
| 49 | + documentService.updateKnowledgeDocument(reqVO); | ||
| 50 | + return success(true); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + | ||
| 54 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; | ||
| 11 | +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService; | ||
| 12 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import org.springframework.validation.annotation.Validated; | ||
| 16 | +import org.springframework.web.bind.annotation.*; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +@Tag(name = "管理后台 - AI 知识库-段落") | ||
| 22 | +@RestController | ||
| 23 | +@RequestMapping("/ai/knowledge/segment") | ||
| 24 | +public class AiKnowledgeSegmentController { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private AiKnowledgeSegmentService segmentService; | ||
| 28 | + | ||
| 29 | + @GetMapping("/page") | ||
| 30 | + @Operation(summary = "获取段落分页") | ||
| 31 | + public CommonResult<PageResult<AiKnowledgeSegmentRespVO>> getKnowledgeSegmentPageMy(@Validated AiKnowledgeSegmentPageReqVO pageReqVO) { | ||
| 32 | + PageResult<AiKnowledgeSegmentDO> pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO); | ||
| 33 | + return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class)); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + @PutMapping("/update") | ||
| 38 | + @Operation(summary = "更新段落内容") | ||
| 39 | + public CommonResult<Boolean> updateKnowledgeSegment(@Validated @RequestBody AiKnowledgeSegmentUpdateReqVO reqVO) { | ||
| 40 | + segmentService.updateKnowledgeSegment(reqVO); | ||
| 41 | + return success(true); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + @PutMapping("/update-status") | ||
| 45 | + @Operation(summary = "启禁用段落内容") | ||
| 46 | + public CommonResult<Boolean> updateKnowledgeSegmentStatus(@Validated @RequestBody AiKnowledgeSegmentUpdateStatusReqVO reqVO) { | ||
| 47 | + segmentService.updateKnowledgeSegmentStatus(reqVO); | ||
| 48 | + return success(true); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - AI 知识库-文档 分页 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class AiKnowledgeDocumentPageReqVO extends PageParam { | ||
| 10 | + | ||
| 11 | + @Schema(description = "文档名称", example = "Java 开发手册") | ||
| 12 | + private String name; | ||
| 13 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - AI 知识库-文档 Response VO") | ||
| 8 | +@Data | ||
| 9 | +public class AiKnowledgeDocumentRespVO extends PageParam { | ||
| 10 | + | ||
| 11 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 15 | + private Long knowledgeId; | ||
| 16 | + | ||
| 17 | + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") | ||
| 18 | + private String name; | ||
| 19 | + | ||
| 20 | + @Schema(description = "内容", example = "Java 是一门面向对象的语言.....") | ||
| 21 | + private String content; | ||
| 22 | + | ||
| 23 | + @Schema(description = "文档 url", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") | ||
| 24 | + private String url; | ||
| 25 | + | ||
| 26 | + @Schema(description = "token 数量", example = "1024") | ||
| 27 | + private Integer tokens; | ||
| 28 | + | ||
| 29 | + @Schema(description = "字符数", example = "1008") | ||
| 30 | + private Integer wordCount; | ||
| 31 | + | ||
| 32 | + @Schema(description = "切片状态", example = "1") | ||
| 33 | + private Integer sliceStatus; | ||
| 34 | + | ||
| 35 | + @Schema(description = "文档状态", example = "1") | ||
| 36 | + private Integer status; | ||
| 37 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - AI 更新 知识库-文档 Request VO") | ||
| 9 | +@Data | ||
| 10 | +public class AiKnowledgeDocumentUpdateReqVO { | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") | ||
| 14 | + @NotNull(message = "编号不能为空") | ||
| 15 | + private Long id; | ||
| 16 | + | ||
| 17 | + @Schema(description = "是否启用", example = "1") | ||
| 18 | + private Integer status; | ||
| 19 | + | ||
| 20 | + @Schema(description = "名称", example = "Java 开发手册") | ||
| 21 | + private String name; | ||
| 22 | + | ||
| 23 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/AiKnowledgeCreateMyReqVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeCreateMyReqVO.java
| 1 | -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo; | 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import jakarta.validation.constraints.NotBlank; | 4 | import jakarta.validation.constraints.NotBlank; |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/AiKnowledgeDocumentCreateReqVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java
| 1 | -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo; | 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import jakarta.validation.constraints.NotBlank; | 4 | import jakarta.validation.constraints.NotBlank; |
| @@ -6,10 +6,8 @@ import jakarta.validation.constraints.NotNull; | @@ -6,10 +6,8 @@ import jakarta.validation.constraints.NotNull; | ||
| 6 | import lombok.Data; | 6 | import lombok.Data; |
| 7 | import org.hibernate.validator.constraints.URL; | 7 | import org.hibernate.validator.constraints.URL; |
| 8 | 8 | ||
| 9 | -/** | ||
| 10 | - * @author xiaoxin | ||
| 11 | - */ | ||
| 12 | -@Schema(description = "管理后台 - AI 知识库【创建文档】 Request VO") | 9 | + |
| 10 | +@Schema(description = "管理后台 - AI 知识库创建【文档】 Request VO") | ||
| 13 | @Data | 11 | @Data |
| 14 | public class AiKnowledgeDocumentCreateReqVO { | 12 | public class AiKnowledgeDocumentCreateReqVO { |
| 15 | 13 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - AI 知识库 Response VO") | ||
| 8 | +@Data | ||
| 9 | +public class AiKnowledgeRespVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南") | ||
| 15 | + private String name; | ||
| 16 | + | ||
| 17 | + @Schema(description = "知识库描述", example = "ruoyi-vue-pro 用户指南") | ||
| 18 | + private String description; | ||
| 19 | + | ||
| 20 | + @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "14") | ||
| 21 | + private Long modelId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "模型标识", example = "qwen-72b-chat") | ||
| 24 | + private String model; | ||
| 25 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/AiKnowledgeUpdateMyReqVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeUpdateMyReqVO.java
| 1 | -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo; | 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; |
| 2 | 2 | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import jakarta.validation.constraints.NotBlank; | 4 | import jakarta.validation.constraints.NotBlank; |
| @@ -7,7 +7,7 @@ import lombok.Data; | @@ -7,7 +7,7 @@ import lombok.Data; | ||
| 7 | 7 | ||
| 8 | import java.util.List; | 8 | import java.util.List; |
| 9 | 9 | ||
| 10 | -@Schema(description = "管理后台 - AI 知识库创建【我的】 Request VO") | 10 | +@Schema(description = "管理后台 - AI 知识库更新【我的】 Request VO") |
| 11 | @Data | 11 | @Data |
| 12 | public class AiKnowledgeUpdateMyReqVO { | 12 | public class AiKnowledgeUpdateMyReqVO { |
| 13 | 13 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - AI 知识库分页 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class AiKnowledgeSegmentPageReqVO extends PageParam { | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + @Schema(description = "分段状态", example = "1") | ||
| 13 | + private Integer status; | ||
| 14 | + | ||
| 15 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 16 | + private Integer documentId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "分段内容关键字", example = "Java 开发") | ||
| 19 | + private String keyword; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +@Schema(description = "管理后台 - AI 知识库-文档 Response VO") | ||
| 7 | +@Data | ||
| 8 | +public class AiKnowledgeSegmentRespVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 11 | + private Long id; | ||
| 12 | + | ||
| 13 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 14 | + private Long documentId; | ||
| 15 | + | ||
| 16 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 17 | + private Long knowledgeId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "向量库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1858496a-1dde-4edf-a43e-0aed08f37f8c") | ||
| 20 | + private String vectorId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") | ||
| 23 | + private String content; | ||
| 24 | + | ||
| 25 | + @Schema(description = "token 数量", example = "1024") | ||
| 26 | + private Integer tokens; | ||
| 27 | + | ||
| 28 | + @Schema(description = "字符数", example = "1008") | ||
| 29 | + private Integer wordCount; | ||
| 30 | + | ||
| 31 | + @Schema(description = "文档状态", example = "1") | ||
| 32 | + private Integer status; | ||
| 33 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - AI 更新 知识库-段落 request VO") | ||
| 8 | +@Data | ||
| 9 | +public class AiKnowledgeSegmentUpdateReqVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") | ||
| 15 | + private String content; | ||
| 16 | + | ||
| 17 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - AI 更新 知识库-段落 request VO") | ||
| 8 | +@Data | ||
| 9 | +public class AiKnowledgeSegmentUpdateStatusReqVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 15 | + private Integer status; | ||
| 16 | + | ||
| 17 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeBaseDO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java
| @@ -10,15 +10,14 @@ import lombok.Data; | @@ -10,15 +10,14 @@ import lombok.Data; | ||
| 10 | 10 | ||
| 11 | import java.util.List; | 11 | import java.util.List; |
| 12 | 12 | ||
| 13 | -// TODO @xin:要不把 AiKnowledgeBaseDO 改成 AiKnowledgeDO。感觉 base 后缀,感觉有点奇怪(让人以为是基类)。然后,我们很多地方的外键编号,都是 knowledgeId | ||
| 14 | /** | 13 | /** |
| 15 | * AI 知识库 DO | 14 | * AI 知识库 DO |
| 16 | * | 15 | * |
| 17 | * @author xiaoxin | 16 | * @author xiaoxin |
| 18 | */ | 17 | */ |
| 19 | -@TableName(value = "ai_knowledge_base", autoResultMap = true) | 18 | +@TableName(value = "ai_knowledge", autoResultMap = true) |
| 20 | @Data | 19 | @Data |
| 21 | -public class AiKnowledgeBaseDO extends BaseDO { | 20 | +public class AiKnowledgeDO extends BaseDO { |
| 22 | 21 | ||
| 23 | /** | 22 | /** |
| 24 | * 编号 | 23 | * 编号 |
| @@ -46,7 +45,7 @@ public class AiKnowledgeBaseDO extends BaseDO { | @@ -46,7 +45,7 @@ public class AiKnowledgeBaseDO extends BaseDO { | ||
| 46 | @TableField(typeHandler = JacksonTypeHandler.class) | 45 | @TableField(typeHandler = JacksonTypeHandler.class) |
| 47 | private List<Long> visibilityPermissions; | 46 | private List<Long> visibilityPermissions; |
| 48 | /** | 47 | /** |
| 49 | - * 嵌入模型编号,高质量模式时维护 | 48 | + * 嵌入模型编号 |
| 50 | */ | 49 | */ |
| 51 | private Long modelId; | 50 | private Long modelId; |
| 52 | /** | 51 | /** |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java
| @@ -24,7 +24,7 @@ public class AiKnowledgeDocumentDO extends BaseDO { | @@ -24,7 +24,7 @@ public class AiKnowledgeDocumentDO extends BaseDO { | ||
| 24 | /** | 24 | /** |
| 25 | * 知识库编号 | 25 | * 知识库编号 |
| 26 | * | 26 | * |
| 27 | - * 关联 {@link AiKnowledgeBaseDO#getId()} | 27 | + * 关联 {@link AiKnowledgeDO#getId()} |
| 28 | */ | 28 | */ |
| 29 | private Long knowledgeId; | 29 | private Long knowledgeId; |
| 30 | /** | 30 | /** |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java
| @@ -15,6 +15,8 @@ import lombok.Data; | @@ -15,6 +15,8 @@ import lombok.Data; | ||
| 15 | @Data | 15 | @Data |
| 16 | public class AiKnowledgeSegmentDO extends BaseDO { | 16 | public class AiKnowledgeSegmentDO extends BaseDO { |
| 17 | 17 | ||
| 18 | + public static final String FIELD_KNOWLEDGE_ID = "knowledgeId"; | ||
| 19 | + | ||
| 18 | /** | 20 | /** |
| 19 | * 编号 | 21 | * 编号 |
| 20 | */ | 22 | */ |
| @@ -24,10 +26,14 @@ public class AiKnowledgeSegmentDO extends BaseDO { | @@ -24,10 +26,14 @@ public class AiKnowledgeSegmentDO extends BaseDO { | ||
| 24 | * 向量库的编号 | 26 | * 向量库的编号 |
| 25 | */ | 27 | */ |
| 26 | private String vectorId; | 28 | private String vectorId; |
| 27 | - // TODO @新:knowledgeId 加个,会方便点 | 29 | + /** |
| 30 | + * 知识库编号 | ||
| 31 | + * 关联 {@link AiKnowledgeDO#getId()} | ||
| 32 | + */ | ||
| 33 | + private Long knowledgeId; | ||
| 28 | /** | 34 | /** |
| 29 | * 文档编号 | 35 | * 文档编号 |
| 30 | - * | 36 | + * <p> |
| 31 | * 关联 {@link AiKnowledgeDocumentDO#getId()} | 37 | * 关联 {@link AiKnowledgeDocumentDO#getId()} |
| 32 | */ | 38 | */ |
| 33 | private Long documentId; | 39 | private Long documentId; |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java
| 1 | package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; | 1 | package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; | ||
| 4 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; | 7 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 9 | ||
| @@ -11,4 +14,11 @@ import org.apache.ibatis.annotations.Mapper; | @@ -11,4 +14,11 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 11 | */ | 14 | */ |
| 12 | @Mapper | 15 | @Mapper |
| 13 | public interface AiKnowledgeDocumentMapper extends BaseMapperX<AiKnowledgeDocumentDO> { | 16 | public interface AiKnowledgeDocumentMapper extends BaseMapperX<AiKnowledgeDocumentDO> { |
| 17 | + | ||
| 18 | + default PageResult<AiKnowledgeDocumentDO> selectPage(AiKnowledgeDocumentPageReqVO reqVO) { | ||
| 19 | + return selectPage(reqVO, new LambdaQueryWrapperX<AiKnowledgeDocumentDO>() | ||
| 20 | + .likeIfPresent(AiKnowledgeDocumentDO::getName, reqVO.getName()) | ||
| 21 | + .orderByDesc(AiKnowledgeDocumentDO::getId)); | ||
| 22 | + } | ||
| 23 | + | ||
| 14 | } | 24 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeBaseMapper.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java
| 1 | package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; | 1 | package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeBaseDO; | 7 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 8 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; | ||
| 5 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 10 | ||
| 7 | /** | 11 | /** |
| @@ -10,5 +14,12 @@ import org.apache.ibatis.annotations.Mapper; | @@ -10,5 +14,12 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 10 | * @author xiaoxin | 14 | * @author xiaoxin |
| 11 | */ | 15 | */ |
| 12 | @Mapper | 16 | @Mapper |
| 13 | -public interface AiKnowledgeBaseMapper extends BaseMapperX<AiKnowledgeBaseDO> { | 17 | +public interface AiKnowledgeMapper extends BaseMapperX<AiKnowledgeDO> { |
| 18 | + | ||
| 19 | + default PageResult<AiKnowledgeDO> selectPageByMy(Long userId, PageParam pageReqVO) { | ||
| 20 | + return selectPage(pageReqVO, new LambdaQueryWrapperX<AiKnowledgeDO>() | ||
| 21 | + .eq(AiKnowledgeDO::getUserId, userId) | ||
| 22 | + .eq(AiKnowledgeDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) | ||
| 23 | + .orderByDesc(AiKnowledgeDO::getId)); | ||
| 24 | + } | ||
| 14 | } | 25 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java
| 1 | package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; | 1 | package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO; | ||
| 4 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; | 7 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 9 | ||
| @@ -11,4 +14,12 @@ import org.apache.ibatis.annotations.Mapper; | @@ -11,4 +14,12 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 11 | */ | 14 | */ |
| 12 | @Mapper | 15 | @Mapper |
| 13 | public interface AiKnowledgeSegmentMapper extends BaseMapperX<AiKnowledgeSegmentDO> { | 16 | public interface AiKnowledgeSegmentMapper extends BaseMapperX<AiKnowledgeSegmentDO> { |
| 17 | + | ||
| 18 | + default PageResult<AiKnowledgeSegmentDO> selectPage(AiKnowledgeSegmentPageReqVO reqVO) { | ||
| 19 | + return selectPage(reqVO, new LambdaQueryWrapperX<AiKnowledgeSegmentDO>() | ||
| 20 | + .eq(AiKnowledgeSegmentDO::getDocumentId, reqVO.getDocumentId()) | ||
| 21 | + .eqIfPresent(AiKnowledgeSegmentDO::getStatus, reqVO.getStatus()) | ||
| 22 | + .likeIfPresent(AiKnowledgeSegmentDO::getContent, reqVO.getKeyword()) | ||
| 23 | + .orderByDesc(AiKnowledgeSegmentDO::getId)); | ||
| 24 | + } | ||
| 14 | } | 25 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiEmbeddingService.java deleted
| 1 | -package cn.iocoder.yudao.module.ai.service.knowledge; | ||
| 2 | - | ||
| 3 | -import org.springframework.ai.document.Document; | ||
| 4 | -import org.springframework.ai.vectorstore.SearchRequest; | ||
| 5 | - | ||
| 6 | -import java.util.List; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * AI 嵌入 Service 接口 | ||
| 10 | - * | ||
| 11 | - * @author xiaoxin | ||
| 12 | - */ | ||
| 13 | -public interface AiEmbeddingService { | ||
| 14 | - | ||
| 15 | - /** | ||
| 16 | - * 向量化文档并存储 | ||
| 17 | - */ | ||
| 18 | - void add(List<Document> documents); | ||
| 19 | - | ||
| 20 | - /** | ||
| 21 | - * 相似查询 | ||
| 22 | - * | ||
| 23 | - * @param request 查询实体 | ||
| 24 | - */ | ||
| 25 | - List<Document> similaritySearch(SearchRequest request); | ||
| 26 | - | ||
| 27 | -} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiEmbeddingServiceImpl.java deleted
| 1 | -package cn.iocoder.yudao.module.ai.service.knowledge; | ||
| 2 | - | ||
| 3 | -import jakarta.annotation.Resource; | ||
| 4 | -import org.springframework.ai.document.Document; | ||
| 5 | -import org.springframework.ai.vectorstore.RedisVectorStore; | ||
| 6 | -import org.springframework.ai.vectorstore.SearchRequest; | ||
| 7 | -import org.springframework.stereotype.Service; | ||
| 8 | - | ||
| 9 | -import java.util.List; | ||
| 10 | - | ||
| 11 | -// TODO @xin:是不是不用 AiEmbeddingServiceImpl,直接 vectorStore 注入到需要的地方就好啦。通过 KnowledgeDocumentService 返回就好。 | ||
| 12 | -/** | ||
| 13 | - * AI 嵌入 Service 实现类 | ||
| 14 | - * | ||
| 15 | - * @author xiaoxin | ||
| 16 | - */ | ||
| 17 | -@Service | ||
| 18 | -public class AiEmbeddingServiceImpl implements AiEmbeddingService { | ||
| 19 | - | ||
| 20 | - @Resource | ||
| 21 | - private RedisVectorStore vectorStore; | ||
| 22 | - | ||
| 23 | - @Override | ||
| 24 | -// @Async | ||
| 25 | - // TODO xiaoxin 报错先注释 | ||
| 26 | - public void add(List<Document> documents) { | ||
| 27 | - vectorStore.add(documents); | ||
| 28 | - } | ||
| 29 | - | ||
| 30 | - @Override | ||
| 31 | - public List<Document> similaritySearch(SearchRequest request) { | ||
| 32 | - return vectorStore.similaritySearch(request); | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | -} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java
| 1 | package cn.iocoder.yudao.module.ai.service.knowledge; | 1 | package cn.iocoder.yudao.module.ai.service.knowledge; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeDocumentCreateReqVO; | 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; | ||
| 4 | 8 | ||
| 5 | /** | 9 | /** |
| 6 | * AI 知识库-文档 Service 接口 | 10 | * AI 知识库-文档 Service 接口 |
| @@ -17,4 +21,19 @@ public interface AiKnowledgeDocumentService { | @@ -17,4 +21,19 @@ public interface AiKnowledgeDocumentService { | ||
| 17 | */ | 21 | */ |
| 18 | Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO); | 22 | Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO); |
| 19 | 23 | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 获取文档分页 | ||
| 27 | + * | ||
| 28 | + * @param pageReqVO 分页参数 | ||
| 29 | + * @return 文档分页 | ||
| 30 | + */ | ||
| 31 | + PageResult<AiKnowledgeDocumentDO> getKnowledgeDocumentPage(AiKnowledgeDocumentPageReqVO pageReqVO); | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 更新文档 | ||
| 35 | + * | ||
| 36 | + * @param reqVO 更新信息 | ||
| 37 | + */ | ||
| 38 | + void updateKnowledgeDocument(AiKnowledgeDocumentUpdateReqVO reqVO); | ||
| 20 | } | 39 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
| 1 | package cn.iocoder.yudao.module.ai.service.knowledge; | 1 | package cn.iocoder.yudao.module.ai.service.knowledge; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.http.HttpUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeDocumentCreateReqVO; | 9 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; |
| 10 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentUpdateReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; | ||
| 8 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; | 13 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; |
| 9 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; | 14 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; |
| 15 | +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||
| 10 | import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeDocumentMapper; | 16 | import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeDocumentMapper; |
| 11 | import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper; | 17 | import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper; |
| 12 | import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum; | 18 | import cn.iocoder.yudao.module.ai.enums.knowledge.AiKnowledgeDocumentStatusEnum; |
| 19 | +import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | ||
| 20 | +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | ||
| 13 | import jakarta.annotation.Resource; | 21 | import jakarta.annotation.Resource; |
| 14 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
| 15 | import org.springframework.ai.document.Document; | 23 | import org.springframework.ai.document.Document; |
| 16 | import org.springframework.ai.reader.tika.TikaDocumentReader; | 24 | import org.springframework.ai.reader.tika.TikaDocumentReader; |
| 17 | -import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; | 25 | +import org.springframework.ai.tokenizer.TokenCountEstimator; |
| 18 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; | 26 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; |
| 19 | -import org.springframework.beans.factory.annotation.Value; | 27 | +import org.springframework.ai.vectorstore.VectorStore; |
| 28 | +import org.springframework.core.io.ByteArrayResource; | ||
| 20 | import org.springframework.stereotype.Service; | 29 | import org.springframework.stereotype.Service; |
| 21 | import org.springframework.transaction.annotation.Transactional; | 30 | import org.springframework.transaction.annotation.Transactional; |
| 22 | 31 | ||
| 23 | import java.util.List; | 32 | import java.util.List; |
| 24 | -import java.util.Objects; | 33 | +import java.util.Map; |
| 34 | + | ||
| 35 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 36 | +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_DOCUMENT_NOT_EXISTS; | ||
| 25 | 37 | ||
| 26 | /** | 38 | /** |
| 27 | * AI 知识库-文档 Service 实现类 | 39 | * AI 知识库-文档 Service 实现类 |
| @@ -39,53 +51,99 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | @@ -39,53 +51,99 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic | ||
| 39 | 51 | ||
| 40 | @Resource | 52 | @Resource |
| 41 | private TokenTextSplitter tokenTextSplitter; | 53 | private TokenTextSplitter tokenTextSplitter; |
| 42 | - | ||
| 43 | @Resource | 54 | @Resource |
| 44 | - private AiEmbeddingService embeddingService; | 55 | + private TokenCountEstimator tokenCountEstimator; |
| 45 | 56 | ||
| 46 | - // TODO @xin:@Resource 注入 | ||
| 47 | - private static final JTokkitTokenCountEstimator TOKEN_COUNT_ESTIMATOR = new JTokkitTokenCountEstimator(); | 57 | + @Resource |
| 58 | + private AiApiKeyService apiKeyService; | ||
| 59 | + @Resource | ||
| 60 | + private AiKnowledgeService knowledgeService; | ||
| 61 | + @Resource | ||
| 62 | + private AiChatModelService chatModelService; | ||
| 48 | 63 | ||
| 49 | - // TODO xiaoxin 临时测试用,后续删 | ||
| 50 | - @Value("classpath:/webapp/test/Fel.pdf") | ||
| 51 | - private org.springframework.core.io.Resource data; | ||
| 52 | 64 | ||
| 53 | // TODO 芋艿:需要 review 下,代码格式; | 65 | // TODO 芋艿:需要 review 下,代码格式; |
| 54 | - // TODO @xin:最好有 1、/2、/3 这种,让代码更有层次感 | ||
| 55 | @Override | 66 | @Override |
| 56 | @Transactional(rollbackFor = Exception.class) | 67 | @Transactional(rollbackFor = Exception.class) |
| 57 | public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) { | 68 | public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) { |
| 58 | - // TODO xiaoxin 后续从 url 加载 | ||
| 59 | - TikaDocumentReader loader = new TikaDocumentReader(data); | ||
| 60 | - // 加载文档 | 69 | + // 1.1 下载文档 |
| 70 | + String url = createReqVO.getUrl(); | ||
| 71 | + // 1.2 加载文档 | ||
| 72 | + TikaDocumentReader loader = new TikaDocumentReader(downloadFile(url)); | ||
| 61 | List<Document> documents = loader.get(); | 73 | List<Document> documents = loader.get(); |
| 62 | Document document = CollUtil.getFirst(documents); | 74 | Document document = CollUtil.getFirst(documents); |
| 63 | - // TODO @xin:是不是不存在,就抛出异常呀;厚泽 return 呀; | ||
| 64 | - // TODO 芋艿 文档层面有没有可能会比较大,这两个字段是否可以从分段表计算得出?回复:先直接算; | ||
| 65 | - Integer tokens = Objects.nonNull(document) ? TOKEN_COUNT_ESTIMATOR.estimate(document.getContent()) : 0; | ||
| 66 | - Integer wordCount = Objects.nonNull(document) ? document.getContent().length() : 0; | 75 | + String content = document.getContent(); |
| 76 | + Integer tokens = tokenCountEstimator.estimate(content); | ||
| 77 | + Integer wordCount = content.length(); | ||
| 67 | 78 | ||
| 79 | + // 1.3 文档记录入库 | ||
| 68 | AiKnowledgeDocumentDO documentDO = BeanUtils.toBean(createReqVO, AiKnowledgeDocumentDO.class) | 80 | AiKnowledgeDocumentDO documentDO = BeanUtils.toBean(createReqVO, AiKnowledgeDocumentDO.class) |
| 69 | .setTokens(tokens).setWordCount(wordCount) | 81 | .setTokens(tokens).setWordCount(wordCount) |
| 70 | .setStatus(CommonStatusEnum.ENABLE.getStatus()).setSliceStatus(AiKnowledgeDocumentStatusEnum.SUCCESS.getStatus()); | 82 | .setStatus(CommonStatusEnum.ENABLE.getStatus()).setSliceStatus(AiKnowledgeDocumentStatusEnum.SUCCESS.getStatus()); |
| 71 | - // 文档记录入库 | ||
| 72 | documentMapper.insert(documentDO); | 83 | documentMapper.insert(documentDO); |
| 73 | Long documentId = documentDO.getId(); | 84 | Long documentId = documentDO.getId(); |
| 74 | if (CollUtil.isEmpty(documents)) { | 85 | if (CollUtil.isEmpty(documents)) { |
| 75 | return documentId; | 86 | return documentId; |
| 76 | } | 87 | } |
| 77 | 88 | ||
| 78 | - // 文档分段 | 89 | + // 2.1 文档分段 |
| 79 | List<Document> segments = tokenTextSplitter.apply(documents); | 90 | List<Document> segments = tokenTextSplitter.apply(documents); |
| 80 | - // 分段内容入库 | 91 | + // 2.2 分段内容入库 |
| 81 | List<AiKnowledgeSegmentDO> segmentDOList = CollectionUtils.convertList(segments, | 92 | List<AiKnowledgeSegmentDO> segmentDOList = CollectionUtils.convertList(segments, |
| 82 | - segment -> new AiKnowledgeSegmentDO().setContent(segment.getContent()).setDocumentId(documentId) | ||
| 83 | - .setTokens(TOKEN_COUNT_ESTIMATOR.estimate(segment.getContent())).setWordCount(segment.getContent().length()) | 93 | + segment -> new AiKnowledgeSegmentDO().setContent(segment.getContent()).setDocumentId(documentId).setKnowledgeId(createReqVO.getKnowledgeId()).setVectorId(segment.getId()) |
| 94 | + .setTokens(tokenCountEstimator.estimate(segment.getContent())).setWordCount(segment.getContent().length()) | ||
| 84 | .setStatus(CommonStatusEnum.ENABLE.getStatus())); | 95 | .setStatus(CommonStatusEnum.ENABLE.getStatus())); |
| 85 | segmentMapper.insertBatch(segmentDOList); | 96 | segmentMapper.insertBatch(segmentDOList); |
| 86 | - // 向量化并存储 | ||
| 87 | - embeddingService.add(segments); | 97 | + |
| 98 | + // 3.1 document 补充源数据 | ||
| 99 | + segments.forEach(segment -> { | ||
| 100 | + Map<String, Object> metadata = segment.getMetadata(); | ||
| 101 | + metadata.put(AiKnowledgeSegmentDO.FIELD_KNOWLEDGE_ID, createReqVO.getKnowledgeId()); | ||
| 102 | + }); | ||
| 103 | + | ||
| 104 | + AiKnowledgeDO knowledge = knowledgeService.validateKnowledgeExists(createReqVO.getKnowledgeId()); | ||
| 105 | + AiChatModelDO model = chatModelService.validateChatModel(knowledge.getModelId()); | ||
| 106 | + // 3.2 获取向量存储实例 | ||
| 107 | + VectorStore vectorStore = apiKeyService.getOrCreateVectorStore(model.getKeyId()); | ||
| 108 | + // 3.3 向量化并存储 | ||
| 109 | + vectorStore.add(segments); | ||
| 88 | return documentId; | 110 | return documentId; |
| 89 | } | 111 | } |
| 90 | 112 | ||
| 113 | + @Override | ||
| 114 | + public PageResult<AiKnowledgeDocumentDO> getKnowledgeDocumentPage(AiKnowledgeDocumentPageReqVO pageReqVO) { | ||
| 115 | + return documentMapper.selectPage(pageReqVO); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + @Override | ||
| 119 | + public void updateKnowledgeDocument(AiKnowledgeDocumentUpdateReqVO reqVO) { | ||
| 120 | + validateKnowledgeDocumentExists(reqVO.getId()); | ||
| 121 | + AiKnowledgeDocumentDO document = BeanUtils.toBean(reqVO, AiKnowledgeDocumentDO.class); | ||
| 122 | + documentMapper.updateById(document); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + /** | ||
| 126 | + * 校验文档是否存在 | ||
| 127 | + * | ||
| 128 | + * @param id 文档编号 | ||
| 129 | + * @return 文档信息 | ||
| 130 | + */ | ||
| 131 | + private AiKnowledgeDocumentDO validateKnowledgeDocumentExists(Long id) { | ||
| 132 | + AiKnowledgeDocumentDO knowledgeDocument = documentMapper.selectById(id); | ||
| 133 | + if (knowledgeDocument == null) { | ||
| 134 | + throw exception(KNOWLEDGE_DOCUMENT_NOT_EXISTS); | ||
| 135 | + } | ||
| 136 | + return knowledgeDocument; | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + private org.springframework.core.io.Resource downloadFile(String url) { | ||
| 140 | + try { | ||
| 141 | + byte[] bytes = HttpUtil.downloadBytes(url); | ||
| 142 | + return new ByteArrayResource(bytes); | ||
| 143 | + } catch (Exception e) { | ||
| 144 | + log.error("[downloadFile][url({}) 下载失败]", url, e); | ||
| 145 | + throw new RuntimeException(e); | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + | ||
| 91 | } | 149 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentService.java
| 1 | package cn.iocoder.yudao.module.ai.service.knowledge; | 1 | package cn.iocoder.yudao.module.ai.service.knowledge; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; | ||
| 8 | + | ||
| 3 | /** | 9 | /** |
| 4 | * AI 知识库分片 Service 接口 | 10 | * AI 知识库分片 Service 接口 |
| 5 | * | 11 | * |
| @@ -7,4 +13,25 @@ package cn.iocoder.yudao.module.ai.service.knowledge; | @@ -7,4 +13,25 @@ package cn.iocoder.yudao.module.ai.service.knowledge; | ||
| 7 | */ | 13 | */ |
| 8 | public interface AiKnowledgeSegmentService { | 14 | public interface AiKnowledgeSegmentService { |
| 9 | 15 | ||
| 16 | + /** | ||
| 17 | + * 获取段落分页 | ||
| 18 | + * | ||
| 19 | + * @param pageReqVO 分页查询 | ||
| 20 | + * @return 文档分页 | ||
| 21 | + */ | ||
| 22 | + PageResult<AiKnowledgeSegmentDO> getKnowledgeSegmentPage(AiKnowledgeSegmentPageReqVO pageReqVO); | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 更新段落内容 | ||
| 26 | + * | ||
| 27 | + * @param reqVO 更新内容 | ||
| 28 | + */ | ||
| 29 | + void updateKnowledgeSegment(AiKnowledgeSegmentUpdateReqVO reqVO); | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 更新状态 | ||
| 33 | + * | ||
| 34 | + * @param reqVO 更新内容 | ||
| 35 | + */ | ||
| 36 | + void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO); | ||
| 10 | } | 37 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
| 1 | package cn.iocoder.yudao.module.ai.service.knowledge; | 1 | package cn.iocoder.yudao.module.ai.service.knowledge; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; | ||
| 9 | +import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper; | ||
| 10 | +import jakarta.annotation.Resource; | ||
| 3 | import lombok.extern.slf4j.Slf4j; | 11 | import lombok.extern.slf4j.Slf4j; |
| 4 | import org.springframework.stereotype.Service; | 12 | import org.springframework.stereotype.Service; |
| 5 | 13 | ||
| @@ -12,4 +20,23 @@ import org.springframework.stereotype.Service; | @@ -12,4 +20,23 @@ import org.springframework.stereotype.Service; | ||
| 12 | @Slf4j | 20 | @Slf4j |
| 13 | public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService { | 21 | public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService { |
| 14 | 22 | ||
| 23 | + @Resource | ||
| 24 | + private AiKnowledgeSegmentMapper segmentMapper; | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public PageResult<AiKnowledgeSegmentDO> getKnowledgeSegmentPage(AiKnowledgeSegmentPageReqVO pageReqVO) { | ||
| 28 | + return segmentMapper.selectPage(pageReqVO); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public void updateKnowledgeSegment(AiKnowledgeSegmentUpdateReqVO reqVO) { | ||
| 33 | + segmentMapper.updateById(BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class)); | ||
| 34 | + // TODO @xin 重新向量化 | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public void updateKnowledgeSegmentStatus(AiKnowledgeSegmentUpdateStatusReqVO reqVO) { | ||
| 39 | + segmentMapper.updateById(BeanUtils.toBean(reqVO, AiKnowledgeSegmentDO.class)); | ||
| 40 | + // TODO @xin 1.禁用删除向量 2.启用重新向量化 | ||
| 41 | + } | ||
| 15 | } | 42 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeBaseService.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeService.java
| 1 | package cn.iocoder.yudao.module.ai.service.knowledge; | 1 | package cn.iocoder.yudao.module.ai.service.knowledge; |
| 2 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeCreateMyReqVO; | ||
| 3 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeUpdateMyReqVO; | 2 | + |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; | ||
| 4 | 8 | ||
| 5 | /** | 9 | /** |
| 6 | * AI 知识库-基础信息 Service 接口 | 10 | * AI 知识库-基础信息 Service 接口 |
| 7 | * | 11 | * |
| 8 | * @author xiaoxin | 12 | * @author xiaoxin |
| 9 | */ | 13 | */ |
| 10 | -public interface AiKnowledgeBaseService { | 14 | +public interface AiKnowledgeService { |
| 11 | 15 | ||
| 12 | /** | 16 | /** |
| 13 | * 创建【我的】知识库 | 17 | * 创建【我的】知识库 |
| 14 | * | 18 | * |
| 15 | * @param createReqVO 创建信息 | 19 | * @param createReqVO 创建信息 |
| 16 | - * @param userId 用户编号 | 20 | + * @param userId 用户编号 |
| 17 | * @return 编号 | 21 | * @return 编号 |
| 18 | */ | 22 | */ |
| 19 | Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId); | 23 | Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId); |
| @@ -23,8 +27,24 @@ public interface AiKnowledgeBaseService { | @@ -23,8 +27,24 @@ public interface AiKnowledgeBaseService { | ||
| 23 | * 创建【我的】知识库 | 27 | * 创建【我的】知识库 |
| 24 | * | 28 | * |
| 25 | * @param updateReqVO 更新信息 | 29 | * @param updateReqVO 更新信息 |
| 26 | - * @param userId 用户编号 | 30 | + * @param userId 用户编号 |
| 27 | */ | 31 | */ |
| 28 | void updateKnowledgeMy(AiKnowledgeUpdateMyReqVO updateReqVO, Long userId); | 32 | void updateKnowledgeMy(AiKnowledgeUpdateMyReqVO updateReqVO, Long userId); |
| 29 | 33 | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 校验知识库是否存在 | ||
| 37 | + * | ||
| 38 | + * @param id 记录编号 | ||
| 39 | + */ | ||
| 40 | + AiKnowledgeDO validateKnowledgeExists(Long id); | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 获得【我的】知识库分页 | ||
| 44 | + * | ||
| 45 | + * @param userId 用户编号 | ||
| 46 | + * @param pageReqVO 分页查询 | ||
| 47 | + * @return 知识库分页 | ||
| 48 | + */ | ||
| 49 | + PageResult<AiKnowledgeDO> getKnowledgePageMy(Long userId, PageParam pageReqVO); | ||
| 30 | } | 50 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeBaseServiceImpl.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeServiceImpl.java
| 1 | package cn.iocoder.yudao.module.ai.service.knowledge; | 1 | package cn.iocoder.yudao.module.ai.service.knowledge; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.lang.Assert; | ||
| 4 | import cn.hutool.core.util.ObjUtil; | 3 | import cn.hutool.core.util.ObjUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeCreateMyReqVO; | ||
| 8 | -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.AiKnowledgeUpdateMyReqVO; | ||
| 9 | -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeBaseDO; | 8 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeCreateMyReqVO; |
| 9 | +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeUpdateMyReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; | ||
| 10 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | 11 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; |
| 11 | -import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeBaseMapper; | 12 | +import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeMapper; |
| 12 | import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | 13 | import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; |
| 13 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 14 | import lombok.extern.slf4j.Slf4j; | 15 | import lombok.extern.slf4j.Slf4j; |
| @@ -24,56 +25,54 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_ | @@ -24,56 +25,54 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_NOT_ | ||
| 24 | */ | 25 | */ |
| 25 | @Service | 26 | @Service |
| 26 | @Slf4j | 27 | @Slf4j |
| 27 | -public class AiKnowledgeBaseServiceImpl implements AiKnowledgeBaseService { | 28 | +public class AiKnowledgeServiceImpl implements AiKnowledgeService { |
| 28 | 29 | ||
| 29 | @Resource | 30 | @Resource |
| 30 | private AiChatModelService chatModalService; | 31 | private AiChatModelService chatModalService; |
| 31 | 32 | ||
| 32 | @Resource | 33 | @Resource |
| 33 | - private AiKnowledgeBaseMapper knowledgeBaseMapper; | 34 | + private AiKnowledgeMapper knowledgeMapper; |
| 34 | 35 | ||
| 35 | @Override | 36 | @Override |
| 36 | public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) { | 37 | public Long createKnowledgeMy(AiKnowledgeCreateMyReqVO createReqVO, Long userId) { |
| 37 | - // TODO @xin:貌似直接调用 chatModalService.validateChatModel(id) 完事,不用搞个方法 | ||
| 38 | // 1. 校验模型配置 | 38 | // 1. 校验模型配置 |
| 39 | - AiChatModelDO model = validateChatModel(createReqVO.getModelId()); | 39 | + AiChatModelDO model = chatModalService.validateChatModel(createReqVO.getModelId()); |
| 40 | 40 | ||
| 41 | // 2. 插入知识库 | 41 | // 2. 插入知识库 |
| 42 | - // TODO @xin:不用 DO 结尾 | ||
| 43 | - AiKnowledgeBaseDO knowledgeBaseDO = BeanUtils.toBean(createReqVO, AiKnowledgeBaseDO.class) | 42 | + AiKnowledgeDO knowledgeBase = BeanUtils.toBean(createReqVO, AiKnowledgeDO.class) |
| 44 | .setModel(model.getModel()).setUserId(userId).setStatus(CommonStatusEnum.ENABLE.getStatus()); | 43 | .setModel(model.getModel()).setUserId(userId).setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| 45 | - knowledgeBaseMapper.insert(knowledgeBaseDO); | ||
| 46 | - return knowledgeBaseDO.getId(); | 44 | + knowledgeMapper.insert(knowledgeBase); |
| 45 | + return knowledgeBase.getId(); | ||
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | @Override | 48 | @Override |
| 50 | public void updateKnowledgeMy(AiKnowledgeUpdateMyReqVO updateReqVO, Long userId) { | 49 | public void updateKnowledgeMy(AiKnowledgeUpdateMyReqVO updateReqVO, Long userId) { |
| 51 | // 1.1 校验知识库存在 | 50 | // 1.1 校验知识库存在 |
| 52 | - AiKnowledgeBaseDO knowledgeBaseDO = validateKnowledgeExists(updateReqVO.getId()); | 51 | + AiKnowledgeDO knowledgeBaseDO = validateKnowledgeExists(updateReqVO.getId()); |
| 53 | if (ObjUtil.notEqual(knowledgeBaseDO.getUserId(), userId)) { | 52 | if (ObjUtil.notEqual(knowledgeBaseDO.getUserId(), userId)) { |
| 54 | throw exception(KNOWLEDGE_NOT_EXISTS); | 53 | throw exception(KNOWLEDGE_NOT_EXISTS); |
| 55 | } | 54 | } |
| 56 | // 1.2 校验模型配置 | 55 | // 1.2 校验模型配置 |
| 57 | - AiChatModelDO model = validateChatModel(updateReqVO.getModelId()); | 56 | + AiChatModelDO model = chatModalService.validateChatModel(updateReqVO.getModelId()); |
| 58 | 57 | ||
| 59 | // 2. 更新知识库 | 58 | // 2. 更新知识库 |
| 60 | - AiKnowledgeBaseDO updateDO = BeanUtils.toBean(updateReqVO, AiKnowledgeBaseDO.class); | 59 | + AiKnowledgeDO updateDO = BeanUtils.toBean(updateReqVO, AiKnowledgeDO.class); |
| 61 | updateDO.setModel(model.getModel()); | 60 | updateDO.setModel(model.getModel()); |
| 62 | - knowledgeBaseMapper.updateById(updateDO); | 61 | + knowledgeMapper.updateById(updateDO); |
| 63 | } | 62 | } |
| 64 | 63 | ||
| 65 | - private AiChatModelDO validateChatModel(Long id) { | ||
| 66 | - AiChatModelDO model = chatModalService.validateChatModel(id); | ||
| 67 | - Assert.notNull(model, "未找到对应嵌入模型"); | ||
| 68 | - return model; | ||
| 69 | - } | ||
| 70 | - | ||
| 71 | - public AiKnowledgeBaseDO validateKnowledgeExists(Long id) { | ||
| 72 | - AiKnowledgeBaseDO knowledgeBase = knowledgeBaseMapper.selectById(id); | 64 | + @Override |
| 65 | + public AiKnowledgeDO validateKnowledgeExists(Long id) { | ||
| 66 | + AiKnowledgeDO knowledgeBase = knowledgeMapper.selectById(id); | ||
| 73 | if (knowledgeBase == null) { | 67 | if (knowledgeBase == null) { |
| 74 | throw exception(KNOWLEDGE_NOT_EXISTS); | 68 | throw exception(KNOWLEDGE_NOT_EXISTS); |
| 75 | } | 69 | } |
| 76 | return knowledgeBase; | 70 | return knowledgeBase; |
| 77 | } | 71 | } |
| 78 | 72 | ||
| 73 | + @Override | ||
| 74 | + public PageResult<AiKnowledgeDO> getKnowledgePageMy(Long userId, PageParam pageReqVO) { | ||
| 75 | + return knowledgeMapper.selectPageByMy(userId, pageReqVO); | ||
| 76 | + } | ||
| 77 | + | ||
| 79 | } | 78 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java
| @@ -9,7 +9,9 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR | @@ -9,7 +9,9 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR | ||
| 9 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; | 9 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; |
| 10 | import jakarta.validation.Valid; | 10 | import jakarta.validation.Valid; |
| 11 | import org.springframework.ai.chat.model.ChatModel; | 11 | import org.springframework.ai.chat.model.ChatModel; |
| 12 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 12 | import org.springframework.ai.image.ImageModel; | 13 | import org.springframework.ai.image.ImageModel; |
| 14 | +import org.springframework.ai.vectorstore.VectorStore; | ||
| 13 | 15 | ||
| 14 | import java.util.List; | 16 | import java.util.List; |
| 15 | 17 | ||
| @@ -84,6 +86,14 @@ public interface AiApiKeyService { | @@ -84,6 +86,14 @@ public interface AiApiKeyService { | ||
| 84 | ChatModel getChatModel(Long id); | 86 | ChatModel getChatModel(Long id); |
| 85 | 87 | ||
| 86 | /** | 88 | /** |
| 89 | + * 获得 EmbeddingModel 对象 | ||
| 90 | + * | ||
| 91 | + * @param id 编号 | ||
| 92 | + * @return EmbeddingModel 对象 | ||
| 93 | + */ | ||
| 94 | + EmbeddingModel getEmbeddingModel(Long id); | ||
| 95 | + | ||
| 96 | + /** | ||
| 87 | * 获得 ImageModel 对象 | 97 | * 获得 ImageModel 对象 |
| 88 | * | 98 | * |
| 89 | * TODO 可优化点:目前默认获取 platform 对应的第一个开启的配置用于绘画;后续可以支持配置选择 | 99 | * TODO 可优化点:目前默认获取 platform 对应的第一个开启的配置用于绘画;后续可以支持配置选择 |
| @@ -111,4 +121,12 @@ public interface AiApiKeyService { | @@ -111,4 +121,12 @@ public interface AiApiKeyService { | ||
| 111 | */ | 121 | */ |
| 112 | SunoApi getSunoApi(); | 122 | SunoApi getSunoApi(); |
| 113 | 123 | ||
| 124 | + /** | ||
| 125 | + * 获得 vector 对象 | ||
| 126 | + * | ||
| 127 | + * @param id 编号 | ||
| 128 | + * @return VectorStore 对象 | ||
| 129 | + */ | ||
| 130 | + VectorStore getOrCreateVectorStore(Long id); | ||
| 131 | + | ||
| 114 | } | 132 | } |
| 115 | \ No newline at end of file | 133 | \ No newline at end of file |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.model; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.model; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | 3 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 4 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; | 4 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; |
| 5 | +import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactory; | ||
| 5 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; | 6 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| 6 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; | 7 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 8 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| @@ -13,7 +14,9 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; | @@ -13,7 +14,9 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; | ||
| 13 | import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; | 14 | import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; |
| 14 | import jakarta.annotation.Resource; | 15 | import jakarta.annotation.Resource; |
| 15 | import org.springframework.ai.chat.model.ChatModel; | 16 | import org.springframework.ai.chat.model.ChatModel; |
| 17 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 16 | import org.springframework.ai.image.ImageModel; | 18 | import org.springframework.ai.image.ImageModel; |
| 19 | +import org.springframework.ai.vectorstore.VectorStore; | ||
| 17 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
| 18 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 19 | 22 | ||
| @@ -36,6 +39,8 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | @@ -36,6 +39,8 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | ||
| 36 | 39 | ||
| 37 | @Resource | 40 | @Resource |
| 38 | private AiModelFactory modelFactory; | 41 | private AiModelFactory modelFactory; |
| 42 | + @Resource | ||
| 43 | + private AiVectorStoreFactory vectorFactory; | ||
| 39 | 44 | ||
| 40 | @Override | 45 | @Override |
| 41 | public Long createApiKey(AiApiKeySaveReqVO createReqVO) { | 46 | public Long createApiKey(AiApiKeySaveReqVO createReqVO) { |
| @@ -105,6 +110,13 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | @@ -105,6 +110,13 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | ||
| 105 | } | 110 | } |
| 106 | 111 | ||
| 107 | @Override | 112 | @Override |
| 113 | + public EmbeddingModel getEmbeddingModel(Long id) { | ||
| 114 | + AiApiKeyDO apiKey = validateApiKey(id); | ||
| 115 | + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform()); | ||
| 116 | + return modelFactory.getOrCreateEmbeddingModel(platform, apiKey.getApiKey(), apiKey.getUrl()); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + @Override | ||
| 108 | public ImageModel getImageModel(AiPlatformEnum platform) { | 120 | public ImageModel getImageModel(AiPlatformEnum platform) { |
| 109 | AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getPlatform(), CommonStatusEnum.ENABLE.getStatus()); | 121 | AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getPlatform(), CommonStatusEnum.ENABLE.getStatus()); |
| 110 | if (apiKey == null) { | 122 | if (apiKey == null) { |
| @@ -132,4 +144,11 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | @@ -132,4 +144,11 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | ||
| 132 | } | 144 | } |
| 133 | return modelFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl()); | 145 | return modelFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl()); |
| 134 | } | 146 | } |
| 147 | + | ||
| 148 | + @Override | ||
| 149 | + public VectorStore getOrCreateVectorStore(Long id) { | ||
| 150 | + AiApiKeyDO apiKey = validateApiKey(id); | ||
| 151 | + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform()); | ||
| 152 | + return vectorFactory.getOrCreateVectorStore(getEmbeddingModel(id), platform, apiKey.getApiKey(), apiKey.getUrl()); | ||
| 153 | + } | ||
| 135 | } | 154 | } |
| 136 | \ No newline at end of file | 155 | \ No newline at end of file |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
| @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.ai.config; | @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.ai.config; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; | 3 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; |
| 4 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl; | 4 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl; |
| 5 | +import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactory; | ||
| 6 | +import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactoryImpl; | ||
| 5 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; | 7 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; |
| 6 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions; | 8 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions; |
| 7 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; | 9 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| @@ -10,20 +12,15 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; | @@ -10,20 +12,15 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; | ||
| 10 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatOptions; | 12 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatOptions; |
| 11 | import com.alibaba.cloud.ai.tongyi.TongYiAutoConfiguration; | 13 | import com.alibaba.cloud.ai.tongyi.TongYiAutoConfiguration; |
| 12 | import lombok.extern.slf4j.Slf4j; | 14 | import lombok.extern.slf4j.Slf4j; |
| 13 | -import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; | ||
| 14 | -import org.springframework.ai.document.MetadataMode; | ||
| 15 | -import org.springframework.ai.embedding.EmbeddingModel; | 15 | +import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; |
| 16 | +import org.springframework.ai.tokenizer.TokenCountEstimator; | ||
| 16 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; | 17 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; |
| 17 | -import org.springframework.ai.transformers.TransformersEmbeddingModel; | ||
| 18 | -import org.springframework.ai.vectorstore.RedisVectorStore; | ||
| 19 | import org.springframework.boot.autoconfigure.AutoConfiguration; | 18 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 20 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 21 | -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | ||
| 22 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 20 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 23 | import org.springframework.context.annotation.Bean; | 21 | import org.springframework.context.annotation.Bean; |
| 24 | import org.springframework.context.annotation.Import; | 22 | import org.springframework.context.annotation.Import; |
| 25 | import org.springframework.context.annotation.Lazy; | 23 | import org.springframework.context.annotation.Lazy; |
| 26 | -import redis.clients.jedis.JedisPooled; | ||
| 27 | 24 | ||
| 28 | /** | 25 | /** |
| 29 | * 芋道 AI 自动配置 | 26 | * 芋道 AI 自动配置 |
| @@ -41,6 +38,12 @@ public class YudaoAiAutoConfiguration { | @@ -41,6 +38,12 @@ public class YudaoAiAutoConfiguration { | ||
| 41 | return new AiModelFactoryImpl(); | 38 | return new AiModelFactoryImpl(); |
| 42 | } | 39 | } |
| 43 | 40 | ||
| 41 | + @Bean | ||
| 42 | + public AiVectorStoreFactory aiVectorFactory() { | ||
| 43 | + return new AiVectorStoreFactoryImpl(); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + | ||
| 44 | // ========== 各种 AI Client 创建 ========== | 47 | // ========== 各种 AI Client 创建 ========== |
| 45 | 48 | ||
| 46 | @Bean | 49 | @Bean |
| @@ -83,35 +86,42 @@ public class YudaoAiAutoConfiguration { | @@ -83,35 +86,42 @@ public class YudaoAiAutoConfiguration { | ||
| 83 | } | 86 | } |
| 84 | 87 | ||
| 85 | // ========== rag 相关 ========== | 88 | // ========== rag 相关 ========== |
| 86 | - @Bean | ||
| 87 | - @Lazy // TODO 芋艿:临时注释,避免无法启动 | ||
| 88 | - public EmbeddingModel transformersEmbeddingClient() { | ||
| 89 | - return new TransformersEmbeddingModel(MetadataMode.EMBED); | ||
| 90 | - } | 89 | + // TODO @xin 免费版本 |
| 90 | +// @Bean | ||
| 91 | +// @Lazy // TODO 芋艿:临时注释,避免无法启动」 | ||
| 92 | +// public EmbeddingModel transformersEmbeddingClient() { | ||
| 93 | +// return new TransformersEmbeddingModel(MetadataMode.EMBED); | ||
| 94 | +// } | ||
| 91 | 95 | ||
| 92 | /** | 96 | /** |
| 93 | - * 我们启动有加载很多 Embedding 模型,不晓得取哪个好,先 new 个 TransformersEmbeddingModel 跑 | 97 | + * TODO @xin 默认版本先不弄,目前都先取对应的 EmbeddingModel |
| 94 | */ | 98 | */ |
| 99 | +// @Bean | ||
| 100 | +// @Lazy // TODO 芋艿:临时注释,避免无法启动 | ||
| 101 | +// public RedisVectorStore vectorStore(TongYiTextEmbeddingModel tongYiTextEmbeddingModel, RedisVectorStoreProperties properties, | ||
| 102 | +// RedisProperties redisProperties) { | ||
| 103 | +// var config = RedisVectorStore.RedisVectorStoreConfig.builder() | ||
| 104 | +// .withIndexName(properties.getIndex()) | ||
| 105 | +// .withPrefix(properties.getPrefix()) | ||
| 106 | +// .build(); | ||
| 107 | +// | ||
| 108 | +// RedisVectorStore redisVectorStore = new RedisVectorStore(config, tongYiTextEmbeddingModel, | ||
| 109 | +// new JedisPooled(redisProperties.getHost(), redisProperties.getPort()), | ||
| 110 | +// properties.isInitializeSchema()); | ||
| 111 | +// redisVectorStore.afterPropertiesSet(); | ||
| 112 | +// return redisVectorStore; | ||
| 113 | +// } | ||
| 114 | + | ||
| 95 | @Bean | 115 | @Bean |
| 96 | @Lazy // TODO 芋艿:临时注释,避免无法启动 | 116 | @Lazy // TODO 芋艿:临时注释,避免无法启动 |
| 97 | - public RedisVectorStore vectorStore(TransformersEmbeddingModel transformersEmbeddingModel, RedisVectorStoreProperties properties, | ||
| 98 | - RedisProperties redisProperties) { | ||
| 99 | - var config = RedisVectorStore.RedisVectorStoreConfig.builder() | ||
| 100 | - .withIndexName(properties.getIndex()) | ||
| 101 | - .withPrefix(properties.getPrefix()) | ||
| 102 | - .build(); | ||
| 103 | - | ||
| 104 | - RedisVectorStore redisVectorStore = new RedisVectorStore(config, transformersEmbeddingModel, | ||
| 105 | - new JedisPooled(redisProperties.getHost(), redisProperties.getPort()), | ||
| 106 | - properties.isInitializeSchema()); | ||
| 107 | - redisVectorStore.afterPropertiesSet(); | ||
| 108 | - return redisVectorStore; | 117 | + public TokenTextSplitter tokenTextSplitter() { |
| 118 | + return new TokenTextSplitter(500, 100, 5, 10000, true); | ||
| 109 | } | 119 | } |
| 110 | 120 | ||
| 111 | @Bean | 121 | @Bean |
| 112 | @Lazy // TODO 芋艿:临时注释,避免无法启动 | 122 | @Lazy // TODO 芋艿:临时注释,避免无法启动 |
| 113 | - public TokenTextSplitter tokenTextSplitter() { | ||
| 114 | - return new TokenTextSplitter(500, 100, 5, 10000, true); | 123 | + public TokenCountEstimator tokenCountEstimator() { |
| 124 | + return new JTokkitTokenCountEstimator(); | ||
| 115 | } | 125 | } |
| 116 | 126 | ||
| 117 | } | 127 | } |
| 118 | \ No newline at end of file | 128 | \ No newline at end of file |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactory.java
| @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | ||
| 4 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; | 4 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| 5 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; | 5 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 6 | import org.springframework.ai.chat.model.ChatModel; | 6 | import org.springframework.ai.chat.model.ChatModel; |
| 7 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 7 | import org.springframework.ai.image.ImageModel; | 8 | import org.springframework.ai.image.ImageModel; |
| 8 | 9 | ||
| 9 | /** | 10 | /** |
| @@ -26,6 +27,18 @@ public interface AiModelFactory { | @@ -26,6 +27,18 @@ public interface AiModelFactory { | ||
| 26 | ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url); | 27 | ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url); |
| 27 | 28 | ||
| 28 | /** | 29 | /** |
| 30 | + * 基于指定配置,获得 EmbeddingModel 对象 | ||
| 31 | + * <p> | ||
| 32 | + * 如果不存在,则进行创建 | ||
| 33 | + * | ||
| 34 | + * @param platform 平台 | ||
| 35 | + * @param apiKey API KEY | ||
| 36 | + * @param url API URL | ||
| 37 | + * @return ChatModel 对象 | ||
| 38 | + */ | ||
| 39 | + EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url); | ||
| 40 | + | ||
| 41 | + /** | ||
| 29 | * 基于默认配置,获得 ChatModel 对象 | 42 | * 基于默认配置,获得 ChatModel 对象 |
| 30 | * | 43 | * |
| 31 | * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 | 44 | * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
| @@ -21,6 +21,7 @@ import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; | @@ -21,6 +21,7 @@ import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; | ||
| 21 | import com.alibaba.cloud.ai.tongyi.image.TongYiImagesProperties; | 21 | import com.alibaba.cloud.ai.tongyi.image.TongYiImagesProperties; |
| 22 | import com.alibaba.dashscope.aigc.generation.Generation; | 22 | import com.alibaba.dashscope.aigc.generation.Generation; |
| 23 | import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; | 23 | import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; |
| 24 | +import com.alibaba.dashscope.embeddings.TextEmbedding; | ||
| 24 | import com.azure.ai.openai.OpenAIClient; | 25 | import com.azure.ai.openai.OpenAIClient; |
| 25 | import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; | 26 | import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; |
| 26 | import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; | 27 | import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; |
| @@ -37,6 +38,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; | @@ -37,6 +38,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; | ||
| 37 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties; | 38 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties; |
| 38 | import org.springframework.ai.azure.openai.AzureOpenAiChatModel; | 39 | import org.springframework.ai.azure.openai.AzureOpenAiChatModel; |
| 39 | import org.springframework.ai.chat.model.ChatModel; | 40 | import org.springframework.ai.chat.model.ChatModel; |
| 41 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 40 | import org.springframework.ai.image.ImageModel; | 42 | import org.springframework.ai.image.ImageModel; |
| 41 | import org.springframework.ai.model.function.FunctionCallbackContext; | 43 | import org.springframework.ai.model.function.FunctionCallbackContext; |
| 42 | import org.springframework.ai.ollama.OllamaChatModel; | 44 | import org.springframework.ai.ollama.OllamaChatModel; |
| @@ -98,6 +100,21 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -98,6 +100,21 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 98 | } | 100 | } |
| 99 | 101 | ||
| 100 | @Override | 102 | @Override |
| 103 | + public EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url) { | ||
| 104 | + String cacheKey = buildClientCacheKey(EmbeddingModel.class, platform, apiKey, url); | ||
| 105 | + return Singleton.get(cacheKey, (Func0<EmbeddingModel>) () -> { | ||
| 106 | + // TODO @xin 先测试一个 | ||
| 107 | + switch (platform) { | ||
| 108 | + case TONG_YI: | ||
| 109 | + return buildTongYiEmbeddingModel(apiKey); | ||
| 110 | + default: | ||
| 111 | + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); | ||
| 112 | + } | ||
| 113 | + }); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + | ||
| 117 | + @Override | ||
| 101 | public ChatModel getDefaultChatModel(AiPlatformEnum platform) { | 118 | public ChatModel getDefaultChatModel(AiPlatformEnum platform) { |
| 102 | //noinspection EnhancedSwitchMigration | 119 | //noinspection EnhancedSwitchMigration |
| 103 | switch (platform) { | 120 | switch (platform) { |
| @@ -239,7 +256,7 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -239,7 +256,7 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 239 | 256 | ||
| 240 | /** | 257 | /** |
| 241 | * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiChatModel( | 258 | * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiChatModel( |
| 242 | - * ZhiPuAiConnectionProperties, ZhiPuAiChatProperties, RestClient.Builder, List, FunctionCallbackContext, RetryTemplate, ResponseErrorHandler)} | 259 | + *ZhiPuAiConnectionProperties, ZhiPuAiChatProperties, RestClient.Builder, List, FunctionCallbackContext, RetryTemplate, ResponseErrorHandler)} |
| 243 | */ | 260 | */ |
| 244 | private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { | 261 | private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { |
| 245 | url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL); | 262 | url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL); |
| @@ -249,7 +266,7 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -249,7 +266,7 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 249 | 266 | ||
| 250 | /** | 267 | /** |
| 251 | * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiImageModel( | 268 | * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiImageModel( |
| 252 | - * ZhiPuAiConnectionProperties, ZhiPuAiImageProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)} | 269 | + *ZhiPuAiConnectionProperties, ZhiPuAiImageProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)} |
| 253 | */ | 270 | */ |
| 254 | private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { | 271 | private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { |
| 255 | url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL); | 272 | url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL); |
| @@ -315,4 +332,15 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -315,4 +332,15 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 315 | return new StabilityAiImageModel(stabilityAiApi); | 332 | return new StabilityAiImageModel(stabilityAiApi); |
| 316 | } | 333 | } |
| 317 | 334 | ||
| 335 | + // ========== 各种创建 EmbeddingModel 的方法 ========== | ||
| 336 | + | ||
| 337 | + /** | ||
| 338 | + * 可参考 {@link TongYiAutoConfiguration#tongYiTextEmbeddingClient(TextEmbedding, TongYiConnectionProperties)} | ||
| 339 | + */ | ||
| 340 | + private EmbeddingModel buildTongYiEmbeddingModel(String apiKey) { | ||
| 341 | + TongYiConnectionProperties connectionProperties = new TongYiConnectionProperties(); | ||
| 342 | + connectionProperties.setApiKey(apiKey); | ||
| 343 | + return new TongYiAutoConfiguration().tongYiTextEmbeddingClient(SpringUtil.getBean(TextEmbedding.class), connectionProperties); | ||
| 344 | + } | ||
| 345 | + | ||
| 318 | } | 346 | } |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiVectorStoreFactory.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.core.factory; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | ||
| 4 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 5 | +import org.springframework.ai.vectorstore.VectorStore; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * AI Vector 模型工厂的接口类 | ||
| 9 | + * @author xiaoxin | ||
| 10 | + */ | ||
| 11 | +public interface AiVectorStoreFactory { | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 基于指定配置,获得 VectorStore 对象 | ||
| 16 | + * <p> | ||
| 17 | + * 如果不存在,则进行创建 | ||
| 18 | + * | ||
| 19 | + * @param embeddingModel 嵌入模型 | ||
| 20 | + * @param platform 平台 | ||
| 21 | + * @param apiKey API KEY | ||
| 22 | + * @param url API URL | ||
| 23 | + * @return VectorStore 对象 | ||
| 24 | + */ | ||
| 25 | + VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url); | ||
| 26 | + | ||
| 27 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiVectorStoreFactoryImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.core.factory; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.lang.Singleton; | ||
| 4 | +import cn.hutool.core.lang.func.Func0; | ||
| 5 | +import cn.hutool.core.util.ArrayUtil; | ||
| 6 | +import cn.hutool.core.util.StrUtil; | ||
| 7 | +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | ||
| 8 | +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; | ||
| 9 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 10 | +import org.springframework.ai.vectorstore.RedisVectorStore; | ||
| 11 | +import org.springframework.ai.vectorstore.VectorStore; | ||
| 12 | +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | ||
| 13 | +import redis.clients.jedis.JedisPooled; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * AI Vector 模型工厂的实现类 | ||
| 17 | + * 使用 redisVectorStore 实现 VectorStore | ||
| 18 | + * | ||
| 19 | + * @author xiaoxin | ||
| 20 | + */ | ||
| 21 | +public class AiVectorStoreFactoryImpl implements AiVectorStoreFactory { | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url) { | ||
| 25 | + String cacheKey = buildClientCacheKey(VectorStore.class, platform, apiKey, url); | ||
| 26 | + return Singleton.get(cacheKey, (Func0<VectorStore>) () -> { | ||
| 27 | + // TODO 芋艿 @xin 这两个配置取哪好呢 | ||
| 28 | + // TODO 不同模型的向量维度可能会不一样,目前看貌似是以 index 来做区分的,维度不一样存不到一个 index 上 | ||
| 29 | + String index = "default-index"; | ||
| 30 | + String prefix = "default:"; | ||
| 31 | + var config = RedisVectorStore.RedisVectorStoreConfig.builder() | ||
| 32 | + .withIndexName(index) | ||
| 33 | + .withPrefix(prefix) | ||
| 34 | + .build(); | ||
| 35 | + RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); | ||
| 36 | + RedisVectorStore redisVectorStore = new RedisVectorStore(config, embeddingModel, | ||
| 37 | + new JedisPooled(redisProperties.getHost(), redisProperties.getPort()), | ||
| 38 | + true); | ||
| 39 | + redisVectorStore.afterPropertiesSet(); | ||
| 40 | + return redisVectorStore; | ||
| 41 | + }); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + private static String buildClientCacheKey(Class<?> clazz, Object... params) { | ||
| 46 | + if (ArrayUtil.isEmpty(params)) { | ||
| 47 | + return clazz.getName(); | ||
| 48 | + } | ||
| 49 | + return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_")); | ||
| 50 | + } | ||
| 51 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreAutoConfiguration.java
| @@ -19,6 +19,7 @@ import org.springframework.ai.embedding.EmbeddingModel; | @@ -19,6 +19,7 @@ import org.springframework.ai.embedding.EmbeddingModel; | ||
| 19 | import org.springframework.ai.vectorstore.RedisVectorStore; | 19 | import org.springframework.ai.vectorstore.RedisVectorStore; |
| 20 | import org.springframework.ai.vectorstore.RedisVectorStore.RedisVectorStoreConfig; | 20 | import org.springframework.ai.vectorstore.RedisVectorStore.RedisVectorStoreConfig; |
| 21 | import org.springframework.boot.autoconfigure.AutoConfiguration; | 21 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 22 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
| 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | 23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| 23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | 24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| 24 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; | 25 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; |
| @@ -38,7 +39,7 @@ import redis.clients.jedis.JedisPooled; | @@ -38,7 +39,7 @@ import redis.clients.jedis.JedisPooled; | ||
| 38 | */ | 39 | */ |
| 39 | @AutoConfiguration(after = RedisAutoConfiguration.class) | 40 | @AutoConfiguration(after = RedisAutoConfiguration.class) |
| 40 | @ConditionalOnClass({JedisPooled.class, JedisConnectionFactory.class, RedisVectorStore.class, EmbeddingModel.class}) | 41 | @ConditionalOnClass({JedisPooled.class, JedisConnectionFactory.class, RedisVectorStore.class, EmbeddingModel.class}) |
| 41 | -//@ConditionalOnBean(JedisConnectionFactory.class) | 42 | +@ConditionalOnBean(JedisConnectionFactory.class) |
| 42 | @EnableConfigurationProperties(RedisVectorStoreProperties.class) | 43 | @EnableConfigurationProperties(RedisVectorStoreProperties.class) |
| 43 | public class RedisVectorStoreAutoConfiguration { | 44 | public class RedisVectorStoreAutoConfiguration { |
| 44 | 45 |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/webapp/test/Fel.pdf deleted
No preview for this file type