mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-03-18 21:30:01 +08:00
# RAGFlow Go Implementation Plan 🚀 This repository tracks the progress of porting RAGFlow to Go. We'll implement core features and provide performance comparisons between Python and Go versions. ## Implementation Checklist - [x] User Management APIs - [x] Dataset Management Operations - [x] Retrieval Test - [x] Chat Management Operations - [x] Infinity Go SDK --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com> Co-authored-by: Yingfeng Zhang <yingfeng.zhang@gmail.com>
221 lines
6.0 KiB
Go
221 lines
6.0 KiB
Go
//
|
|
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
package service
|
|
|
|
import (
|
|
"ragflow/internal/dao"
|
|
"ragflow/internal/model"
|
|
)
|
|
|
|
// FileService file service
|
|
type FileService struct {
|
|
fileDAO *dao.FileDAO
|
|
file2DocumentDAO *dao.File2DocumentDAO
|
|
}
|
|
|
|
// NewFileService create file service
|
|
func NewFileService() *FileService {
|
|
return &FileService{
|
|
fileDAO: dao.NewFileDAO(),
|
|
file2DocumentDAO: dao.NewFile2DocumentDAO(),
|
|
}
|
|
}
|
|
|
|
// FileInfo file info with additional fields
|
|
type FileInfo struct {
|
|
*model.File
|
|
Size int64 `json:"size"`
|
|
KbsInfo []map[string]interface{} `json:"kbs_info"`
|
|
HasChildFolder bool `json:"has_child_folder,omitempty"`
|
|
}
|
|
|
|
// ListFilesResponse list files response
|
|
type ListFilesResponse struct {
|
|
Total int64 `json:"total"`
|
|
Files []map[string]interface{} `json:"files"`
|
|
ParentFolder map[string]interface{} `json:"parent_folder"`
|
|
}
|
|
|
|
// GetRootFolder gets or creates root folder for tenant
|
|
func (s *FileService) GetRootFolder(tenantID string) (map[string]interface{}, error) {
|
|
file, err := s.fileDAO.GetRootFolder(tenantID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return s.toFileResponse(file), nil
|
|
}
|
|
|
|
// ListFiles lists files by parent folder ID
|
|
func (s *FileService) ListFiles(tenantID, pfID string, page, pageSize int, orderby string, desc bool, keywords string) (*ListFilesResponse, error) {
|
|
// If pfID is empty, get root folder
|
|
if pfID == "" {
|
|
rootFolder, err := s.fileDAO.GetRootFolder(tenantID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pfID = rootFolder.ID
|
|
}
|
|
|
|
// Check if parent folder exists
|
|
if _, err := s.fileDAO.GetByID(pfID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get files by parent folder ID
|
|
files, total, err := s.fileDAO.GetByPfID(tenantID, pfID, page, pageSize, orderby, desc, keywords)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get parent folder
|
|
parentFolder, err := s.fileDAO.GetParentFolder(pfID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Process files to add additional info
|
|
fileResponses := make([]map[string]interface{}, len(files))
|
|
for i, file := range files {
|
|
fileInfo := s.toFileInfo(file)
|
|
|
|
// If folder, calculate size and check for child folders
|
|
if file.Type == "folder" {
|
|
folderSize, err := s.fileDAO.GetFolderSize(file.ID)
|
|
if err == nil {
|
|
fileInfo.Size = folderSize
|
|
}
|
|
hasChild, err := s.fileDAO.HasChildFolder(file.ID)
|
|
if err == nil {
|
|
fileInfo.HasChildFolder = hasChild
|
|
}
|
|
fileInfo.KbsInfo = []map[string]interface{}{}
|
|
} else {
|
|
// Get KB info for non-folder files
|
|
kbsInfo, err := s.file2DocumentDAO.GetKBInfoByFileID(file.ID)
|
|
if err != nil {
|
|
kbsInfo = []map[string]interface{}{}
|
|
}
|
|
fileInfo.KbsInfo = kbsInfo
|
|
}
|
|
|
|
fileResponses[i] = s.fileInfoToResponse(fileInfo)
|
|
}
|
|
|
|
return &ListFilesResponse{
|
|
Total: total,
|
|
Files: fileResponses,
|
|
ParentFolder: s.toFileResponse(parentFolder),
|
|
}, nil
|
|
}
|
|
|
|
// toFileResponse converts file model to response format
|
|
func (s *FileService) toFileResponse(file *model.File) map[string]interface{} {
|
|
result := map[string]interface{}{
|
|
"id": file.ID,
|
|
"parent_id": file.ParentID,
|
|
"tenant_id": file.TenantID,
|
|
"created_by": file.CreatedBy,
|
|
"name": file.Name,
|
|
"size": file.Size,
|
|
"type": file.Type,
|
|
"create_time": file.CreateTime,
|
|
"update_time": file.UpdateTime,
|
|
}
|
|
|
|
if file.Location != nil {
|
|
result["location"] = *file.Location
|
|
}
|
|
result["source_type"] = file.SourceType
|
|
|
|
return result
|
|
}
|
|
|
|
// toFileInfo converts file model to FileInfo
|
|
func (s *FileService) toFileInfo(file *model.File) *FileInfo {
|
|
return &FileInfo{
|
|
File: file,
|
|
Size: file.Size,
|
|
KbsInfo: []map[string]interface{}{},
|
|
HasChildFolder: false,
|
|
}
|
|
}
|
|
|
|
// fileInfoToResponse converts FileInfo to response map
|
|
func (s *FileService) fileInfoToResponse(info *FileInfo) map[string]interface{} {
|
|
result := map[string]interface{}{
|
|
"id": info.File.ID,
|
|
"parent_id": info.File.ParentID,
|
|
"tenant_id": info.File.TenantID,
|
|
"created_by": info.File.CreatedBy,
|
|
"name": info.File.Name,
|
|
"size": info.Size,
|
|
"type": info.File.Type,
|
|
"create_time": info.File.CreateTime,
|
|
"update_time": info.File.UpdateTime,
|
|
"kbs_info": info.KbsInfo,
|
|
}
|
|
|
|
if info.File.Location != nil {
|
|
result["location"] = *info.File.Location
|
|
}
|
|
result["source_type"] = info.File.SourceType
|
|
|
|
if info.File.Type == "folder" {
|
|
result["has_child_folder"] = info.HasChildFolder
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// GetParentFolder gets parent folder of a file
|
|
func (s *FileService) GetParentFolder(fileID string) (map[string]interface{}, error) {
|
|
// Check if file exists
|
|
if _, err := s.fileDAO.GetByID(fileID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get parent folder
|
|
parentFolder, err := s.fileDAO.GetParentFolder(fileID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.toFileResponse(parentFolder), nil
|
|
}
|
|
|
|
// GetAllParentFolders gets all parent folders in path
|
|
func (s *FileService) GetAllParentFolders(fileID string) ([]map[string]interface{}, error) {
|
|
// Check if file exists
|
|
if _, err := s.fileDAO.GetByID(fileID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get all parent folders
|
|
parentFolders, err := s.fileDAO.GetAllParentFolders(fileID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Convert to response format
|
|
result := make([]map[string]interface{}, len(parentFolders))
|
|
for i, folder := range parentFolders {
|
|
result[i] = s.toFileResponse(folder)
|
|
}
|
|
|
|
return result, nil
|
|
}
|