Spaces:
Configuration error
Configuration error
| package openai | |
| import ( | |
| "errors" | |
| "fmt" | |
| "os" | |
| "path/filepath" | |
| "sync/atomic" | |
| "time" | |
| "github.com/microcosm-cc/bluemonday" | |
| "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" | |
| // UploadFilesEndpoint https://platform.openai.com/docs/api-reference/files/create | |
| 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 | |
| } | |
| // Check the file size | |
| 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", "") //TODO put in purpose dirs | |
| if purpose == "" { | |
| return c.Status(fiber.StatusBadRequest).SendString("Purpose is not defined") | |
| } | |
| // Sanitize the filename to prevent directory traversal | |
| filename := utils.SanitizeFileName(file.Filename) | |
| savePath := filepath.Join(appConfig.UploadDir, filename) | |
| // Check if file already exists | |
| 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: " + bluemonday.StrictPolicy().Sanitize(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 | |
| } | |
| // ListFilesEndpoint https://platform.openai.com/docs/api-reference/files/list | |
| // @Summary List files. | |
| // @Success 200 {object} schema.ListFiles "Response" | |
| // @Router /v1/files [get] | |
| 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) | |
| } | |
| // GetFilesEndpoint is the OpenAI API endpoint to get files https://platform.openai.com/docs/api-reference/files/retrieve | |
| // @Summary Returns information about a specific file. | |
| // @Success 200 {object} schema.File "Response" | |
| // @Router /v1/files/{file_id} [get] | |
| 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(bluemonday.StrictPolicy().Sanitize(err.Error())) | |
| } | |
| return c.JSON(file) | |
| } | |
| } | |
| type DeleteStatus struct { | |
| Id string | |
| Object string | |
| Deleted bool | |
| } | |
| // DeleteFilesEndpoint is the OpenAI API endpoint to delete files https://platform.openai.com/docs/api-reference/files/delete | |
| // @Summary Delete a file. | |
| // @Success 200 {object} DeleteStatus "Response" | |
| // @Router /v1/files/{file_id} [delete] | |
| 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(bluemonday.StrictPolicy().Sanitize(err.Error())) | |
| } | |
| err = os.Remove(filepath.Join(appConfig.UploadDir, file.Filename)) | |
| if err != nil { | |
| // If the file doesn't exist then we should just continue to remove it | |
| if !errors.Is(err, os.ErrNotExist) { | |
| return c.Status(fiber.StatusInternalServerError).SendString(bluemonday.StrictPolicy().Sanitize(fmt.Sprintf("Unable to delete file: %s, %v", file.Filename, err))) | |
| } | |
| } | |
| // Remove upload from list | |
| 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, | |
| }) | |
| } | |
| } | |
| // GetFilesContentsEndpoint is the OpenAI API endpoint to get files content https://platform.openai.com/docs/api-reference/files/retrieve-contents | |
| // @Summary Returns information about a specific file. | |
| // @Success 200 {string} binary "file" | |
| // @Router /v1/files/{file_id}/content [get] | |
| // GetFilesContentsEndpoint | |
| 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(bluemonday.StrictPolicy().Sanitize(err.Error())) | |
| } | |
| fileContents, err := os.ReadFile(filepath.Join(appConfig.UploadDir, file.Filename)) | |
| if err != nil { | |
| return c.Status(fiber.StatusInternalServerError).SendString(bluemonday.StrictPolicy().Sanitize(err.Error())) | |
| } | |
| return c.Send(fileContents) | |
| } | |
| } | |