config

package
v0.10.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 31, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package config defines the amoxtli workspace configuration file (.amoxtli/config.yaml): parsing, environment variable interpolation and validation. The mapping of each field to the library API lives in internal/cli/runtime.

Index

Constants

View Source
const (
	ImageStoreAuto     = "auto"
	ImageStoreFS       = "fs"
	ImageStoreDatabase = "database"
	ImageStoreNone     = "none"
)

Image store backends.

View Source
const (
	// ProfileFast disables every per-search chat call (no HyDE, no Judge):
	// embeddings + weighted RRF fusion + dedup only.
	ProfileFast = "fast"
	// ProfileBalanced keeps HyDE (one cached, seeded chat call) but no Judge.
	ProfileBalanced = "balanced"
	// ProfilePrecision adds the fused grounding evaluator on top of HyDE.
	ProfilePrecision = "precision"
)

Retrieval profiles: presets of the LLM retrieval stages, from cheapest to most thorough. The SciFact evaluations showed the embedder dominates quality, so the cheap profile is usually competitive.

View Source
const DefaultImagesPath = "blobs"

DefaultImagesPath is the blob directory used when images.path is left empty, relative to the .amoxtli directory.

View Source
const DefaultLLMCachePath = "cache"

DefaultLLMCachePath is the LLM cache root used when llm.cache.path is left empty, relative to the .amoxtli directory.

View Source
const Template = `` /* 9531-byte string literal not displayed */

Template is the commented configuration written by "amoxtli init". It must stay loadable as-is (comments are not expanded, see ExpandEnv).

Variables

ImageStores lists the accepted images.store values.

Profiles lists the accepted retrieval.profile values.

View Source
var StageNames = []string{"hyde", "judge", "grounding", "rerank", "decompose", "reformulate", "translate"}

StageNames lists the retrieval stages accepted under llm.stages, mirroring amoxtli.Stages.

View Source
var SupportedProviders = []string{"openai", "openrouter", "mistral"}

SupportedProviders lists the llm.chat / llm.embeddings providers the CLI can wire. All share provider.CommonOptions (model, base_url, api_key).

Functions

func ExpandEnv

func ExpandEnv(s string, lookup func(string) (string, bool)) (string, error)

ExpandEnv expands $VAR and ${VAR} references in s using lookup, supporting the ${VAR:-default} fallback syntax and $$ as a literal dollar escape. A reference to an undefined variable without a default is an error (fail fast rather than silently injecting an empty secret).

Full-line comments (lines whose first non-blank character is '#') are left untouched, so configuration examples in comments are not expanded.

Types

type ClientConfig

type ClientConfig struct {
	Provider string `yaml:"provider"`
	BaseURL  string `yaml:"base_url"`
	Model    string `yaml:"model"`
	APIKey   string `yaml:"api_key"`
}

type CodeIndexingConfig added in v0.0.4

type CodeIndexingConfig struct {
	// Enabled accepts true, false or "auto"; auto (the default) enables
	// source-code indexing (it is pure Go and needs no external tool). Source
	// files are split into declaration-level sections and tagged with
	// `type=code` and `language=<name>` metadata, filterable at search time.
	Enabled Toggle `yaml:"enabled"`
	// Extensions extends or overrides the built-in extension→language mapping,
	// e.g. {".phtml": "php"}. Languages: go, javascript, typescript, tsx,
	// python, php.
	Extensions map[string]string `yaml:"extensions"`
}

type Config

type Config struct {
	Version   int             `yaml:"version"`
	Store     StoreConfig     `yaml:"store"`
	Index     IndexConfig     `yaml:"index"`
	LLM       LLMConfig       `yaml:"llm"`
	Retrieval RetrievalConfig `yaml:"retrieval"`
	Converter ConverterConfig `yaml:"converter"`
	Indexing  IndexingConfig  `yaml:"indexing"`
	Images    ImagesConfig    `yaml:"images"`
}

func Default

func Default() *Config

Default returns the configuration used when a field is absent from the file; zero numeric values defer to the library defaults.

func Load

func Load(path string) (*Config, error)

Load reads, expands and validates the configuration file at path. Variable references are resolved against the process environment, then against an optional .env file sitting next to the configuration file.

func Parse

func Parse(raw string, lookup func(string) (string, bool)) (*Config, error)

Parse expands and decodes a raw configuration document, then validates it. Unknown fields are rejected to catch typos early.

func (*Config) CodeEnabled added in v0.0.4

func (c *Config) CodeEnabled() bool

