|
package openai |
|
|
|
import ( |
|
"errors" |
|
"fmt" |
|
"os" |
|
"path/filepath" |
|
"sync/atomic" |
|
"time" |
|
|
|
"github.com/mudler/LocalAI/core/config" |
|
"github.com/mudler/LocalAI/core/schema" |
|
|
|
"github.com/gofiber/fiber/v2" |
|
"github.com/mudler/LocalAI/pkg/utils" |
|
) |
|
|
|
var UploadedFiles []schema.File |
|
|
|
const UploadedFilesFile = "uploadedFiles.json" |
|
|
|
|
|
func UploadFilesEndpoint(cm *config.BackendConfigLoader, appConfig *config.ApplicationConfig) func(c *fiber.Ctx) error { |
|
return func(c *fiber.Ctx) error { |
|
file, err := c.FormFile("file") |
|
if err != nil { |
|
return err |
|
} |
|
|
|
|
|
if file.Size > int64(appConfig.UploadLimitMB*1024*1024) { |
|
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("File size %d exceeds upload limit %d", file.Size, appConfig.UploadLimitMB)) |
|
} |
|
|
|
purpose := c.FormValue("purpose", "") |
|
if purpose == "" { |
|
return c.Status(fiber.StatusBadRequest).SendString("Purpose is not defined") |
|
} |
|
|
|
|
|
filename := utils.SanitizeFileName(file.Filename) |
|
|
|
savePath := filepath.Join(appConfig.UploadDir, filename) |
|
|
|
|
|
if _, err := os.Stat(savePath); !os.IsNotExist(err) { |
|
return c.Status(fiber.StatusBadRequest).SendString("File already exists") |
|
} |
|
|
|
err = c.SaveFile(file, savePath) |
|
if err != nil { |
|
return c.Status(fiber.StatusInternalServerError).SendString("Failed to save file: " + err.Error()) |
|
} |
|
|
|
f := schema.File{ |
|
ID: fmt.Sprintf("file-%d", getNextFileId()), |
|
Object: "file", |
|
Bytes: int(file.Size), |
|
CreatedAt: time.Now(), |
|
Filename: file.Filename, |
|
Purpose: purpose, |
|
} |
|
|
|
UploadedFiles = append(UploadedFiles, f) |
|
utils.SaveConfig(appConfig.UploadDir, UploadedFilesFile, UploadedFiles) |
|
return c.Status(fiber.StatusOK).JSON(f) |
|
} |
|
} |
|
|
|
var currentFileId int64 = 0 |
|
|
|
func getNextFileId() int64 { |
|
atomic.AddInt64(¤tId, 1) |
|
return currentId |
|
} |
|
|
|
|
|
|
|
|
|
|
|
func ListFilesEndpoint(cm *config.BackendConfigLoader, appConfig *config.ApplicationConfig) func(c *fiber.Ctx) error { |
|
|
|
return func(c *fiber.Ctx) error { |
|
var listFiles schema.ListFiles |
|
|
|
purpose := c.Query("purpose") |
|
if purpose == "" { |
|
listFiles.Data = UploadedFiles |
|
} else { |
|
for _, f := range UploadedFiles { |
|
if purpose == f.Purpose { |
|
listFiles.Data = append(listFiles.Data, f) |
|
} |
|
} |
|
} |
|
listFiles.Object = "list" |
|
return c.Status(fiber.StatusOK).JSON(listFiles) |
|
} |
|
} |
|
|
|
func getFileFromRequest(c *fiber.Ctx) (*schema.File, error) { |
|
id := c.Params("file_id") |
|
if id == "" { |
|
return nil, fmt.Errorf("file_id parameter is required") |
|
} |
|
|
|
for _, f := range UploadedFiles { |
|
if id == f.ID { |
|
return &f, nil |
|
} |
|
} |
|
|
|
return nil, fmt.Errorf("unable to find file id %s", id) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
func GetFilesEndpoint(cm *config.BackendConfigLoader, appConfig *config.ApplicationConfig) func(c *fiber.Ctx) error { |
|
return func(c *fiber.Ctx) error { |
|
file, err := getFileFromRequest(c) |
|
if err != nil { |
|
return c.Status(fiber.StatusInternalServerError).SendString(err.Error()) |
|
} |
|
|
|
return c.JSON(file) |
|
} |
|
} |
|
|
|
type DeleteStatus struct { |
|
Id string |
|
Object string |
|
Deleted bool |
|
} |
|
|
|
|
|
|
|
|
|
|
|
func DeleteFilesEndpoint(cm *config.BackendConfigLoader, appConfig *config.ApplicationConfig) func(c *fiber.Ctx) error { |
|
|
|
return func(c *fiber.Ctx) error { |
|
file, err := getFileFromRequest(c) |
|
if err != nil { |
|
return c.Status(fiber.StatusInternalServerError).SendString(err.Error()) |
|
} |
|
|
|
err = os.Remove(filepath.Join(appConfig.UploadDir, file.Filename)) |
|
if err != nil { |
|
|
|
if !errors.Is(err, os.ErrNotExist) { |
|
return c.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("Unable to delete file: %s, %v", file.Filename, err)) |
|
} |
|
} |
|
|
|
|
|
for i, f := range UploadedFiles { |
|
if f.ID == file.ID { |
|
UploadedFiles = append(UploadedFiles[:i], UploadedFiles[i+1:]...) |
|
break |
|
} |
|
} |
|
|
|
utils.SaveConfig(appConfig.UploadDir, UploadedFilesFile, UploadedFiles) |
|
return c.JSON(DeleteStatus{ |
|
Id: file.ID, |
|
Object: "file", |
|
Deleted: true, |
|
}) |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
func GetFilesContentsEndpoint(cm *config.BackendConfigLoader, appConfig *config.ApplicationConfig) func(c *fiber.Ctx) error { |
|
return func(c *fiber.Ctx) error { |
|
file, err := getFileFromRequest(c) |
|
if err != nil { |
|
return c.Status(fiber.StatusInternalServerError).SendString(err.Error()) |
|
} |
|
|
|
fileContents, err := os.ReadFile(filepath.Join(appConfig.UploadDir, file.Filename)) |
|
if err != nil { |
|
return c.Status(fiber.StatusInternalServerError).SendString(err.Error()) |
|
} |
|
|
|
return c.Send(fileContents) |
|
} |
|
} |
|
|