- internal/llama/template.go: ChatML/Llama3 template engine with stop tokens - internal/agent/reasoning.go: parse <think>/<reasoning> tags from LLM output - companion/promptbuilder.go: output structured BuildResult, add date/time context - agent/agent.go: wire templates + reasoning split into message loop - storage: add reasoning TEXT column to messages table + migration - channel/tui.go: collapsible reasoning (tab toggle), mouse scroll, polished dimmed style - config: CHAT_TEMPLATE env var (chatml|llama3|none) - plan.md: mark Phase 2 complete, add themes TODO
162 lines
3.6 KiB
Go
162 lines
3.6 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type Config struct {
|
|
// llama.cpp server
|
|
LlamaCppURL string
|
|
Model string
|
|
SystemPrompt string
|
|
Temperature float64
|
|
TopP float64
|
|
MaxTokens int
|
|
ContextSize int
|
|
|
|
// SQLite
|
|
DBPath string
|
|
CompanionDB string
|
|
|
|
// Matrix
|
|
MatrixEnabled bool
|
|
MatrixHomeserver string
|
|
MatrixUser string
|
|
MatrixToken string
|
|
|
|
// Scheduler
|
|
SchedulerInterval time.Duration
|
|
AutoDiary bool
|
|
DiaryHour int
|
|
|
|
// Memory
|
|
MemoryTopK int
|
|
MemoryMinScore float64
|
|
|
|
// Chat template
|
|
ChatTemplate string
|
|
|
|
// Embedding
|
|
EmbeddingModel string
|
|
|
|
// Personality
|
|
TraitChangeMaxDaily float64
|
|
TraitChangeMaxMonthly float64
|
|
|
|
// Logging
|
|
LogLevel string
|
|
|
|
// API
|
|
APIEnabled bool
|
|
APIPort string
|
|
}
|
|
|
|
func Load() *Config {
|
|
return &Config{
|
|
LlamaCppURL: getEnv("LLAMACPP_URL", "http://localhost:8080"),
|
|
Model: getEnv("MODEL_NAME", ""),
|
|
SystemPrompt: getEnv("SYSTEM_PROMPT", "You are Diva, a curious and thoughtful AI companion."),
|
|
Temperature: getEnvFloat("TEMPERATURE", 0.85),
|
|
TopP: getEnvFloat("TOP_P", 0.9),
|
|
MaxTokens: getEnvInt("MAX_TOKENS", 2048),
|
|
ContextSize: getEnvInt("CONTEXT_SIZE", 8192),
|
|
|
|
DBPath: getEnv("DB_PATH", "./data/divacode.db"),
|
|
CompanionDB: getEnv("COMPANION_DB_PATH", "./data/companion.db"),
|
|
|
|
MatrixEnabled: getEnvBool("MATRIX_ENABLED", false),
|
|
MatrixHomeserver: getEnv("MATRIX_HOMESERVER", ""),
|
|
MatrixUser: getEnv("MATRIX_USER", ""),
|
|
MatrixToken: getEnv("MATRIX_TOKEN", ""),
|
|
|
|
SchedulerInterval: getEnvDuration("SCHEDULER_INTERVAL", 15*time.Minute),
|
|
AutoDiary: getEnvBool("AUTO_DIARY", true),
|
|
DiaryHour: getEnvInt("DIARY_HOUR", 23),
|
|
|
|
MemoryTopK: getEnvInt("MEMORY_TOP_K", 5),
|
|
MemoryMinScore: getEnvFloat("MEMORY_MIN_SCORE", 0.6),
|
|
|
|
ChatTemplate: getEnv("CHAT_TEMPLATE", "chatml"),
|
|
|
|
EmbeddingModel: getEnv("EMBEDDING_MODEL", ""),
|
|
|
|
TraitChangeMaxDaily: getEnvFloat("TRAIT_CHANGE_MAX_DAILY", 0.005),
|
|
TraitChangeMaxMonthly: getEnvFloat("TRAIT_CHANGE_MAX_MONTHLY", 0.05),
|
|
|
|
LogLevel: getEnv("LOG_LEVEL", "INFO"),
|
|
|
|
APIEnabled: getEnvBool("API_ENABLED", false),
|
|
APIPort: getEnv("API_PORT", "8080"),
|
|
}
|
|
}
|
|
|
|
func (c *Config) Validate() error {
|
|
if c.LlamaCppURL == "" {
|
|
return fmt.Errorf("LLAMACPP_URL is required")
|
|
}
|
|
if c.DBPath == "" {
|
|
return fmt.Errorf("DB_PATH is required")
|
|
}
|
|
if c.CompanionDB == "" {
|
|
return fmt.Errorf("COMPANION_DB_PATH is required")
|
|
}
|
|
if c.SystemPrompt == "" {
|
|
return fmt.Errorf("SYSTEM_PROMPT is required")
|
|
}
|
|
if c.DiaryHour < 0 || c.DiaryHour > 23 {
|
|
return fmt.Errorf("DIARY_HOUR must be 0-23")
|
|
}
|
|
switch c.ChatTemplate {
|
|
case "chatml", "llama3", "none":
|
|
default:
|
|
return fmt.Errorf("CHAT_TEMPLATE must be chatml, llama3, or none")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvInt(key string, fallback int) int {
|
|
if v := os.Getenv(key); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil {
|
|
return n
|
|
}
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvFloat(key string, fallback float64) float64 {
|
|
if v := os.Getenv(key); v != "" {
|
|
if f, err := strconv.ParseFloat(v, 64); err == nil {
|
|
return f
|
|
}
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvBool(key string, fallback bool) bool {
|
|
if v := os.Getenv(key); v != "" {
|
|
if b, err := strconv.ParseBool(v); err == nil {
|
|
return b
|
|
}
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvDuration(key string, fallback time.Duration) time.Duration {
|
|
if v := os.Getenv(key); v != "" {
|
|
if d, err := time.ParseDuration(v); err == nil {
|
|
return d
|
|
}
|
|
}
|
|
return fallback
|
|
}
|