CodeEnabled resolves the source-code indexing toggle; it defaults to enabled (pure Go, no external dependency).

func (*Config) EmbeddedVisionEnabled added in v0.9.0

func (c *Config) EmbeddedVisionEnabled() bool

EmbeddedVisionEnabled reports whether the images embedded in documents must be described too. It depends on the vision converter being enabled.

func (*Config) GroundingEnabled added in v0.6.0

func (c *Config) GroundingEnabled() bool

GroundingEnabled reports whether the evidence evaluator runs on every search, and therefore whether a grounding verdict is available to surface. It mirrors the option wiring in runtime.retrievalOptions: the iterative orchestration and the precision profile both imply it.

func (*Config) HasChat

func (c *Config) HasChat() bool

HasChat reports whether a chat completion client is configured.

func (*Config) HasEmbeddings

func (c *Config) HasEmbeddings() bool

HasEmbeddings reports whether an embeddings client is configured.

func (*Config) HasLocalState added in v0.0.10

func (c *Config) HasLocalState() bool

HasLocalState reports whether the workspace opens any file-based backend that a single process must hold exclusively (bleve, sqlite-vec or the sqlite store). When false, the workspace is fully backed by a client-server database and several processes may run against it concurrently, so the exclusive workspace lock is skipped.

func (*Config) ImageStoreDriver added in v0.9.0

func (c *Config) ImageStoreDriver() string

ImageStoreDriver resolves the images.store toggle: "auto" picks "database" when the document store is PostgreSQL — everything in one server — and "fs" otherwise.

func (*Config) ImagesEnabled added in v0.9.0

func (c *Config) ImagesEnabled() bool

ImagesEnabled reports whether images must be stored. An explicit backend is an opt-in on its own (the library API can store images without the converter); left to "auto", storage follows the vision converter, since nothing would produce image references without it.

func (*Config) ImagesPath added in v0.9.0

func (c *Config) ImagesPath() string

ImagesPath returns the configured blob directory, falling back to DefaultImagesPath. The path may be relative to the .amoxtli directory (resolve it with workspace.Resolve).

func (*Config) IndexDriver added in v0.0.10

func (c *Config) IndexDriver() string

IndexDriver returns the normalized index backend ("local" when unset).

func (*Config) IterativeRetrievalEnabled added in v0.6.0

func (c *Config) IterativeRetrievalEnabled() bool

IterativeRetrievalEnabled reports whether searches should run the grounding-driven re-retrieval orchestration. It requires a chat client, so callers can use it as the single decision point between SearchPage and SearchIterative.

func (*Config) LLMCacheEnabled added in v0.2.0

func (c *Config) LLMCacheEnabled() bool

LLMCacheEnabled resolves the LLM cache toggle: enabled by default as soon as an embeddings or chat client is configured.

func (*Config) LLMCachePath added in v0.2.0

func (c *Config) LLMCachePath() string

LLMCachePath returns the configured LLM cache root directory, falling back to DefaultLLMCachePath. The path may be relative to the .amoxtli directory (resolve it with workspace.Resolve).

func (*Config) PostgresIndexDSN added in v0.0.10

func (c *Config) PostgresIndexDSN() string

PostgresIndexDSN returns the DSN the postgres index should connect to, falling back to the store DSN when the index DSN is left empty and the store is itself postgres.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks cross-field constraints and rejects combinations that would fail later with an obscure error.

func (*Config) VectorEnabled

func (c *Config) VectorEnabled() bool

VectorEnabled resolves the vector index toggle against the presence of an embeddings client. It only governs the local sqlite-vec index; the postgres index manages its vector leg internally.

func (*Config) VisionChat added in v0.9.0

func (c *Config) VisionChat() *ClientConfig

VisionChat resolves the chat client used to describe images: the dedicated converter.vision.chat when set, llm.chat otherwise, nil when neither is configured.

func (*Config) VisionEnabled added in v0.9.0

func (c *Config) VisionEnabled() bool

VisionEnabled reports whether image files should be described by a vision LLM and indexed as markdown.

func (*Config) VisionExtensions added in v0.9.0

func (c *Config) VisionExtensions() []string

VisionExtensions returns the extensions routed to the vision converter, falling back to the built-in image list.

type ConverterConfig

type ConverterConfig struct {
	Pandoc      PandocConfig          `yaml:"pandoc"`
	LibreOffice LibreOfficeConfig     `yaml:"libreoffice"`
	GenAI       GenAIConverterConfig  `yaml:"genai"`
	Vision      VisionConverterConfig `yaml:"vision"`
}

