@@ -12,6 +12,7 @@ import (
1212 "fmt"
1313 "os"
1414 "strconv"
15+ "strings"
1516 "time"
1617
1718 "gopkg.in/yaml.v3"
@@ -25,9 +26,38 @@ type Config struct {
2526 Queue QueueConfig `yaml:"queue"`
2627 LLM LLMConfig `yaml:"llm"`
2728 Retrieval RetrievalConfig `yaml:"retrieval"`
29+ Ingest IngestConfig `yaml:"ingest"`
2830 Log LogConfig `yaml:"log"`
2931}
3032
33+ // IngestConfig configures retrieval-quality boosters that run during
34+ // the ingest pipeline (between summarize and StatusReady).
35+ type IngestConfig struct {
36+ HyDE HyDEConfig `yaml:"hyde"`
37+ }
38+
39+ // HyDEConfig configures the HyDE candidate-question stage. For each
40+ // leaf section the pipeline asks the LLM to enumerate questions the
41+ // section's content can answer; those are later folded into the
42+ // retrieval prompt to widen lexical/semantic overlap with user queries.
43+ type HyDEConfig struct {
44+ // Enabled toggles the stage. Default: true. Disable to skip an LLM
45+ // call per leaf when ingest budget matters more than recall.
46+ Enabled bool `yaml:"enabled"`
47+
48+ // Model, when non-empty, overrides the LLM model used for HyDE
49+ // generation. Defaults to the same model used for summarization.
50+ Model string `yaml:"model"`
51+
52+ // NumQuestions caps the questions generated per leaf section.
53+ // Default: 5.
54+ NumQuestions int `yaml:"num_questions"`
55+
56+ // Concurrency bounds parallel LLM calls during the HyDE stage.
57+ // Default: 4.
58+ Concurrency int `yaml:"concurrency"`
59+ }
60+
3161// ServerConfig configures the HTTP server.
3262//
3363// TLS is opt-in. If TLS.CertFile and TLS.KeyFile are both set the engine
@@ -241,6 +271,13 @@ func Default() Config {
241271 TTLSeconds : 600 ,
242272 },
243273 },
274+ Ingest : IngestConfig {
275+ HyDE : HyDEConfig {
276+ Enabled : true ,
277+ NumQuestions : 5 ,
278+ Concurrency : 4 ,
279+ },
280+ },
244281 Log : LogConfig {Level : "info" , Format : "json" },
245282 }
246283}
@@ -344,6 +381,29 @@ func applyEnvOverrides(c *Config) {
344381 if v := os .Getenv ("VLE_RETRIEVAL_AGENTIC_MODEL" ); v != "" {
345382 c .Retrieval .Agentic .Model = v
346383 }
384+ // Ingest / HyDE knobs. Booleans accept the usual truthy strings —
385+ // kept narrow so a typo doesn't silently flip the flag.
386+ if v := os .Getenv ("VLE_INGEST_HYDE_ENABLED" ); v != "" {
387+ switch strings .ToLower (strings .TrimSpace (v )) {
388+ case "1" , "true" , "yes" , "on" :
389+ c .Ingest .HyDE .Enabled = true
390+ case "0" , "false" , "no" , "off" :
391+ c .Ingest .HyDE .Enabled = false
392+ }
393+ }
394+ if v := os .Getenv ("VLE_INGEST_HYDE_MODEL" ); v != "" {
395+ c .Ingest .HyDE .Model = v
396+ }
397+ if v := os .Getenv ("VLE_INGEST_HYDE_NUM_QUESTIONS" ); v != "" {
398+ if n , err := strconv .Atoi (v ); err == nil && n > 0 {
399+ c .Ingest .HyDE .NumQuestions = n
400+ }
401+ }
402+ if v := os .Getenv ("VLE_INGEST_HYDE_CONCURRENCY" ); v != "" {
403+ if n , err := strconv .Atoi (v ); err == nil && n > 0 {
404+ c .Ingest .HyDE .Concurrency = n
405+ }
406+ }
347407}
348408
349409// Validate checks that required fields for the selected drivers are set.
@@ -416,5 +476,12 @@ func (c Config) Validate() error {
416476 return fmt .Errorf ("server.tls.min_version must be 1.2 or 1.3, got %q" , v )
417477 }
418478
479+ if c .Ingest .HyDE .NumQuestions < 0 {
480+ return fmt .Errorf ("ingest.hyde.num_questions must be >= 0, got %d" , c .Ingest .HyDE .NumQuestions )
481+ }
482+ if c .Ingest .HyDE .Concurrency < 0 {
483+ return fmt .Errorf ("ingest.hyde.concurrency must be >= 0, got %d" , c .Ingest .HyDE .Concurrency )
484+ }
485+
419486 return nil
420487}
0 commit comments