Files

153 lines
5.0 KiB
Go

package conf
import (
"strings"
"github.com/sjzar/chatlog/internal/whisper"
)
// OpenAISettings captures provider-specific fields retained for backwards compatibility.
type OpenAISettings struct {
APIKey string `mapstructure:"api_key" json:"api_key"`
BaseURL string `mapstructure:"base_url" json:"base_url"`
Organization string `mapstructure:"organization" json:"organization"`
Project string `mapstructure:"project" json:"project"`
Proxy string `mapstructure:"proxy" json:"proxy"`
}
// SpeechConfig controls optional speech-to-text features.
type SpeechConfig struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
Provider string `mapstructure:"provider" json:"provider"`
Model string `mapstructure:"model" json:"model"`
TranslateModel string `mapstructure:"translate_model" json:"translate_model"`
Threads int `mapstructure:"threads" json:"threads"`
Language string `mapstructure:"language" json:"language"`
Translate *bool `mapstructure:"translate" json:"translate"`
InitialPrompt string `mapstructure:"initial_prompt" json:"initial_prompt"`
Temperature *float64 `mapstructure:"temperature" json:"temperature"`
TemperatureFallback *float64 `mapstructure:"temperature_fallback" json:"temperature_fallback"`
APIKey string `mapstructure:"api_key" json:"api_key"`
BaseURL string `mapstructure:"base_url" json:"base_url"`
Organization string `mapstructure:"organization" json:"organization"`
Project string `mapstructure:"project" json:"project"`
Proxy string `mapstructure:"proxy" json:"proxy"`
ServiceURL string `mapstructure:"service_url" json:"service_url"`
ServiceOutput string `mapstructure:"service_output" json:"service_output"`
WordTimestamps bool `mapstructure:"word_timestamps" json:"word_timestamps"`
VADFilter bool `mapstructure:"vad_filter" json:"vad_filter"`
RequestTimeoutSeconds int `mapstructure:"request_timeout_seconds" json:"request_timeout_seconds"`
OpenAI OpenAISettings `mapstructure:"openai" json:"openai"`
}
// Normalize hydrates legacy OpenAI fields into the flattened structure and applies defaults.
func (c *SpeechConfig) Normalize() {
if c == nil {
return
}
provider := strings.ToLower(strings.TrimSpace(c.Provider))
if provider == "" {
provider = "openai"
}
c.Provider = provider
if c.APIKey == "" {
c.APIKey = c.OpenAI.APIKey
}
if c.BaseURL == "" {
c.BaseURL = c.OpenAI.BaseURL
}
if c.Organization == "" {
c.Organization = c.OpenAI.Organization
}
if c.Project == "" {
c.Project = c.OpenAI.Project
}
if c.Proxy == "" {
c.Proxy = c.OpenAI.Proxy
}
c.APIKey = strings.TrimSpace(c.APIKey)
c.BaseURL = strings.TrimSpace(c.BaseURL)
c.Organization = strings.TrimSpace(c.Organization)
c.Project = strings.TrimSpace(c.Project)
c.Proxy = strings.TrimSpace(c.Proxy)
c.Model = strings.TrimSpace(c.Model)
c.ServiceURL = strings.TrimSpace(c.ServiceURL)
c.ServiceOutput = strings.TrimSpace(c.ServiceOutput)
switch c.Provider {
case "webservice", "local", "docker", "http", "whisper-asr":
if c.ServiceURL == "" {
c.ServiceURL = "http://127.0.0.1:9000"
}
if c.ServiceOutput == "" {
c.ServiceOutput = "json"
}
c.ServiceOutput = strings.ToLower(c.ServiceOutput)
case "whispercpp", "whisper.cpp", "cpp":
c.Provider = "whispercpp"
default:
if c.Provider != "openai" {
c.Provider = "openai"
}
}
}
// PrepareForSave syncs the flattened OpenAI fields back into the legacy nested structure.
func (c *SpeechConfig) PrepareForSave() {
if c == nil {
return
}
c.Provider = strings.ToLower(strings.TrimSpace(c.Provider))
if c.Provider == "" {
c.Provider = "openai"
}
c.Model = strings.TrimSpace(c.Model)
c.ServiceURL = strings.TrimSpace(c.ServiceURL)
c.ServiceOutput = strings.ToLower(strings.TrimSpace(c.ServiceOutput))
c.OpenAI.APIKey = c.APIKey
c.OpenAI.BaseURL = c.BaseURL
c.OpenAI.Organization = c.Organization
c.OpenAI.Project = c.Project
c.OpenAI.Proxy = c.Proxy
}
// ToOptions converts the speech config into runtime options for a transcription backend.
func (c *SpeechConfig) ToOptions() whisper.Options {
var opts whisper.Options
if c == nil {
return opts
}
if c.Language != "" {
opts.Language = c.Language
opts.LanguageSet = true
}
if c.Translate != nil {
opts.Translate = *c.Translate
opts.TranslateSet = true
}
if c.Threads > 0 {
opts.Threads = c.Threads
opts.ThreadsSet = true
}
if c.InitialPrompt != "" {
opts.InitialPrompt = c.InitialPrompt
opts.InitialPromptSet = true
}
if c.Temperature != nil {
opts.Temperature = float32(*c.Temperature)
opts.TemperatureSet = true
}
if c.TemperatureFallback != nil {
opts.TemperatureFloor = float32(*c.TemperatureFallback)
opts.TemperatureFloorSet = true
}
return opts
}