type DecompositionConfig

type DecompositionConfig struct {
	Enabled       bool `yaml:"enabled"`
	MaxSubQueries int  `yaml:"max_sub_queries"`
}

type EmbeddedVisionConfig added in v0.9.0

type EmbeddedVisionConfig struct {
	// Enabled turns on the enrichment. It requires converter.vision.enabled.
	Enabled bool `yaml:"enabled"`
	// MinDimensions is the smallest accepted side, in pixels: below it an
	// image is an icon or a bullet, never content. 0 defers to the library
	// default (64).
	MinDimensions int `yaml:"min_dimensions"`
	// MaxImagesPerDocument bounds the number of distinct images described per
	// document — the main cost lever on image-rich corpora. 0 defers to the
	// library default (32).
	MaxImagesPerDocument int `yaml:"max_images_per_document"`
	// Concurrency bounds the parallel descriptions of a single document. 0
	// defers to the library default (2).
	Concurrency int `yaml:"concurrency"`
}

EmbeddedVisionConfig configures the description of the images embedded in markdown documents (native .md as well as converter output: pandoc, LibreOffice, GenAI OCR). The description is inserted as text next to the image, so it is indexed and searched like the rest of the document.

Relative image paths are resolved against the directory of the indexed file and strictly confined to it; remote (http/https) images are never fetched.

type FulltextIndexConfig

type FulltextIndexConfig struct {
	Enabled bool    `yaml:"enabled"`
	Path    string  `yaml:"path"`
	Weight  float64 `yaml:"weight"`
}

type GenAIConverterConfig

type GenAIConverterConfig struct {
	// Enabled turns on the GenAI (OCR/LLM) converter. It is opt-in: a DSN and
	// at least one extension are required.
	Enabled bool `yaml:"enabled"`
	// DSN selects the extraction backend, e.g. mistral://?apiKey=${MISTRAL_API_KEY}
	// or marker://host:port.
	DSN string `yaml:"dsn"`
	// Extensions are routed to this converter (e.g. .pdf, .png, .jpg).
	Extensions []string `yaml:"extensions"`
}

type ImagesConfig added in v0.9.0

type ImagesConfig struct {
	// Store selects the backend: "auto" (the default), "fs", "database" or
	// "none". Auto follows the document store: "database" when it is
	// PostgreSQL (one server to back up), "fs" when it is SQLite (keeping the
	// bytes out of a file bleve and sqlite-vec already sit next to).
	Store string `yaml:"store"`
	// Path is the directory of the "fs" backend, relative to the .amoxtli
	// directory (default "blobs").
	Path string `yaml:"path"`
	// MaxSize bounds the size of a stored image, in bytes; 0 defers to the
	// library default (10 MiB, aligned with converter.vision.max_image_size).
	MaxSize int64 `yaml:"max_size"`
}

ImagesConfig configures the storage of the images referenced by the indexed documents, which is what makes them displayable again (MCP fetch_image) rather than merely searchable.

type IndexConfig

type IndexConfig struct {
	// Driver selects the index backend. "local" (the default) uses the
	// file-based bleve full-text index and the sqlite-vec vector index,
	// configured through the fulltext/vector sections below. "postgres" uses a
	// single hybrid PostgreSQL index (native full-text + pgvector), suitable
	// for a shared deployment where several processes query the same database
	// concurrently.
	Driver   string              `yaml:"driver"`
	Fulltext FulltextIndexConfig `yaml:"fulltext"`
	Vector   VectorIndexConfig   `yaml:"vector"`
	Postgres PostgresIndexConfig `yaml:"postgres"`
}

type IndexingConfig

type IndexingConfig struct {
	MaxWordsPerSection int                `yaml:"max_words_per_section"`
	TaskParallelism    int                `yaml:"task_parallelism"`
	PersistentTasks    bool               `yaml:"persistent_tasks"`
	Code               CodeIndexingConfig `yaml:"code"`
}

type IterativeConfig

type IterativeConfig struct {
	Enabled   bool `yaml:"enabled"`
	MaxRounds int  `yaml:"max_rounds"`
}

type LLMCacheConfig added in v0.2.0

type LLMCacheConfig struct {
	// Enabled accepts true, false or "auto"; auto (the default) enables the
	// cache whenever an embeddings or chat client is configured.
	Enabled Toggle `yaml:"enabled"`
	// Path is the cache root directory, relative to the .amoxtli directory
	// (default "cache"). Entries are keyed by model, so switching model never
	// serves results from the wrong space.
	Path string `yaml:"path"`
}

