config: voice defaults and its normalise/validate arms follow (V-410)
Same block, second half. applyDefaults and validate now call normaliseVoice and validateVoice, in the same order the inline arms ran.
This commit is contained in:
@@ -534,22 +534,10 @@ const (
|
|||||||
DefaultTickInterval = 60 * time.Second
|
DefaultTickInterval = 60 * time.Second
|
||||||
DefaultRepeatInterval = 5 * time.Minute
|
DefaultRepeatInterval = 5 * time.Minute
|
||||||
DefaultAutotuneInterval = 10 * time.Minute
|
DefaultAutotuneInterval = 10 * time.Minute
|
||||||
DefaultRouterThreshold = 0.55
|
|
||||||
// DefaultIntakeJournal — entries kept in the unified intake journal
|
// DefaultIntakeJournal — entries kept in the unified intake journal
|
||||||
// (Vikunja #283). A busy day is a few hundred intake writes, so this is
|
// (Vikunja #283). A busy day is a few hundred intake writes, so this is
|
||||||
// roughly "today and yesterday" at a few hundred KB of memory.
|
// roughly "today and yesterday" at a few hundred KB of memory.
|
||||||
DefaultIntakeJournal = 512
|
DefaultIntakeJournal = 512
|
||||||
DefaultQueryMinScore = 0.55
|
|
||||||
// Read off the margin sweep in internal/memory/recalleval on the e5
|
|
||||||
// embedder: 0.008 answers 68% of real questions (down from 72%) and cuts
|
|
||||||
// false recall from 5/5 to 1/5. Every larger delta costs real recall
|
|
||||||
// without removing that last one until 0.020, which drops recall to 44%.
|
|
||||||
DefaultQueryMinMargin = 0.008
|
|
||||||
// DefaultClarifyMaxAttempts — see dialogue.DefaultMaxAttempts.
|
|
||||||
DefaultClarifyMaxAttempts = 3
|
|
||||||
DefaultToolTimeout = 30 * time.Second
|
|
||||||
// DefaultLLMRouter — route with the resident model unless told otherwise.
|
|
||||||
DefaultLLMRouter = true
|
|
||||||
|
|
||||||
DefaultFactEnrichmentInterval = 30 * time.Second
|
DefaultFactEnrichmentInterval = 30 * time.Second
|
||||||
|
|
||||||
@@ -669,32 +657,7 @@ func (c *Config) applyDefaults() {
|
|||||||
|
|
||||||
c.normaliseWorkstation()
|
c.normaliseWorkstation()
|
||||||
|
|
||||||
if c.Voice != nil {
|
c.normaliseVoice()
|
||||||
if c.Voice.RouterThreshold <= 0 {
|
|
||||||
c.Voice.RouterThreshold = DefaultRouterThreshold
|
|
||||||
}
|
|
||||||
if c.Voice.QueryMinScore <= 0 {
|
|
||||||
c.Voice.QueryMinScore = DefaultQueryMinScore
|
|
||||||
}
|
|
||||||
// Unset ⇒ default. Negative is how you turn the margin off on purpose,
|
|
||||||
// so it is clamped to 0 rather than replaced by the default.
|
|
||||||
switch {
|
|
||||||
case c.Voice.QueryMinMargin == 0:
|
|
||||||
c.Voice.QueryMinMargin = DefaultQueryMinMargin
|
|
||||||
case c.Voice.QueryMinMargin < 0:
|
|
||||||
c.Voice.QueryMinMargin = 0
|
|
||||||
}
|
|
||||||
if c.Voice.ClarifyMaxAttempts <= 0 {
|
|
||||||
c.Voice.ClarifyMaxAttempts = DefaultClarifyMaxAttempts
|
|
||||||
}
|
|
||||||
if c.Voice.ToolTimeout <= 0 {
|
|
||||||
c.Voice.ToolTimeout = Duration(DefaultToolTimeout)
|
|
||||||
}
|
|
||||||
if c.Voice.LLMRouter == nil {
|
|
||||||
on := DefaultLLMRouter
|
|
||||||
c.Voice.LLMRouter = &on
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// routines: default severity to care-class (1) — the safe floor: a
|
// routines: default severity to care-class (1) — the safe floor: a
|
||||||
// misconfigured routine can't blast an away channel at 3am.
|
// misconfigured routine can't blast an away channel at 3am.
|
||||||
@@ -712,15 +675,6 @@ func (c *Config) applyDefaults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseLLMRouter reports whether to route with the resident model. Unset means
|
|
||||||
// on; only an explicit false in the config turns it off.
|
|
||||||
func (v *VoiceConfig) UseLLMRouter() bool {
|
|
||||||
if v == nil || v.LLMRouter == nil {
|
|
||||||
return DefaultLLMRouter
|
|
||||||
}
|
|
||||||
return *v.LLMRouter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) validate() error {
|
func (c *Config) validate() error {
|
||||||
if c.Phraser != nil {
|
if c.Phraser != nil {
|
||||||
if c.Phraser.ModelPath == "" {
|
if c.Phraser.ModelPath == "" {
|
||||||
@@ -743,16 +697,8 @@ func (c *Config) validate() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.Voice != nil && c.Voice.Enabled {
|
if err := c.validateVoice(); err != nil {
|
||||||
if c.Voice.Bind == "" {
|
return err
|
||||||
return errors.New("voice.enabled set but voice.bind is empty — refusing to start a voice surface with no bind address")
|
|
||||||
}
|
|
||||||
if c.Voice.Embedder != nil {
|
|
||||||
partial := c.Voice.Embedder.ModelPath == "" || c.Voice.Embedder.TokenizerPath == "" || c.Voice.Embedder.LibPath == ""
|
|
||||||
if partial {
|
|
||||||
return errors.New("voice.embedder: all three of model_path, tokenizer_path, lib_path must be set, or remove embedder to use the floor stub")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// routines: name + body required, cron must parse. A typo here should fail
|
// routines: name + body required, cron must parse. A typo here should fail
|
||||||
// at startup, not silently never fire.
|
// at startup, not silently never fire.
|
||||||
|
|||||||
@@ -1,5 +1,84 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Voice defaults, applied in normaliseVoice.
|
||||||
|
const (
|
||||||
|
DefaultRouterThreshold = 0.55
|
||||||
|
DefaultQueryMinScore = 0.55
|
||||||
|
// Read off the margin sweep in internal/memory/recalleval on the e5
|
||||||
|
// embedder: 0.008 answers 68% of real questions (down from 72%) and cuts
|
||||||
|
// false recall from 5/5 to 1/5. Every larger delta costs real recall
|
||||||
|
// without removing that last one until 0.020, which drops recall to 44%.
|
||||||
|
DefaultQueryMinMargin = 0.008
|
||||||
|
// DefaultClarifyMaxAttempts — see dialogue.DefaultMaxAttempts.
|
||||||
|
DefaultClarifyMaxAttempts = 3
|
||||||
|
DefaultToolTimeout = 30 * time.Second
|
||||||
|
// DefaultLLMRouter — route with the resident model unless told otherwise.
|
||||||
|
DefaultLLMRouter = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// UseLLMRouter reports whether to route with the resident model. Unset means
|
||||||
|
// on; only an explicit false in the config turns it off.
|
||||||
|
func (v *VoiceConfig) UseLLMRouter() bool {
|
||||||
|
if v == nil || v.LLMRouter == nil {
|
||||||
|
return DefaultLLMRouter
|
||||||
|
}
|
||||||
|
return *v.LLMRouter
|
||||||
|
}
|
||||||
|
|
||||||
|
// normaliseVoice applies the block's defaults. An absent block stays nil: the
|
||||||
|
// surface is off and there is nothing to tune.
|
||||||
|
func (c *Config) normaliseVoice() {
|
||||||
|
if c.Voice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.Voice.RouterThreshold <= 0 {
|
||||||
|
c.Voice.RouterThreshold = DefaultRouterThreshold
|
||||||
|
}
|
||||||
|
if c.Voice.QueryMinScore <= 0 {
|
||||||
|
c.Voice.QueryMinScore = DefaultQueryMinScore
|
||||||
|
}
|
||||||
|
// Unset ⇒ default. Negative is how you turn the margin off on purpose,
|
||||||
|
// so it is clamped to 0 rather than replaced by the default.
|
||||||
|
switch {
|
||||||
|
case c.Voice.QueryMinMargin == 0:
|
||||||
|
c.Voice.QueryMinMargin = DefaultQueryMinMargin
|
||||||
|
case c.Voice.QueryMinMargin < 0:
|
||||||
|
c.Voice.QueryMinMargin = 0
|
||||||
|
}
|
||||||
|
if c.Voice.ClarifyMaxAttempts <= 0 {
|
||||||
|
c.Voice.ClarifyMaxAttempts = DefaultClarifyMaxAttempts
|
||||||
|
}
|
||||||
|
if c.Voice.ToolTimeout <= 0 {
|
||||||
|
c.Voice.ToolTimeout = Duration(DefaultToolTimeout)
|
||||||
|
}
|
||||||
|
if c.Voice.LLMRouter == nil {
|
||||||
|
on := DefaultLLMRouter
|
||||||
|
c.Voice.LLMRouter = &on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateVoice refuses a surface that would listen nowhere, and an embedder
|
||||||
|
// block with only some of its three paths filled in.
|
||||||
|
func (c *Config) validateVoice() error {
|
||||||
|
if c.Voice == nil || !c.Voice.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if c.Voice.Bind == "" {
|
||||||
|
return errors.New("voice.enabled set but voice.bind is empty — refusing to start a voice surface with no bind address")
|
||||||
|
}
|
||||||
|
if e := c.Voice.Embedder; e != nil {
|
||||||
|
if e.ModelPath == "" || e.TokenizerPath == "" || e.LibPath == "" {
|
||||||
|
return errors.New("voice.embedder: all three of model_path, tokenizer_path, lib_path must be set, or remove embedder to use the floor stub")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// VoiceConfig — the client↔core TCP surface + the stt/tts worker-module
|
// VoiceConfig — the client↔core TCP surface + the stt/tts worker-module
|
||||||
// seams.
|
// seams.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user