Configuration Reference

On this page

All configuration lives in config.py as a tree of @dataclass definitions rooted at ContextEngineConfig. Every sub-config has a sensible default, so ContextEngineConfig() works with zero arguments.

Python · 6 lines
from zerda.context import ContextEngineConfig

config = ContextEngineConfig()
config.retriever.top_k = 30
config.composer.template = "structured"
config.guard.check_relevance = True

ContextEngineConfig (root)

FieldTypeDefaultPurpose
query_analyzerQueryAnalyzerConfignew instanceSee below
retrieverRetrieverConfignew instanceSee below
filter_cfgFilterConfignew instanceSee below
rankingRankingConfignew instanceSee below
composerComposerConfignew instanceSee below
guardGuardConfignew instanceSee below
cacheCacheConfignew instanceSee below
languagestr"auto"Documented values: "auto", "ar", "en". Note: grepping the implementation, this field is not actually read anywhere outside of being stored — language detection is performed per-query by RuleBasedQueryAnalyzer regardless of this setting.
enable_adaptiveboolTrueGates whether AdaptiveLearningSystem.record() and .suggest_budget() do anything.
multi_turnboolTrueGates whether ContextEngine creates a ConversationHistory and uses it for query enrichment.

It also exposes three backward-compatible properties that proxy into composer:

  • max_context_length (get/set) → composer.max_context_length
  • separator (get only) → composer.separator
  • template (get only) → composer.template

ContextConfig is a plain alias: ContextConfig = ContextEngineConfig. They are the same class.

QueryAnalyzerConfig

FieldTypeDefaultPurpose
budget_lowint800Context budget (chars) assigned to QueryComplexity.LOW queries
budget_mediumint2000Context budget assigned to QueryComplexity.MEDIUM queries
budget_highint4000Context budget assigned to QueryComplexity.HIGH queries
custom_entitiesList[str][]Domain-specific terms always recognized as entities if present in the query (case-insensitive substring match)
arabic_thresholdfloat0.3Minimum ratio of Arabic characters to non-space characters for a query to be classified as Arabic

RetrieverConfig

FieldTypeDefaultPurpose
top_kint20Number of results requested from the hybrid retriever before filtering/ranking
vector_weightfloat0.60Weight of vector similarity in the hybrid composite score
keyword_weightfloat0.30Weight of BM25 score in the hybrid composite score
metadata_weightfloat0.10Weight of metadata-match score in the hybrid composite score
use_vectorboolTrueEnable/disable the vector retrieval branch
use_keywordboolTrueEnable/disable the BM25 keyword retrieval branch
use_metadataboolFalseEnable/disable the metadata-filter retrieval branch (also requires filters to be passed at call time)
metadata_filtersDict[str, str]{}Stored but not read by any code path inspected — actual filters are passed per-call to retrieve(..., filters=...) instead
min_vector_scorefloat0.0Minimum cosine similarity for a vector hit to be kept

[!WARNING] metadata_filters vs. per-call filters RetrieverConfig.metadata_filters exists as a field but is never referenced by retriever.py, engine.py, or pipeline.py. The filters that actually take effect are the ones passed as the metadata_filters argument to ContextEngine.run(), which flow into HybridRetriever.retrieve(filters=...). Don't rely on the config field.

FilterConfig

FieldTypeDefaultPurpose
dedup_methodstr"hash"Documented values: "hash", "prefix", "semantic". Note: ChunkFilter.filter() always performs hash-based dedup (_dedup_hash) regardless of this value — it is not branched on anywhere in pipeline.py. Semantic dedup is available, but only via the separate filter_with_embeddings() method, not gated by this field.
prefix_lengthint100Used only by the legacy legacy_compat.PrefixDeduplication, not by ChunkFilter
semantic_sim_thresholdfloat0.92Cosine similarity threshold above which two chunks are considered semantic duplicates, used by ChunkFilter._dedup_semantic (called from filter_with_embeddings)
min_chunk_lengthint20Chunks shorter than this (characters) are dropped
max_chunk_lengthint4000Chunks longer than this (characters) are dropped
noise_patternsList[str]3 regexes (blank lines, divider lines, page-number lines, in Arabic and English)Any chunk whose stripped text fully matches one of these regexes (via re.match) is treated as noise and removed

RankingConfig

FieldTypeDefaultPurpose
weight_vector_scorefloat0.40Weight of vector similarity in CompositeRanker's score
weight_keyword_scorefloat0.25Weight of a keyword-overlap boost (fraction of query keywords found in chunk text)
weight_source_qualityfloat0.20Weight of normalized SourceQuality (0–1)
weight_recencyfloat0.10Weight of ScoredChunk.recency_score (you must populate this yourself — nothing in the package sets it automatically)
weight_positionfloat0.05Weight of a position score that decays by 0.01 per unit of retrieval_rank
max_chunks_to_rankint15Maximum chunks kept after ranking, passed on to the composer

[!NOTE] Weights don't have to sum to 1.0 The implementation never normalizes these weights — it computes a plain weighted sum. If you change weights without checking the total, the resulting composite_score scale will shift accordingly. This mostly matters if you compare scores across different configurations.

ComposerConfig

FieldTypeDefaultPurpose
max_context_lengthint2000Default budget (characters) if no per-query budget overrides it
separatorstr"\n---\n"String inserted between formatted chunks
templatestr"arabic"One of "arabic", "english", "minimal", "structured" — selects a ContextTemplate (see api/pipeline)
include_scoresboolFalseIf True, uses the template's chunk_fmt_score variant, embedding the composite score in each chunk's header
include_metadataboolFalseIf True, appends up to 5 metadata key/value pairs after each chunk
include_sourcesboolTrueStored but not read anywhere in pipeline — all four built-in templates always include a source label regardless of this flag
group_by_sourceboolFalseIf True, groups chunks by .source before formatting, ordering groups by their best chunk's score
summarize_long_chunksboolFalseStored but not implemented anywhere — see Architecture
min_compression_charsint50Stored but not referenced by any code path inspected (note: legacy_compat.GreedyCompression has its own separate hardcoded MIN_CONTENT_LENGTH = 50, which is not wired to this config field)

GuardConfig

FieldTypeDefaultPurpose
enabledboolTrueMaster switch; if False, ContextGuard.validate() always returns (True, []) immediately
min_context_lengthint10Below this many characters, the guard fails (passed=False)
max_context_lengthint8000Above this, the guard adds a warning but does not fail
check_emptyboolTrueIf True and the context is blank/whitespace-only, the guard fails immediately with ["context is empty ⚠"], short-circuiting the remaining checks
check_relevanceboolFalseRequires an embed_fn to be passed to ContextGuard.__init__; if enabled without one, this check is silently skipped (no error)
relevance_thresholdfloat0.10Minimum cosine similarity between query and context embeddings for the relevance check to pass
check_source_coverageboolTrueAdds a (non-failing) warning if no [Source: ...]/[المصدر: ...]-style marker or --- separator is found in the context

CacheConfig

FieldTypeDefaultPurpose
enabledboolTrueIf True, ContextEngine constructs a ContextCache; if False, caching is skipped entirely (no cache object is created)
max_sizeint256Maximum number of distinct queries cached (LRU eviction)
ttl_secondsint300Cache entries older than this are treated as a miss and evicted on next access

LengthCounter

Not a dataclass — a type alias: LengthCounter = Callable[[str], int]. Used wherever the codebase needs to measure "length" abstractly (characters by default via char_counter, or tokens via make_token_counter).

Related pages