LLMCacheConfig configures the persistent LLM cache. Embedding a text is deterministic for a given model — and the HyDE completion is seeded per query — so both are reused across runs: re-indexing unchanged content and repeating a query become cache hits instead of billable, rate-limited calls.

type LLMConfig

type LLMConfig struct {
	Chat       *ClientConfig `yaml:"chat"`
	Embeddings *ClientConfig `yaml:"embeddings"`
	// Stages assigns a dedicated chat client to individual retrieval stages
	// (hyde, judge, grounding, rerank, decompose, reformulate), overriding
	// llm.chat for that stage. The main cost lever of a search: point the
	// high-volume stages (hyde, judge) at a small fast model while keeping a
	// stronger model as the default. Requires llm.chat.
	Stages map[string]*ClientConfig `yaml:"stages"`
	// Cache is the persistent on-disk LLM cache: embedding vectors (below
	// <path>/embeddings) and deterministic seeded chat completions such as
	// HyDE (below <path>/chat).
	Cache LLMCacheConfig `yaml:"cache"`
}

type LibreOfficeConfig

type LibreOfficeConfig struct {
	// Enabled accepts true, false or "auto"; auto enables the LibreOffice
	// converter when both the libreoffice and pandoc binaries are found. It
	// supersedes the standalone pandoc converter, adding .doc support.
	Enabled Toggle `yaml:"enabled"`
}

type PandocConfig

type PandocConfig struct {
	// Enabled accepts true, false or "auto"; auto enables the pandoc
	// converter when the binary is found in the PATH.
	Enabled Toggle `yaml:"enabled"`
}

type PostgresIndexConfig added in v0.0.10

type PostgresIndexConfig struct {
	// DSN is the PostgreSQL connection string. When empty it defaults to
	// store.dsn (only valid when the store is also postgres), letting the index
	// and the document store share a single database.
	DSN    string  `yaml:"dsn"`
	Weight float64 `yaml:"weight"`
	// VectorSize is the pgvector column dimension; 0 defers to the library
	// default.
	VectorSize int `yaml:"vector_size"`
	// MaxWords bounds the chunk size sent to the embeddings model; 0 defers to
	// the library default.
	MaxWords int `yaml:"max_words"`
	// TextSearchConfig is the regconfig used when language detection is
	// inconclusive; empty defers to the library default ("simple").
	TextSearchConfig string `yaml:"text_search_config"`
}

PostgresIndexConfig configures the hybrid PostgreSQL index (index.driver: postgres). The vector leg is active only when llm.embeddings is configured; otherwise the index degrades to full-text search only.

type RetrievalConfig

type RetrievalConfig struct {
	// Profile selects a preset of retrieval stages: "fast" (no per-search
	// chat call), "balanced" (HyDE only) or "precision" (HyDE + grounding
	// evaluator). Empty keeps the historical default (HyDE + Judge when
	// llm.chat is configured). Explicit keys below still apply on top of the
	// profile (they can enable more stages, not disable the profile's).
	Profile           string `yaml:"profile"`
	Reranking         bool   `yaml:"reranking"`
	GroundingCheck    bool   `yaml:"grounding_check"`
	GroundingFailOpen bool   `yaml:"grounding_fail_open"`
	// GroundingMode is how the grounding verdict is applied to the evidence:
	// "demote" (default) keeps every document but ranks irrelevant ones last —
	// preserving recall@k while improving ranking; "filter" drops the
	// irrelevant documents — high list precision but truncated recall, for
	// short-list RAG. Empty defers to the library default (demote).
	GroundingMode string `yaml:"grounding_mode"`
	// MaxTotalWords bounds the prompt size (in words) of the LLM retrieval
	// stages (reranker, judge, evidence evaluator). Keep it low enough that the
	// resulting prompt fits your chat endpoint's context window: words are only
	// a coarse proxy for tokens (~1.8 tokens/word on mixed prose and code), so
	// 18000 words already overflow a 32k-token limit. Zero defers to the
	// library default (8000).
	MaxTotalWords int `yaml:"max_total_words"`
	// MaxSectionWords bounds how many words of each retrieved section are
	// included in those prompts, on top of MaxTotalWords. Relevance is almost
	// always judgeable from the beginning of a section, so a low cap cuts the
	// per-search prompt cost. Zero defers to the library default (200).
	MaxSectionWords int                 `yaml:"max_section_words"`
	Iterative       IterativeConfig     `yaml:"iterative"`
	Decomposition   DecompositionConfig `yaml:"decomposition"`
	Translation     TranslationConfig   `yaml:"translation"`
}

