feat: better language selection
This commit is contained in:
@@ -1074,38 +1074,6 @@ func TestConfig_Validate_GroqTranscription(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfig_Validate_GroqTranslation(t *testing.T) {
|
||||
config := &Config{
|
||||
Recording: RecordingConfig{
|
||||
SampleRate: 16000,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
Timeout: time.Minute,
|
||||
},
|
||||
Transcription: TranscriptionConfig{
|
||||
Provider: "groq-translation",
|
||||
APIKey: "gsk-test-key",
|
||||
Language: "es",
|
||||
Model: "whisper-large-v3", // Translation only supports non-turbo
|
||||
},
|
||||
Injection: InjectionConfig{
|
||||
Backends: []string{"ydotool", "wtype", "clipboard"}, YdotoolTimeout: 5 * time.Second,
|
||||
WtypeTimeout: time.Second,
|
||||
ClipboardTimeout: time.Second,
|
||||
},
|
||||
Notifications: NotificationsConfig{
|
||||
Type: "log",
|
||||
},
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
if err != nil {
|
||||
t.Errorf("Validate() should have passed with valid groq-translation config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfig_Validate_GroqInvalidModel(t *testing.T) {
|
||||
config := &Config{
|
||||
Recording: RecordingConfig{
|
||||
@@ -1248,41 +1216,6 @@ func TestConfig_ToTranscriberConfig_GroqWithEnvVar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfig_Validate_GroqTranslation_RejectsTurbo(t *testing.T) {
|
||||
config := &Config{
|
||||
Recording: RecordingConfig{
|
||||
SampleRate: 16000,
|
||||
Channels: 1,
|
||||
Format: "s16",
|
||||
BufferSize: 8192,
|
||||
ChannelBufferSize: 30,
|
||||
Timeout: time.Minute,
|
||||
},
|
||||
Transcription: TranscriptionConfig{
|
||||
Provider: "groq-translation",
|
||||
APIKey: "gsk-test-key",
|
||||
Language: "es",
|
||||
Model: "whisper-large-v3-turbo", // Turbo not supported for translation
|
||||
},
|
||||
Injection: InjectionConfig{
|
||||
Backends: []string{"ydotool", "wtype", "clipboard"}, YdotoolTimeout: 5 * time.Second,
|
||||
WtypeTimeout: time.Second,
|
||||
ClipboardTimeout: time.Second,
|
||||
},
|
||||
Notifications: NotificationsConfig{
|
||||
Type: "log",
|
||||
},
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
if err == nil {
|
||||
t.Error("Validate() should have rejected whisper-large-v3-turbo for groq-translation")
|
||||
}
|
||||
if err != nil && err.Error() != "invalid model for groq-translation: whisper-large-v3-turbo (must be whisper-large-v3, turbo version not supported for translation)" {
|
||||
t.Errorf("Unexpected error message: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessagesConfig_Resolve_Defaults(t *testing.T) {
|
||||
cfg := createTestConfig()
|
||||
msgs := cfg.Notifications.Messages.Resolve()
|
||||
|
||||
@@ -104,7 +104,7 @@ func (c *Config) migrateTranscriptionAPIKey(apiKey string) {
|
||||
switch providerName {
|
||||
case "openai":
|
||||
c.Providers["openai"] = ProviderConfig{APIKey: apiKey}
|
||||
case "groq-transcription", "groq-translation":
|
||||
case "groq-transcription":
|
||||
c.Providers["groq"] = ProviderConfig{APIKey: apiKey}
|
||||
case "mistral-transcription":
|
||||
c.Providers["mistral"] = ProviderConfig{APIKey: apiKey}
|
||||
|
||||
@@ -246,7 +246,7 @@ keywords = []
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
[transcription]
|
||||
provider = "openai" # "openai", "groq-transcription", "groq-translation", "mistral-transcription", "elevenlabs", "whisper-cpp"
|
||||
provider = "openai" # "openai", "groq-transcription", "mistral-transcription", "elevenlabs", "whisper-cpp"
|
||||
model = "whisper-1" # Model: OpenAI="whisper-1", Groq="whisper-large-v3", Mistral="voxtral-mini-latest", ElevenLabs="scribe_v1"
|
||||
language = "" # ISO 639-1 code (e.g., en, es, de). Empty for auto-detect.
|
||||
threads = 0 # CPU threads for local transcription (0 = auto: uses NumCPU-1)
|
||||
@@ -325,7 +325,6 @@ keywords = []
|
||||
# Transcription providers:
|
||||
# - "openai": OpenAI Whisper API (cloud-based, excellent accuracy)
|
||||
# - "groq-transcription": Groq Whisper API (very fast, models: whisper-large-v3, whisper-large-v3-turbo)
|
||||
# - "groq-translation": Groq translation to English (always outputs English text, model: whisper-large-v3)
|
||||
# - "mistral-transcription": Mistral Voxtral API (excellent for European languages, model: voxtral-mini-latest)
|
||||
# - "elevenlabs": ElevenLabs Scribe API (99 languages, models: scribe_v1, scribe_v2)
|
||||
#
|
||||
|
||||
@@ -2,19 +2,17 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/leonardotrapani/hyprvoice/internal/language"
|
||||
"github.com/leonardotrapani/hyprvoice/internal/provider"
|
||||
)
|
||||
|
||||
// mapConfigProviderToRegistryName maps config provider names to provider registry names
|
||||
// Config uses names like "groq-transcription", "groq-translation", "mistral-transcription"
|
||||
// Config uses names like "groq-transcription", "mistral-transcription"
|
||||
// Registry uses base names like "groq", "mistral"
|
||||
func mapConfigProviderToRegistryName(configProvider string) string {
|
||||
switch configProvider {
|
||||
case "groq-transcription", "groq-translation":
|
||||
case "groq-transcription":
|
||||
return "groq"
|
||||
case "mistral-transcription":
|
||||
return "mistral"
|
||||
@@ -85,21 +83,11 @@ func (c *Config) Validate() error {
|
||||
}
|
||||
}
|
||||
|
||||
// validate language codes - warn if not recognized but don't error
|
||||
if c.Transcription.Language != "" && !language.IsValidCode(c.Transcription.Language) {
|
||||
log.Printf("warning: unrecognized language code '%s' in transcription.language, will be passed as-is to provider", c.Transcription.Language)
|
||||
}
|
||||
|
||||
// validate model exists
|
||||
if c.Transcription.Model == "" {
|
||||
return fmt.Errorf("invalid transcription.model: empty")
|
||||
}
|
||||
|
||||
// groq-translation is a special case - only supports whisper-large-v3
|
||||
if c.Transcription.Provider == "groq-translation" && c.Transcription.Model != "whisper-large-v3" {
|
||||
return fmt.Errorf("invalid model for groq-translation: %s (must be whisper-large-v3, turbo version not supported for translation)", c.Transcription.Model)
|
||||
}
|
||||
|
||||
// validate model exists in provider
|
||||
_, err := provider.GetModel(registryName, c.Transcription.Model)
|
||||
if err != nil {
|
||||
@@ -205,11 +193,6 @@ func ValidateModelLanguageCompatibility(registryProvider, modelID, langCode stri
|
||||
}
|
||||
|
||||
// language not supported - build helpful error message
|
||||
langName := language.FromCode(langCode).Name
|
||||
if langName == "Auto-detect" {
|
||||
langName = langCode // use code if not found
|
||||
}
|
||||
|
||||
// truncate supported languages for error message
|
||||
supported := model.SupportedLanguages
|
||||
suffix := ""
|
||||
@@ -225,9 +208,8 @@ func ValidateModelLanguageCompatibility(registryProvider, modelID, langCode stri
|
||||
}
|
||||
|
||||
return fmt.Errorf(
|
||||
"model %s does not support %s (%s).%s Supported: %s%s",
|
||||
"model %s does not support language '%s'.%s Supported: %s%s",
|
||||
model.Name,
|
||||
langName,
|
||||
langCode,
|
||||
docsHint,
|
||||
strings.Join(supported, ", "),
|
||||
|
||||
Reference in New Issue
Block a user