294 lines
8.9 KiB
Go
294 lines
8.9 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"knowlege-lsxd/internal/errors"
|
|
"knowlege-lsxd/internal/logger"
|
|
"knowlege-lsxd/internal/types"
|
|
"knowlege-lsxd/internal/types/interfaces"
|
|
)
|
|
|
|
// KnowledgeBaseHandler defines the HTTP handler for knowledge base operations
|
|
type KnowledgeBaseHandler struct {
|
|
service interfaces.KnowledgeBaseService
|
|
knowledgeService interfaces.KnowledgeService
|
|
}
|
|
|
|
// NewKnowledgeBaseHandler creates a new knowledge base handler instance
|
|
func NewKnowledgeBaseHandler(
|
|
service interfaces.KnowledgeBaseService,
|
|
knowledgeService interfaces.KnowledgeService,
|
|
) *KnowledgeBaseHandler {
|
|
return &KnowledgeBaseHandler{service: service, knowledgeService: knowledgeService}
|
|
}
|
|
|
|
// HybridSearch handles requests to perform hybrid vector and keyword search on a knowledge base
|
|
func (h *KnowledgeBaseHandler) HybridSearch(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
|
|
logger.Info(ctx, "Start hybrid search")
|
|
|
|
// Validate knowledge base ID
|
|
id := c.Param("id")
|
|
if id == "" {
|
|
logger.Error(ctx, "Knowledge base ID is empty")
|
|
c.Error(errors.NewBadRequestError("Knowledge base ID cannot be empty"))
|
|
return
|
|
}
|
|
|
|
// Parse request body
|
|
var req types.SearchParams
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
logger.Error(ctx, "Failed to parse request parameters", err)
|
|
c.Error(errors.NewBadRequestError("Invalid request parameters").WithDetails(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Executing hybrid search, knowledge base ID: %s, query: %s", id, req.QueryText)
|
|
|
|
// Execute hybrid search with default search parameters
|
|
results, err := h.service.HybridSearch(ctx, id, req)
|
|
if err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
c.Error(errors.NewInternalServerError(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Hybrid search completed, knowledge base ID: %s, result count: %d", id, len(results))
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"data": results,
|
|
})
|
|
}
|
|
|
|
// CreateKnowledgeBase handles requests to create a new knowledge base
|
|
func (h *KnowledgeBaseHandler) CreateKnowledgeBase(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
|
|
logger.Info(ctx, "Start creating knowledge base")
|
|
|
|
// Parse request body
|
|
var req types.KnowledgeBase
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
logger.Error(ctx, "Failed to parse request parameters", err)
|
|
c.Error(errors.NewBadRequestError("Invalid request parameters").WithDetails(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Creating knowledge base, name: %s", req.Name)
|
|
// Create knowledge base using the service
|
|
kb, err := h.service.CreateKnowledgeBase(ctx, &req)
|
|
if err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
c.Error(errors.NewInternalServerError(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Knowledge base created successfully, ID: %s, name: %s", kb.ID, kb.Name)
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"success": true,
|
|
"data": kb,
|
|
})
|
|
}
|
|
|
|
// validateAndGetKnowledgeBase validates request parameters and retrieves the knowledge base
|
|
// Returns the knowledge base, knowledge base ID, and any errors encountered
|
|
func (h *KnowledgeBaseHandler) validateAndGetKnowledgeBase(c *gin.Context) (*types.KnowledgeBase, string, error) {
|
|
ctx := c.Request.Context()
|
|
|
|
// Get tenant ID from context
|
|
tenantID, exists := c.Get(types.TenantIDContextKey.String())
|
|
if !exists {
|
|
logger.Error(ctx, "Failed to get tenant ID")
|
|
return nil, "", errors.NewUnauthorizedError("Unauthorized")
|
|
}
|
|
|
|
// Get knowledge base ID from URL parameter
|
|
id := c.Param("id")
|
|
if id == "" {
|
|
logger.Error(ctx, "Knowledge base ID is empty")
|
|
return nil, "", errors.NewBadRequestError("Knowledge base ID cannot be empty")
|
|
}
|
|
|
|
logger.Infof(ctx, "Retrieving knowledge base, ID: %s", id)
|
|
|
|
// Verify tenant has permission to access this knowledge base
|
|
kb, err := h.service.GetKnowledgeBaseByID(ctx, id)
|
|
if err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
return nil, id, errors.NewInternalServerError(err.Error())
|
|
}
|
|
|
|
// Verify tenant ownership
|
|
if kb.TenantID != tenantID.(uint) {
|
|
logger.Warnf(
|
|
ctx,
|
|
"Tenant has no permission to access this knowledge base, knowledge base ID: %s, "+
|
|
"request tenant ID: %d, knowledge base tenant ID: %d",
|
|
id, tenantID.(uint), kb.TenantID,
|
|
)
|
|
return nil, id, errors.NewForbiddenError("No permission to operate")
|
|
}
|
|
|
|
return kb, id, nil
|
|
}
|
|
|
|
// GetKnowledgeBase handles requests to retrieve a knowledge base by ID
|
|
func (h *KnowledgeBaseHandler) GetKnowledgeBase(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
logger.Info(ctx, "Start retrieving knowledge base")
|
|
|
|
// Validate and get the knowledge base
|
|
kb, id, err := h.validateAndGetKnowledgeBase(c)
|
|
if err != nil {
|
|
c.Error(err)
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Retrieved knowledge base successfully, ID: %s, name: %s", id, kb.Name)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"data": kb,
|
|
})
|
|
}
|
|
|
|
// ListKnowledgeBases handles requests to list all knowledge bases for a tenant
|
|
func (h *KnowledgeBaseHandler) ListKnowledgeBases(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
|
|
logger.Info(ctx, "Start retrieving knowledge base list")
|
|
|
|
// Get tenant ID from context
|
|
tenantID, exists := c.Get(types.TenantIDContextKey.String())
|
|
if !exists {
|
|
logger.Error(ctx, "Failed to get tenant ID")
|
|
c.Error(errors.NewUnauthorizedError("Unauthorized"))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Retrieving knowledge base list for tenant, tenant ID: %d", tenantID.(uint))
|
|
|
|
// Get all knowledge bases for this tenant
|
|
kbs, err := h.service.ListKnowledgeBases(ctx)
|
|
if err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
c.Error(errors.NewInternalServerError(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(
|
|
ctx,
|
|
"Retrieved knowledge base list successfully, tenant ID: %d, total: %d knowledge bases",
|
|
tenantID.(uint), len(kbs),
|
|
)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"data": kbs,
|
|
})
|
|
}
|
|
|
|
// UpdateKnowledgeBaseRequest defines the request body structure for updating a knowledge base
|
|
type UpdateKnowledgeBaseRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
Description string `json:"description"`
|
|
Config *types.KnowledgeBaseConfig `json:"config" binding:"required"`
|
|
}
|
|
|
|
// UpdateKnowledgeBase handles requests to update an existing knowledge base
|
|
func (h *KnowledgeBaseHandler) UpdateKnowledgeBase(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
logger.Info(ctx, "Start updating knowledge base")
|
|
|
|
// Validate and get the knowledge base
|
|
_, id, err := h.validateAndGetKnowledgeBase(c)
|
|
if err != nil {
|
|
c.Error(err)
|
|
return
|
|
}
|
|
|
|
// Parse request body
|
|
var req UpdateKnowledgeBaseRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
logger.Error(ctx, "Failed to parse request parameters", err)
|
|
c.Error(errors.NewBadRequestError("Invalid request parameters").WithDetails(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Updating knowledge base, ID: %s, name: %s", id, req.Name)
|
|
|
|
// Update the knowledge base
|
|
kb, err := h.service.UpdateKnowledgeBase(ctx, id, req.Name, req.Description, req.Config)
|
|
if err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
c.Error(errors.NewInternalServerError(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Knowledge base updated successfully, ID: %s", id)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"data": kb,
|
|
})
|
|
}
|
|
|
|
// DeleteKnowledgeBase handles requests to delete a knowledge base
|
|
func (h *KnowledgeBaseHandler) DeleteKnowledgeBase(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
logger.Info(ctx, "Start deleting knowledge base")
|
|
|
|
// Validate and get the knowledge base
|
|
kb, id, err := h.validateAndGetKnowledgeBase(c)
|
|
if err != nil {
|
|
c.Error(err)
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Deleting knowledge base, ID: %s, name: %s", id, kb.Name)
|
|
|
|
// Delete the knowledge base
|
|
if err := h.service.DeleteKnowledgeBase(ctx, id); err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
c.Error(errors.NewInternalServerError(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Knowledge base deleted successfully, ID: %s", id)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"message": "Knowledge base deleted successfully",
|
|
})
|
|
}
|
|
|
|
type CopyKnowledgeBaseRequest struct {
|
|
SourceID string `json:"source_id" binding:"required"`
|
|
TargetID string `json:"target_id"`
|
|
}
|
|
|
|
func (h *KnowledgeBaseHandler) CopyKnowledgeBase(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
logger.Info(ctx, "Start copy knowledge base")
|
|
|
|
var req CopyKnowledgeBaseRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
logger.Error(ctx, "Failed to parse request parameters", err)
|
|
c.Error(errors.NewBadRequestError("Invalid request parameters").WithDetails(err.Error()))
|
|
return
|
|
}
|
|
|
|
logger.Infof(ctx, "Copy knowledge base, ID: %s to ID: %s", req.SourceID, req.TargetID)
|
|
|
|
err := h.knowledgeService.CloneKnowledgeBase(ctx, req.SourceID, req.TargetID)
|
|
if err != nil {
|
|
logger.ErrorWithFields(ctx, err, nil)
|
|
c.Error(errors.NewInternalServerError(err.Error()))
|
|
return
|
|
}
|
|
logger.Infof(ctx, "Knowledge base copy successfully, ID: %s to ID: %s", req.SourceID, req.TargetID)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"message": "Knowledge base copy successfully",
|
|
})
|
|
}
|