mirror of
https://github.com/mudler/LocalAI.git
synced 2024-12-24 06:46:39 +00:00
feat(welcome): add simple welcome page (#1912)
* feat(welcome): add simple welcome page * feat(api): add 404 handling
This commit is contained in:
parent
93f0b7ae03
commit
66ee4afb95
@ -15,6 +15,7 @@ type ApplicationConfig struct {
|
|||||||
ConfigFile string
|
ConfigFile string
|
||||||
ModelPath string
|
ModelPath string
|
||||||
UploadLimitMB, Threads, ContextSize int
|
UploadLimitMB, Threads, ContextSize int
|
||||||
|
DisableWelcomePage bool
|
||||||
F16 bool
|
F16 bool
|
||||||
Debug, DisableMessage bool
|
Debug, DisableMessage bool
|
||||||
ImageDir string
|
ImageDir string
|
||||||
@ -105,6 +106,10 @@ var EnableWatchDogBusyCheck = func(o *ApplicationConfig) {
|
|||||||
o.WatchDogBusy = true
|
o.WatchDogBusy = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DisableWelcomePage = func(o *ApplicationConfig) {
|
||||||
|
o.DisableWelcomePage = true
|
||||||
|
}
|
||||||
|
|
||||||
func SetWatchDogBusyTimeout(t time.Duration) AppOption {
|
func SetWatchDogBusyTimeout(t time.Duration) AppOption {
|
||||||
return func(o *ApplicationConfig) {
|
return func(o *ApplicationConfig) {
|
||||||
o.WatchDogBusyTimeout = t
|
o.WatchDogBusyTimeout = t
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/go-skynet/LocalAI/pkg/utils"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-skynet/LocalAI/pkg/utils"
|
||||||
|
|
||||||
"github.com/go-skynet/LocalAI/core/http/endpoints/elevenlabs"
|
"github.com/go-skynet/LocalAI/core/http/endpoints/elevenlabs"
|
||||||
"github.com/go-skynet/LocalAI/core/http/endpoints/localai"
|
"github.com/go-skynet/LocalAI/core/http/endpoints/localai"
|
||||||
"github.com/go-skynet/LocalAI/core/http/endpoints/openai"
|
"github.com/go-skynet/LocalAI/core/http/endpoints/openai"
|
||||||
@ -21,6 +24,7 @@ import (
|
|||||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||||
|
"github.com/gofiber/template/html/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readAuthHeader(c *fiber.Ctx) string {
|
func readAuthHeader(c *fiber.Ctx) string {
|
||||||
@ -41,9 +45,14 @@ func readAuthHeader(c *fiber.Ctx) string {
|
|||||||
return authHeader
|
return authHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:embed views/*
|
||||||
|
var viewsfs embed.FS
|
||||||
|
|
||||||
func App(cl *config.BackendConfigLoader, ml *model.ModelLoader, appConfig *config.ApplicationConfig) (*fiber.App, error) {
|
func App(cl *config.BackendConfigLoader, ml *model.ModelLoader, appConfig *config.ApplicationConfig) (*fiber.App, error) {
|
||||||
|
engine := html.NewFileSystem(http.FS(viewsfs), ".html")
|
||||||
// Return errors as JSON responses
|
// Return errors as JSON responses
|
||||||
app := fiber.New(fiber.Config{
|
app := fiber.New(fiber.Config{
|
||||||
|
Views: engine,
|
||||||
BodyLimit: appConfig.UploadLimitMB * 1024 * 1024, // this is the default limit of 4MB
|
BodyLimit: appConfig.UploadLimitMB * 1024 * 1024, // this is the default limit of 4MB
|
||||||
DisableStartupMessage: appConfig.DisableMessage,
|
DisableStartupMessage: appConfig.DisableMessage,
|
||||||
// Override default error handler
|
// Override default error handler
|
||||||
@ -168,6 +177,21 @@ func App(cl *config.BackendConfigLoader, ml *model.ModelLoader, appConfig *confi
|
|||||||
utils.LoadConfig(appConfig.ConfigsDir, openai.AssistantsConfigFile, &openai.Assistants)
|
utils.LoadConfig(appConfig.ConfigsDir, openai.AssistantsConfigFile, &openai.Assistants)
|
||||||
utils.LoadConfig(appConfig.ConfigsDir, openai.AssistantsFileConfigFile, &openai.AssistantFiles)
|
utils.LoadConfig(appConfig.ConfigsDir, openai.AssistantsFileConfigFile, &openai.AssistantFiles)
|
||||||
|
|
||||||
|
if !appConfig.DisableWelcomePage {
|
||||||
|
models, _ := ml.ListModels()
|
||||||
|
backendConfigs := cl.GetAllBackendConfigs()
|
||||||
|
app.Get("/", auth, func(c *fiber.Ctx) error {
|
||||||
|
// Render index
|
||||||
|
return c.Render("views/index", fiber.Map{
|
||||||
|
"Title": "LocalAI API - " + internal.PrintableVersion(),
|
||||||
|
"Version": internal.PrintableVersion(),
|
||||||
|
"Models": models,
|
||||||
|
"ModelsConfig": backendConfigs,
|
||||||
|
"ApplicationConfig": appConfig,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
modelGalleryEndpointService := localai.CreateModelGalleryEndpointService(appConfig.Galleries, appConfig.ModelPath, galleryService)
|
modelGalleryEndpointService := localai.CreateModelGalleryEndpointService(appConfig.Galleries, appConfig.ModelPath, galleryService)
|
||||||
app.Post("/models/apply", auth, modelGalleryEndpointService.ApplyModelGalleryEndpoint())
|
app.Post("/models/apply", auth, modelGalleryEndpointService.ApplyModelGalleryEndpoint())
|
||||||
app.Get("/models/available", auth, modelGalleryEndpointService.ListModelFromGalleryEndpoint())
|
app.Get("/models/available", auth, modelGalleryEndpointService.ListModelFromGalleryEndpoint())
|
||||||
@ -275,5 +299,21 @@ func App(cl *config.BackendConfigLoader, ml *model.ModelLoader, appConfig *confi
|
|||||||
|
|
||||||
app.Get("/metrics", localai.LocalAIMetricsEndpoint())
|
app.Get("/metrics", localai.LocalAIMetricsEndpoint())
|
||||||
|
|
||||||
|
// Define a custom 404 handler
|
||||||
|
app.Use(func(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
// Check if the request accepts JSON
|
||||||
|
if string(c.Context().Request.Header.ContentType()) == "application/json" || len(c.Accepts("html")) == 0 {
|
||||||
|
// The client expects a JSON response
|
||||||
|
c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
||||||
|
"error": "Resource not found",
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// The client expects an HTML response
|
||||||
|
c.Status(fiber.StatusNotFound).Render("views/404", fiber.Map{})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
return app, nil
|
return app, nil
|
||||||
}
|
}
|
||||||
|
33
core/http/views/404.html
Normal file
33
core/http/views/404.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
{{template "views/partials/head" .}}
|
||||||
|
|
||||||
|
<body class="bg-black text-white">
|
||||||
|
<div class="flex flex-col min-h-screen">
|
||||||
|
|
||||||
|
{{template "views/partials/navbar" .}}
|
||||||
|
|
||||||
|
<div class="container mx-auto px-4 flex-grow">
|
||||||
|
<div class="header text-center py-12">
|
||||||
|
<h1 class="text-5xl font-bold">Welcome to your LocalAI instance!</h1>
|
||||||
|
<div class="mt-6">
|
||||||
|
<!-- <a href="/" aria-label="HomePage" alt="HomePage">
|
||||||
|
<img class="mx-auto w-1/4 h-auto" src="https://github.com/go-skynet/LocalAI/assets/2420543/0966aa2a-166e-4f99-a3e5-6c915fc997dd" alt="LocalAI Logo">
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
<p class="mt-4 text-lg">The FOSS alternative to OpenAI, Claude, ...</p>
|
||||||
|
<a href="https://localai.io" target="_blank" class="mt-4 inline-block bg-blue-500 text-white py-2 px-4 rounded transition duration-300 ease-in-out hover:bg-blue-700"><i class="fas fa-book-reader pr-2"></i>Documentation</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="models mt-12">
|
||||||
|
<h2 class="text-center text-3xl font-semibold">Nothing found!</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{template "views/partials/footer" .}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
58
core/http/views/index.html
Normal file
58
core/http/views/index.html
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{.Title}}</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Roboto:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-black text-white">
|
||||||
|
|
||||||
|
<div class="flex flex-col min-h-screen">
|
||||||
|
|
||||||
|
{{template "views/partials/navbar" .}}
|
||||||
|
|
||||||
|
<div class="container mx-auto px-4 flex-grow">
|
||||||
|
<div class="header text-center py-12">
|
||||||
|
<h1 class="text-5xl font-bold">Welcome to your LocalAI instance!</h1>
|
||||||
|
<div class="mt-6">
|
||||||
|
<!-- <a href="/" aria-label="HomePage" alt="HomePage">
|
||||||
|
<img class="mx-auto w-1/4 h-auto" src="https://github.com/go-skynet/LocalAI/assets/2420543/0966aa2a-166e-4f99-a3e5-6c915fc997dd" alt="LocalAI Logo">
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
<p class="mt-4 text-lg">The FOSS alternative to OpenAI, Claude, ...</p>
|
||||||
|
<a href="https://localai.io" target="_blank" class="mt-4 inline-block bg-blue-500 text-white py-2 px-4 rounded transition duration-300 ease-in-out hover:bg-blue-700"><i class="fas fa-book-reader pr-2"></i>Documentation</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="models mt-12">
|
||||||
|
<h2 class="text-center text-3xl font-semibold">Installed models</h2>
|
||||||
|
<p class="text-center mt-4 text-xl">We have {{len .ModelsConfig}} pre-loaded models available.</p>
|
||||||
|
<ul class="mt-8">
|
||||||
|
{{ range .ModelsConfig }}
|
||||||
|
<li class="border border-gray-600 p-4 rounded mb-4">
|
||||||
|
<p class="font-bold"><i class="fas fa-brain pr-2"></i>{{.Name}}</p>
|
||||||
|
{{ if .Usage }}
|
||||||
|
<div class="text-sm bg-gray-800 text-gray-300 p-2 rounded mt-2"><code>{{.Usage}}</code></div>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Description }}
|
||||||
|
<p class="mt-2 text-gray-400">{{.Description}}</p>
|
||||||
|
{{ end }}
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{template "views/partials/footer" .}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
4
core/http/views/partials/footer.html
Normal file
4
core/http/views/partials/footer.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<footer class="text-center py-8">
|
||||||
|
LocalAI Version {{.Version}}<br>
|
||||||
|
<a href='https://localai.io' class="text-blue-400 hover:text-blue-600" target="_blank">LocalAI</a> © 2023-2024 <a href='https://mudler.pm' class="text-blue-400 hover:text-blue-600" target="_blank">Ettore Di Giacinto</a>
|
||||||
|
</footer>
|
13
core/http/views/partials/head.html
Normal file
13
core/http/views/partials/head.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{.Title}}</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Roboto:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
15
core/http/views/partials/navbar.html
Normal file
15
core/http/views/partials/navbar.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<nav class="bg-gray-800 shadow-lg">
|
||||||
|
<div class="container mx-auto px-4 py-4">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<!-- Logo Image: Replace 'logo_url_here' with your actual logo URL -->
|
||||||
|
<a href="/" class="text-white text-xl font-bold"><img src="https://github.com/go-skynet/LocalAI/assets/2420543/0966aa2a-166e-4f99-a3e5-6c915fc997dd" alt="LocalAI Logo" class="h-10 mr-3 border-2 border-gray-300 shadow rounded"></a>
|
||||||
|
<a href="/" class="text-white text-xl font-bold">LocalAI</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="/" class="text-gray-400 hover:text-white px-3 py-2 rounded"><i class="fas fa-home pr-2"></i>Home</a>
|
||||||
|
<a href="https://localai.io" class="text-gray-400 hover:text-white px-3 py-2 rounded" target="_blank" ><i class="fas fa-book-reader pr-2"></i> Documentation</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
3
go.mod
3
go.mod
@ -75,6 +75,9 @@ require (
|
|||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/gofiber/template v1.8.3 // indirect
|
||||||
|
github.com/gofiber/template/html/v2 v2.1.1 // indirect
|
||||||
|
github.com/gofiber/utils v1.1.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/golang/snappy v0.0.2 // indirect
|
github.com/golang/snappy v0.0.2 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -96,6 +96,12 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw=
|
github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw=
|
||||||
github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw=
|
github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw=
|
||||||
|
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
|
||||||
|
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
||||||
|
github.com/gofiber/template/html/v2 v2.1.1 h1:QEy3O3EBkvwDthy5bXVGUseOyO6ldJoiDxlF4+MJiV8=
|
||||||
|
github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQbNa4x1CVNFW0wju0=
|
||||||
|
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||||
|
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
11
main.go
11
main.go
@ -189,6 +189,12 @@ func main() {
|
|||||||
EnvVars: []string{"WATCHDOG_IDLE"},
|
EnvVars: []string{"WATCHDOG_IDLE"},
|
||||||
Value: false,
|
Value: false,
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "disable-welcome",
|
||||||
|
Usage: "Disable welcome pages",
|
||||||
|
EnvVars: []string{"DISABLE_WELCOME"},
|
||||||
|
Value: false,
|
||||||
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "enable-watchdog-busy",
|
Name: "enable-watchdog-busy",
|
||||||
Usage: "Enable watchdog for stopping busy backends that exceed a defined threshold.",
|
Usage: "Enable watchdog for stopping busy backends that exceed a defined threshold.",
|
||||||
@ -264,6 +270,11 @@ For a list of compatible model, check out: https://localai.io/model-compatibilit
|
|||||||
|
|
||||||
idleWatchDog := ctx.Bool("enable-watchdog-idle")
|
idleWatchDog := ctx.Bool("enable-watchdog-idle")
|
||||||
busyWatchDog := ctx.Bool("enable-watchdog-busy")
|
busyWatchDog := ctx.Bool("enable-watchdog-busy")
|
||||||
|
|
||||||
|
if ctx.Bool("disable-welcome") {
|
||||||
|
opts = append(opts, config.DisableWelcomePage)
|
||||||
|
}
|
||||||
|
|
||||||
if idleWatchDog || busyWatchDog {
|
if idleWatchDog || busyWatchDog {
|
||||||
opts = append(opts, config.EnableWatchDog)
|
opts = append(opts, config.EnableWatchDog)
|
||||||
if idleWatchDog {
|
if idleWatchDog {
|
||||||
|
Loading…
Reference in New Issue
Block a user