mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
refactor: Remove knowledge base-related API handlers that are already included in the dataset. (#14094)
### What problem does this PR solve? refactor: Remove knowledge base-related API handlers that are already included in the dataset. ### Type of change - [x] Refactoring
This commit is contained in:
@@ -23,7 +23,6 @@ import (
|
||||
"ragflow/internal/common"
|
||||
"ragflow/internal/engine"
|
||||
"ragflow/internal/service"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -82,39 +81,6 @@ var (
|
||||
ErrForbidden = &HTTPError{Code: common.CodeForbidden, Message: "Forbidden user"}
|
||||
)
|
||||
|
||||
// CreateKB handles the create knowledge base request
|
||||
// @Summary Create Knowledge Base
|
||||
// @Description Create a new knowledge base (dataset)
|
||||
// @Tags knowledgebase
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @Param request body service.CreateKBRequest true "knowledge base info"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/kb/create [post]
|
||||
func (h *KnowledgebaseHandler) CreateKB(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
var req service.CreateKBRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
jsonError(c, common.CodeDataError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
result, code, err := h.kbService.CreateKB(&req, user.ID)
|
||||
if err != nil {
|
||||
jsonError(c, code, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
jsonResponse(c, common.CodeSuccess, result, "success")
|
||||
}
|
||||
|
||||
// UpdateKB handles the update knowledge base request
|
||||
// @Summary Update Knowledge Base
|
||||
// @Description Update an existing knowledge base
|
||||
// @Tags knowledgebase
|
||||
@@ -215,131 +181,7 @@ func (h *KnowledgebaseHandler) GetDetail(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
jsonResponse(c, common.CodeSuccess, result, "success")
|
||||
}
|
||||
|
||||
// ListKbs handles the list knowledge bases request
|
||||
// @Summary List Knowledge Bases
|
||||
// @Description List knowledge bases with pagination and filtering
|
||||
// @Tags knowledgebase
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @Param request body service.ListKbsRequest true "list options"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/kb/list [post]
|
||||
func (h *KnowledgebaseHandler) ListKbs(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
var req service.ListKbsRequest
|
||||
if c.Request.ContentLength > 0 {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
jsonError(c, common.CodeDataError, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get parameters from request or query string
|
||||
keywords := ""
|
||||
if req.Keywords != nil {
|
||||
keywords = *req.Keywords
|
||||
} else if queryKeywords := c.Query("keywords"); queryKeywords != "" {
|
||||
keywords = queryKeywords
|
||||
}
|
||||
|
||||
page := 0
|
||||
if req.Page != nil {
|
||||
page = *req.Page
|
||||
} else if pageStr := c.Query("page"); pageStr != "" {
|
||||
if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
|
||||
page = p
|
||||
}
|
||||
}
|
||||
|
||||
pageSize := 0
|
||||
if req.PageSize != nil {
|
||||
pageSize = *req.PageSize
|
||||
} else if pageSizeStr := c.Query("page_size"); pageSizeStr != "" {
|
||||
if ps, err := strconv.Atoi(pageSizeStr); err == nil && ps > 0 {
|
||||
pageSize = ps
|
||||
}
|
||||
}
|
||||
|
||||
parserID := ""
|
||||
if req.ParserID != nil {
|
||||
parserID = *req.ParserID
|
||||
} else if queryParserID := c.Query("parser_id"); queryParserID != "" {
|
||||
parserID = queryParserID
|
||||
}
|
||||
|
||||
orderby := "update_time"
|
||||
if req.Orderby != nil {
|
||||
orderby = *req.Orderby
|
||||
} else if queryOrderby := c.Query("orderby"); queryOrderby != "" {
|
||||
orderby = queryOrderby
|
||||
}
|
||||
|
||||
desc := true
|
||||
if req.Desc != nil {
|
||||
desc = *req.Desc
|
||||
} else if descStr := c.Query("desc"); descStr != "" {
|
||||
desc = strings.ToLower(descStr) == "true"
|
||||
}
|
||||
|
||||
var ownerIDs []string
|
||||
if req.OwnerIDs != nil {
|
||||
ownerIDs = *req.OwnerIDs
|
||||
}
|
||||
|
||||
result, code, err := h.kbService.ListKbs(keywords, page, pageSize, parserID, orderby, desc, ownerIDs, user.ID)
|
||||
if err != nil {
|
||||
jsonError(c, code, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
jsonResponse(c, common.CodeSuccess, result, "success")
|
||||
}
|
||||
|
||||
// DeleteKB handles the delete knowledge base request
|
||||
// @Summary Delete Knowledge Base
|
||||
// @Description Soft delete a knowledge base
|
||||
// @Tags knowledgebase
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @Param request body object{kb_id string} true "knowledge base id"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/kb/rm [post]
|
||||
func (h *KnowledgebaseHandler) DeleteKB(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
KBID string `json:"kb_id" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
jsonError(c, common.CodeDataError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
code, err := h.kbService.DeleteKB(req.KBID, user.ID)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "authorization") {
|
||||
jsonError(c, common.CodeAuthenticationError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonError(c, code, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
jsonResponse(c, common.CodeSuccess, true, "success")
|
||||
jsonResponse(c, common.CodeSuccess, result, "success")
|
||||
}
|
||||
|
||||
// ListTags handles the list tags request for a knowledge base
|
||||
|
||||
@@ -175,11 +175,11 @@ func (r *Router) Setup(engine *gin.Engine) {
|
||||
// message.GET("/:memory_id/:message_id/content", r.memoryHandler.GetMessageContent)
|
||||
// }
|
||||
|
||||
chats := v1.Group("/chats")
|
||||
{
|
||||
chats.GET("", r.chatHandler.ListChats)
|
||||
chats.GET("/:chat_id", r.chatHandler.GetChat)
|
||||
}
|
||||
chats := v1.Group("/chats")
|
||||
{
|
||||
chats.GET("", r.chatHandler.ListChats)
|
||||
chats.GET("/:chat_id", r.chatHandler.GetChat)
|
||||
}
|
||||
|
||||
searches := v1.Group("/searches")
|
||||
{
|
||||
@@ -245,12 +245,9 @@ func (r *Router) Setup(engine *gin.Engine) {
|
||||
// Knowledge base routes
|
||||
kb := authorized.Group("/v1/kb")
|
||||
{
|
||||
kb.POST("/create", r.knowledgebaseHandler.CreateKB)
|
||||
kb.POST("/update", r.knowledgebaseHandler.UpdateKB)
|
||||
kb.POST("/update_metadata_setting", r.knowledgebaseHandler.UpdateMetadataSetting)
|
||||
kb.GET("/detail", r.knowledgebaseHandler.GetDetail)
|
||||
kb.POST("/list", r.knowledgebaseHandler.ListKbs)
|
||||
kb.POST("/rm", r.knowledgebaseHandler.DeleteKB)
|
||||
kb.GET("/tags", r.knowledgebaseHandler.ListTagsFromKbs)
|
||||
kb.GET("/get_meta", r.knowledgebaseHandler.GetMeta)
|
||||
kb.GET("/basic_info", r.knowledgebaseHandler.GetBasicInfo)
|
||||
|
||||
@@ -395,9 +395,18 @@ func (s *DatasetsService) CreateDataset(req *CreateDatasetRequest, tenantID stri
|
||||
now := time.Now().Unix()
|
||||
nowDate := time.Now().Truncate(time.Second)
|
||||
status := string(entity.StatusValid)
|
||||
// Deduplicate name within tenant
|
||||
duplicateName, err := common.DuplicateName(func(n, tid string) bool {
|
||||
existing, err := s.kbDAO.GetByName(n, tid)
|
||||
return err == nil && existing != nil
|
||||
}, name, tenantID)
|
||||
if err != nil {
|
||||
return nil, common.CodeDataError, err
|
||||
}
|
||||
|
||||
kb := &entity.Knowledgebase{
|
||||
ID: kbID,
|
||||
Name: s.kbDAO.DuplicateName(name, tenantID),
|
||||
Name: duplicateName,
|
||||
TenantID: tenantID,
|
||||
CreatedBy: tenantID,
|
||||
ParserID: parserID,
|
||||
|
||||
@@ -52,22 +52,6 @@ func NewKnowledgebaseService() *KnowledgebaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// CreateKBRequest represents the request for creating a knowledge base
|
||||
type CreateKBRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
ParserID *string `json:"parser_id,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Language *string `json:"language,omitempty"`
|
||||
Permission *string `json:"permission,omitempty"`
|
||||
Avatar *string `json:"avatar,omitempty"`
|
||||
ParserConfig map[string]interface{} `json:"parser_config,omitempty"`
|
||||
}
|
||||
|
||||
// CreateKBResponse represents the response for creating a knowledge base
|
||||
type CreateKBResponse struct {
|
||||
KBID string `json:"kb_id"`
|
||||
}
|
||||
|
||||
// UpdateKBRequest represents the request for updating a knowledge base
|
||||
type UpdateKBRequest struct {
|
||||
KBID string `json:"kb_id" binding:"required"`
|
||||
@@ -89,106 +73,12 @@ type UpdateMetadataSettingRequest struct {
|
||||
EnableMetadata *bool `json:"enable_metadata,omitempty"`
|
||||
}
|
||||
|
||||
// ListKbsRequest represents the request for listing knowledge bases
|
||||
type ListKbsRequest struct {
|
||||
Keywords *string `json:"keywords,omitempty"`
|
||||
Page *int `json:"page,omitempty"`
|
||||
PageSize *int `json:"page_size,omitempty"`
|
||||
ParserID *string `json:"parser_id,omitempty"`
|
||||
Orderby *string `json:"orderby,omitempty"`
|
||||
Desc *bool `json:"desc,omitempty"`
|
||||
OwnerIDs *[]string `json:"owner_ids,omitempty"`
|
||||
}
|
||||
|
||||
// ListKbsResponse represents the response for listing knowledge bases
|
||||
type ListKbsResponse struct {
|
||||
KBs []map[string]interface{} `json:"kbs"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
// CreateKB creates a new knowledge base
|
||||
// This matches the Python create endpoint in kb_app.py
|
||||
func (s *KnowledgebaseService) CreateKB(req *CreateKBRequest, tenantID string) (*CreateKBResponse, common.ErrorCode, error) {
|
||||
// Validate name is a string
|
||||
if !isValidString(req.Name) {
|
||||
return nil, common.CodeDataError, errors.New("Dataset name must be string.")
|
||||
}
|
||||
|
||||
// Trim and validate name
|
||||
name := strings.TrimSpace(req.Name)
|
||||
if name == "" {
|
||||
return nil, common.CodeDataError, errors.New("Dataset name can't be empty.")
|
||||
}
|
||||
|
||||
// Check name length (using UTF-8 byte length like Python)
|
||||
if len(name) > entity.DatasetNameLimit {
|
||||
return nil, common.CodeDataError, fmt.Errorf("Dataset name length is %d which is large than %d", len(name), entity.DatasetNameLimit)
|
||||
}
|
||||
|
||||
// Verify tenant exists
|
||||
tenant, err := s.tenantDAO.GetByID(tenantID)
|
||||
if err != nil {
|
||||
return nil, common.CodeDataError, errors.New("Tenant not found.")
|
||||
}
|
||||
|
||||
// Deduplicate name within tenant
|
||||
duplicateName := s.kbDAO.DuplicateName(name, tenantID)
|
||||
|
||||
// Get parser ID (default to "naive")
|
||||
parserID := "naive"
|
||||
if req.ParserID != nil && *req.ParserID != "" {
|
||||
parserID = *req.ParserID
|
||||
}
|
||||
|
||||
// Get parser config with defaults
|
||||
parserConfig := getParserConfig(parserID, req.ParserConfig)
|
||||
parserConfig["llm_id"] = tenant.LLMID
|
||||
|
||||
// Generate KB ID
|
||||
kbID := common.GenerateUUID()
|
||||
|
||||
// Create knowledge base model
|
||||
now := time.Now().Unix()
|
||||
nowDate := time.Now().Truncate(time.Second)
|
||||
kb := &entity.Knowledgebase{
|
||||
ID: kbID,
|
||||
Name: duplicateName,
|
||||
TenantID: tenantID,
|
||||
CreatedBy: tenantID,
|
||||
ParserID: parserID,
|
||||
ParserConfig: parserConfig,
|
||||
Permission: "me",
|
||||
EmbdID: "",
|
||||
}
|
||||
kb.CreateTime = &now
|
||||
kb.UpdateTime = &now
|
||||
kb.CreateDate = &nowDate
|
||||
kb.UpdateDate = &nowDate
|
||||
status := string(entity.StatusValid)
|
||||
kb.Status = &status
|
||||
|
||||
// Set optional fields
|
||||
if req.Description != nil {
|
||||
kb.Description = req.Description
|
||||
}
|
||||
if req.Language != nil {
|
||||
kb.Language = req.Language
|
||||
}
|
||||
if req.Permission != nil {
|
||||
kb.Permission = *req.Permission
|
||||
}
|
||||
if req.Avatar != nil {
|
||||
kb.Avatar = req.Avatar
|
||||
}
|
||||
|
||||
// Create in database
|
||||
if err = s.kbDAO.Create(kb); err != nil {
|
||||
return nil, common.CodeServerError, fmt.Errorf("failed to create knowledge base: %w", err)
|
||||
}
|
||||
|
||||
return &CreateKBResponse{KBID: kbID}, common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// CreateDatasetTableRequest represents the request for creating a dataset table
|
||||
type CreateDatasetTableRequest struct {
|
||||
KBID string `json:"kb_id" binding:"required"`
|
||||
@@ -394,80 +284,6 @@ func (s *KnowledgebaseService) GetDetail(kbID, userID string) (*entity.Knowledge
|
||||
return detail, common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// ListKbs lists knowledge bases with pagination and filtering
|
||||
// This matches the Python list endpoint in kb_app.py
|
||||
func (s *KnowledgebaseService) ListKbs(keywords string, page int, pageSize int, parserID string, orderby string, desc bool, ownerIDs []string, userID string) (*ListKbsResponse, common.ErrorCode, error) {
|
||||
var kbs []*entity.KnowledgebaseListItem
|
||||
var total int64
|
||||
var err error
|
||||
|
||||
if len(ownerIDs) > 0 {
|
||||
// List by owner IDs
|
||||
kbs, total, err = s.kbDAO.GetByTenantIDs(ownerIDs, userID, page, pageSize, orderby, desc, keywords, parserID)
|
||||
} else {
|
||||
// Get tenant IDs for user
|
||||
tenantIDs, err := s.userTenantDAO.GetTenantIDsByUserID(userID)
|
||||
if err != nil {
|
||||
return nil, common.CodeServerError, err
|
||||
}
|
||||
|
||||
kbs, total, err = s.kbDAO.GetByTenantIDs(tenantIDs, userID, page, pageSize, orderby, desc, keywords, parserID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, common.CodeServerError, err
|
||||
}
|
||||
|
||||
// Convert to map slice
|
||||
kbMaps := make([]map[string]interface{}, len(kbs))
|
||||
for i, kb := range kbs {
|
||||
kbMaps[i] = map[string]interface{}{
|
||||
"id": kb.ID,
|
||||
"avatar": kb.Avatar,
|
||||
"name": kb.Name,
|
||||
"language": kb.Language,
|
||||
"description": kb.Description,
|
||||
"tenant_id": kb.TenantID,
|
||||
"permission": kb.Permission,
|
||||
"doc_num": kb.DocNum,
|
||||
"token_num": kb.TokenNum,
|
||||
"chunk_num": kb.ChunkNum,
|
||||
"parser_id": kb.ParserID,
|
||||
"embd_id": kb.EmbdID,
|
||||
"nickname": kb.Nickname,
|
||||
"tenant_avatar": kb.TenantAvatar,
|
||||
"update_time": kb.UpdateTime,
|
||||
}
|
||||
}
|
||||
|
||||
return &ListKbsResponse{
|
||||
KBs: kbMaps,
|
||||
Total: total,
|
||||
}, common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// DeleteKB soft deletes a knowledge base
|
||||
// This matches the Python rm endpoint in kb_app.py
|
||||
func (s *KnowledgebaseService) DeleteKB(kbID, userID string) (common.ErrorCode, error) {
|
||||
// Check authorization
|
||||
if !s.kbDAO.Accessible4Deletion(kbID, userID) {
|
||||
return common.CodeAuthenticationError, errors.New("No authorization.")
|
||||
}
|
||||
|
||||
// Verify ownership
|
||||
kbs, err := s.kbDAO.Query(map[string]interface{}{"created_by": userID, "id": kbID})
|
||||
if err != nil || len(kbs) == 0 {
|
||||
return common.CodeOperatingError, errors.New("only owner of dataset authorized for this operation")
|
||||
}
|
||||
|
||||
// Soft delete
|
||||
if err := s.kbDAO.Delete(kbID); err != nil {
|
||||
return common.CodeServerError, fmt.Errorf("database error (knowledgebase removal): %w", err)
|
||||
}
|
||||
|
||||
return common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// Accessible checks if a knowledge base is accessible by a user
|
||||
func (s *KnowledgebaseService) Accessible(kbID, userID string) bool {
|
||||
return s.kbDAO.Accessible(kbID, userID)
|
||||
|
||||
@@ -60,7 +60,7 @@ export default defineConfig(({ mode }) => {
|
||||
},
|
||||
},
|
||||
hybrid: {
|
||||
'^(/api/v1/memories)|^(/v1/user/info)|^(/v1/user/tenant_info)|^(/v1/tenant/list)|^(/v1/system/config)|^(/v1/user/login)|^(/v1/user/logout)|^(/api/v1/files)':
|
||||
'^(/v1/kb)|^(/v1/document)|^(/v1/llm/list)|^(/api/v1/datasets)|^(/api/v1/memories)|^(/v1/user)|^(/v1/user/tenant_info)|^(/v1/tenant/list)|^(/v1/system/config)|^(/v1/user/login)|^(/v1/user/logout)|^(/api/v1/files)':
|
||||
{
|
||||
target: 'http://127.0.0.1:9384/',
|
||||
changeOrigin: true,
|
||||
|
||||
Reference in New Issue
Block a user