package config import ( "log" "os" "github.com/spf13/viper" ) type Config struct { Server struct { IP string Port int AccessToken string } Log struct { Level string LogPath string `mapstructure:"logPath"` } `mapstructure:"log"` Chat struct { ApiKey string `mapstructure:"api_key"` BaseUrl string `mapstructure:"base_url"` Model string `mapstructure:"model"` MaxTokens int `mapstructure:"max_tokens"` Temperature float32 `mapstructure:"temperature"` TopP float32 `mapstructure:"top_p"` PresencePenalty float32 `mapstructure:"presence_penalty"` FrequencyPenalty float32 `mapstructure:"frequency_penalty"` BotDesc string `mapstructure:"bot_desc"` MinResponseTokens int `mapstructure:"min_response_tokens"` ContextTTL int `mapstructure:"context_ttl"` ContextLen int `mapstructure:"context_len"` } Mysql struct { DSN string MaxLifeTime int MaxOpenConn int MaxIdleConn int } Redis struct { Host string Port int Pwd string `mapstructure:"pwd"` } DependOn struct { Sensitive struct { Address string AccessToken string } Keywords struct { Address string AccessToken string } Tokenizer struct { Address string } } Vector struct { Provider string Threshold float32 Tencent struct { Url string Username string Pwd string Database string Timeout int MaxIdleConnPerHost int ReadConsistency string IdleConnTimeout int } Pgvector struct { DSN string `mapstructure:"dsn"` Table string `mapstructure:"table"` Dimensions int `mapstructure:"dimensions"` MaxLifeTime int `mapstructure:"maxLifeTime"` MaxOpenConn int `mapstructure:"maxOpenConn"` MaxIdleConn int `mapstructure:"maxIdleConn"` } } Embedding struct { Provider string BaseUrl string `mapstructure:"base_url"` ApiKey string `mapstructure:"api_key"` Model string `mapstructure:"model"` Timeout int } VectorDB struct { Url string Username string Pwd string Database string Timeout int MaxIdleConnPerHost int ReadConsistency string IdleConnTimeout int } } var conf *Config func InitConfig(filePath string, typ ...string) { v := viper.New() v.SetConfigFile(filePath) if len(typ) > 0 { v.SetConfigType(typ[0]) } err := v.ReadInConfig() if err != nil { log.Fatal(err) } conf = &Config{} err = v.Unmarshal(conf) if err != nil { log.Fatal(err) } normalizeConfig(conf) applySecretEnvOverrides(conf) } func GetConfig() *Config { return conf } func normalizeConfig(conf *Config) { if conf.Vector.Provider == "" { conf.Vector.Provider = "tencent" } if conf.Vector.Threshold == 0 { conf.Vector.Threshold = 0.99 } // Backfill the new vector.tencent block from the legacy vectorDB config. if conf.Vector.Tencent.Url == "" { conf.Vector.Tencent.Url = conf.VectorDB.Url } if conf.Vector.Tencent.Username == "" { conf.Vector.Tencent.Username = conf.VectorDB.Username } if conf.Vector.Tencent.Pwd == "" { conf.Vector.Tencent.Pwd = conf.VectorDB.Pwd } if conf.Vector.Tencent.Database == "" { conf.Vector.Tencent.Database = conf.VectorDB.Database } if conf.Vector.Tencent.Timeout == 0 { conf.Vector.Tencent.Timeout = conf.VectorDB.Timeout } if conf.Vector.Tencent.MaxIdleConnPerHost == 0 { conf.Vector.Tencent.MaxIdleConnPerHost = conf.VectorDB.MaxIdleConnPerHost } if conf.Vector.Tencent.ReadConsistency == "" { conf.Vector.Tencent.ReadConsistency = conf.VectorDB.ReadConsistency } if conf.Vector.Tencent.IdleConnTimeout == 0 { conf.Vector.Tencent.IdleConnTimeout = conf.VectorDB.IdleConnTimeout } if conf.Embedding.Provider == "" { conf.Embedding.Provider = "openai-compatible" } if conf.Embedding.BaseUrl == "" { conf.Embedding.BaseUrl = conf.Chat.BaseUrl } if conf.Embedding.ApiKey == "" { conf.Embedding.ApiKey = conf.Chat.ApiKey } if conf.Embedding.Timeout == 0 { conf.Embedding.Timeout = 10 } } func applySecretEnvOverrides(conf *Config) { if v := os.Getenv("MOONSHOT_API_KEY"); v != "" { conf.Chat.ApiKey = v } if v := os.Getenv("AI_CHAT_EMBEDDING_API_KEY"); v != "" { conf.Embedding.ApiKey = v } if v := os.Getenv("REDIS_PASSWORD"); v != "" { conf.Redis.Pwd = v } }