Initial commit: LlamaLink Go rewrite
Complete rewrite from Python/FastAPI to Go/Gin: - Go backend: auth (API keys + bcrypt), llama.cpp subprocess manager, hot-swap multi-model, rate limiting, quota system, webhooks - Vue 3 SPA admin panel (src/) with Tailwind CSS - Deployment: Docker multi-stage, docker-compose, nginx, systemd - GORM/SQLite models: ApiKey, Model, UsageLog, Quota, Webhook - REST API: /api/v1/admin/* (keys, models, chat, usage, health) - Embedded frontend via go:embed (build output at web/dist/) Removed legacy Python artifacts (app/, tests/, pyproject.toml, etc.)
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
// Server
|
||||
LlamalinkEnv string
|
||||
LlamalinkHost string
|
||||
LlamalinkPort int
|
||||
|
||||
// Database
|
||||
DatabaseURL string
|
||||
DatabaseMaxOpenConns int
|
||||
DatabaseMaxIdleConns int
|
||||
DatabaseConnMaxLifetime int // seconds
|
||||
|
||||
// Llama server management
|
||||
ManageLlamaServer bool
|
||||
LlamaServerBin string
|
||||
LlamaServerHost string
|
||||
LlamaServerPort int
|
||||
LlamaServerStartupTimeout int // seconds
|
||||
LlamaServerStopTimeout int // seconds
|
||||
ModelSwapCooldown int // seconds
|
||||
|
||||
// Rate limiting
|
||||
RateLimitPerMinute int
|
||||
RateLimitStorage string // "memory" or "redis"
|
||||
|
||||
// Auth
|
||||
AdminToken string
|
||||
|
||||
// Logging
|
||||
LogLevel string
|
||||
LogFormat string // "json" or "text"
|
||||
}
|
||||
|
||||
func Load() *Config {
|
||||
c := &Config{
|
||||
LlamalinkEnv: getEnv("LLAMALINK_ENV", "development"),
|
||||
LlamalinkHost: getEnv("LLAMALINK_HOST", "0.0.0.0"),
|
||||
LlamalinkPort: intEnv("LLAMALINK_PORT", 8000),
|
||||
DatabaseURL: getEnv("DATABASE_URL", "sqlite:///./llamalink.db"),
|
||||
DatabaseMaxOpenConns: intEnv("DATABASE_MAX_OPEN_CONNS", 25),
|
||||
DatabaseMaxIdleConns: intEnv("DATABASE_MAX_IDLE_CONNS", 5),
|
||||
DatabaseConnMaxLifetime: intEnv("DATABASE_CONN_MAX_LIFETIME", 300),
|
||||
ManageLlamaServer: boolEnv("MANAGE_LLAMA_SERVER", true),
|
||||
LlamaServerBin: getEnv("LLAMA_SERVER_BIN", "/usr/local/bin/llama-server"),
|
||||
LlamaServerHost: getEnv("LLAMA_SERVER_HOST", "127.0.0.1"),
|
||||
LlamaServerPort: intEnv("LLAMA_SERVER_PORT", 8080),
|
||||
LlamaServerStartupTimeout: intEnv("LLAMA_SERVER_STARTUP_TIMEOUT", 120),
|
||||
LlamaServerStopTimeout: intEnv("LLAMA_SERVER_STOP_TIMEOUT", 10),
|
||||
ModelSwapCooldown: intEnv("MODEL_SWAP_COOLDOWN", 2),
|
||||
RateLimitPerMinute: intEnv("RATE_LIMIT_PER_MINUTE", 60),
|
||||
RateLimitStorage: getEnv("RATE_LIMIT_STORAGE", "memory"),
|
||||
AdminToken: getEnv("ADMIN_TOKEN", "changeme"),
|
||||
LogLevel: getEnv("LOG_LEVEL", "info"),
|
||||
LogFormat: getEnv("LOG_FORMAT", "json"),
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) LlamaServerURL() string {
|
||||
return "http://" + c.LlamaServerHost + ":" + strconv.Itoa(c.LlamaServerPort)
|
||||
}
|
||||
|
||||
func (c *Config) LlamaServerStartupTimeoutDuration() time.Duration {
|
||||
return time.Duration(c.LlamaServerStartupTimeout) * time.Second
|
||||
}
|
||||
|
||||
func (c *Config) LlamaServerStopTimeoutDuration() time.Duration {
|
||||
return time.Duration(c.LlamaServerStopTimeout) * time.Second
|
||||
}
|
||||
|
||||
func (c *Config) ModelSwapCooldownDuration() time.Duration {
|
||||
return time.Duration(c.ModelSwapCooldown) * time.Second
|
||||
}
|
||||
|
||||
func (c *Config) Logger() *slog.Logger {
|
||||
var level slog.Level
|
||||
switch c.LogLevel {
|
||||
case "debug":
|
||||
level = slog.LevelDebug
|
||||
case "warn":
|
||||
level = slog.LevelWarn
|
||||
case "error":
|
||||
level = slog.LevelError
|
||||
default:
|
||||
level = slog.LevelInfo
|
||||
}
|
||||
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: level,
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
if c.LogFormat == "text" {
|
||||
handler = slog.NewTextHandler(os.Stdout, opts)
|
||||
} else {
|
||||
handler = slog.NewJSONHandler(os.Stdout, opts)
|
||||
}
|
||||
|
||||
return slog.New(handler)
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func intEnv(key string, defaultValue int) int {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
if i, err := strconv.Atoi(v); err == nil {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func boolEnv(key string, defaultValue bool) bool {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
if v == "true" || v == "1" || v == "yes" {
|
||||
return true
|
||||
}
|
||||
if v == "false" || v == "0" || v == "no" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
Reference in New Issue
Block a user