Skip to content

fix(config): preserve KB default fallbacks#609

Open
VectorPeak wants to merge 1 commit into
HKUDS:devfrom
VectorPeak:codex/kb-config-empty-defaults
Open

fix(config): preserve KB default fallbacks#609
VectorPeak wants to merge 1 commit into
HKUDS:devfrom
VectorPeak:codex/kb-config-empty-defaults

Conversation

@VectorPeak

@VectorPeak VectorPeak commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes KB config fallback handling so empty or missing per-KB rag_provider and search_mode values in kb_config.json are treated as unset instead of overriding configured global defaults.

What Problem This Solves

KnowledgeBaseConfigService.get_kb_config() is the read boundary that turns the persisted kb_config.json entry for a knowledge base into the runtime configuration used by RAG pipelines. The previous merge order applied default values first, then expanded **kb_config, so persisted per-KB empty strings could shadow the configured global defaults.

A config shaped like this should mean "this KB has no explicit provider or search mode; use the global defaults":

{
  "defaults": {"rag_provider": "graphrag", "search_mode": "global"},
  "knowledge_bases": {
    "kb-empty": {"path": "kb-empty", "rag_provider": "", "search_mode": ""}
  }
}

Instead, the empty per-KB values were allowed to participate as if they were real overrides. For search_mode, the empty string could replace the intended global mode. For rag_provider, the empty value was even more misleading because provider normalization can collapse unknown or empty values back to the hardcoded default provider, llamaindex, before the configured global default, such as graphrag, is applied.

This makes the effective runtime config depend on whether a KB entry contains blank fields versus missing fields, even though both represent "unset" values from the user's point of view.

Changes

This PR makes the config fallback behavior explicit at the central config service boundary:

  • missing or blank per-KB rag_provider values are treated as unset during payload normalization instead of being materialized immediately as llamaindex
  • get_kb_config() now applies the final rag_provider and search_mode fallback assignments after merging the KB entry, so blank persisted values cannot shadow global defaults
  • legacy index compatibility checks now use the resolved provider, preserving the existing rebuild detection behavior without forcing a missing per-KB provider into the stored KB config

Valid non-empty per-KB overrides still take priority over global defaults. Unknown legacy provider strings still normalize to llamaindex and keep the existing reindex hint behavior. The change is intentionally limited to KB config fallback handling and does not alter RAG pipeline selection, indexing, retrieval, or unrelated config modules.

Evidence

The added config test covers both affected fallback shapes:

empty per-KB rag_provider/search_mode -> falls back to defaults
missing per-KB rag_provider/search_mode -> falls back to defaults

Focused validation for the PR passed locally:

uvx --from pytest==8.4.2 --with pytest-asyncio --with PyYAML --with pydantic --with croniter --with requests pytest -q tests\services\config\test_knowledge_base_config.py
uvx ruff check deeptutor\services\config\knowledge_base_config.py tests\services\config\test_knowledge_base_config.py
uvx ruff format --check deeptutor\services\config\knowledge_base_config.py tests\services\config\test_knowledge_base_config.py
git diff --check

Possible call chain / impact

kb_config.json
-> knowledge_bases[<kb_name>]
-> KnowledgeBaseConfigService._normalize_payload()
-> KnowledgeBaseConfigService.get_kb_config()
-> per-KB config merge/fallback handling
-> selected rag_provider/search_mode for that KB

The change affects only empty or missing per-KB fallback handling. Explicit non-empty per-KB overrides remain the higher-priority KB-specific values, legacy unknown provider normalization still falls back to llamaindex, and unrelated config modules are not changed.

Related Issues

  • Related to #...

Module(s) Affected

  • agents
  • api
  • config
  • core
  • knowledge
  • logging
  • services
  • tools
  • utils
  • web (Frontend)
  • docs (Documentation)
  • scripts
  • tests
  • Other: ...

Checklist

  • I have read and followed the contribution guidelines.
  • My code follows the project's coding standards.
  • I have run pre-commit run --all-files and fixed any issues.
  • I have added relevant tests for my changes.
  • I have updated the documentation (if necessary).
  • My changes do not introduce any new security vulnerabilities.

Additional Notes

Evidence:

  • Added test_get_kb_config_empty_or_missing_fields_fall_back_to_defaults, covering empty per-KB rag_provider / search_mode and a KB entry with those fields missing.
  • uvx --from pytest==8.4.2 --with pytest-asyncio --with PyYAML --with pydantic --with croniter --with requests pytest -q tests\services\config\test_knowledge_base_config.py passed: 17 tests.
  • uvx ruff check deeptutor\services\config\knowledge_base_config.py tests\services\config\test_knowledge_base_config.py passed.
  • uvx ruff format --check deeptutor\services\config\knowledge_base_config.py tests\services\config\test_knowledge_base_config.py passed.
  • git diff --check passed.

pre-commit run --all-files was attempted via uvx pre-commit run --all-files. Python hooks passed through Ruff, but the full run could not complete cleanly in this Windows environment because:

  • prettier attempted to reformat many unrelated web/ files; those unrelated formatter side effects were reverted and are not included in this PR.
  • bandit failed with repository configuration error: Unknown test found in profile: B105.
  • mypy reported existing Windows platform issues around POSIX-only APIs such as resource.setrlimit, os.fork, os.getpgid, and os.killpg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant