Refine handling of POST /api/v1/datasets/search in GO (#15583)

### What problem does this PR solve?

Refine handling of POST /api/v1/datasets/search in GO

### Type of change

- [x] Refactoring
This commit is contained in:
qinling0210
2026-06-08 11:49:37 +08:00
committed by GitHub
parent 074c331cdf
commit c960dc2a4c
70 changed files with 8580 additions and 1915 deletions

View File

@@ -40,91 +40,6 @@ func NewChunkHandler(chunkService *service.ChunkService, userService *service.Us
}
}
// RetrievalTest performs retrieval test for chunks
// @Summary Retrieval Test
// @Description Test retrieval of chunks based on question and knowledge base
// @Tags chunks
// @Accept json
// @Produce json
// @Param request body service.RetrievalTestRequest true "retrieval test parameters"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/datasets/search [post]
func (h *ChunkHandler) RetrievalTest(c *gin.Context) {
user, errorCode, errorMessage := GetUser(c)
if errorCode != common.CodeSuccess {
jsonError(c, errorCode, errorMessage)
return
}
// Bind JSON request
var req service.RetrievalTestRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": err.Error(),
})
return
}
// Set default values for optional parameters
if req.Page == nil {
defaultPage := 1
req.Page = &defaultPage
}
if req.Size == nil {
defaultSize := 30
req.Size = &defaultSize
}
if req.TopK == nil {
defaultTopK := 1024
req.TopK = &defaultTopK
}
if req.UseKG == nil {
defaultUseKG := false
req.UseKG = &defaultUseKG
}
// Validate required fields
if req.Question == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "question is required",
})
return
}
if req.Datasets == nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "kb_id is required",
})
return
}
if len(req.Datasets) == 0 {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "kb_id array cannot be empty",
})
return
}
// Call service with user ID for permission checks
resp, err := h.chunkService.RetrievalTest(&req, user.ID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"data": resp,
"message": "success",
})
}
// Get retrieves a chunk by ID
func (h *ChunkHandler) Get(c *gin.Context) {
user, errorCode, errorMessage := GetUser(c)
@@ -134,16 +49,20 @@ func (h *ChunkHandler) Get(c *gin.Context) {
}
chunkID := c.Param("chunk_id")
if chunkID == "" {
datasetID := c.Param("dataset_id")
documentID := c.Param("document_id")
if chunkID == "" || datasetID == "" || documentID == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "chunk_id is required",
"message": "dataset_id, document_id and chunk_id are required",
})
return
}
req := &service.GetChunkRequest{
ChunkID: chunkID,
ChunkID: chunkID,
DocumentID: documentID,
DatasetID: datasetID,
}
resp, err := h.chunkService.Get(req, user.ID)

View File

@@ -602,6 +602,86 @@ func (h *DatasetsHandler) ListMetadataFlattened(c *gin.Context) {
jsonResponse(c, common.CodeSuccess, flattenedMeta, "success")
}
// SearchDatasets searches chunks across datasets based on a question
// @Summary Search Datasets
// @Description Search for relevant chunks across one or more datasets based on a question
// @Tags datasets
// @Accept json
// @Produce json
// @Param request body service.SearchDatasetsRequest true "search parameters"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/datasets/search [post]
func (h *DatasetsHandler) SearchDatasets(c *gin.Context) {
user, errorCode, errorMessage := GetUser(c)
if errorCode != common.CodeSuccess {
jsonError(c, errorCode, errorMessage)
return
}
var req service.SearchDatasetsRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": err.Error(),
})
return
}
if req.Page == nil {
defaultPage := 1
req.Page = &defaultPage
}
if req.Size == nil {
defaultSize := 30
req.Size = &defaultSize
}
if req.TopK == nil {
defaultTopK := 1024
req.TopK = &defaultTopK
}
if req.UseKG == nil {
defaultUseKG := false
req.UseKG = &defaultUseKG
}
if req.Question == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "question is required",
})
return
}
if req.DatasetIDs == nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "kb_id is required",
})
return
}
if len(req.DatasetIDs) == 0 {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "kb_id array cannot be empty",
})
return
}
resp, err := h.datasetsService.SearchDatasets(&req, user.ID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 0,
"data": resp,
})
}
func firstStringValue(value interface{}) string {
switch v := value.(type) {
case string:

View File

@@ -42,10 +42,11 @@ type SearchbotRealLLM struct {
}
func (r *SearchbotRealLLM) Chat(tenantID, modelID string, messages []modelModule.Message, config *modelModule.ChatConfig) (*modelModule.ChatResponse, error) {
chatModel, err := r.Svc.GetChatModel(tenantID, modelID)
driver, modelName, apiConfig, _, err := r.Svc.GetModelConfigFromProviderInstance(tenantID, entity.ModelTypeChat, modelID)
if err != nil {
return nil, err
}
chatModel := modelModule.NewChatModel(driver, &modelName, apiConfig)
return chatModel.ModelDriver.ChatWithMessages(*chatModel.ModelName, messages, chatModel.APIConfig, config)
}