diff --git a/script/sql/rag_document.sql b/script/sql/rag_document.sql new file mode 100644 index 0000000..50979eb --- /dev/null +++ b/script/sql/rag_document.sql @@ -0,0 +1,44 @@ +DROP TABLE IF EXISTS rag_document; + +CREATE TABLE rag_document ( + id BIGSERIAL PRIMARY KEY, + store_id BIGINT NOT NULL, + attachment_id BIGINT NOT NULL, + document_title VARCHAR(255) NOT NULL, + document_summary VARCHAR(1000) DEFAULT '', + parse_status VARCHAR(50) NOT NULL DEFAULT 'UPLOADED', + index_status VARCHAR(50) NOT NULL DEFAULT 'PENDING', + enabled BOOLEAN NOT NULL DEFAULT TRUE, + error_message VARCHAR(1000) DEFAULT '', + version INTEGER NOT NULL DEFAULT 1, + create_time TIMESTAMP, + update_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + create_by VARCHAR(64), + update_by VARCHAR(64), + CONSTRAINT uk_rag_document_attachment UNIQUE (attachment_id), + CONSTRAINT fk_rag_document_store_id FOREIGN KEY (store_id) REFERENCES rag_store (id), + CONSTRAINT fk_rag_document_attachment_id FOREIGN KEY (attachment_id) REFERENCES sys_attachment (id) +); + +CREATE INDEX idx_rag_document_store_id ON rag_document (store_id); +CREATE INDEX idx_rag_document_parse_status ON rag_document (parse_status); +CREATE INDEX idx_rag_document_index_status ON rag_document (index_status); +CREATE INDEX idx_rag_document_enabled ON rag_document (enabled); + +COMMENT ON TABLE rag_document IS 'RAG知识库文档表'; +COMMENT ON COLUMN rag_document.id IS 'ID'; +COMMENT ON COLUMN rag_document.store_id IS '知识库ID'; +COMMENT ON COLUMN rag_document.attachment_id IS '附件ID'; +COMMENT ON COLUMN rag_document.document_title IS '文档标题'; +COMMENT ON COLUMN rag_document.document_summary IS '文档摘要'; +COMMENT ON COLUMN rag_document.parse_status IS '解析状态'; +COMMENT ON COLUMN rag_document.index_status IS '索引状态'; +COMMENT ON COLUMN rag_document.enabled IS '是否启用'; +COMMENT ON COLUMN rag_document.error_message IS '失败原因'; +COMMENT ON COLUMN rag_document.version IS '版本'; +COMMENT ON COLUMN rag_document.create_time IS '创建时间'; +COMMENT ON COLUMN rag_document.update_time IS '更新时间'; +COMMENT ON COLUMN rag_document.remark IS '备注'; +COMMENT ON COLUMN rag_document.create_by IS '创建者'; +COMMENT ON COLUMN rag_document.update_by IS '更新者'; diff --git a/script/sql/rag_store.sql b/script/sql/rag_store.sql new file mode 100644 index 0000000..4ab9ba5 --- /dev/null +++ b/script/sql/rag_store.sql @@ -0,0 +1,32 @@ +DROP TABLE IF EXISTS rag_store; + +CREATE TABLE rag_store ( + id BIGSERIAL PRIMARY KEY, + store_code VARCHAR(100) NOT NULL, + store_name VARCHAR(200) NOT NULL, + description VARCHAR(1000) DEFAULT '', + status VARCHAR(50) NOT NULL DEFAULT 'ENABLED', + version INTEGER NOT NULL DEFAULT 1, + create_time TIMESTAMP, + update_time TIMESTAMP, + remark VARCHAR(500) DEFAULT '', + create_by VARCHAR(64), + update_by VARCHAR(64), + CONSTRAINT uk_rag_store_code UNIQUE (store_code) +); + +CREATE INDEX idx_rag_store_status ON rag_store (status); +CREATE INDEX idx_rag_store_create_time ON rag_store (create_time); + +COMMENT ON TABLE rag_store IS 'RAG知识库主表'; +COMMENT ON COLUMN rag_store.id IS 'ID'; +COMMENT ON COLUMN rag_store.store_code IS '知识库编码'; +COMMENT ON COLUMN rag_store.store_name IS '知识库名称'; +COMMENT ON COLUMN rag_store.description IS '知识库描述'; +COMMENT ON COLUMN rag_store.status IS '状态'; +COMMENT ON COLUMN rag_store.version IS '版本'; +COMMENT ON COLUMN rag_store.create_time IS '创建时间'; +COMMENT ON COLUMN rag_store.update_time IS '更新时间'; +COMMENT ON COLUMN rag_store.remark IS '备注'; +COMMENT ON COLUMN rag_store.create_by IS '创建者'; +COMMENT ON COLUMN rag_store.update_by IS '更新者'; diff --git a/src/main/java/com/bruce/rag/constant/RagSystemConstants.java b/src/main/java/com/bruce/rag/constant/RagSystemConstants.java new file mode 100644 index 0000000..78b360a --- /dev/null +++ b/src/main/java/com/bruce/rag/constant/RagSystemConstants.java @@ -0,0 +1,11 @@ +package com.bruce.rag.constant; + +public final class RagSystemConstants { + + public static final String RAG_STORE = "RAG_STORE"; + + public static final String RAG_DOCUMENT = "RAG_DOCUMENT"; + + private RagSystemConstants() { + } +} diff --git a/src/main/java/com/bruce/rag/controller/RagDocumentController.java b/src/main/java/com/bruce/rag/controller/RagDocumentController.java new file mode 100644 index 0000000..86d0f59 --- /dev/null +++ b/src/main/java/com/bruce/rag/controller/RagDocumentController.java @@ -0,0 +1,29 @@ +package com.bruce.rag.controller; + +import com.bruce.rag.entity.RagDocument; +import com.bruce.rag.service.IRagDocumentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@Tag(name = "RAG知识库文档管理") +@RestController +@RequestMapping("/api/rag/documents") +public class RagDocumentController { + + private final IRagDocumentService ragDocumentService; + + public RagDocumentController(IRagDocumentService ragDocumentService) { + this.ragDocumentService = ragDocumentService; + } + + @Operation(summary = "查询全部知识库文档") + @GetMapping + public List list() { + return ragDocumentService.list(); + } +} diff --git a/src/main/java/com/bruce/rag/controller/RagStoreController.java b/src/main/java/com/bruce/rag/controller/RagStoreController.java new file mode 100644 index 0000000..5431f4d --- /dev/null +++ b/src/main/java/com/bruce/rag/controller/RagStoreController.java @@ -0,0 +1,29 @@ +package com.bruce.rag.controller; + +import com.bruce.rag.entity.RagStore; +import com.bruce.rag.service.IRagStoreService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@Tag(name = "RAG知识库管理") +@RestController +@RequestMapping("/api/rag/stores") +public class RagStoreController { + + private final IRagStoreService ragStoreService; + + public RagStoreController(IRagStoreService ragStoreService) { + this.ragStoreService = ragStoreService; + } + + @Operation(summary = "查询全部知识库") + @GetMapping + public List list() { + return ragStoreService.list(); + } +} diff --git a/src/main/java/com/bruce/rag/entity/RagDocument.java b/src/main/java/com/bruce/rag/entity/RagDocument.java new file mode 100644 index 0000000..5f07d5a --- /dev/null +++ b/src/main/java/com/bruce/rag/entity/RagDocument.java @@ -0,0 +1,51 @@ +package com.bruce.rag.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.bruce.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName("rag_document") +@Schema(description = "RAG知识库文档") +public class RagDocument extends BaseEntity { + + @Schema(description = "知识库ID") + @TableField("store_id") + private Long storeId; + + @Schema(description = "附件ID") + @TableField("attachment_id") + private Long attachmentId; + + @Schema(description = "文档标题") + @TableField("document_title") + private String documentTitle; + + @Schema(description = "文档摘要") + @TableField("document_summary") + private String documentSummary; + + @Schema(description = "解析状态") + @TableField("parse_status") + private String parseStatus; + + @Schema(description = "索引状态") + @TableField("index_status") + private String indexStatus; + + @Schema(description = "是否启用") + private Boolean enabled; + + @Schema(description = "失败原因") + @TableField("error_message") + private String errorMessage; + + @Schema(description = "备注") + private String remark; +} diff --git a/src/main/java/com/bruce/rag/entity/RagStore.java b/src/main/java/com/bruce/rag/entity/RagStore.java new file mode 100644 index 0000000..f4b25ea --- /dev/null +++ b/src/main/java/com/bruce/rag/entity/RagStore.java @@ -0,0 +1,31 @@ +package com.bruce.rag.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.bruce.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName("rag_store") +@Schema(description = "RAG知识库") +public class RagStore extends BaseEntity { + + @Schema(description = "知识库编码") + private String storeCode; + + @Schema(description = "知识库名称") + private String storeName; + + @Schema(description = "知识库描述") + private String description; + + @Schema(description = "状态") + private String status; + + @Schema(description = "备注") + private String remark; +} diff --git a/src/main/java/com/bruce/rag/mapper/RagDocumentMapper.java b/src/main/java/com/bruce/rag/mapper/RagDocumentMapper.java new file mode 100644 index 0000000..be7722a --- /dev/null +++ b/src/main/java/com/bruce/rag/mapper/RagDocumentMapper.java @@ -0,0 +1,9 @@ +package com.bruce.rag.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.bruce.rag.entity.RagDocument; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface RagDocumentMapper extends BaseMapper { +} diff --git a/src/main/java/com/bruce/rag/mapper/RagStoreMapper.java b/src/main/java/com/bruce/rag/mapper/RagStoreMapper.java new file mode 100644 index 0000000..4424f28 --- /dev/null +++ b/src/main/java/com/bruce/rag/mapper/RagStoreMapper.java @@ -0,0 +1,9 @@ +package com.bruce.rag.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.bruce.rag.entity.RagStore; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface RagStoreMapper extends BaseMapper { +} diff --git a/src/main/java/com/bruce/rag/service/IRagDocumentService.java b/src/main/java/com/bruce/rag/service/IRagDocumentService.java new file mode 100644 index 0000000..992405a --- /dev/null +++ b/src/main/java/com/bruce/rag/service/IRagDocumentService.java @@ -0,0 +1,7 @@ +package com.bruce.rag.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bruce.rag.entity.RagDocument; + +public interface IRagDocumentService extends IService { +} diff --git a/src/main/java/com/bruce/rag/service/IRagStoreService.java b/src/main/java/com/bruce/rag/service/IRagStoreService.java new file mode 100644 index 0000000..e03adb0 --- /dev/null +++ b/src/main/java/com/bruce/rag/service/IRagStoreService.java @@ -0,0 +1,7 @@ +package com.bruce.rag.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bruce.rag.entity.RagStore; + +public interface IRagStoreService extends IService { +} diff --git a/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java b/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java new file mode 100644 index 0000000..cf94e10 --- /dev/null +++ b/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java @@ -0,0 +1,11 @@ +package com.bruce.rag.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bruce.rag.entity.RagDocument; +import com.bruce.rag.mapper.RagDocumentMapper; +import com.bruce.rag.service.IRagDocumentService; +import org.springframework.stereotype.Service; + +@Service +public class RagDocumentServiceImpl extends ServiceImpl implements IRagDocumentService { +} diff --git a/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java b/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java new file mode 100644 index 0000000..b9df274 --- /dev/null +++ b/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java @@ -0,0 +1,11 @@ +package com.bruce.rag.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bruce.rag.entity.RagStore; +import com.bruce.rag.mapper.RagStoreMapper; +import com.bruce.rag.service.IRagStoreService; +import org.springframework.stereotype.Service; + +@Service +public class RagStoreServiceImpl extends ServiceImpl implements IRagStoreService { +} diff --git a/src/test/java/com/bruce/common/enumconfig/EnumDefinitionTests.java b/src/test/java/com/bruce/common/enumconfig/EnumDefinitionTests.java new file mode 100644 index 0000000..1b89a19 --- /dev/null +++ b/src/test/java/com/bruce/common/enumconfig/EnumDefinitionTests.java @@ -0,0 +1,30 @@ +package com.bruce.common.enumconfig; + +import com.bruce.common.enums.BaseDictEnum; +import com.bruce.common.enums.EnableStatusEnum; +import com.bruce.rag.enums.RagIndexStatusEnum; +import com.bruce.rag.enums.RagParseStatusEnum; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EnumDefinitionTests { + + @Test + void enumDefinitionsShouldExist() { + assertTrue(BaseDictEnum.class.isAssignableFrom(EnableStatusEnum.class)); + assertTrue(BaseDictEnum.class.isAssignableFrom(RagParseStatusEnum.class)); + assertTrue(BaseDictEnum.class.isAssignableFrom(RagIndexStatusEnum.class)); + } + + @Test + void enumCodesShouldBeStable() { + assertEquals("ENABLED", EnableStatusEnum.ENABLED.getCode()); + assertEquals("DISABLED", EnableStatusEnum.DISABLED.getCode()); + assertEquals("UPLOADED", RagParseStatusEnum.UPLOADED.getCode()); + assertEquals("FAILED", RagParseStatusEnum.FAILED.getCode()); + assertEquals("PENDING", RagIndexStatusEnum.PENDING.getCode()); + assertEquals("INDEXED", RagIndexStatusEnum.INDEXED.getCode()); + } +} diff --git a/src/test/java/com/bruce/rag/RagComponentStructureTests.java b/src/test/java/com/bruce/rag/RagComponentStructureTests.java new file mode 100644 index 0000000..c14c0e3 --- /dev/null +++ b/src/test/java/com/bruce/rag/RagComponentStructureTests.java @@ -0,0 +1,49 @@ +package com.bruce.rag; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bruce.rag.constant.RagSystemConstants; +import com.bruce.rag.controller.RagDocumentController; +import com.bruce.rag.controller.RagStoreController; +import com.bruce.rag.entity.RagDocument; +import com.bruce.rag.entity.RagStore; +import com.bruce.rag.mapper.RagDocumentMapper; +import com.bruce.rag.mapper.RagStoreMapper; +import com.bruce.rag.service.IRagDocumentService; +import com.bruce.rag.service.IRagStoreService; +import com.bruce.rag.service.impl.RagDocumentServiceImpl; +import com.bruce.rag.service.impl.RagStoreServiceImpl; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class RagComponentStructureTests { + + @Test + void ragComponentsShouldReuseMybatisPlusBaseTypes() { + assertTrue(BaseMapper.class.isAssignableFrom(RagStoreMapper.class)); + assertTrue(BaseMapper.class.isAssignableFrom(RagDocumentMapper.class)); + assertTrue(IService.class.isAssignableFrom(IRagStoreService.class)); + assertTrue(IService.class.isAssignableFrom(IRagDocumentService.class)); + assertTrue(ServiceImpl.class.isAssignableFrom(RagStoreServiceImpl.class)); + assertTrue(ServiceImpl.class.isAssignableFrom(RagDocumentServiceImpl.class)); + } + + @Test + void ragSourceTypesAndDocumentRelationShouldExist() throws NoSuchFieldException { + Field storeIdField = RagDocument.class.getDeclaredField("storeId"); + Field attachmentIdField = RagDocument.class.getDeclaredField("attachmentId"); + + assertEquals("RAG_STORE", RagSystemConstants.RAG_STORE); + assertEquals("RAG_DOCUMENT", RagSystemConstants.RAG_DOCUMENT); + assertEquals(Long.class, storeIdField.getType()); + assertEquals(Long.class, attachmentIdField.getType()); + assertTrue(RagStore.class.getSimpleName().contains("RagStore")); + assertTrue(RagStoreController.class.getSimpleName().contains("RagStoreController")); + assertTrue(RagDocumentController.class.getSimpleName().contains("RagDocumentController")); + } +}