type StoreConfig

type StoreConfig struct {
	// Driver selects the document store backend: "sqlite" (file-based) or
	// "postgres" (client-server, for a shared/concurrent deployment).
	Driver string `yaml:"driver"`
	// DSN is the store location. For sqlite it is a path relative to the
	// .amoxtli directory; for postgres it is a connection string
	// (postgres://user:pass@host:5432/db?sslmode=disable).
	DSN string `yaml:"dsn"`
}

type Toggle

type Toggle string

Toggle is a tri-state flag accepting true, false or "auto" in YAML.

const (
	ToggleAuto  Toggle = "auto"
	ToggleTrue  Toggle = "true"
	ToggleFalse Toggle = "false"
)

func (Toggle) Resolve

func (t Toggle) Resolve(auto bool) bool

Resolve returns the boolean value of the toggle, falling back to auto when the toggle is "auto" (or unset).

func (*Toggle) UnmarshalYAML

func (t *Toggle) UnmarshalYAML(node *yaml.Node) error

type TranslationConfig added in v0.10.0

type TranslationConfig struct {
	Enabled bool `yaml:"enabled"`
	// MaxLanguages bounds how many corpus languages the query is translated
	// into, most represented first. Zero defers to the library default (2).
	MaxLanguages int `yaml:"max_languages"`
}

TranslationConfig widens the query sent to the full-text index with its translation into the languages the corpus is written in (metadata "lang", detected at ingestion). Off by default: it costs one chat call per distinct query and only pays off when questions and documents are in different languages.

type VectorIndexConfig

type VectorIndexConfig struct {
	// Enabled accepts true, false or "auto"; auto enables the vector index
	// when an embeddings client is configured.
	Enabled    Toggle  `yaml:"enabled"`
	Path       string  `yaml:"path"`
	Weight     float64 `yaml:"weight"`
	VectorSize int     `yaml:"vector_size"`
	MaxWords   int     `yaml:"max_words"`
	// EmbeddingsConcurrency bounds how many embedding batches are computed in
	// parallel for a single document. It is the main lever for large-file
	// indexing latency (one big file is a single task, so cross-file parallelism
	// does not help it). Raise it if your embeddings endpoint tolerates more
	// concurrent requests; lower it to avoid rate limiting (429). 0 defers to the
	// library default.
	EmbeddingsConcurrency int `yaml:"embeddings_concurrency"`
	// ReadPool is the number of dedicated read connections opened for
	// concurrent searches (WAL). 0 defers to the library default (4).
	ReadPool int `yaml:"read_pool"`
	// CoarseQuantization enables the two-stage vector search: a fast KNN on
	// binary-quantized vectors preselects candidates, re-scored with the full
	// float vectors. Worthwhile on large corpora (100k+ chunks); requires a
	// vector size divisible by 8. Off by default.
	CoarseQuantization bool `yaml:"coarse_quantization"`
}

type VisionConverterConfig added in v0.9.0

type VisionConverterConfig struct {
	// Enabled turns on the vision converter. It is opt-in and requires a chat
	// client: the dedicated one below, or llm.chat.
	Enabled bool `yaml:"enabled"`
	// Chat is a dedicated chat client pointing at a vision-capable model.
	// When absent, llm.chat is reused — which then must itself support image
	// attachments.
	Chat *ClientConfig `yaml:"chat"`
	// Extensions are routed to this converter; empty defers to the built-in
	// list (see VisionExtensions).
	Extensions []string `yaml:"extensions"`
	// MaxImageSize bounds the size of an image sent to the model, in bytes;
	// 0 defers to the library default (10 MiB). Oversized files are rejected
	// before any call.
	MaxImageSize int64 `yaml:"max_image_size"`
	// Prompt replaces the built-in description prompt. It is part of the
	// description cache key, so changing it invalidates previous descriptions.
	Prompt string `yaml:"prompt"`
	// Embedded describes the images embedded in documents, on top of the
	// standalone image files handled by the converter itself.
	Embedded EmbeddedVisionConfig `yaml:"embedded"`
}

VisionConverterConfig configures the description of image files by a vision LLM: each image becomes a markdown document (title, description, visible text) tagged with type=image, searchable like any other document.

Extensions are routed before converter.genai (see convert.Routed and runtime.newFileConverter): an extension listed here wins over the same extension listed under converter.genai.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL