Configuring with coniti.toml and overrides¶
Built and verified
The container and its config loading are built and verified. The base
Container accepts four keys: memory (default in_memory),
embedding (default local_hash), structures (default [flat]) and
strategy (default default). A subclass with its own slots accepts its own
keys.
Config files are trusted input
A kind can be a class path such as "my_pkg.embedders:TinyEmbedder".
Resolving it imports that module, and importing runs code. Treat a config
file like code: only load files you wrote or trust.
Where the config is found¶
Container(config) looks in this order and uses the first that applies:
configargument: aPathorstrpath to a file, or a mapping (a dict used directly).- The
CONITI_CONFIGenvironment variable (a file path). ./coniti.tomlin the working directory, unless you passsearch_cwd=False.- Nothing: only the defaults apply.
A path that is given (argument or environment variable) must exist. TOML and
JSON are built in; YAML needs the yaml extra. A missing, malformed or
unreadable file raises ConfigError.
Unknown top-level keys are rejected (typo safety), and the error lists the known keys.
Format¶
Top-level keys are piece names: memory, embedding and structures (a list)
and strategy.
# coniti.toml
[memory]
kind = "in_memory"
[embedding]
kind = "local_hash"
params = { dim = 64, seed = 7 }
[[structures]]
kind = "flat"
Structures are given the embedder’s dim automatically, so you set the
dimension once, under [embedding].
class is an alias for a class-path kind; give one or the other, not both:
The strategy is chosen the same way (default is the only built-in kind):
segment_tree is built too (time-range summaries; see structure):
Priority and merging¶
default < config < bind < override < explicit argument.
- A higher layer naming the same implementation, or giving only
params, deep-merges its params over the lower layer. - A higher layer naming a different implementation replaces the lower binding.
- A list-valued piece (such as
structures) is replaced as a whole, never merged.
from coniti import Container, Embedder
c = Container("coniti.toml")
c.bind(Embedder, {"kind": "local_hash", "params": {"dim": 128}}) # permanent for c
with c.override(Embedder, MyEmbedder()): # temporary, restores on exit
...
c.resolved() # per piece: layer, kind, params, spec id, implementation; builds nothing
Changing the embedding dimension rebuilds the structures to match; leaving an
override restores the previous ones. A Strategy can be overridden the same way.
Changing the defaults without editing coniti¶
Use a config file, bind / override, or subclass Container and replace
defaults (and slots to add pieces). See container for a runnable example.
Errors¶
Any invalid binding raises ConfigError, a ValueError carrying .key (the
piece) and .layer; both are named in the message. Cases include an unknown
kind, an unimportable class path, a class that does not subclass the interface,
bad params, a wrong binding type, a dependency cycle, a factory that raises, and
a malformed or missing config file.